diff --git a/@config/shared-theme-zh.ts b/@config/shared-theme-zh.ts
index c4f0f19974..f4a00c28c7 100644
--- a/@config/shared-theme-zh.ts
+++ b/@config/shared-theme-zh.ts
@@ -1,6 +1,7 @@
import { defineConfig, type DefaultTheme } from 'vitepress'
import { github, branch } from './config'
+
export default function(version: string) {
return defineConfig({
lang: 'zh-Hans',
diff --git a/README.md b/README.md
index 738b0cbb7e..d1aecc873f 100644
--- a/README.md
+++ b/README.md
@@ -11,17 +11,17 @@ npm install
## Generate Sidebar
-node ./scripts/create-sidebar.js versions/3.8/zh/SUMMARY.md
+node ./scripts/create-sidebar.js versions/4.0/zh/SUMMARY.md
-node ./scripts/create-sidebar.js versions/3.8/en/SUMMARY.md
+node ./scripts/create-sidebar.js versions/4.0/en/SUMMARY.md
## Run In Dev Mode
-npx vitepress dev versions/3.8
+npx vitepress dev versions/4.0
## Build
-node ./scripts/publish.js --version=versions/3.8
+node ./scripts/publish.js --version=versions/4.0
## Build All
@@ -29,6 +29,6 @@ node ./scripts/publish.js --version=versions/all
## Preview
-npx vitepress preview versions/3.8
+npx vitepress preview versions/4.0
-> Change the '3.8' above to operate another version.
\ No newline at end of file
+> Change the '4.0' above to operate another version.
\ No newline at end of file
diff --git a/package.json b/package.json
index 61aeaedebd..17f0a3e489 100644
--- a/package.json
+++ b/package.json
@@ -4,9 +4,9 @@
"description": "cocos-creator-docs",
"type": "module",
"scripts": {
- "docs:dev": "cross-env __APIDOC__=https://docs.cocos.com/creator/3.8/api vitepress dev versions/3.8 --port=5001 --host",
- "docs:build": "cross-env __APIDOC__=https://docs.cocos.com/creator/3.8/api vitepress build versions/3.8",
- "docs:preview": "vitepress preview versions/3.8"
+ "docs:dev": "cross-env __APIDOC__=https://docs.cocos.com/creator/4.0/api vitepress dev versions/4.0 --port=5001 --host",
+ "docs:build": "cross-env __APIDOC__=https://docs.cocos.com/creator/4.0/api vitepress build versions/4.0",
+ "docs:preview": "vitepress preview versions/4.0"
},
"keywords": [],
"author": "cocos",
diff --git a/versions.json b/versions.json
index b23f82bad3..c698c6e269 100644
--- a/versions.json
+++ b/versions.json
@@ -1,4 +1,7 @@
[
+ {
+ "version": "4.0"
+ },
{
"version": "3.8"
},
diff --git a/versions/4.0/.vitepress/config/index.ts b/versions/4.0/.vitepress/config/index.ts
new file mode 100644
index 0000000000..fcab5171f3
--- /dev/null
+++ b/versions/4.0/.vitepress/config/index.ts
@@ -0,0 +1,58 @@
+import { defineConfig } from 'vitepress'
+import { shared } from '../../../../@config/shared'
+
+// 每个语言的配置
+import configZhFn from '../../../../@config/shared-theme-zh'
+import configEnFn from '../../../../@config/shared-theme-en'
+import { nav } from '../../../../@config/shared';
+
+// 侧边栏数据
+import menusEN from '../../en/summary.json' with {type: 'json'};
+import menusZH from '../../zh/summary.json' with {type: 'json'};
+
+import { version } from './version.ts';
+
+// 英文配置
+const configEn = configEnFn(version);
+const en = defineConfig({
+ lang: configEn.lang,
+ description: configEn.description,
+
+ themeConfig: {
+ ...configEn.themeConfig,
+
+ nav: nav(version, 'en'),
+
+ sidebar: {
+ '/en/': { base: '/en/', items: menusEN },
+ }
+ }
+})
+
+// 中文配置
+const configZh = configZhFn(version);
+const zh = defineConfig({
+ lang: configZh.lang,
+ description: configZh.description,
+
+ themeConfig: {
+ ...configZh.themeConfig,
+
+ nav: nav(version, 'zh'),
+
+ sidebar: {
+ '/zh/': { base: '/zh/', items: menusZH },
+ }
+ }
+})
+
+export default defineConfig({
+ ...shared,
+ base: `/creator/${version}/manual/` , // `/${version}/`
+ locales: {
+ // 我们的文档都在 /en/ /zh/ 等文件夹里面,没有在根目录的文档 所以不用配 root
+ // root: { label: 'English', ...en },
+ en: { label: 'English', ...en },
+ zh: { label: '简体中文', ...zh }
+ }
+})
diff --git a/versions/4.0/.vitepress/config/version.ts b/versions/4.0/.vitepress/config/version.ts
new file mode 100644
index 0000000000..54aea805fc
--- /dev/null
+++ b/versions/4.0/.vitepress/config/version.ts
@@ -0,0 +1 @@
+export const version = '4.0';
\ No newline at end of file
diff --git a/versions/4.0/.vitepress/theme/index.ts b/versions/4.0/.vitepress/theme/index.ts
new file mode 100644
index 0000000000..cb25ea07fb
--- /dev/null
+++ b/versions/4.0/.vitepress/theme/index.ts
@@ -0,0 +1,6 @@
+
+import theme from '../../../../@config/theme/index.ts'
+import { version } from '../config/version.ts'
+
+export default theme(version)
+
diff --git a/versions/4.0/en/2d-object/2d-render/add-render-component.png b/versions/4.0/en/2d-object/2d-render/add-render-component.png
new file mode 100644
index 0000000000..00384113be
Binary files /dev/null and b/versions/4.0/en/2d-object/2d-render/add-render-component.png differ
diff --git a/versions/4.0/en/2d-object/2d-render/create-2d.png b/versions/4.0/en/2d-object/2d-render/create-2d.png
new file mode 100644
index 0000000000..c0400a8c67
Binary files /dev/null and b/versions/4.0/en/2d-object/2d-render/create-2d.png differ
diff --git a/versions/4.0/en/2d-object/2d-render/index.md b/versions/4.0/en/2d-object/2d-render/index.md
new file mode 100644
index 0000000000..e1ebc76e74
--- /dev/null
+++ b/versions/4.0/en/2d-object/2d-render/index.md
@@ -0,0 +1,45 @@
+# 2D Render Description
+
+All rendering objects in the engine that do not own a model are 2D rendering objects. Unlike 3D objects, 2D objects do not have model information, and their vertex information is held by the Rect information of the UITransform component and created by the engine, and they have no thickness themselves. Due to the design requirements of the engine, the 2D render object needs to be a child of the RenderRoot node (the node with the RenderRoot2D component) in order to complete the data collection operation.
+
+The rendering requirements for the 2D render object are twofold:
+1. It needs to have a UITransform component
+2. It needs to be a child of a RenderRoot node
+
+## 2D Rendering Object Visibility Description
+
+Since there is no difference between 2D rendering objects and 3D renderable nodes in terms of camera visibility, users need to control the layer property of the node and set the Visibility of the camera to match the group rendering. If there are multiple cameras in the scene, wrong layer settings may cause the node to be rendered repeatedly or not at all.
+
+## 2D Renderable Components
+
+Components that have rendering capabilities in their own right are called 2D Renderable components, including:
+
+- [Sprite Component Reference](../../ui-system/components/editor/sprite.md)
+- [Label Component Reference](../../ui-system/components/editor/label.md)
+- [Mask Component Reference](../../ui-system/components/editor/mask.md)
+- [Graphics Component Reference](../../ui-system/components/editor/graphics.md)
+- [RichText Component Reference](../../ui-system/components/editor/richtext.md)
+- [UIStaticBatch Component Reference](../../ui-system/components/editor/ui-static.md)
+- [TiledMap Component Reference](../../editor/components/tiledmap.md)
+- [TiledTile Component Reference](../../editor/components/tiledtile.md)
+- [Spine Skeletal Component Reference](../../editor/components/spine.md)
+- [DragonBones ArmatureDisplay Component Reference](../../editor/components/dragonbones.md)
+- [MotionStreak Component Reference](../../editor/components/motion-streak.md)
+
+## How to add 2D Renderable Components
+
+Some 2D renderable components are built into the editor. After creating a RenderRoot node, create a node with 2D renderable components under this node:
+
+
+
+2D renderable components can also be added by adding components to the node, the nodes under the 2D menu in the components menu are all 2D renderable components:
+
+
+
+> **Note**: only one renderable component can be added to each node, and repeated additions will result in error reporting.
+
+## 2D Renderable Component Rules Introduction
+
+- [Rendering Order Rules](../../ui-system/components/engine/priority.md)
+- [2D Renderable Component Batching Rules](../../ui-system/components/engine/ui-batch.md)
+- [Custom Materials for 2D Rendering Objects](../../ui-system/components/engine/ui-material.md)
diff --git a/versions/4.0/en/2d-object/index.md b/versions/4.0/en/2d-object/index.md
new file mode 100644
index 0000000000..338ff9ae25
--- /dev/null
+++ b/versions/4.0/en/2d-object/index.md
@@ -0,0 +1,20 @@
+# 2D Objects Overview
+
+Unlike 3D model objects, 2D rendering objects are referred to as the rendering of images that do not involve models. 2D rendering objects are handled differently from 3D models in terms of the underlying data submission, and follow their own rules with some specific adjustments for better efficiency and experience.
+
+## 2D Object Rendering Structure Description
+
+The RenderRoot node (the node with the RenderRoot2D component) is the entry point for 2D object data collection, and all 2D rendering objects must be rendered under the RenderRoot node. Since the Canvas component inherits from the RenderRoot2D component, the Canvas component can also be the entry point for data collection. 2D rendering nodes must have a UITransform component as a requirement for rendering vertex data, click or alignment policies, etc.
+
+2D rendering can also support rendering of models, the only condition is that nodes with model components (e.g. `MeshRenderer`/`SkinnedMeshRenderer`) must have **UI/UIMeshRenderer** components added to them in order to render on the same pipeline as the UI.
+
+The 2D rendering flow is as follows:
+
+
+
+## 2D object classification
+
+2D objects can be broadly classified into two categories, **2D rendering objects** and **User-interface (UI)**. The difference is that 2D rendering objects are generally only responsible for rendering 2D objects, while UI is more about user interaction. For more details on the differences, users can refer to the specific descriptions:
+
+- [2D Renderable Component Description](2d-render/index.md)
+- [UI System](ui-system/index.md)
diff --git a/versions/4.0/en/2d-object/render.png b/versions/4.0/en/2d-object/render.png
new file mode 100644
index 0000000000..87660bc658
Binary files /dev/null and b/versions/4.0/en/2d-object/render.png differ
diff --git a/versions/4.0/en/2d-object/ui-system/add-ui-component.png b/versions/4.0/en/2d-object/ui-system/add-ui-component.png
new file mode 100644
index 0000000000..c329cb01c9
Binary files /dev/null and b/versions/4.0/en/2d-object/ui-system/add-ui-component.png differ
diff --git a/versions/4.0/en/2d-object/ui-system/create-ui.png b/versions/4.0/en/2d-object/ui-system/create-ui.png
new file mode 100644
index 0000000000..c7042f971d
Binary files /dev/null and b/versions/4.0/en/2d-object/ui-system/create-ui.png differ
diff --git a/versions/4.0/en/2d-object/ui-system/index.md b/versions/4.0/en/2d-object/ui-system/index.md
new file mode 100644
index 0000000000..9ef6cd1886
--- /dev/null
+++ b/versions/4.0/en/2d-object/ui-system/index.md
@@ -0,0 +1,49 @@
+# UI System
+
+This section introduces the powerful and flexible UI (User Interface) system in Cocos Creator. By assembling different UI components to produce UI interfaces that can be adapted to multiple screen resolutions, dynamically generate and update display content from data, and support multiple layout styles.
+
+## Getting Started with UI
+
+The difference between defining UI and 2D rendering objects in the engine mainly lies in adaptation and interaction. All UI needs to be under a Canvas node to make adaptation behavior, and the Canvas component itself inherits from `RenderRoot2D` component, it can also be used as an entry point for data collection.
+
+The UI is a necessary interactive part of game development. Generally, buttons, text, backgrounds, etc. on the game are made through the UI. When starting to create a UI, first it is necessary to determine the size of the display area (design resolution) of the current design content, which can be set in the **Project -> Project Settings -> Project Data** panel in the menu bar.
+
+
+
+Once the design resolution is set, start creating UI elements, all of which are contained under the Canvas node. The Canvas node can be created by clicking the **+** button in the **Hierarchy** panel on the top left and selecting **UI Component -> Canvas**. The Canvas node has a [Canvas](../../ui-system/components/editor/canvas.md) component, which can be associated with a camera.
+
+> **Notes**:
+>
+> 1. Multiple Canvas nodes can exist in a scene, but a Canvas node should not be nested under another Canvas node or its children.
+> 2. Canvas components are not one-to-one with camera, their previous rendering depends on the layer of the node and the Visibility of the camera, so you should pay extra attention to layer management to get the desired rendering effect when you have multiple Canvas.
+
+Next, create UI nodes under the Canvas node. The editor comes with the following UI nodes:
+
+
+
+UI components can be viewed by selecting the node and clicking **Add Component** in the **Inspector** panel.
+
+
+
+The order in which UI components are rendered is a depth ordering scheme, which means that the ordering of the child nodes under the Canvas node already determines the entire [rendering order](../../ui-system/components/engine/priority.md).
+
+In general game development, the necessary UI elements are not only basic 2D renderable components such as Sprite, Label (text), Mask, but also Layout, Widget (alignment), etc., which are used to quickly build the interface. Sprite and Label are used to render images and text, Mask is mainly used to limit the display content, more commonly used in chat boxes and backpacks, etc. Layout is generally used for single arrangement of buttons, neat arrangement of props in backpacks, etc.
+The last important feature is the Widget, which is mainly used for display alignment. When finishing designing the UI and publish it to different platforms, the actual device resolution of the platform is bound to be different from our design resolution, therefore some trade-offs need to be made in order to adapt it. It is necessary to add a widget component to it, and always ensure that it is aligned to the top left of our design resolution. Please review the [Alignment Strategy](../../ui-system/components/engine/widget-align.md) and [Alignment](../../ui-system/components/editor/widget.md) documentation.
+
+Once the interface is created, some people may notice that the iPhone 7 displays differently than the iPhone X. This is actually the same problem with the device resolution we mentioned above. When you design in design resolution and finally publish in device resolution, there is a pixel deviation because the resolution of different models of mobile devices may not be the same, so there is another conversion process that needs to be done that is screen adaptation.
+Notice in the **Projects -> Project Settings -> Project Data** page in the menu bar, there are two more options **Fit Width / Fit Height**, which can be easily adapted to different devices by following the screen adaptation rules and combining with the Widget component. The specific adaptation rules can be found in the [Multi-Resolution Adaptation Scheme](../../ui-system/components/engine/multi-resolution.md) documentation.
+
+## UI components
+
+UI components mostly do not have rendering capabilities themselves, but hold 2D renderable components for rendering, which themselves have more ability to quickly form user-interactive interfaces, and take on functions such as event response, typography adaptation, etc.
+
+For specific descriptions of each UI component, please refer to the [UI Components](../../ui-system/components/editor/base-component.md) documentation.
+
+## UI Practice Guide
+
+- [Multi-Resolution Adaptation Scheme](../../ui-system/components/engine/multi-resolution.md)
+- [Alignment Strategy](../../ui-system/components/engine/widget-align.md)
+- [Label Layout](../../ui-system/components/engine/label-layout.md)
+- [Auto Layout Container](../../ui-system/components/engine/auto-layout.md)
+- [Create a List of Dynamically Generated Content](../../ui-system/components/engine/list-with-data.md)
+- [Use a Sliced Sprite to make a UI image](../../ui-system/components/engine/sliced-sprite.md)
diff --git a/versions/4.0/en/2d-object/ui-system/resolution_config.png b/versions/4.0/en/2d-object/ui-system/resolution_config.png
new file mode 100644
index 0000000000..6ab88f3dfe
Binary files /dev/null and b/versions/4.0/en/2d-object/ui-system/resolution_config.png differ
diff --git a/versions/4.0/en/CONTRIBUTING.md b/versions/4.0/en/CONTRIBUTING.md
new file mode 100644
index 0000000000..aee8654f65
--- /dev/null
+++ b/versions/4.0/en/CONTRIBUTING.md
@@ -0,0 +1,309 @@
+# English document writing standard
+
+The purpose of the format specification is to provide uniform writing guidelines and make the finished document have a better reading experience.
+
+## Use # for the title, separate the upper and lower text with a blank line
+
+Use # for the first-level title.
+Use ## for the second-level title.
+Use ### for the third-level title.
+and so on...
+
+Under normal circumstances, do not skip the use of headings, for example, the third-level headings cannot appear directly under the first-level heading.
+
+Example (correct):
+
+> \# Main Heading
+>
+> \## Sub-heading 1
+>
+> \### Sub-heading 2
+
+Example (NOT correct):
+
+> \# Main Heading
+>
+> \### Sub-heading 1
+
+## Use correct initial capital letters for proper English nouns and component names
+
+Correct usage:
+
+> Log in with GitHub
+>
+> Sprite component
+
+Incorrect usage:
+
+> Login with github
+>
+> sprite component
+
+## Use spaces
+
+### A space needs to be added between the number and the unit
+
+Correct usage:
+
+> The bandwidth of my home is 1 Gbps, and the total hard disk is 10 TB.
+
+Incorrect usage:
+
+> The bandwidth of my home is 1Gbps, and the total hard disk is 10TB.
+
+**Exception: There is no need to add a space between degree/percentage and number**
+
+Correct usage:
+
+> Today is a high temperature of 233°.
+>
+> The new MacBook Pro has a 15% increase in CPU performance.
+
+Incorrect usage:
+
+> Today is a high temperature of 233 °.
+>
+> The new MacBook Pro has a 15% increase in CPU performance.
+
+### Add a jump link to a document in this repository
+
+URL link format: **[url document name]\(url document path)**. Use halfwidth English punctuation.
+
+> e.g.: [Monitor and launch events]\(../scripting/events.md).
+
+Correct usage:
+
+> For details, please refer to the [Monitor and Launch Events](../scripting/events.md) documentation.
+
+Incorrect usage:
+
+> For details, please refer to the [Monitor and Launch Events] (../scripting/events.md) documentation.
+
+### Add a URL to the API document
+
+URL link format: **[url document name]\(url document directory)**. Use half-width English punctuation, and no spaces between [] and ()
+
+> e.g: [Mask API]\(\_\_APIDOC\_\_/en/class/Mask). Use **.html** for file name suffixes across documents
+
+## Use bold between adjacent text
+
+**Panel names, components or other important interface elements in the editor** are expressed in bold.
+
+> Format: open \*\*Inspector\*\* panel to view properties.
+
+Correct usage:
+
+> Open **Inspector** panel to view properties.
+>
+> Click the **Create** button to create a new node.
+>
+> Drag any picture resource to the **Sprite Frame** property.
+
+Note that the property name in the editor should be written in the format displayed in the Inspector panel.
+
+## Use backtick between the adjacent text
+
+**Script attributes and method names are written according to the format displayed in the API**, expressed by backtick.
+
+> Format: Set the scale of the node through \`this.node.scale\`
+
+Correct usage:
+
+> Set the scale of the node through `this.node.scale`.
+
+**File name and file path**, use backtick to indicate.
+
+Format: \`/mypath/myfile.ts\`
+
+If it is a full path, you need to add / before it, if it is not a full path, you don’t need it.
+
+Correct usage:
+
+> The subpackage directory is under the `build/quickgame/dist` directory.
+
+## Use blank lines
+
+### The code paragraph and the context need to be separated by a blank line
+
+Example:
+
+> Save Prefab, the code example is as follows:
+>
+> \```js
+> Editor.Ipc.sendToPanel('scene','scene:apply-prefab', node.uuid);
+> \```
+>
+> Continue text part.
+
+The effect is as follows:
+
+> Save Prefab, the code example is as follows:
+>
+> ```js
+> Editor.Ipc.sendToPanel('scene','scene:apply-prefab', node.uuid);
+> ```
+>
+> Continue text part.
+
+### The picture and the upper and lower text need to be separated by a blank line
+
+Picture format: **![Picture description]\(relative path of the picture)**. Use halfwidth English punctuation, and no spaces between !, [], ().
+
+> e.g.: !\[background]\(quick-start/background.png)
+
+If the picture is added to the text, it needs to add a space between the adjacent text
+
+## Use blank lines or \ for line breaks
+
+If you use the Enter key to wrap, there will be no wrap effect on GitBook and a space will be added
+
+**Use blank line wrap effect**:
+
+> First line
+>
+> Second line
+
+**Use \ wrapping effect**:
+
+> First line
+> Second line
+
+**Use the enter key to wrap the line effect (not recommended)**:
+
+> First line
+> Second line
+
+## Note writing format
+
+> Format: **> \*\*Note\*\*: do not mix Chinese and English symbols in Chinese and English documents.**
+
+When the note is more than two points, the writing format is as follows:
+
+> \> \*\*Notes\*\*:
+> \> 1. The first point.
+> \> 2. The second point.
+> \> 3. One last point.
+
+The effect is as follows:
+
+> **Notes**:
+> 1. The first point.
+> 2. The second point.
+> 3. One last point.
+
+## Introduction
+
+### Used in the text-point introduction
+
+When the main text is introduced with-points, the main text in the points, including pictures, need to be indented with 2/4 spaces. Generally, indents with two spaces are used. e.g.:
+
+> \- Point introduction 1
+>
+> (Two spaces) The body part that begins the first division.
+>
+> \- Introduction 2
+>
+> (Two spaces) The body part that begins the second division.
+>
+> (Two spaces) !\[image]\(image link)
+
+The effect is as follows:
+
+> - Point introduction 1
+>
+> Start the text part of the first division.
+>
+> - Introduction 2
+>
+> Start the text part of the second point.
+>
+> !\[image]\(image link)
+
+### Introduction to the use of digital points in the text
+
+When the main text is introduced with **number** points, the main text in the points including pictures need to be indented with **4** spaces. e.g.:
+
+> 1\. Point introduction 1
+>
+> (4 spaces) The part of the body that begins the first division.
+>
+> 2\. Point introduction 2
+>
+> (4 spaces) The part of the body that begins the second division.
+>
+> (4 spaces) !\[image]\(image link)
+
+The effect is as follows:
+
+> 1. Sub-point introduction 1
+>
+> Start the text part of the first division.
+>
+> 2. Sub-point introduction 2
+>
+> Start the text part of the second point.
+>
+> !\[image]\(image link)
+
+## The table uniformly uses left alignment
+
+e.g.:
+
+> | Property | Function Description |
+> | \:---- | :------ |
+> | Property 1 | Description 1 |
+> | Property 2 | Description 2 |
+
+Appropriate spaces can be reserved before and after for easy editing.
+
+## Grammar suggestions
+
+- __Firstly__ -> __First__.
+- At present, —> Currently,
+- Related Reference Links —> Reference documentation
+- do not use phrases like: "Now let me explain", "he should do this"
+- text like this should be avoided: "If you have never written a program and don’t worry, we will provide all the required code in the tutorial, just copy and paste it to the correct location, and then find your programmer partner to solve this part of the work. Let's start creating the script that drives the main character's actions."
+- text like this should be avoided: "So, "
+
+## About product name
+
+1. Cocos Creator
+2. Cocos Creator 2.4.3
+3. v2.4.3
+4. v3.0
+5. The engine (where refer to the runtime)
+6. The editor (where refer to the IDE)
+
+**Versions**:
+
+- 2.4.3 (3.0.0)
+- 2.4.3 Preview (GA/RC/Alpha/Beta ...)
+- 2.4.x (3.0.x)
+- 2.4 (3.0)
+- 2.x (3.x)
+
+**Never use**:
+
+1. CCC or ccc
+2. Cocos (where refer to Cocos Creator)
+3. IDE (where refer to Cocos Creator)
+
+## Technical designations
+
+- json -> JSON
+- js or JS -> JavaScript
+- ts or TS -> TypeScript
+
+## Footnote
+
+Example:
+
+Text prior to footnote reference.\[^1]
+
+\[^1]: Comment to include in footnote.
+
+The effect is as follows:
+
+Text prior to footnote reference.[^1]
+
+[^1]: Comment to include in footnote.
diff --git a/versions/4.0/en/SUMMARY.md b/versions/4.0/en/SUMMARY.md
new file mode 100644
index 0000000000..89b80e8c92
--- /dev/null
+++ b/versions/4.0/en/SUMMARY.md
@@ -0,0 +1,517 @@
+# Summary
+
+## User Manual 4.0 (LTS)
+
+- [Cocos Creator 4.0 LTS](index.md)
+- [About Cocos Creator](getting-started/introduction/index.md)
+- [Support](getting-started/support.md)
+
+## Understanding the Basics
+
+- [Getting Started](getting-started/index.md)
+
+ - [Install and Launch](getting-started/install/index.md)
+ - [Dashboard](getting-started/dashboard/index.md)
+ - [Hello World!](getting-started/helloworld/index.md)
+ - [Project Structure](getting-started/project-structure/index.md)
+- [Editor Interfaces](editor/index.md)
+ - [Scene](editor/scene/index.md)
+ - [Hierarchy](editor/hierarchy/index.md)
+ - [Assets](editor/assets/index.md)
+ - [Inspector](editor/inspector/index.md)
+ - [Console](editor/console/index.md)
+ - [Preferences](editor/preferences/index.md)
+ - [Project Settings](editor/project/index.md)
+ - [Main Menu](editor/mainMenu/index.md)
+ - [Tool Bar](editor/toolbar/index.md)
+ - [Editor Layout](editor/editor-layout/index.md)
+ - [Preview & Debugging](editor/preview/index.md)
+- [Glossary](glossary/index.md)
+- [Cocos Creator Quick Guide for Unity Developers](guide/unity/index.md)
+
+## Tutorials
+
+- [Quick Start: Making Your First 2D Game](getting-started/first-game-2d/index.md)
+ - [Handle Touch Events](getting-started/first-game-2d/touch.md)
+- [Quick Start: Make Your First 3D Game](getting-started/first-game/index.md)
+ - [Advanced: Add Light, Shadow and Skeleton Animation](getting-started/first-game/advance.md)
+- [Examples & Tutorials](cases-and-tutorials/index.md)
+
+## Basic Workflow
+
+- [Upgrade Guide](release-notes/index.md)
+ - [Cocos Creator 3.0 Upgrade Guide](release-notes/upgrade-guide-v3.0.md)
+ - [Cocos Creator 3.0 Material Upgrade Guide](material-system/effect-2.x-to-3.0.md)
+ - [Cocos Creator 3.1 Material Upgrade Guide](material-system/Material-upgrade-documentation-for-v3.0-to-v3.1.md)
+ - [Cocos Creator 3.5 Material Upgrade Guide](material-system/effect-upgrade-documentation-for-v3.4.2-to-v3.5.md)
+ - [Cocos Creator 3.5 Native Built Project Upgrade Guide](engine/template/native-upgrade-to-v3.5.md)
+ - [Cocos Creator 3.6 Native Built Project Upgrade Guide](engine/template/native-upgrade-to-v3.6.md)
+ - [Cocos Creator 3.6.0 Build Template and settings.json Upgrade Guide](release-notes/build-template-settings-upgrade-guide-v3.6.md)
+ - [Upgrade Guide: Effect from v3.5.x to v3.6.0](material-system/effect-upgrade-documentation-for-v3.5-to-v3.6.md)
+ - [Upgrade Guide: Particle from v3.5.x to v3.6.0](particle-system/particle-upgrade-documentation-for-v3.5-to-v3.6.md)
+
+- [Scene Creation](concepts/scene/index.md)
+ - [Scene Assets](asset/scene.md)
+ - [Nodes and Components](concepts/scene/node-component.md)
+ - [Coordinate Systems and Transformations](concepts/scene/coord.md)
+ - [Node Hierarchy and Rendering Order](concepts/scene/node-tree.md)
+ - [Build a Scene Image Using the Scene Panel](concepts/scene/scene-editing.md)
+ - [Level of Details](editor/rendering/lod.md)
+
+- [Assets](asset/index.md)
+ - [Asset Workflow](asset/asset-workflow.md)
+ - [Images](asset/image.md)
+ - [Textures](asset/texture.md)
+ - [Sprite Frames](asset/sprite-frame.md)
+ - [Auto Trim for SpriteFrame](ui-system/components/engine/trim.md)
+ - [Texture Compression](asset/compress-texture.md)
+ - [Texture Cube](asset/texture-cube.md)
+ - [Atlas](asset/atlas.md)
+ - [Auto Atlas](asset/auto-atlas.md)
+ - [Label Atlas](asset/label-atlas.md)
+ - [Prefab](asset/prefab.md)
+ - [Fonts](asset/font.md)
+ - [Audio](asset/audio.md)
+ - [Material](asset/material.md)
+ - [FBX Smart Material Conversion](importer/materials/fbx-materials.md)
+ - [Model](asset/model/mesh.md)
+ - [Importing Models Exported from DCC Tools](asset/model/dcc-export-mesh.md)
+ - [Export FBX file from 3ds Max](asset/model/max-export-fbx.md)
+ - [Export FBX file from Maya](asset/model/maya-export-fbx.md)
+ - [glTF](asset/model/glTF.md)
+ - [Programmatically Create Meshes](asset/model/scripting-mesh.md)
+ - [Spine Skeletal Animation](asset/spine.md)
+ - [DragonBones Skeletal Animation](asset/dragonbones.md)
+ - [TiledMap](asset/tiledmap.md)
+
+- [Scripting Guide and Event System](scripting/index.md)
+ - [Programming Language Support](scripting/language-support.md)
+ - [Scripting Basics](scripting/script-basics.md)
+ - [Script Creation](scripting/setup.md)
+ - [Coding Environment Setup](scripting/coding-setup.md)
+ - [Operating Environment](scripting/basic.md)
+ - [Decorator](scripting/decorator.md)
+ - [Property Attributes](scripting/reference/attributes.md)
+ - [Life Cycle Callbacks](scripting/life-cycle-callbacks.md)
+ - [Development Notes](scripting/readonly.md)
+ - [Using Scripts](scripting/usage.md)
+ - [Access Nodes and Components](scripting/access-node-component.md)
+ - [Common Node and Component Interfaces](scripting/basic-node-api.md)
+ - [Create and Destroy Nodes](scripting/create-destroy.md)
+ - [Scheduler](scripting/scheduler.md)
+ - [Components and Component Execution Order](scripting/component.md)
+ - [Loading and Switching Scenes](scripting/scene-managing.md)
+ - [Obtaining and Loading Assets](scripting/load-assets.md)
+ - [tsconfig Configuration](scripting/tsconfig.md)
+ - [Advanced Scripting](scripting/reference-class.md)
+ - [Events](engine/event/index.md)
+ - [Listening to and Launching Events](engine/event/event-emit.md)
+ - [Input Event System](engine/event/event-input.md)
+ - [Node Event System](engine/event/event-node.md)
+ - [Screen Event System](engine/event/event-screen.md)
+ - [Event API](engine/event/event-api.md)
+ - [Modules](scripting/modules/index.md)
+ - [Engine Modules](scripting/modules/engine.md)
+ - [External Module Usage Case](scripting/modules/example.md)
+ - [Module Specification](scripting/modules/spec.md)
+ - [Import Maps](scripting/modules/import-map.md)
+ - [Plugin Scripts](scripting/external-scripts.md)
+
+- [Cross-platform Publishing](editor/publish/index.md)
+ - [General Build Options](editor/publish/build-options.md)
+ - [Fundamentals for Publishing to Native Platforms](editor/publish/publish-native-index.md)
+ - [General Native Build Options](editor/publish/native-options.md)
+ - [Setting up Native Development Environment](editor/publish/setup-native-development.md)
+ - [Debugging JavaScript on Native Platforms](editor/publish/debug-jsb.md)
+ - [Integrating Input SDK](editor/publish/gpg-input-sdk.md)
+ - [Publishing Android Apps](editor/publish/android/index.md)
+ - [Android Publishing Example](editor/publish/android/build-example-android.md)
+ - [Build Options - Android](editor/publish/android/build-options-android.md)
+ - [Upgrading Android Project to v3.8](release-notes/upgrade-3.8-android.md)
+ - [Publish to Google Play on PC](editor/publish/google-play-games/index.md)
+ - [Build and Run](editor/publish/google-play-games/build-and-run.md)
+ - [Integrating Input SDK](editor/publish/gpg-input-sdk.md)
+ - [Publishing iOS Apps](editor/publish/ios/index.md)
+ - [iOS Publishing Example](editor/publish/ios/build-example-ios.md)
+ - [Build Options - iOS](editor/publish/ios/build-options-ios.md)
+ - [Publish to HuaWei AppGallery Connect](editor/publish/publish-huawei-agc.md)
+ - [Publishing Huawei HarmonyOS Apps](editor/publish/publish-huawei-ohos.md)
+ - [Publishing macOS Desktop Application](editor/publish/mac/index.md)
+ - [macOS Publishing Example](editor/publish/mac/build-example-mac.md)
+ - [Build Options - macOS](editor/publish/mac/build-options-mac.md)
+ - [Publishing Windows Desktop Application](editor/publish/windows/index.md)
+ - [Windows Publishing Example](editor/publish/windows/build-example-windows.md)
+ - [Build Options - Windows](editor/publish/windows/build-options-windows.md)
+ - [Publish to Mini Game Platforms](editor/publish/publish-mini-game.md)
+ - [Publish to HUAWEI AppGallery Connect](editor/publish/publish-huawei-agc.md)
+ - [Publish to Alipay Mini Game](editor/publish/publish-alipay-mini-game.md)
+ - [Publish to Taobao Mini Game](editor/publish/publish-taobao-mini-game.md)
+ - [Publish to WeChat Mini Games](editor/publish/publish-wechatgame.md)
+ - [WeChat Mini Games Engine Plugin Instructions](editor/publish/wechatgame-plugin.md)
+ - [Access to WeChat PC Mini Games](editor/publish/publish-pc-wechatgame.md)
+ - [Publish to Douyin Mini Games](editor/publish/publish-bytedance-mini-game.md)
+ - [Access to Douyin PC Mini Games](editor/publish/publish-pc-bytedance.md)
+ - [Publish to Huawei Quick Games](editor/publish/publish-huawei-quick-game.md)
+ - [Publish to OPPO Mini Games](editor/publish/publish-oppo-mini-game.md)
+ - [Publish to vivo Mini Games](editor/publish/publish-vivo-mini-game.md)
+ - [Publish to Honor Mini Games](editor/publish/publish-honor-mini-game.md)
+ - [Publish to Baidu Mini Games](editor/publish/publish-baidu-mini-game.md)
+ - [Access to Open Data Context](editor/publish/build-open-data-context.md)
+ - [Mini Game Subpackage](editor/publish/subpackage.md)
+ - [Introduction to the Build Process and FAQ](editor/publish/build-guide.md)
+ - [Publish to Facebook Instant Games](editor/publish/publish-fb-instant-games.md)
+ - [Publish to Web Platforms](editor/publish/publish-web.md)
+ - [Publish from the Command Line](editor/publish/publish-in-command-line.md)
+ - [Custom Project Build Template](editor/publish/custom-project-build-template.md)
+ - [Build Process and FAQ](editor/publish/build-guide.md)
+
+## Function Modules
+
+- [Graphics](module-map/graphics.md)
+ - [Render Pipeline](render-pipeline/overview.md)
+ - [Built-in Render Pipeline](render-pipeline/builtin-pipeline.md)
+ - [Custom rendering of pipelines](render-pipeline/custom-pipeline.md)
+ - [Use Post Process](render-pipeline/use-post-process.md)
+ - [Custom Post Process](render-pipeline/post-process/custom.md)
+
+ - [Camera](editor/components/camera-component.md)
+ - [Lighting](concepts/scene/light.md)
+ - [Physically Based Lighting](concepts/scene/light/pbr-lighting.md)
+ - [Lights](concepts/scene/light/lightType/index.md)
+ - [Directional Lights](concepts/scene/light/lightType/dir-light.md)
+ - [Spherical Lights](concepts/scene/light/lightType/sphere-light.md)
+ - [Spotlights](concepts/scene/light/lightType/spot-light.md)
+ - [Ambient Light](concepts/scene/light/lightType/ambient.md)
+ - [Additive Per-Pixel Lights](concepts/scene/light/additive-per-pixel-lights.md)
+ - [Shadows](concepts/scene/light/shadow.md)
+ - [Imaged Based Lighting](concepts/scene/light/probe/index.md)
+ - [Lightmapping](concepts/scene/light/lightmap.md)
+ - [Light Probes](concepts/scene/light/probe/light-probe.md)
+ - [Light Probe Panel](concepts/scene/light/probe/light-probe-panel.md)
+ - [Reflection Probe](concepts/scene/light/probe/reflection-probe.md)
+ - [Reflection Probe Panel](concepts/scene/light/probe/reflection-probe-panel.md)
+ - [Reflection Probe Art Workflow](concepts/scene/light/probe/reflection-art-workflow.md)
+ - [IBL Example](concepts/scene/light/probe/example.md)
+ - [Meshes](module-map/mesh/index.md)
+ - [MeshRenderer](engine/renderable/model-component.md)
+ - [SkinnedMeshRenderer](module-map/mesh/skinnedMeshRenderer.md)
+ - [SkinnedMeshBatchRenderer](module-map/mesh/skinnedMeshBatchRenderer.md)
+ - [Importing Models Exported from DCC Tools](asset/model/dcc-export-mesh.md)
+ - [Export FBX file from 3ds Max](asset/model/max-export-fbx.md)
+ - [Export FBX file from Maya](asset/model/maya-export-fbx.md)
+ - [glTF](asset/model/glTF.md)
+ - [Programmatically Create Meshes](asset/model/scripting-mesh.md)
+ - [Vertex Animation Texture (VAT)](asset/model/vat.md)
+ - [Textures](module-map/texture/index.md)
+ - [Textures](asset/texture.md)
+ - [Texture Cube](asset/texture-cube.md)
+ - [Texture Compression](asset/compress-texture.md)
+ - [RenderTexture](asset/render-texture.md)
+ - [Material System Overview](material-system/overview.md)
+ - [Programmatic Use of Materials](material-system/material-script.md)
+ - [Builtin Materials](material-system/builtin-material.md)
+ - [Material System Classes Diagram](material-system/material-structure.md)
+ - [Shader Overview](shader/index.md)
+ - [Create and Use Shader](shader/effect-inspector.md)
+ - [Built-in Shaders](shader/effect-builtin.md)
+ - [Physically Based Rendering - PBR](shader/effect-builtin-pbr.md)
+ - [Toon Shading](shader/effect-builtin-toon.md)
+ - [Unlit Shading](shader/effect-builtin-unlit.md)
+ - [Syntax](shader/effect-syntax.md)
+ - [Optional Pass Parameters](shader/pass-parameter-list.md)
+ - [YAML 101](shader/yaml-101.md)
+ - [GLSL](shader/glsl.md)
+ - [Preprocessor Macro Definition](shader/macros.md)
+ - [Chunk](shader/effect-chunk-index.md)
+ - [Built-in Uniforms](shader/uniform.md)
+ - [Common Functions](shader/common-functions.md)
+ - [Render Flow of Forward Rendering and Deferred Shading](shader/forward-and-deferred.md)
+ - [Surface Shader](shader/surface-shader.md)
+ - [Guide to Built-in Surface Shader](shader/surface-shader/builtin-surface-shader.md)
+ - [Surface Shader Overview](shader/surface-shader/surface-shader-structure.md)
+ - [Surface Shader Execution Flow](shader/surface-shader/shader-code-flow.md)
+ - [Include](shader/surface-shader/includes.md)
+ - [Macro Remapping](shader/surface-shader/macro-remapping.md)
+ - [Function Replacement Using Macros](shader/surface-shader/function-replace.md)
+ - [Surface Shader Built-in Replaceable Functions](shader/surface-shader/surface-function.md)
+ - [Render Usages](shader/surface-shader/render-usage.md)
+ - [Lighting Models](shader/surface-shader/lighting-mode.md)
+ - [Surface Material Data Structure](shader/surface-shader/surface-data-struct.md)
+ - [Shader Stages](shader/surface-shader/shader-stage.md)
+ - [Shader Assembly](shader/surface-shader/shader-assembly.md)
+ - [VS Inputs](shader/surface-shader/vs-input.md)
+ - [FS Inputs](shader/surface-shader/fs-input.md)
+ - [Customize Surface Shader](shader/surface-shader/customize-surface-shader.md)
+ - [Rendering Debug View](shader/surface-shader/rendering-debug-view.md)
+ - [Legacy Shader](shader/legacy-shader/legacy-shader.md)
+ - [Guide to Built-in Legacy Shaders](shader/legacy-shader/legacy-shader-builtins.md)
+ - [Legacy Shader Key Functions and Structures](shader/legacy-shader/legacy-shader-func-struct.md)
+ - [Write Shaders](shader/write-effect-overview.md)
+ - [2D Sprite Shader: Gradient](shader/write-effect-2d-sprite-gradient.md)
+ - [3D Shader: RimLight](write-effect-3d-rim-light.md)
+ - [Skin material](shader/advanced-shader/skin.md)
+ - [Instanced Attributes](shader/instanced-attributes.md)
+ - [UBO Layout](shader/ubo-layout.md)
+ - [Fallback to WebGL 1.0](shader/webgl-100-fallback.md)
+ - [VSCode Extension - Cocos Effect](shader/vscode-plugin.md)
+ - [Compute Shader](shader/compute-shader.md)
+
+ - [2D Rendering Sorting](engine/rendering/sorting-2d.md)
+ - [3D Rendering Sorting](engine/rendering/sorting.md)
+ - [Effects](module-map/effects/index.md)
+ - [Billboard](particle-system/billboard-component.md)
+ - [Line](particle-system/line-component.md)
+ - [Skybox](concepts/scene/skybox.md)
+ - [Global Fog](concepts/scene/fog.md)
+ - [Geometry Renderer](geometry-renderer/index.md)
+
+- [2D Objects](2d-object/index.md)
+ - [2D Render](2d-object/2d-render/index.md)
+ - [Rendering Order](ui-system/components/engine/priority.md)
+ - [2D Renderable Component Batching Rules](ui-system/components/engine/ui-batch.md)
+ - [Custom Materials for 2D Rendering Objects](ui-system/components/engine/ui-material.md)
+ - [2D Renderable Components](ui-system/components/editor/render-component.md)
+ - [Sprite Component Reference](ui-system/components/editor/sprite.md)
+ - [Label Component Reference](ui-system/components/editor/label.md)
+ - [Mask Component Reference](ui-system/components/editor/mask.md)
+ - [Graphics Component Reference](ui-system/components/editor/graphics.md)
+ - [RichText Component Reference](ui-system/components/editor/richtext.md)
+ - [UIStaticBatch Component Reference](ui-system/components/editor/ui-static.md)
+ - [Spine Skeleton Component Reference](editor/components/spine.md)
+ - [DragonBones ArmatureDisplay Component Reference](editor/components/dragonbones.md)
+ - [TiledMap Component Reference](editor/components/tiledmap.md)
+ - [TiledTile Component Reference](editor/components/tiledtile.md)
+ - [MotionStreak Component Reference](editor/components/motion-streak.md)
+ - [UI System](2d-object/ui-system/index.md)
+ - [UI Components](ui-system/components/editor/base-component.md)
+ - [Canvas Component Reference](ui-system/components/editor/canvas.md)
+ - [UITransform Component Reference](ui-system/components/editor/ui-transform.md)
+ - [Widget Component Reference](ui-system/components/editor/widget.md)
+ - [Button Component Reference](ui-system/components/editor/button.md)
+ - [Layout Component Reference](ui-system/components/editor/layout.md)
+ - [EditBox Component Reference](ui-system/components/editor/editbox.md)
+ - [ScrollView Component Reference](ui-system/components/editor/scrollview.md)
+ - [ScrollBar Component Reference](ui-system/components/editor/scrollbar.md)
+ - [ProgressBar Component Reference](ui-system/components/editor/progress.md)
+ - [LabelOutline Component Reference](ui-system/components/editor/label-outline.md)
+ - [LabelShadow Component Reference](ui-system/components/editor/label-shadow.md)
+ - [Toggle Component Reference](ui-system/components/editor/toggle.md)
+ - [ToggleContainer Component Reference](ui-system/components/editor/toggleContainer.md)
+ - [Slider Component Reference](ui-system/components/editor/slider.md)
+ - [PageView Component Reference](ui-system/components/editor/pageview.md)
+ - [PageViewIndicator Component Reference](ui-system/components/editor/pageviewindicator.md)
+ - [UIMeshRenderer Component Reference](ui-system/components/editor/ui-model.md)
+ - [UICoordinateTracker Component Reference](ui-system/components/editor/ui-coordinate-tracker.md)
+ - [UIOpacity Component Reference](ui-system/components/editor/ui-opacity.md)
+ - [UISkew Component Reference](ui-system/components/editor/ui-skew.md)
+ - [BlockInputEvents Component Reference](ui-system/components/editor/block-input-events.md)
+ - [WebView Component Reference](ui-system/components/editor/webview.md)
+ - [VideoPlayer Component Reference](ui-system/components/editor/videoplayer.md)
+ - [SafeArea Component Reference](ui-system/components/editor/safearea.md)
+ - [UI Practice Guide](ui-system/components/engine/usage-ui.md)
+ - [Multi-Resolution Adaption](ui-system/components/engine/multi-resolution.md)
+ - [Widget Alignment](ui-system/components/engine/widget-align.md)
+ - [Label Layout](ui-system/components/engine/label-layout.md)
+ - [Auto Layout Container](ui-system/components/engine/auto-layout.md)
+ - [Create a List of Dynamically Generated Content](ui-system/components/engine/list-with-data.md)
+ - [Stretchable UI Sprite](ui-system/components/engine/sliced-sprite.md)
+ - [Android Large Screen Adaptation](ui-system/components/engine/large-screen.md)
+
+- [Animation](animation/index.md)
+ - [Animation Clip](animation/animation-clip.md)
+ - [Animation Component Reference](animation/animation-comp.md)
+ - [Animation Panel](animation/animation.md)
+ - [Creating Animation Components and Animation Clips](animation/animation-create.md)
+ - [Get Familiar with the Animation Panel](animation/animation-editor.md)
+ - [Editing Animation Clips](animation/edit-animation-clip.md)
+ - [Editing Animation Easing Curve](animation/animation-curve.md)
+ - [Adding Animation Events](animation/animation-event.md)
+ - [Using Animation Curves](animation/use-animation-curve.md)
+ - [Curve Editor](animation/curve-editor.md)
+ - [Skeletal Animation](animation/skeletal-animation.md)
+ - [Joint Texture Layout Settings](animation/joint-texture-layout.md)
+ - [Controlling Animation with Scripts](animation/animation-component.md)
+ - [Animation State](animation/animation-state.md)
+ - [Embedded Player](animation/embedded-player.md)
+ - [Marionette Animation System](animation/marionette/index.md)
+ - [Animation Graph Assets](animation/marionette/animation-graph.md)
+ - [Animation Controller Reference](animation/marionette/animation-controller.md)
+ - [Animation Graph Panel](animation/marionette/animation-graph-panel.md)
+ - [Animation Graph Layer](animation/marionette/animation-graph-layer.md)
+ - [Animation State Machine](animation/marionette/animation-graph-basics.md)
+ - [State Transition](animation/marionette/state-transition.md)
+ - [Animation Mask](animation/marionette/animation-mask.md)
+ - [Animation Graph Variants](animation/marionette/animation-variant.md)
+ - [Procedural Animation](animation/marionette/procedural-animation/index.md)
+ - [Introduction to Procedural Animation](animation/marionette/procedural-animation/introduce.md)
+ - [Enable Procedural Animation](animation/marionette/procedural-animation/enabling.md)
+ - [Pose Graph](animation/marionette/procedural-animation/pose-graph/index.md)
+ - [Pose Graph View](animation/marionette/procedural-animation/pose-graph/pose-nodes/node-operation.md)
+ - [Pose Nodes](animation/marionette/procedural-animation/pose-graph/pose-nodes/index.md)
+ - [Blend Pose](animation/marionette/procedural-animation/pose-graph/pose-nodes/blend-poses.md)
+ - [Modify Poses](animation/marionette/procedural-animation/pose-graph/pose-nodes/modify-pose.md)
+ - [Play or Sample Animation](animation/marionette/procedural-animation/pose-graph/pose-nodes/play-or-sample-motion.md)
+
+- [Audio System](audio-system/overview.md)
+ - [AudioSource Component Reference](audio-system/audiosource.md)
+ - [AudioMgr Example](audio-system/audioExample.md)
+ - [Compatibility Notes](audio-system/audioLimit.md)
+
+- [Physics System](physics/index.md)
+ - [Physics 2D](physics-2d/physics-2d.md)
+ - [2D Physics Manager](physics-2d/physics-2d-system.md)
+ - [2D RigidBody](physics-2d/physics-2d-rigid-body.md)
+ - [2D Physics Collider](physics-2d/physics-2d-collider.md)
+ - [2D Contact Callback](physics-2d/physics-2d-contact-callback.md)
+ - [2D Physics Joint](physics-2d/physics-2d-joint.md)
+ - [Physics 3D](physics/physics.md)
+ - [Physics Engines](physics/physics-engine.md)
+ - [Physics System Configuration](physics/physics-configs.md)
+ - [Group and Mask](physics/physics-group-mask.md)
+ - [Physics Components](physics/physics-component.md)
+ - [Collider](physics/physics-collider.md)
+ - [Rigidbody](physics/physics-rigidbody.md)
+ - [Constant Force](physics/physics-constantForce.md)
+ - [Constraint](physics/physics-constraint.md)
+ - [Physics Material](physics/physics-material.md)
+ - [Physics Event](physics/physics-event.md)
+ - [Raycast Detection](physics/physics-raycast.md)
+ - [Geometry Cast Detection](physics/physics-sweep.md)
+ - [Continuous Collision Detection](physics/physics-ccd.md)
+ - [Character Controller](physics/character-controller/index.md)
+ - [Physics Application Cases](physics/physics-example.md)
+
+- [Particle System](particle-system/index.md)
+ - [2D Particle System](particle-system/2d-particle/2d-particle.md)
+ - [3D Particle System](particle-system/overview.md)
+ - [Particle System Module](particle-system/module.md)
+ - [Main Module](particle-system/main-module.md)
+ - [Shape Module](particle-system/emitter.md)
+ - [Velocity Overtime Module](particle-system/velocity-module.md)
+ - [Force Overtime Module](particle-system/force-module.md)
+ - [Size Overtime Module](particle-system/size-module.md)
+ - [Rotation Overtime Module](particle-system/rotation-module.md)
+ - [Color Over Life Time Module](particle-system/color-module.md)
+ - [Texture Animation Module](particle-system/texture-animation-module.md)
+ - [Limit Velocity Overtime Module](particle-system/limit-velocity-module.md)
+ - [Trail Module](particle-system/trail-module.md)
+ - [Renderer Module](particle-system/renderer.md)
+ - [Particle Properties Editor](particle-system/editor/index.md)
+ - [Curve Editor](particle-system/editor/curve-editor.md)
+ - [Gradient Editor](particle-system/editor/gradient-editor.md)
+ - [Particle Editor](particle-system/editor/particle-effect-panel.md)
+
+- [Tween System](tween/index.md)
+ - [Tween Interface](tween/tween-interface.md)
+ - [Tween Function](tween/tween-function.md)
+ - [Tween Examples](tween/tween-example.md)
+
+- [Terrain System](editor/terrain/index.md)
+
+- [Asset Manager](asset/asset-manager.md)
+ - [AssetManager Upgrade Guide](asset/asset-manager-upgrade-guide.md)
+ - [Asset Bundle Upgrade Guide](asset/subpackage-upgrade-guide.md)
+ - [Asset Loading](asset/dynamic-load-resources.md)
+ - [Asset Bundle](asset/bundle.md)
+ - [Release Of Assets](asset/release-manager.md)
+ - [Download and Parse](asset/downloader-parser.md)
+ - [Loading and Preloading](asset/preload-load.md)
+ - [Cache Manager](asset/cache-manager.md)
+ - [Optional Parameters](asset/options.md)
+ - [Pipeline and Task](asset/pipeline-task.md)
+ - [Resource Management Considerations --- meta files](asset/meta.md)
+
+- [Localization](editor/l10n/overview.md)
+ - [Translation Service Provider](editor/l10n/translation-service.md)
+ - [Collect and Count](editor/l10n/collect-and-count.md)
+ - [Compile Language](editor/l10n/compile-language.md)
+ - [L10nLabel](editor/l10n/l10n-label.md)
+ - [Sample](editor/l10n/script-using.md)
+
+- [XR](xr/index.md)
+ - [Version History](xr/version-history.md)
+ - [Architecture](xr/architecture/index.md)
+ - [Built-in Resources and Prefabs](xr/architecture/assets.md)
+ - [XR Components](xr/architecture/component.md)
+ - [XR Preview](xr/architecture/preview.md)
+ - [XR Video Player](xr/architecture/xr-video-player.md)
+ - [XR Preview in Browser](xr/architecture/xr-webview.md)
+ - [XR Spatial Audio](xr/architecture/xr-spatial-audio.md)
+ - [XR Composition Layer](xr/architecture/xr-composition-layer.md)
+ - [Passthrough](xr/architecture/xr-pass-through.md)
+ - [AR](xr/architecture/ar-introduce.md)
+ - [AR Camera](xr/architecture/ar-camera.md)
+ - [AR Manager](xr/architecture/ar-manager.md)
+ - [AR Automated Behavior Editing](xr/architecture/ar-tracking-component.md)
+ - [AR Interaction](xr/architecture/ar-interaction.md)
+ - [Quick Start](xr/project-deploy/index.md)
+ - [VR Project Creation](xr/project-deploy/vr-proj-deploy.md)
+ - [VR Building and Publishing](xr/project-deploy/vr-proj-pub.md)
+ - [AR Project Creation](xr/project-deploy/ar-proj-deploy.md)
+ - [AR Building and Publishing](xr/project-deploy/ar-proj-pub.md)
+ - [WebXR Project Setup](xr/project-deploy/webxr-proj-deploy.md)
+ - [WebXR Building and Publishing](xr/project-deploy/webxr-proj-pub.md)
+- [Native Development](native/overview.md)
+ - [Native Platform Secondary Development Guide](advanced-topics/native-secondary-development.md)
+ - [JavaScript and Android Communication with Reflection](advanced-topics/java-reflection.md)
+ - [JavaScript and iOS/macOS Communication with Reflection](advanced-topics/oc-reflection.md)
+ - [JavaScript and Java Communication using JsbBridge](advanced-topics/js-java-bridge.md)
+ - [JavaScript and Objective-C Communication using JsbBridge](advanced-topics/js-oc-bridge.md)
+ - [JsbBridgeWrapper - An Event Mechanism based on JsbBridge](advanced-topics/jsb-bridge-wrapper.md)
+ - [Tutorial: JSB 2.0](advanced-topics/JSB2.0-learning.md)
+ - [JSB Manual Binding](advanced-topics/jsb-manual-binding.md)
+ - [JSB Auto Binding](advanced-topics/jsb-auto-binding.md)
+ - [Swig](advanced-topics/jsb-swig.md)
+ - [Swig Tutorial](advanced-topics/jsb/swig/tutorial/index.md)
+ - [CMake Usage Introduction](advanced-topics/cmake-learning.md)
+ - [Native Engine Memory Leak Detection System](advanced-topics/memory-leak-detector.md)
+ - [Native Scene Culling](advanced-topics/native-scene-culling.md)
+ - [Native Profiler](advanced-topics/profiler.md)
+ - [Native Plugins](advanced-topics/native-plugins/brief.md)
+ - [Cocos Native Plugin Quick Tutorial](advanced-topics/native-plugins/tutorial.md)
+ - [Optimization of Cross-Language Invocation](advanced-topics/jsb-optimizations.md)
+
+## Advanced Tutorials
+
+- [Editor Extension](editor/extension/readme.md)
+ - [Extension Manager](editor/extension/extension-manager.md)
+ - [Extension Templates and Compile Builds](editor/extension/create-extension.md)
+ - [Getting Started Example - Menu](editor/extension/first.md)
+ - [Getting Started Example - Panel](editor/extension/first-panel.md)
+ - [Getting Started Example - First Data Interaction](editor/extension/first-communication.md)
+ - [Change the Name of a Extension](editor/extension/extension-change-name.md)
+ - [Install and Share](editor/extension/install.md)
+ - [Submitting Resources to Cocos Store](editor/extension/store/upload-store.md)
+ - [Extend Existing Functionality](editor/extension/contributions.md)
+ - [Customize the Main Menu](editor/extension/contributions-menu.md)
+ - [Customized Messages](editor/extension/contributions-messages.md)
+ - [Calling the Engine API and Project Script](editor/extension/scene-script.md)
+ - [Extending the Assets Panel](editor/assets/extension.md)
+ - [Custom Asset Database](editor/extension/contributions-database.md)
+ - [Custom Inspector Panel](editor/extension/inspector.md)
+ - [Extending Build Process](editor/publish/custom-build-plugin.md)
+ - [Extending Project Settings Panel](editor/extension/contributions-project.md)
+ - [Extending the Preferences Panels](editor/extension/contributions-preferences.md)
+ - [Extending Shortcut](editor/extension/contributions-shortcuts.md)
+ - [Extension Details](editor/extension/basic.md)
+ - [Extension Infrastructure](editor/extension/package.md)
+ - [Definition of Extension](editor/extension/define.md)
+ - [Message System](editor/extension/messages.md)
+ - [Configuration System](editor/extension/profile.md)
+ - [Extension Panel](editor/extension/panel.md)
+ - [UI Components](editor/extension/ui.md)
+- [Advanced Topics](advanced-topics/index.md)
+ - [Submit Code to Cocos Engine Repository](submit-pr/submit-pr.md)
+ - [User Data Storage](advanced-topics/data-storage.md)
+ - [Custom loading Wasm/Asm files and modules](advanced-topics/wasm-asm-load.md)
+ - [Converting Native Code to Wasm/Asm Files Using Emscripten](advanced-topics/wasm-asm-create.md)
+ - [Engine Customization Workflow](advanced-topics/engine-customization.md)
+ - [Web Preview Customization Workflow](editor/preview/browser.md)
+ - [Dynamic Atlas](advanced-topics/dynamic-atlas.md)
+ - [Mangle Engine Internal Properties](advanced-topics/mangle-properties.md)
+ - [Hot Update Tutorial](advanced-topics/hot-update.md)
+ - [AssetManager for Hot Update](advanced-topics/hot-update-manager.md)
+ - [HTTP Request](advanced-topics/http.md)
+ - [WebSocket Introduction](advanced-topics/websocket-introduction.md)
+ - [WebSocket Client](advanced-topics/websocket.md)
+ - [WebSocket Server](advanced-topics/websocket-server.md)
diff --git a/versions/4.0/en/_layouts/website/header.html b/versions/4.0/en/_layouts/website/header.html
new file mode 100644
index 0000000000..1a997e5dba
--- /dev/null
+++ b/versions/4.0/en/_layouts/website/header.html
@@ -0,0 +1,48 @@
+{% extends template.self %}
+{% block book_header %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/versions/4.0/en/_layouts/website/page.html b/versions/4.0/en/_layouts/website/page.html
new file mode 100644
index 0000000000..a5f5f58425
--- /dev/null
+++ b/versions/4.0/en/_layouts/website/page.html
@@ -0,0 +1,56 @@
+{% extends template.self %}
+{% block book_sidebar %}
+
+ {{ super() }}
+{% endblock %}
+{% block javascript %}
+ {{ super() }}
+
+{% endblock %}
diff --git a/versions/4.0/en/advanced-topics/JSB2.0-learning.md b/versions/4.0/en/advanced-topics/JSB2.0-learning.md
new file mode 100644
index 0000000000..27d90dde3c
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/JSB2.0-learning.md
@@ -0,0 +1,1200 @@
+# Tutorial: JSB 2.0
+
+## The Abstraction Layer of Script Engine
+
+### Architecture
+
+
+
+### Macro
+
+The abstraction layer is bound to take more CPU execution time than using the JS engine API directly. How to minimize the overhead of the abstraction layer becomes the first goal of the design.
+
+Most of work in JS binding is actually setting JS related operations with CPP callbacks and associating CPP object within the callback function. In fact, it mainly contains the following two situation:
+
+- Register JS functions (including global functions, class constructors, class destructors, class member functions, and class static member functions), binding revenant CPP callbacks
+- Register accessors for JS properties, bind CPP callbacks for reading and writing properties respectively
+
+How to achieve the minimum overhead for the abstract layer and expose the unified API?
+
+For example, to register a JS function in CPP, there are different definitions in JavaScriptCore, SpiderMonkey, V8, ChakraCore as follows:
+
+- JavaScriptCore
+
+ ```c++
+ JSValueRef JSB_foo_func(
+ JSContextRef _cx,
+ JSObjectRef _function,
+ JSObjectRef _thisObject,
+ size_t argc,
+ const JSValueRef _argv[],
+ JSValueRef* _exception
+ );
+ ```
+
+- SpiderMonkey
+
+ ```c++
+ bool JSB_foo_func(
+ JSContext* _cx,
+ unsigned argc,
+ JS::Value* _vp
+ );
+ ```
+
+- V8
+
+ ```c++
+ void JSB_foo_func(
+ const v8::FunctionCallbackInfo& v8args
+ );
+ ```
+
+- ChakraCore
+
+ ```c++
+ JsValueRef JSB_foo_func(
+ JsValueRef _callee,
+ bool _isConstructCall,
+ JsValueRef* _argv,
+ unsigned short argc,
+ void* _callbackState
+ );
+ ```
+
+We evaluated several options and eventually decided to use `macros` to reduce the differences between the definition and parameter types of different JS engine callbacks, regardless of which engine is used, and developers could use an unified callback definition. We refer to the definition of Lua callback function. The definition of all JS to CPP callback functions in the abstract layer is defined as:
+
+```c++
+bool foo(se::State& s)
+{
+ ...
+ ...
+}
+SE_BIND_FUNC(foo) // Binding a JS function as an example
+```
+
+After a developer has bound a JS function, remember to wrap the callback function with the macros which start with `SE_BIND_`. Currently, we provide the following macros:
+
+- **SE_BIND_PROP_GET**: Wrap a JS object property read callback function
+- **SE_BIND_PROP_SET**: Wrap a JS object property written callback function
+- **SE_BIND_FUNC_AS_PROP_GET**: Wrap a member function as a JS property getter callback function.
+- **SE_BIND_FUNC_AS_PROP_SET**: Wrap a member function as a JS property setter callback function
+- **SE_BIND_FUNC**: Wrap a JS function that can be used for global functions, class member functions or class static functions
+- **SE_BIND_FUNC_FAST**: Wrap a parameter-less C++ function into a JS function in a faster way.
+- **SE_DECLARE_FUNC**: Declare a JS function, generally used in the header file
+- **SE_BIND_CTOR**: Wrap a JS constructor
+- **SE_BIND_SUB_CLS_CTOR**: Wrap the constructor of a JS subclass.
+- **SE_BIND_FINALIZE_FUNC**: Wrap the finalize function of a JS object, finalize function is invoked when the object is released by Garbage Collector
+- **SE_DECLARE_FINALIZE_FUNC**: Declares the finalize function of a JS object
+- **_SE**: The macro for making callback be recognized by different JS engine. Note that the first character is underscored, similar to `_T ('xxx')` in Windows for wrapping Unicode or MultiBytes string
+
+ > **Note**: the first character is an underscore, similar to `_T("xxx")` used in Windows to wrap Unicode or MultiBytes strings.
+
+## API
+
+### CPP Namespace
+
+All types of the abstraction layer are under the `se` namespace, which is an abbreviation of `ScriptEngine`.
+
+### Types
+
+#### se::ScriptEngine
+
+`se::ScriptEngine` is the JS engine administrator, responsible for JS engine initialization, destruction, restart, native module registration, loading scripts, doing garbage collection, JS exception cleanup and whether to enable the debugger. It is a singleton that could be accessed via `se::ScriptEngine::getInstance()`.
+
+#### se::Value
+
+`se::Value` can be understood as a JS variable reference in the CPP layer. There are six types of JS variables: `object`, `number`, `bigint` `string`, `boolean`, `null`, `undefined`, so `se::Value` uses an `union` to include `object`, `number`, `string`, `boolean`, `int64_t` these 5 kinds of `value types`, `non-value types` like `null` and `undefined` can be represented by `_type` directly.
+
+```c++
+namespace se {
+ class Value {
+ enum class Type : char
+ {
+ Undefined = 0,
+ Null,
+ Number,
+ Boolean,
+ String,
+ Object,
+ BigInt, // mostly used to store a 8 bytes pointer
+ };
+ ...
+ ...
+ private:
+ union {
+ bool _boolean;
+ double _number;
+ std::string* _string;
+ Object* _object;
+ int64_t _bigint;
+ } _u;
+
+ Type _type;
+ ...
+ ...
+ };
+}
+```
+
+If `se::Value` stores the underlying data types, such as `number`, `string`, `boolean`, which is directly stored by `value copy`.
+The storage of `object` is special because it is a `weak reference` to JS objects via `se::Object*`.
+
+#### se::Object
+
+`se::Object` extends from `se::RefCounter` which is a class for reference count management. Currently, only `se::Object` inherits from `se::RefCounter` in the abstraction layer.
+
+As we mentioned in the last section, `se::Object` is a weak reference to the JS object, therefore I will explain why it's a weak reference.
+
+**Reason 1: The requirement of controlling the life cycle of CPP objects by JS objects**
+
+After creating a Sprite in the script layer via `var xhr = new XMLHttpRequest();`, we create a `se::Object` in the constructor callback and leave it in a global map (NativePtrToObjectMap), this map is used to query the `XMLHttpRequest*` to get the corresponding JS object `se::Object*`.
+
+```c++
+/// native/cocos/bindings/manual/jsb_xmlhttprequest.cpp
+static bool XMLHttpRequest_constructor(se::State& s)
+{
+ XMLHttpRequest* cobj = JSB_ALLOC(XMLHttpRequest);
+ s.thisObject()->setPrivateData(cobj);
+ return true;
+}
+SE_BIND_CTOR(XMLHttpRequest_constructor, __jsb_XMLHttpRequest_class, XMLHttpRequest_finalize)
+
+/// native/cocos/bindings/jswrapper/v8/Object.cpp
+void Object::setPrivateObject(PrivateObjectBase *data) {
+ // ...
+ if (data != nullptr) {
+ _privateData = data->getRaw();
+ NativePtrToObjectMap::emplace(_privateData, this);
+ } else {
+ _privateData = nullptr;
+ }
+}
+```
+
+Imagine if you force `se::Object` to be a strong reference to a JS object that leaves JS objects out of GC control and the finalize callback will never be fired because `se::Object` is always present in map which will cause memory leak.
+
+**Reason 2: More flexible, supporting strong reference by calling the se::Object::root method manually**
+
+`se::Object` provides `root/unroot` method for developers to invoke, `root` will put JS object into the area not be scanned by the GC. After calling `root`, `se::Object*` is a strong reference to the JS object. JS object will be put back to the area scanned by the GC only when `se::Object` is destructed or `unroot` is called to make root count to zero.
+
+Under normal circumstances, if the C++ object is not a subclass of `cc::Ref`, the C++ object will be used to control the life cycle of the JS object in binding. Binding the engine modules, like Spine, DragonBones, Box2d and other third-party libraries uses this method. When the C++ object is released, it is necessary to find the corresponding `se::Object` in the `NativePtrToObjectMap`, then manually `unroot` and `decRef` it. Take the binding of `spTrackEntry` in Spine as an example:
+
+```c++
+spTrackEntry_setDisposeCallback([](spTrackEntry* entry){
+ se::Object* seObj = nullptr;
+
+ auto iter = se::NativePtrToObjectMap::find(entry);
+ if (iter != se::NativePtrToObjectMap::end())
+ {
+ // Save se::Object pointer for being used in cleanup method.
+ seObj = iter->second;
+ // Unmap native and js object since native object was destroyed.
+ // Otherwise, it may trigger 'assertion' in se::Object::setPrivateData later
+ // Since native obj is already released and the new native object may be assigned with the same address.
+ se::NativePtrToObjectMap::erase(iter);
+ } else {
+ return;
+ }
+
+ auto cleanup = [seObj](){
+
+ auto se = se::ScriptEngine::getInstance();
+ if (!se->isValid() || se->isInCleanup())
+ return;
+
+ se::AutoHandleScope hs;
+ se->clearException();
+
+ // The mapping of native object & se::Object was cleared in above code.
+ // The private data (native object) may be a different object associated with other se::Object.
+ // Therefore, don't clear the mapping again.
+ seObj->clearPrivateData(false);
+ seObj->unroot(); // Unroot, making JS objects subject to GC management
+ seObj->decRef(); // Release se::Object
+ };
+
+ if (!se::ScriptEngine::getInstance()->isGarbageCollecting()) {
+ cleanup();
+ }
+ else {
+ CleanupTask::pushTaskToAutoReleasePool(cleanup);
+ }
+ });
+```
+
+**C++ Object lifecycle management**
+
+Prior to 3.6, the destructor callback `_finalize` would call `delete` or `release` to release the corresponding C++ object, depending on the object type and whether it existed in `se::NonRefNativePtrCreatedByCtorMap`. Since 3.6, the `_finalize` callback has been deprecated and left empty for the time being for debugging purposes. `se::Object` establishes a lifecycle association with C++ objects via `se::PrivateObjectBase` objects. The three subclasses of `se::PrivateObjectBase` correspond to different release policies.
+
+- `se::CCSharedPtrPrivateObject`
+
+uses `cc::IntrusivePtr` to store pointers to C++ objects, requiring that the C++ class inherits from `cc::RefCounted`. Where `cc::IntrusivePtr` is a smart pointer type that automatically increments or decrements the reference count of `cc::RefCounted`. When the reference count is 0, destructions are triggered.
+
+- `se::SharedPrivateObject`
+
+Use `std::shared_ptr` to store C++ object pointers, requiring that C++ classes **do not inherit** from `cc::RefCounted`. Due to the nature of `shared_ptr` itself, all strong references are required to be `shared_ptr`. Destructing C++ objects is triggered when all `shared_ptr`s are destroyed.
+
+- `se::RawRefPrivateObject`
+
+Uses a bare pointer, which defaults to a weak reference to a C++ object. It can be converted to a strong reference by calling `tryAllowDestroyInGC`. As a weak reference, GC does not trigger destructing the object.
+
+**Associate native objects**.
+
+After 3.6 `se::Object::setPrivateData(void *)` is extended to:
+```c++
+template
+inline void setPrivateData(T *data);
+```
+can automatically create `SharedPrivateObject` or `CCSharedPtrPrivateObject` based on type information, but does not support `RawRefPrivateObject`.
+
+We can use `setPrivateObject` to display the type of the specified `PrivateObject`:
+```c++
+// se::SharedPrivateObject
+obj->setPrivateObject(se::shared_private_object(v));
+
+// se::CCSharedPtrPrivateObject
+obj->setPrivateObject(se::ccshared_private_object(v));
+
+// se::RawRefPrivateObject
+obj->setPrivateObject(se::rawref_private_object(v));
+```
+
+
+__Object Types__
+
+The creation of native binding object has been hidden in the `SE_BIND_CTOR` and `SE_BIND_SUB_CLS_CTOR` macros, if developers need to use the `se::Object` in the binding callback, just get it by invoking `s.thisObject()`. Where `s` is `se::State&` which will be described in the following chapters.
+
+In addition, `se::Object` currently supports the manual creation of the following objects:
+
+- Plain Object: Created by `se::Object::createPlainObject`, similar to `var a = {};` in JS
+- Array Object: Created by `se::Object::createArrayObject`, similar to `var a = [];` in JS
+- Uint8 Typed Array Object: Created by `se::Object::createTypedArray`, like `var a = new Uint8Array(buffer);` in JS
+- Array Buffer Object: Created by `se::Object::createArrayBufferObject` similar to `var a = new ArrayBuffer(len);` in JS
+
+__The Release of The Objects Created Manually__
+
+`se::Object::createXXX` is unlike the create method in Cocos Creator, the abstraction layer is a completely separate module which does not rely on the autorelease mechanism in Cocos Creator. Although `se::Object` also inherits the reference count class `se::RefCounter`, developers need to handle the release for **objects created manually**.
+
+```c++
+se::Object* obj = se::Object::createPlainObject();
+...
+...
+obj->decRef(); // Decrease the reference count to avoid memory leak
+```
+
+#### se::HandleObject (recommended helper class for managing the objects created manually)
+
+- If using manual creation of objects in complex logic, developers often forget to deal with `decRef` in different conditions
+
+ ```c++
+ bool foo()
+ {
+ se::Object* obj = se::Object::createPlainObject();
+ if (var1)
+ return false; // Return directly, forget to do 'decRef' operation
+
+ if (var2)
+ return false; // Return directly, forget to do 'decRef' operation
+ ...
+ ...
+ obj->decRef();
+ return true;
+ }
+ ```
+
+ Plus adding `decRef` to different return condition branches can result in logically complex and difficult to maintain, and it is easy to forget about `decRef` if you make another return branch later.
+
+- If the JS engine did a GC operationJS engine right after `se::Object::createXXX`, which will result in the `se::Object` reference to an illegal pointer, the program may crash.
+
+In order to solve the above problems, the abstraction layer defines a type that assists in the management of **manually created objects**, namely `se::HandleObject`.
+
+`se::HandleObject` is a helper class for easier management of the `release (decRef)`, `root`, and `unroot` operations of manually created `se::Object` objects.
+
+The following two code snippets are equivalent, the use of `se::HandleObject` significantly smaller amount of code, and more secure.
+
+```c++
+{
+ se::HandleObject obj(se::Object::createPlainObject());
+ obj->setProperty(...);
+ otherObject->setProperty("foo", se::Value(obj));
+}
+```
+
+Is equal to:
+
+```C++
+{
+ se::Object* obj = se::Object::createPlainObject();
+ obj->root(); // Root the object immediately to prevent the object being garbage collected.
+
+ obj->setProperty(...);
+ otherObject->setProperty("foo", se::Value(obj));
+
+ obj->unroot(); // Call unroot while the object is needed anymore.
+ obj->decRef(); // Decrease the reference count to avoid memory leak.
+}
+```
+
+> **NOTES**:
+>
+> 1. Do not try to use `se::HandleObject` to create a native binding object. In the `JavaScript controls of C++` mode, the release of the bound object will be automatically handled by the abstraction layer. In the `C++ controls JavaScript` mode, the previous chapter has already described it.
+> 2. The `se::HandleObject` object can only be allocated on the stack, and a `se::Object` pointer must be passed in.
+
+#### se::Class
+
+`se::Class` is used to expose CPP classes to JS, it creates a constructor function in JS that has a corresponding name.
+
+It has the following methods:
+
+- `static se::Class* create(className, obj, parentProto, ctor)`: **Creating a Class**. If the registration is successful, it is then possible to create an object by calling `var xxx = new SomeClass ();` in the JavaScript layer.
+- `bool defineFunction(name, func)`: Define a member function for a class.
+- `bool defineProperty(name, getter, setter)`: Define a property accessor for a class.
+- `bool defineStaticFunction(name, func)`: Define a static function for a class, the JavaScript function could be accessed by `SomeClass.foo()` rather than calling `var obj = new SomeClass(); obj.foo()`, this means it's a class method instead of an instance method.
+- `bool defineStaticProperty(name, getter, setter)`: Define a static property accessor which could be invoked by `SomeClass.propertyA`, it's nothing about instance object.
+- `bool defineFinalizeFunction(func)`: Define the finalize callback function after JS object is garbage collected.
+- `bool install()`: Install a class JS engine.
+- `Object* getProto()`: Get the prototype of JS constructor installed, similar to `Foo.prototype` of `function Foo(){}` in JS.
+- `const char* getName() const`: Get the class name which is also the name of JS constructor.
+
+> **NOTE**: you do not need to release memory manually after `se::Class` type is created, it will be automatically encapsulated layer.
+
+You could look through the API documentation or code comments for more specific API instructions.
+
+#### se::AutoHandleScope
+
+The `se::AutoHandleScope` object type is purely a concept introduced to address V8 compatibility issues. In V8, any action that calls `v8::Local<>` on a CPP function that needs to trigger a JS related operation, such as calling a JS function, accessing a JS property, etc, requires a `v8::HandleScope` function be invoked before calling these operations, otherwise it will cause the program to crash.
+
+So the concept of `se::AutoHandleScope` was introduced into the abstraction layer, which is implemented only on V8, and the other JS engines are currently just empty implementations.
+
+Developers need to remember that in any code execution from CPP, you need to declare a `se::AutoHandleScope` before calling JS's logic. For example:
+
+```c++
+class SomeClass {
+ void update(float dt) {
+ se::ScriptEngine::getInstance()->clearException(); // Clear JS exceptions
+ se::AutoHandleScope hs; // Declare a handle scope, it's needed for V8
+
+ se::Object* obj = ...;
+ obj->setProperty(...);
+ ...
+ ...
+ obj->call(...);
+ }
+};
+```
+
+#### se::State
+
+In the previous section, we have mentioned the `se::State` type, which is an environment in the binding callback. We can get the current CPP pointer, `se::Object` object pointer, parameter list and return value reference through `se::State` argument.
+
+```c++
+bool foo(se::State& s)
+{
+ // Get native object pointer bound with the current JS object.
+ SomeClass* cobj = (SomeClass*)s.nativeThisObject();
+ // Get se::Object pointer that represents the current JS object.
+ se::Object* thisObject = s.thisObject();
+ // Get argument list of the current function.
+ const se::ValueArray& args = s.args();
+ // Set return value for current function.
+ s.rval().setInt32(100);
+ // Return true to indicate the function is executed successfully.
+ return true;
+}
+SE_BIND_FUNC(foo)
+```
+
+## Does The Abstraction Layer Depend on Cocos Creator?
+
+**No, it doesn't.**
+
+This abstraction layer was originally designed as a stand-alone module which is completely independent of Cocos Creator engine. Developers can copy the abstraction layer code in `cocos/scripting/jswrapper` directory and paste them to other projects directly.
+
+## Manual Binding
+
+### Define A Callback Function
+
+```c++
+static bool Foo_balabala(se::State& s)
+{
+ const auto& args = s.args();
+ int argc = (int)args.size();
+
+ if (argc >= 2) // Limit the number of parameters must be greater than or equal to 2, or throw an error to the JS layer and return false. {
+ ...
+ ...
+ return true;
+ }
+
+ SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", argc, 2) ;
+ return false;
+}
+
+// If binding a function, we use SE_BIND_FUNC macro. For binding a constructor, destructor, subclass constructor, please use SE_BIND_balabala macros memtioned above.
+SE_BIND_FUNC(Foo_balabala)
+```
+
+### Set A Property Value for JS object
+
+```c++
+se::Object* globalObj = se::ScriptEngine::getInstance()->getGlobalObject(); // We get the global object just for easier demonstration.
+globalObj->setProperty("foo", se::Value(100)); // Set a property called `foo` with a value of 100 to the global object.
+```
+
+Next, use the `foo` global variable in JS directly.
+
+```js
+log("foo value: " + foo); // Print `foo value: 100`.
+```
+
+### Set A Property Accessor for JS Object
+
+```c++
+// The read callback of "foo" property of the global object
+static bool Global_get_foo(se::State& s)
+{
+ NativeObj* cobj = (NativeObj*)s.nativeThisObject();
+ int32_t ret = cobj->getValue();
+ s.rval().setInt32(ret);
+ return true;
+}
+SE_BIND_PROP_GET(Global_get_foo)
+
+// The write callback of "foo" property of the global object
+static bool Global_set_foo(se::State& s)
+{
+ const auto& args = s.args();
+ int argc = (int)args.size();
+ if (argc >= 1)
+ {
+ NativeObj* cobj = (NativeObj*)s.nativeThisObject();
+ int32_t arg1 = args[0].toInt32();
+ cobj->setValue(arg1);
+ // Do not need to call "s.rval().set(se::Value::Undefined)" for functions without return value.
+ return true;
+ }
+
+ SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", argc, 1) ;
+ return false;
+}
+SE_BIND_PROP_SET(Global_set_foo)
+
+void some_func()
+{
+ se::Object* globalObj = se::ScriptEngine::getInstance()->getGlobalObject(); // We get the global object just for easier demonstration.
+ globalObj->defineProperty("foo", _SE(Global_get_foo), _SE(Global_set_foo)); // Use _SE macro to package specific function name.
+}
+```
+
+### Define A Function for JS Object
+
+```c++
+static bool Foo_function(se::State& s)
+{
+ ...
+ ...
+}
+SE_BIND_FUNC(Foo_function)
+
+void some_func()
+{
+ se::Object* globalObj = se::ScriptEngine::getInstance()->getGlobalObject(); // We get the global object just for easier demonstration.
+ globalObj->defineFunction("foo", _SE(Foo_function)); // Use _SE macro to package specific function name.
+}
+```
+
+### Register A CPP Class to JS Virtual Machine
+
+```c++
+static se::Object* __jsb_ns_SomeClass_proto = nullptr;
+static se::Class* __jsb_ns_SomeClass_class = nullptr;
+
+namespace ns {
+ class SomeClass
+ {
+ public:
+ SomeClass()
+ : xxx(0)
+ {}
+
+ void foo() {
+ printf("SomeClass::foo\n");
+
+ Director::getInstance()->getScheduler()->schedule([this](float dt){
+ static int counter = 0;
+ ++counter;
+ if (_cb != nullptr)
+ _cb(counter);
+ }, this, 1.0f, CC_REPEAT_FOREVER, 0.0f, false, "iamkey");
+ }
+
+ static void static_func() {
+ printf("SomeClass::static_func\n");
+ }
+
+ void setCallback(const std::function& cb) {
+ _cb = cb;
+ if (_cb != nullptr)
+ {
+ printf("setCallback(cb)\n");
+ }
+ else
+ {
+ printf("setCallback(nullptr)\n");
+ }
+ }
+
+ int xxx;
+ private:
+ std::function _cb;
+ };
+} // namespace ns {
+
+static bool js_SomeClass_finalize(se::State& s)
+{
+ ns::SomeClass* cobj = (ns::SomeClass*)s.nativeThisObject();
+ delete cobj;
+ return true;
+}
+SE_BIND_FINALIZE_FUNC(js_SomeClass_finalize)
+
+static bool js_SomeClass_constructor(se::State& s)
+{
+ ns::SomeClass* cobj = new ns::SomeClass();
+ s.thisObject()->setPrivateData(cobj);
+ return true;
+}
+SE_BIND_CTOR(js_SomeClass_constructor, __jsb_ns_SomeClass_class, js_SomeClass_finalize)
+
+static bool js_SomeClass_foo(se::State& s)
+{
+ ns::SomeClass* cobj = (ns::SomeClass*)s.nativeThisObject();
+ cobj->foo();
+ return true;
+}
+SE_BIND_FUNC(js_SomeClass_foo)
+
+static bool js_SomeClass_get_xxx(se::State& s)
+{
+ ns::SomeClass* cobj = (ns::SomeClass*)s.nativeThisObject();
+ s.rval().setInt32(cobj->xxx);
+ return true;
+}
+SE_BIND_PROP_GET(js_SomeClass_get_xxx)
+
+static bool js_SomeClass_set_xxx(se::State& s)
+{
+ const auto& args = s.args();
+ int argc = (int)args.size();
+ if (argc > 0)
+ {
+ ns::SomeClass* cobj = (ns::SomeClass*)s.nativeThisObject();
+ cobj->xxx = args[0].toInt32();
+ return true;
+ }
+
+ SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", argc, 1);
+ return false;
+}
+SE_BIND_PROP_SET(js_SomeClass_set_xxx)
+
+static bool js_SomeClass_static_func(se::State& s)
+{
+ ns::SomeClass::static_func();
+ return true;
+}
+SE_BIND_FUNC(js_SomeClass_static_func)
+
+bool js_register_ns_SomeClass(se::Object* global)
+{
+ // Make sure the namespace exists
+ se::Value nsVal;
+ if (!global->getProperty("ns", &nsVal))
+ {
+ // If it doesn't exist, create one. Similar as "var ns = {};" in JS.
+ se::HandleObject jsobj(se::Object::createPlainObject());
+ nsVal.setObject(jsobj);
+
+ // Set the object to the global object with the property name `ns`.
+ global->setProperty("ns", nsVal);
+ }
+ se::Object* ns = nsVal.toObject();
+
+ // Create a se::Class object, developers do not need to consider the release of the se::Class object, which is automatically handled by the ScriptEngine.
+ auto cls = se::Class::create("SomeClass", ns, nullptr, _SE(js_SomeClass_constructor)); // If the registered class doesn't need a constructor, the last argument can be passed in with nullptr, it will make "new SomeClass();" illegal.
+
+ // Define member functions, member properties.
+ cls->defineFunction("foo", _SE(js_SomeClass_foo));
+ cls->defineProperty("xxx", _SE(js_SomeClass_get_xxx), _SE(js_SomeClass_set_xxx));
+
+ // Define finalize callback function
+ cls->defineFinalizeFunction(_SE(js_SomeClass_finalize));
+
+ // Install the class to JS virtual machine
+ cls->install();
+
+ // JSBClassType::registerClass is a helper function in the Cocos Creator native binding code, which is not a part of the ScriptEngine.
+ JSBClassType::registerClass(cls);
+
+ // Save the result to global variable for easily use in other places, for example class inheritance.
+ __jsb_ns_SomeClass_proto = cls->getProto();
+ __jsb_ns_SomeClass_class = cls;
+
+ // Set a property "yyy" with the string value "helloyyy" for each object instantiated by this class.
+ __jsb_ns_SomeClass_proto->setProperty("yyy", se::Value("helloyyy"));
+
+ // Register static member variables and static member functions
+ se::Value ctorVal;
+ if (ns->getProperty("SomeClass", &ctorVal) && ctorVal.isObject())
+ {
+ ctorVal.toObject()->setProperty("static_val", se::Value(200));
+ ctorVal.toObject()->defineFunction("static_func", _SE(js_SomeClass_static_func));
+ }
+
+ // Clear JS exceptions
+ se::ScriptEngine::getInstance()->clearException();
+ return true;
+}
+```
+
+### How to Bind A CPP Callback Function
+
+```c++
+static bool js_SomeClass_setCallback(se::State& s)
+{
+ const auto& args = s.args();
+ int argc = (int)args.size();
+ if (argc >= 1)
+ {
+ ns::SomeClass* cobj = (ns::SomeClass*)s.nativeThisObject();
+
+ se::Value jsFunc = args[0];
+ se::Value jsTarget = argc > 1 ? args[1] : se::Value::Undefined;
+
+ if (jsFunc.isNullOrUndefined())
+ {
+ cobj->setCallback(nullptr);
+ }
+ else
+ {
+ assert(jsFunc.isObject() && jsFunc.toObject()->isFunction());
+
+ se::Object *jsTargetObj = jsTarget.isObject() ? jsTarget.toObject() : nullptr;
+
+ // If the current SomeClass is a class that can be created by "new", we use "se::Object::attachObject" to associate jsFunc with jsTarget to the current object.
+ s.thisObject()->attachObject(jsFunc.toObject());
+ if(jsTargetObj) s.thisObject()->attachObject(jsTargetObj);
+
+ // If the current SomeClass class is a singleton, or a class that always has only one instance, we can not associate it with "se::Object::attachObject".
+ // Instead, you must use "se::Object::root", developers do not need to unroot since unroot operation will be triggered in the destruction of lambda which makes the "se::Value" jsFunc be destroyed, then "se::Object" destructor will do the unroot operation automatically.
+ // The binding function "js_audio_AudioEngine_setFinishCallback" implements it in this way because "AudioEngine" is always a singleton.
+ // Using "s.thisObject->attachObject(jsFunc.toObject);" for binding addCustomEventListener will cause jsFunc and jsTarget variables can't be released, which will result in memory leak.
+
+ // jsFunc.toObject()->root();
+ // jsTarget.toObject()->root();
+
+ cobj->setCallback([jsFunc, jsTargetObj](int counter) {
+
+ // Add the following two lines of code in CPP callback function before passing data to the JS.
+ se::ScriptEngine::getInstance()->clearException();
+ se::AutoHandleScope hs;
+
+
+ se::ValueArray args;
+ args.push_back(se::Value(counter));
+
+ jsFunc.toObject()->call(args, jsTargetObj);
+ });
+ }
+
+ return true;
+ }
+
+ SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", argc, 1);
+ return false;
+}
+SE_BIND_FUNC(js_SomeClass_setCallback)
+```
+
+After SomeClass is registered, use it in JS like the following:
+
+```js
+ var myObj = new ns.SomeClass();
+ myObj.foo();
+ ns.SomeClass.static_func();
+ log("ns.SomeClass.static_val: " + ns.SomeClass.static_val);
+ log("Old myObj.xxx:" + myObj.xxx);
+ myObj.xxx = 1234;
+ log("New myObj.xxx:" + myObj.xxx);
+ log("myObj.yyy: " + myObj.yyy);
+
+ var delegateObj = {
+ onCallback: function(counter) {
+ log("Delegate obj, onCallback: " + counter + ", this.myVar: " + this.myVar);
+ this.setVar();
+ },
+
+ setVar: function() {
+ this.myVar++;
+ },
+
+ myVar: 100
+ };
+
+ myObj.setCallback(delegateObj.onCallback, delegateObj);
+
+ setTimeout(function(){
+ myObj.setCallback(null);
+ }, 6000); // Clear callback after 6 seconds.
+```
+
+There will be some logs outputted in console:
+
+```
+SomeClass::foo
+SomeClass::static_func
+ns.SomeClass.static_val: 200
+Old myObj.xxx:0
+New myObj.xxx:1234
+myObj.yyy: helloyyy
+setCallback(cb)
+Delegate obj, onCallback: 1, this.myVar: 100
+Delegate obj, onCallback: 2, this.myVar: 101
+Delegate obj, onCallback: 3, this.myVar: 102
+Delegate obj, onCallback: 4, this.myVar: 103
+Delegate obj, onCallback: 5, this.myVar: 104
+Delegate obj, onCallback: 6, this.myVar: 105
+setCallback(nullptr)
+```
+
+### How to Use The Helper Functions in Cocos Creator Binding for Easier Native<->JS Type Conversions
+
+The helper functions for native<->JS type conversions are located in `cocos/bindings/manual/jsb_conversions.h`, it includes:
+
+#### Convert se::Value to C++ Type
+
+Support base types `int*t`/`uint*_t`/`float`/`double`/`const char*`/`bool`, `std::string`, bound types, their container types `std::vector`, `std::array`, `std::map`, `std:: unordered_map`, etc.
+
+```c++
+template
+bool sevalue_to_native(const se::Value &from, T *to, se::Object *ctx);
+
+template
+bool sevalue_to_native(const se::Value &from, T *to);
+```
+
+#### Convert C++ Type to se::Value
+
+```c++
+template
+bool nativevalue_to_se(const T &from, se::Value &to, se::Object *ctx);
+
+template
+bool nativevalue_to_se(const T &from, se::Value &to);
+
+```
+
+**The following conversion functions before 3.6 have been deprecated and need to be replaced with the above two groups of functions**
+
+
+```c++
+bool seval_to_int32(const se::Value &v, int32_t *ret);
+bool seval_to_uint32(const se::Value &v, uint32_t *ret);
+bool seval_to_int8(const se::Value &v, int8_t *ret);
+bool seval_to_uint8(const se::Value &v, uint8_t *ret);
+bool seval_to_int16(const se::Value &v, int16_t *ret);
+bool seval_to_uint16(const se::Value &v, uint16_t *ret);
+bool seval_to_boolean(const se::Value &v, bool *ret);
+bool seval_to_float(const se::Value &v, float *ret);
+bool seval_to_double(const se::Value &v, double *ret);
+bool seval_to_size(const se::Value &v, size_t *ret);
+bool seval_to_std_string(const se::Value &v, std::string *ret);
+bool seval_to_Vec2(const se::Value &v, cc::Vec2 *pt);
+bool seval_to_Vec3(const se::Value &v, cc::Vec3 *pt);
+bool seval_to_Vec4(const se::Value &v, cc::Vec4 *pt);
+bool seval_to_Mat4(const se::Value &v, cc::Mat4 *mat);
+bool seval_to_Size(const se::Value &v, cc::Size *size);
+bool seval_to_ccvalue(const se::Value &v, cc::Value *ret);
+bool seval_to_ccvaluemap(const se::Value &v, cc::ValueMap *ret);
+bool seval_to_ccvaluemapintkey(const se::Value &v, cc::ValueMapIntKey *ret);
+bool seval_to_ccvaluevector(const se::Value &v, cc::ValueVector *ret);
+bool sevals_variadic_to_ccvaluevector(const se::ValueArray &args, cc::ValueVector *ret);
+bool seval_to_std_vector_string(const se::Value &v, std::vector *ret);
+bool seval_to_std_vector_int(const se::Value &v, std::vector *ret);
+bool seval_to_std_vector_uint16(const se::Value &v, std::vector *ret);
+bool seval_to_std_vector_float(const se::Value &v, std::vector *ret);
+bool seval_to_std_vector_Vec2(const se::Value &v, std::vector *ret);
+bool seval_to_Uint8Array(const se::Value &v, uint8_t *ret);
+bool seval_to_uintptr_t(const se::Value &v, uintptr_t *ret);
+bool seval_to_std_map_string_string(const se::Value &v, std::map *ret);
+bool seval_to_Data(const se::Value &v, cc::Data *ret);
+bool seval_to_DownloaderHints(const se::Value &v, cc::network::DownloaderHints *ret);
+template
+bool seval_to_native_ptr(const se::Value& v, T* ret);
+template
+typename std::enable_if::value && !std::is_same::value, T>::type
+seval_to_type(const se::Value &v, bool &ok);
+template
+typename std::enable_if::value, T>::type
+seval_to_type(const se::Value &v, bool &ok);
+template
+typename std::enable_if::value, T>::type
+seval_to_type(const se::Value &v, bool &ok);
+template
+typename std::enable_if::value, T>::type
+seval_to_type(const se::Value &v, bool &ok);
+
+template
+typename std::enable_if::value, T>::type
+seval_to_type(const se::Value &v, bool &ok);
+template
+typename std::enable_if::value && std::is_class::type>::value, bool>::type
+seval_to_std_vector(const se::Value &v, std::vector *ret);
+
+template
+typename std::enable_if::value, bool>::type
+seval_to_std_vector(const se::Value &v, std::vector *ret);
+template
+bool seval_to_Map_string_key(const se::Value& v, cc::Map* ret)
+```
+
+Replace with `sevalue_to_native`
+
+```c++
+bool int8_to_seval(int8_t v, se::Value *ret);
+bool uint8_to_seval(uint8_t v, se::Value *ret);
+bool int32_to_seval(int32_t v, se::Value *ret);
+bool uint32_to_seval(uint32_t v, se::Value *ret);
+bool int16_to_seval(uint16_t v, se::Value *ret);
+bool uint16_to_seval(uint16_t v, se::Value *ret);
+bool boolean_to_seval(bool v, se::Value *ret);
+bool float_to_seval(float v, se::Value *ret);
+bool double_to_seval(double v, se::Value *ret);
+bool long_to_seval(long v, se::Value *ret);
+bool ulong_to_seval(unsigned long v, se::Value *ret);
+bool longlong_to_seval(long long v, se::Value *ret);
+bool uintptr_t_to_seval(uintptr_t v, se::Value *ret);
+bool size_to_seval(size_t v, se::Value *ret);
+bool std_string_to_seval(const std::string &v, se::Value *ret);
+bool Vec2_to_seval(const cc::Vec2 &v, se::Value *ret);
+bool Vec3_to_seval(const cc::Vec3 &v, se::Value *ret);
+bool Vec4_to_seval(const cc::Vec4 &v, se::Value *ret);
+bool Mat4_to_seval(const cc::Mat4 &v, se::Value *ret);
+bool Size_to_seval(const cc::Size &v, se::Value *ret);
+bool Rect_to_seval(const cc::Rect &v, se::Value *ret);
+bool ccvalue_to_seval(const cc::Value &v, se::Value *ret);
+bool ccvaluemap_to_seval(const cc::ValueMap &v, se::Value *ret);
+bool ccvaluemapintkey_to_seval(const cc::ValueMapIntKey &v, se::Value *ret);
+bool ccvaluevector_to_seval(const cc::ValueVector &v, se::Value *ret);
+bool std_vector_string_to_seval(const std::vector &v, se::Value *ret);
+bool std_vector_int_to_seval(const std::vector &v, se::Value *ret);
+bool std_vector_uint16_to_seval(const std::vector &v, se::Value *ret);
+bool std_vector_float_to_seval(const std::vector &v, se::Value *ret);
+bool std_map_string_string_to_seval(const std::map &v, se::Value *ret);
+bool ManifestAsset_to_seval(const cc::extension::ManifestAsset &v, se::Value *ret);
+bool Data_to_seval(const cc::Data &v, se::Value *ret);
+bool DownloadTask_to_seval(const cc::network::DownloadTask &v, se::Value *ret);
+template
+typename std::enable_if::value, bool>::type
+native_ptr_to_seval(T *v_c, se::Value *ret, bool *isReturnCachedValue = nullptr);
+template
+typename std::enable_if::value && !std::is_pointer::value, bool>::type
+native_ptr_to_seval(T &v_ref, se::Value *ret, bool *isReturnCachedValue = nullptr);
+template
+bool native_ptr_to_rooted_seval(
+ typename std::enable_if::value, T>::type *v,
+ se::Value *ret, bool *isReturnCachedValue = nullptr);
+template
+typename std::enable_if::value, bool>::type
+native_ptr_to_seval(T *vp, se::Class *cls, se::Value *ret, bool *isReturnCachedValue = nullptr);
+template
+typename std::enable_if::value, bool>::type
+native_ptr_to_seval(T &v_ref, se::Class *cls, se::Value *ret, bool *isReturnCachedValue = nullptr);
+template
+bool native_ptr_to_rooted_seval(
+ typename std::enable_if::value, T>::type *v,
+ se::Class *cls, se::Value *ret, bool *isReturnCachedValue = nullptr);
+template
+typename std::enable_if::value, bool>::type
+native_ptr_to_seval(T *vp, se::Value *ret, bool *isReturnCachedValue = nullptr);
+template
+typename std::enable_if::value, bool>::type
+native_ptr_to_seval(T *vp, se::Class *cls, se::Value *ret, bool *isReturnCachedValue = nullptr);
+template
+bool std_vector_to_seval(const std::vector &v, se::Value *ret);
+template
+bool seval_to_reference(const se::Value &v, T **ret);
+```
+
+Replace with `nativelue_to_se`
+
+Auxiliary conversion functions are not part of the abstraction layer (`Script Engine Wrapper`), they belong to the Cocos Creator binding layer and are encapsulated to facilitate more convenient conversion in the binding code.
+Each conversion function returns the type `bool` indicating whether the conversion was successful or not. Developers need to check the return value after calling these interfaces.
+
+The specific usage is directly known according to interface names. The first parameter in the interface is input, and the second parameter is the output parameter. The usage is as follows:
+
+```c++
+se::Value v;
+bool ok = nativevalue_to_se(100, v); // The second parameter is the output parameter, passing in the address of the output parameter
+```
+
+```c++
+int32_t v;
+bool ok = sevalue_to_native(args[0], &v); // The second parameter is the output parameter, passing in the address of the output parameter
+```
+
+More on manual binding can be found in the [Using JSB Manual Binding](jsb-manual-binding.md) documentation.
+
+## Automatic Binding
+
+### Configure Module `.ini` Files
+
+For more specific, please refer to the engine directory `tools/tojs/cocos.ini` file.
+
+### Understand The Meaning of Each Field in The `.ini` file
+
+```ini
+# Module name
+[cocos]
+
+# The prefix for callback functions and the binding file name.
+prefix = engine
+
+# The namespace of the binding class attaches to.
+target_namespace = jsb
+
+# Automatic binding tools is based on the Android NDK. The android_headers field configures the search path of Android header file.
+android_headers =
+
+# Configure building parameters for Android.
+android_flags = -target armv7-none-linux-androideabi -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -DANDROID -D__ANDROID_API__=14 -gcc-toolchain %(gcc_toolchain_dir)s --sysroot=%(androidndkdir)s/platforms/android-14/arch-arm -idirafter %(androidndkdir)s/sources/android/support/include -idirafter %(androidndkdir)s/sysroot/usr/include -idirafter %(androidndkdir)s/sysroot/usr/include/arm-linux-androideabi -idirafter %(clangllvmdir)s/lib64/clang/5.0/include -I%(androidndkdir)s/sources/cxx-stl/llvm-libc++/include
+
+# Configure the search path for clang header file.
+clang_headers =
+
+# Configure building parameters for clang
+clang_flags = -nostdinc -x c++ -std=c++17 -fsigned-char -mfloat-abi=soft -U__SSE__
+
+# Configure the search path for engine header file
+cocos_headers = -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/platform/android -I%(cocosdir)s/external/sources
+
+# Configure building parameters for engine
+cocos_flags = -DANDROID -DCC_PLATFORM=3 -DCC_PLATFORM_MAC_IOS=1 -DCC_PLATFORM_MAC_OSX=4 -DCC_PLATFORM_WINDOWS=2 -DCC_PLATFORM_ANDROID=3
+
+# Configure extra building parameters
+extra_arguments = %(android_headers)s %(clang_headers)s %(cxxgenerator_headers)s %(cocos_headers)s %(android_flags)s %(clang_flags)s %(cocos_flags)s %(extra_flags)s
+
+# Which header files needed to be parsed
+headers = %(cocosdir)s/cocos/platform/FileUtils.h %(cocosdir)s/cocos/platform/CanvasRenderingContext2D.h %(cocosdir)s/cocos/platform/Device.h %(cocosdir)s/cocos/platform/SAXParser.h
+
+# Rename the header file in the generated binding code
+replace_headers =
+
+# Which classes need to be bound, you can use regular expressions, separated by space.
+classes = FileUtils$ SAXParser CanvasRenderingContext2D CanvasGradient Device DownloaderHints
+
+# Which classes need to be extended at the JS level, separated by spaces.
+classes_need_extend =
+
+# Which classes need to bind properties, separated by commas
+field =
+
+# Which classes need to be skipped, separated by commas
+skip = FileUtils::[getFileData setFilenameLookupDictionary destroyInstance getFullPathCache getContents listFilesRecursively],
+ SAXParser::[(?!(init))],
+ Device::[getDeviceMotionValue],
+ CanvasRenderingContext2D::[setCanvasBufferUpdatedCallback set_.+ fillText strokeText fillRect measureText],
+ Data::[takeBuffer getBytes fastSet copy],
+ Value::[asValueVector asValueMap asIntKeyMap]
+
+# Which classes need to define getters and setters, separated by commas
+getter_setter = CanvasRenderingContext2D::[width//setWidth height//setHeight fillStyle//setFillStyle font//setFont globalCompositeOperation//setGlobalCompositeOperation lineCap//setLineCap lineJoin//setLineJoin lineWidth//setLineWidth strokeStyle//setStrokeStyle textAlign//setTextAlign textBaseline//setTextBaseline]
+
+# Which functions need to be renamed, separated by commas
+rename_functions = FileUtils::[loadFilenameLookupDictionaryFromFile=loadFilenameLookup]
+
+# Which classes need to be renamed, separated by commas
+rename_classes = SAXParser::PlistParser
+
+
+# Which classes do not have parents in JS
+classes_have_no_parents = SAXParser
+
+# Which C++ base classes need to be skipped
+base_classes_to_skip = Ref Clonable
+
+# Which classes are abstract classes which do not have a constructor in JS
+abstract_classes = SAXParser Device
+```
+
+## Remote Debugging and Profile
+
+By default, remote debugging and Profile are enabled in debug mode. If you need to enable them in release mode, you need to manually modify the macro switches in the file `native/engine/common/CMakeLists.txt` generated after building the native platform.
+
+```cmake
+# ...
+if(NOT RES_DIR)
+ message(FATAL_ERROR "RES_DIR is not set!")
+endif()
+
+include(${RES_DIR}/proj/cfg.cmake)
+
+if(NOT COCOS_X_PATH)
+ message(FATAL_ERROR "COCOS_X_PATH is not set!")
+endif()
+# ...
+
+```
+
+Change to:
+
+```cmake
+if(NOT RES_DIR)
+ message(FATAL_ERROR "RES_DIR is not set!")
+endif()
+
+include(${RES_DIR}/proj/cfg.cmake)
+set(USE_V8_DEBUGGER_FORCE ON) ## 覆盖 USE_V8_DEBUGGER_FORCE 的值
+
+if(NOT COCOS_X_PATH)
+ message(FATAL_ERROR "COCOS_X_PATH is not set!")
+endif()
+# ...
+```
+
+And edit file `native/engine/common/Classes/Game.cpp`
+
+```c++
+#if CC_DEBUG
+ _debuggerInfo.enabled = true;
+#else
+ _debuggerInfo.enabled = false;
+#endif
+ // Override the value above
+ _debuggerInfo.enabled = true;
+```
+
+### Remote Debugging V8 in Chrome
+
+#### Windows/Mac
+
+- Compile, run the game (or run directly in the simulator of Creator)
+
+- Open with Chrome: . (If you are using an older version of Chrome, you need to change the `devtools` at the beginning of the address to `chrome-devtools`)
+
+>If the port is occupied, the port will auto-increment by +1. If you cannot connect, please check the port number printed in the console when the App starts.
+
+- Breakpoint debugging:
+
+ 
+
+- Catch JS Heap:
+
+ 
+
+- Profile:
+
+ 
+
+#### Android/iOS
+
+- Make sure your Android/iOS device is on the same network as your PC or Mac
+
+- Compile and run your game
+
+- Open with Chrome: , `xxx.xxx.xxx.xxx` is the IP address of Android/iOS device. (If you are using an older version of Chrome, you need to change the `devtools` at the beginning of the address to `chrome-devtools`)
+- The remote debugging interface is the same as debugging Windows.
+
+>If the port is occupied, the port will auto-increment by +1. If you cannot connect, please check the port number printed in the console when the App starts.
+
+## Q & A
+
+### What's The Difference between se::ScriptEngine and ScriptingCore? Why to keep ScriptingCore?
+
+In Creator v1.7, the abstraction layer was designed as a stand-alone module that had no relation to the engine. The management of the JS engine was moved from the `ScriptingCore` to `se::ScriptEngine` class. `ScriptingCore` was retained in hopes of passing engine events to the abstraction layer, which acts like a adapter.
+
+ScriptingCore only needs to be used once in AppDelegate.cpp, and all subsequent operations only require `se::ScriptEngine`.
+
+```c++
+bool AppDelegate::applicationDidFinishLaunching()
+{
+ ...
+ ...
+ director->setAnimationInterval(1.0 / 60);
+
+ // These two lines set the ScriptingCore adapter to the engine for passing engine events, such as Node's onEnter, onExit, Action's update
+ ScriptingCore* sc = ScriptingCore::getInstance();
+ ScriptEngineManager::getInstance()->setScriptEngine(sc);
+
+ se::ScriptEngine* se = se::ScriptEngine::getInstance();
+ ...
+ ...
+}
+```
+
+### What's The Difference between `se::Object::root/unroot` and `se::Object::incRef/decRef`?
+
+`root`/`unroot` is used to control whether JS objects are controlled by GC, `root` means JS object should not be controlled by GC, `unroot` means it should be controlled by GC. For a `se::Object`, `root` and `unroot` can be called multiple times, `se::Object`'s internal `_rootCount` variables is used to indicate the count of `root` operation. When `unroot` is called and `_rootCount` reach **0**, the JS object associated with `se::Object` is handed over to the GC. Another situation is that if `se::Object` destructor is triggered and `_rootCount` is still greater than 0, it will force the JS object to be controlled by the GC.
+
+`incRef`/`decRef` is used to control the life cycle of `se::Object` CPP object. As mentioned in the previous section, it is recommended that you use `se::HandleObject` to control the manual creation of unbound objects's life cycle. So, in general, developers do not need to touch `incRef`/`decRef`.
+
+### The Association and Disassociation of Object's Life Cycle
+
+Use `se::Object::attachObject` to associate object's life cycle.
+Use `se::Object::dettachObject` to disassociate object's life cycle.
+
+`objA->attachObject(objB);` is similar as `objA.__ nativeRefs[index] = objB` in JS. Only when `objA` is garbage collected, `objB` will be possible garbage collected.
+`objA->dettachObject(objB);` is similar as `delete objA.__nativeRefs[index];` in JS. After invoking dettachObject, objB's life cycle will not be controlled by objA.
+
+### Please DO NOT Assign A Subclass of cc::RefCounted on The Stack
+
+Subclasses of `cc::RefCounted` must be allocated on the heap, via `new`, and then released by `release`. In JS object's finalize callback function, we should use `release` to release. If it is allocated on the stack, the reference count is likely to be 0, and then calling `release` in finalize callback will result `delete` is invoked, which causing the program to crash. So in order to prevent this behavior from happening, developers can identify destructors as `protected` or `private` in the binding classes that inherit from `cc::RefCounted`, ensuring that this problem can be found during compilation.
+
+Example:
+
+```c++
+class CC_EX_DLL EventAssetsManagerEx : public EventCustom
+{
+public:
+ ...
+ ...
+private:
+ virtual ~EventAssetsManagerEx() {}
+ ...
+ ...
+};
+
+EventAssetsManagerEx event(...); // Compilation ERROR
+dispatcher->dispatchEvent(&event);
+
+// Must modify to:
+
+EventAssetsManagerEx* event = new EventAssetsManagerEx(...);
+dispatcher->dispatchEvent(event);
+event->release();
+```
+
+### How to Observe JS Exception?
+
+In AppDelegate.cpp, using `se::ScriptEngine::getInstance()->setExceptionCallback(...)` to set the callback of JS exception.
+
+```c++
+bool AppDelegate::applicationDidFinishLaunching()
+{
+ ...
+ ...
+ se::ScriptEngine* se = se::ScriptEngine::getInstance();
+
+ se->setExceptionCallback([](const char* location, const char* message, const char* stack){
+ // Send exception information to server like Tencent Bugly.
+ // ...
+ // ...
+ });
+
+ jsb_register_all_modules();
+ ...
+ ...
+ return true;
+}
+```
diff --git a/versions/4.0/en/advanced-topics/cmak-learning/code1.png b/versions/4.0/en/advanced-topics/cmak-learning/code1.png
new file mode 100644
index 0000000000..45ce7a8e21
Binary files /dev/null and b/versions/4.0/en/advanced-topics/cmak-learning/code1.png differ
diff --git a/versions/4.0/en/advanced-topics/cmak-learning/code2.png b/versions/4.0/en/advanced-topics/cmak-learning/code2.png
new file mode 100644
index 0000000000..f003e6f321
Binary files /dev/null and b/versions/4.0/en/advanced-topics/cmak-learning/code2.png differ
diff --git a/versions/4.0/en/advanced-topics/cmak-learning/folder3.png b/versions/4.0/en/advanced-topics/cmak-learning/folder3.png
new file mode 100644
index 0000000000..f6e3a1e0d1
Binary files /dev/null and b/versions/4.0/en/advanced-topics/cmak-learning/folder3.png differ
diff --git a/versions/4.0/en/advanced-topics/cmak-learning/folder4.png b/versions/4.0/en/advanced-topics/cmak-learning/folder4.png
new file mode 100644
index 0000000000..45d5877074
Binary files /dev/null and b/versions/4.0/en/advanced-topics/cmak-learning/folder4.png differ
diff --git a/versions/4.0/en/advanced-topics/cmak-learning/project.png b/versions/4.0/en/advanced-topics/cmak-learning/project.png
new file mode 100644
index 0000000000..c0e5a23585
Binary files /dev/null and b/versions/4.0/en/advanced-topics/cmak-learning/project.png differ
diff --git a/versions/4.0/en/advanced-topics/cmake-learning.md b/versions/4.0/en/advanced-topics/cmake-learning.md
new file mode 100644
index 0000000000..7276b84b72
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/cmake-learning.md
@@ -0,0 +1,368 @@
+# Introduction to CMake Usage
+
+CMake is a very powerful build tool that can greatly simplify the software compilation process and improve development efficiency. Cocos Creator uses CMake on various native platforms. Here are some quick advantages of CMake:
+
+- CMake uses the CMakeLists.txt file to describe the entire project's build process, rather than using script files like other build tools.
+- CMake is cross-platform and can run on operating systems such as Windows, Linux, and macOS.
+- CMake can automatically generate Makefiles, Visual Studio, and other IDE project files, simplifying the software compilation process.
+- CMake can easily manage dependency libraries, organize code into modules, etc.
+- CMake supports multiple programming languages, including C, C++, Fortran, Java, Python, etc.
+
+Although CMake is a very powerful build tool, it also has some drawbacks, such as its complex syntax and the need for a certain learning cost.
+
+Developers can learn the syntax of CMake and add their modules to perform specific tasks during the build process. For example, they can define their own preprocessor macros or compiler options to execute custom operations during the build. In addition, they can write scripts to modify project files for different configurations on different platforms, and review [Secondary Development](../editor/publish/native-options.md#secondary-development).
+
+If you want to learn CMake in-depth, you can read other chapters of this tutorial to learn how to install CMake, create CMakeLists.txt files, specify compilers, add source files, add dependency libraries, and build projects, etc. Due to length limitations, this article cannot provide detailed information on how to use FindPackage, set build types, install and test, etc. To master it better, developers need to consult other documents and engage in more practice.
+
+## Installing CMake
+
+For the convenience of developers, Cocos Creator integrates the CMake program internally, which will be used in the build process. Therefore, in general, developers do not need to manually install CMake.
+
+If developers want to use the CMake on their device, they can edit the relevant configuration to do so.
+
+If developers want to use CMake in the command line, they can go to [the official website](https://cmake.org/download/) to download it. On the Mac platform, they can also use Homebrew to install it by executing the following command:
+
+```bash
+brew install cmake
+
+```
+
+## **Getting Started with CMake**
+
+The `CMakeLists.txt` file is the core file of CMake, which describes the entire project's build process. Using this file, you can easily manage the project's building and compilation processes. It contains a series of commands and variables used to specify project names, version numbers, source files, dependency libraries, compiler specifications, compilation options, and other parameters.
+
+Here is a simple example of a CMake hello-world project:
+
+First, create a file named `CMakeLists.txt`. In this file, add the following content:
+
+```
+# CMake Version
+cmake_minimum_required(VERSION 3.10)
+
+# Set project name and main language
+project(helloworld CXX)
+
+add_executable(helloworld main.cpp)
+
+```
+
+Then, create a file named `main.cpp` in the root directory of the project and add the following content::
+
+```
+#include
+
+int main() {
+ std::cout << "Hello, world!" << std::endl;
+ return 0;
+}
+
+```
+
+Finally, create a directory named `build` in the root directory of the project and execute the following command inside it:
+
+```bash
+# Generate the default project files in the build directory. If Visual Studio is installed, it defaults to a Visual Studio project; on Mac, it defaults to a Makefile project. The project file type can be set by specifying -G, for example, -GXcode.
+cmake -B build -S .
+# Generate executable target
+cmake --build build
+```
+
+After executing these commands, an executable file named `helloworld` will be generated in the `build` directory. Running the file will output "Hello, world!".
+
+Two commands used here are `project` and `add_executable`.
+
+`project` is a command in CMake used to specify project name, version number, programming language, and other information. Its syntax is as follows:
+
+```
+project(project_name [version] [LANGUAGES languages...])
+
+```
+
+Here, `project_name` specifies the project name, `version` specifies the version number of the project, and `languages` specifies the programming languages used in the project. If `version` or `languages` are not specified, they can be omitted. For example:
+
+```
+project(MyProject)
+
+```
+
+This command sets the project name as `MyProject`, without specifying the version number and programming language.
+
+`add_executable` is used to add build rules for executable files, and its syntax is as follows:
+
+```
+add_executable(executable_name [source1] [source2] ...)
+
+```
+
+Where `executable_name` is used to specify the name of the executable file, and `source1`, `source2`, and other parameters are used to specify the names of source files. For example:
+
+```
+add_executable(MyProject main.cpp)
+
+```
+
+This command will set the executable file name to `MyProject` and add the `main.cpp` file as a source file to the project.
+
+### Other commonly used CMake commands
+
+### **`message`**
+
+The `message()` command is used to display messages in the CMake console during the build process. It can be used for debugging, testing, and other purposes. Its syntax is as follows:
+
+```
+message([] "message text" ...)
+
+```
+
+The `mode` parameter specifies the message type, which can be `STATUS`, `WARNING`, `AUTHOR_WARNING`, `SEND_ERROR`, `FATAL_ERROR`, or `DEPRECATION`. The `message text` parameter specifies the message to be displayed. For example:
+
+```
+message(STATUS "This is a status message.")
+message(WARNING "This is a warning message.")
+message(AUTHOR_WARNING "This is an author warning message.")
+message(SEND_ERROR "This is a send error message.")
+message(FATAL_ERROR "This is a fatal error message.")
+message(DEPRECATION "This is a deprecation message.")
+
+```
+
+The message type determines the text color and icon displayed in the CMake console. For example, `STATUS` messages are displayed in green, while `WARNING` messages are displayed in yellow with a warning icon. The `FATAL_ERROR` message will stop the build process and display an error message in the console.
+
+### `set`
+
+The `set()` command is mainly used to create or modify variables. The command accepts at least two arguments: the variable name and its value. For example, you can use `set(SRC_FILES main.cpp)` to set the value of the variable `SRC_FILES` to `main.cpp`. If you want to set multiple values (such as a list) for a variable, you can add more arguments to the command, like `set(SRC_FILES main.cpp util.cpp)`. To read the value of a variable, you can use the `${}` syntax, like `message(${SRC_FILES})`.
+
+You can use the `set` command to add elements to a list variable. Specifically, you can use the command `set(SRC_FILES ${SRC_FILES} util.cpp)` to add `util.cpp` to the end of the `SRC_FILES` list. `${SRC_FILES}` represents the current value of the `SRC_FILES` variable. This command can also use other `set` command options, such as `CACHE` and `APPEND`.
+
+### `list`
+
+The `list()` command is used for handling list-type variables. It can accept multiple subcommands, such as `APPEND` (adds an element to the end of the list), `INSERT` (inserts an element at a specified position), `REMOVE_ITEM` (removes a specified element), and so on. For example, the `list(APPEND SRC_FILES util.cpp)` command adds `util.cpp` to the end of the `SRC_FILES` list.
+
+### `add_library`
+
+The `add_library` command is used to define a library target. It requires at least two arguments: the name of the library and the source file. If you provide only one source file, CMake will create a library built from that file. For example, `add_library(MyLib main.cpp)`. If you have multiple source files, you can put them all in the `add_library()` command, like `add_library(MyLib main.cpp util.cpp)`.
+
+CMake supports creating static libraries and dynamic libraries. By default, the `add_library()` command creates a static library. If you want to create a dynamic library, you need to add the `SHARED` parameter to the command, like `add_library(MyLib SHARED main.cpp)`.
+
+If you want to create both static and dynamic libraries, you can list them both, like `add_library(MyLibStatic STATIC main.cpp)` and `add_library(MyLibShared SHARED main.cpp)`.
+
+A static library is a library linked to the executable file at compile time, while a dynamic library is a library loaded at runtime. Static libraries usually only contain the code needed by the executable file, so they are smaller. Dynamic libraries usually contain more code and data, as they need to be executed at runtime. The advantage of dynamic libraries is that they can be updated without recompiling the executable file. They can also be shared among multiple executable files, saving disk space.
+
+When using the `add_library()` command, you can specify the name and type (static or dynamic) of the library, as well as the source files and header files to include. For example, the `add_library(MyLib STATIC main.cpp)` command adds the `main.cpp` source file to the static library named `MyLib`.
+
+### `find_library`
+
+The command is used to locate library files on the system. You need to provide a variable name (to store the path of the found library) and the name of the library. For example, `find_library(MY_LIB NAMES MyLib)`. In this example, CMake will search for the library named `MyLib` in the system's library paths. If found, the value of the `MY_LIB` variable will be set to the full path of the library.
+
+You can use the `find_library` command to locate library files on the system. You need to provide a variable name (to store the path of the found library) and the name of the library.
+
+For example, suppose you want to locate a library named `libexample` that is in the `/usr/local/lib` directory. The absolute path can be converted to a relative path using variables such as `${CMAKE_CURRENT_LIST_DIR}`. You can add the following command to your `CMakeLists.txt` file:
+
+```
+find_library(EXAMPLE_LIB libexample /usr/local/lib)
+
+```
+
+This command will store the path of the `libexample` library in the `EXAMPLE_LIB` variable. If the library cannot be found, the value of the `EXAMPLE_LIB` variable will be empty.
+
+When using the `find_library` command, you can specify the name, path, version, and language of the library. For example, the command `find_library(EXAMPLE_LIB NAMES example PATHS /usr/local/lib VERSION 1.0 LANGUAGES CXX)` will locate a library named `example` with version `1.0` and written in the `C++` language, and store its path in the `EXAMPLE_LIB` variable.
+
+If you want to locate multiple libraries, you can add multiple library names to the command. For example, the command `find_library(LIB1 NAMES lib1 lib1.a PATHS /usr/local/lib)` will locate a library named `lib1` or `lib1.a`, and store its path in the `LIB1` variable.
+
+Note that when using the `find_library` command, you need to ensure that the name, path, version, and language of the library match your project. Otherwise, your project may not link to the library file correctly.
+
+### `target_link_libraries`
+
+The `target_link_libraries()` command is used to link specified libraries to a target. This command requires at least two arguments: the target name and the library name. For example, `target_link_libraries(MyApp MyLib)` will link the `MyLib` library to the `MyApp` target. This means that `MyApp` will use `MyLib` during the build process.
+
+### `target_include_directories`
+
+The `target_include_directories()` command is used to add include directories to a specified target. This command requires at least two arguments: the target name and the directory to be added. For example, `target_include_directories(MyApp PRIVATE include/)` will add the `include/` directory to the include directories of the `MyApp` target. This means that during compilation of `MyApp`, the compiler will search for header files in the `include/` directory.
+
+### `target_compile_options`
+
+The `target_compile_options()` command is used to set compilation options for a specified target. This command requires at least two arguments: the target name and the compilation option. For example, `target_compile_options(MyApp PRIVATE -Wall)` will add the `-Wall` option to the compilation options of `MyApp`. This means that `MyApp` will enable all warnings during compilation (which is the effect of the `-Wall` option).
+
+## Common Tasks
+
+### Adding Source Files
+
+You can use the following command to add source files:
+
+```
+add_executable(MyProject main.cpp math/vec3.cpp math/vec4.cpp)
+
+```
+
+In this example, the source files for `MyProject` include **`main.cpp`**, `math/vec3.cpp`, and `math/vec4.cpp`. If there are more source files, simply add them to this list.
+
+### Adding Dependency Libraries
+
+You can use the following command to add dependency libraries:
+
+```
+target_link_libraries(MyProject MyLibrary)
+
+```
+
+In the example below, the `find_library()` command searches for a static library named `libexample` in the `libs` directory and saves its path to the `LIBS` variable. The `target_link_libraries()` command links this library to the `MyProject` target.
+
+```
+find_library(LIBS libexample libs PATHS ${CMAKE_CURRENT_LIST_DIR}/libs/android/${ANDROID_ABI})
+
+add_executable(MyProject main.cpp)
+target_link_libraries(MyProject ${LIBS})
+
+# add include search path
+target_include_directories(MyProject PUBLIC ${CMAKE_CURRENT_LIST_DIR}/libs/include)
+```
+
+### CMake Variables
+
+CMake has some built-in variables starting with `CMAKE_` that are useful for interacting with the environment. Using these variables can make your CMakeLists.txt file more concise and easier to maintain. For example, the `CMAKE_CURRENT_LIST_DIR` variable is used to store the path of the directory where the currently processed CMakeLists.txt file is located. An example of using this variable in a CMakeLists.txt file is as follows:
+
+```
+add_library(MyLibrary STATIC ${CMAKE_CURRENT_LIST_DIR}/src/my_library.cpp)
+
+```
+
+In the above example, we use the `CMAKE_CURRENT_LIST_DIR` variable to specify the path of the source file. Similarly, the `CMAKE_BINARY_DIR` variable is used to store the path of the root directory of the binary files. An example of using this variable in a CMakeLists.txt file is as follows:
+
+```
+set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
+
+```
+
+Here, the CMAKE_BINARY_DIR variable is used to specify the root directory for executable file output. When compiling the project, the executable file will be output to the ${CMAKE_BINARY_DIR}/bin directory.
+
+Note the difference between the `${CMAKE_BINARY_DIR}` and `${CMAKE_CURRENT_BINARY_DIR}` variables. `${CMAKE_BINARY_DIR}` refers to the root directory of the binary files, while `${CMAKE_CURRENT_BINARY_DIR}` refers to the binary directory of the currently processed CMakeLists.txt file.
+
+Additionally, other commonly used variables include but are not limited to:
+
+- CMAKE_SOURCE_DIR: The directory where the CMakeLists.txt file is located
+- CMAKE_CURRENT_SOURCE_DIR: The directory where the currently processed CMakeLists.txt file is located
+- CMAKE_BINARY_DIR: The root directory of the binary files
+- CMAKE_CURRENT_BINARY_DIR: The binary directory of the currently processed CMakeLists.txt file
+- CMAKE_INSTALL_PREFIX: The root directory of the installation path
+- CMAKE_MODULE_PATH: The root directory of the CMake modules
+- CMAKE_BUILD_TYPE: The build type
+- CMAKE_CXX_FLAGS: C++ compiler options
+
+## Using CMake in Cocos
+
+CMake is natively supported in Android for compiling C++ code. We use Gradle to configure parameters and call CMake commands to generate, compile, and package C++ code. For other native platforms, we use build plugins to call the corresponding CMake commands to generate project files, such as Visual Studio projects on Windows and Xcode projects on Mac. Subsequent development can be completed through the IDE.
+
+Due to the nature of CMake, there may be differences due to different development environments and configurations, so it is not recommended to share generated project files. In addition, modifications to the generated project can be easily overwritten by subsequent generated projects. Instead, the CMakeLists.txt file should be included in the project, and CMake should be used in each development environment to generate the corresponding project files. All modifications to the project should be written in CMake instructions in CMakeLists.txt.
+
+When using CMake and Xcode cocoapods, some issues may arise. The main issue is that the Xcode project files generated by CMake are incompatible with cocoapods integration. This is because cocoapods uses its way of managing Xcode project files, and the generated project files by CMake do not consider this. This can cause problems such as compilation errors, link errors, and overwritten modifications.
+
+To solve this problem, we can select the "Skip Xcode Project Update" option when building for Mac/iOS platforms. This means that subsequent CMake configuration updates for the engine or project will not be synchronized to the Xcode project. After selecting this option, we can collaborate with CocoaPods and build in a regular Xcode project format.
+
+### Share Generated Xcode Project Files
+
+The Xcode project generated by CMake records dependency paths from the following sources:
+
+- The installation path of Xcode
+- The version and installation path of Cocos Creator
+- The version and installation path of the project
+- The path where the project file is located
+
+By using the same directory structure on different devices, Xcode can achieve sharing between different devices.
+
+Another approach is to modify the paths referenced internally in the Xcode project file, which is a more hacky method and will not be discussed in detail here.
+
+In contrast to Xcode, Android Studio compiles CMakeLists.txt directly as the configuration file instead of generating project files. Therefore, the native library generated by CMake for the Android platform should behave consistently on different devices. In addition, the Gradle plugin of Android Studio automatically handles dependency relationships, so there is no need to manually manage dependency directories like in Xcode.
+
+
+### Directory structure
+
+When selecting a native platform to build on, the `native\engine` directory will generate a `current build platform name` folder (e.g.: `android`) and a `common` folder, and CMake will generate `CMakeLists.txt` files in each of these two directories when it is first run, with which serve different purposes:
+
+- In the `current build platform name` folder: `CMakeLists.txt` is mainly used to configure the corresponding build platform. For the Android platform, for example:
+
+ 
+
+- In the `common` folder: `CMakeLists.txt` is mainly used to configure the whole project.
+
+ 
+
+The syntax of `CMakeLists.txt` is relatively simple, consisting of **commands**, **comments** and **spaces**. The commands are case-insensitive, but the parameters and variables in the commands are case-sensitive.
+
+### CMakeLists.txt comments
+
+How to use CMake to compile a project into a dynamic library for other projects? Simply put, enter the compilation information first, and then the CMake command generates the Makefile file needed for compilation according to the configuration in `CMakeLists.txt`.
+
+Taking the Android platform as an example and see how to configure `CMakeLists.txt` in the project directory `native/engine/android`.
+
+```CMake
+# Require CMake version 3.8 or higher
+cmake_minimum_required(VERSION 3.8)
+
+# Set project name option
+option(APP_NAME "Project name" "NewProject")
+
+# Set project name and enable C++
+project(${APP_NAME} CXX)
+
+# Set library name
+set(CC_LIB_NAME cocos)
+
+# Set project directory
+set(CC_PROJECT_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+# Set project source files
+set(CC_PROJ_SOURCES)
+
+# Set common source files
+set(CC_COMMON_SOURCES)
+
+# Set all source files
+set(CC_ALL_SOURCES)
+
+# Include common CMake functions
+include(${CC_PROJECT_DIR}/../common/CMakeLists.txt)
+
+# If you need to add source code, you can modify CC_PROJ_SOURCES here
+
+# Call Android pre-build steps
+cc_android_before_target(${CC_LIB_NAME})
+
+# Add library
+add_library(${CC_LIB_NAME} SHARED ${CC_ALL_SOURCES})
+
+# Call Android post-build steps
+cc_android_after_target(${CC_LIB_NAME})
+```
+
+The `CMakeLists.txt` file in the project directory `native/engine/common` is configured in the same way but with some more basic configuration. For example:
+
+```CMake
+option(USE_SPINE "Enable Spine" ON)
+```
+
+The release package directory generated after the build (e.g.: `build/android`) has a `proj/cfg.cmake` file to store some configuration for the current project. Since `CMakeLists.txt` introduces the `cfg.cmake` file, when the configuration in the `cfg.cmake` file is modified, it will be synchronized to `CMakeLists.txt`; if the configuration is the same, it will be overwritten directly, and the one in the `cfg.cmake` file will prevail.
+
+Starting from 3.6.2, developers can override the options written in `cfg.cmake` through `native/engine/common/localCfg.cmake`, and the file `localCfg.cmake` will be ignored from the GIT.
+
+```CMake
+CMakeLists.txt
+
+# Introduce cfg.cmake
+include(${RES_DIR}/proj/cfg.CMake)
+```
+
+For example, uncheck **Spine Animation** in the editor's main menu **Project -> Project Settings -> Feature Cropping**.
+
+
+
+Then `USE_SPINE` will be set to `OFF` in the re-generated `cfg.make` when building again:
+
+
+
+Then at compile time, CMake generates a **CMakeCache.txt** file based on the configuration (e.g.: `CMakeLists.txt` and the `cfg.make` configuration file introduced in `CMakeLists.txt`), which contains the **various input parameters that the project needs to rely on** when building.
+
+
+
+### **Further Learning**
+
+You can refer to the following resources for further learning: [CMake Official Documentation](https://cmake.org/documentation/)
diff --git a/versions/4.0/en/advanced-topics/data-storage.md b/versions/4.0/en/advanced-topics/data-storage.md
new file mode 100644
index 0000000000..2f76a5ecc9
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/data-storage.md
@@ -0,0 +1,78 @@
+# User Data Storage
+
+We will have a lot of user data to store to the disk, such as music toggle and language preferences. If it's an offline game you will also need to store game progress locally. In Cocos Creator we use `cc.sys.localStorage` API to save and read user data.
+
+`cc.sys.localStorage` API is quite similar to [Web Storage API](http://devdocs.io/dom/storage). When running on Web platform it will call Web Storage API directly, on native platform it will use sqlite to save and read data on disk.
+
+There's an example project you can see data storage API work in action: [Tutorial Data Storage](https://github.com/cocos-creator/tutorial-storage).
+
+## Save data
+
+`cc.sys.localStorage.setItem(key, value)`
+
+This method requires 2 parameter:
+- `key` is the key you use to index the data.
+- `value` is the data itself.
+
+If we want to store the how much gold player owns, we use `gold` as the key:
+
+`cc.sys.localStorage.setItem('gold', 100);`
+
+For complex data as object, we can first serialize it to JSON:
+
+```js
+userData = {
+ name: 'Tracer',
+ level: 1,
+ gold: 100
+};
+
+cc.sys.localStorage.setItem('userData', JSON.stringify(userData));
+```
+
+## Read data
+
+`cc.sys.localStorage.getItem(key)`
+
+`getItem` method only needs one parameter: the key. Continue with above example:
+
+```js
+var userData = JSON.parse(cc.sys.localStorage.getItem('userData'));
+```
+
+## Clear data
+
+Data can be cleared from storage when it is no longer needed:
+
+`cc.sys.localStorage.clear()`
+
+## Remove key-value pair
+
+We can remove a key-value data from the storage when we don't need it anymore:
+
+`cc.sys.localStorage.removeItem(key)`
+
+## Encryption
+
+For single player game, apply encryption to user profile data can make it harder to hack your game. You can import any third party encryption library and use it to encrypt your data before using `setItem`.
+
+Let's take [encryptjs](https://www.npmjs.com/package/encryptjs) as example, put the library file into your project. To save data:
+
+```js
+var encrypt=require('encryptjs');
+var secretkey= 'open_sesame'; // you can specify the key for encryption, beware for web game it's visible on client side!
+
+var dataString = JSON.stringify(userData);
+var encrypted = encrypt.encrypt(dataString,secretkey,256);
+
+cc.sys.localStorage.setItem('userData', encrypted);
+```
+
+To load data:
+
+```js
+var cipherText = cc.sys.localStorage.getItem('userData');
+var userData=JSON.parse(encrypt.decrypt(cipherText,secretkey,256));
+```
+
+> **Note**: data encryption cannot guarantee the safety of user profile data. If you want to make sure it's not hackable please load and save data with a secured server.
diff --git a/versions/4.0/en/advanced-topics/dynamic-atlas.md b/versions/4.0/en/advanced-topics/dynamic-atlas.md
new file mode 100644
index 0000000000..e191d74e85
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/dynamic-atlas.md
@@ -0,0 +1,37 @@
+# Dynamic Atlas
+
+Reducing the number of DrawCalls is a very direct and effective way to improve game rendering efficiency. One of the most important factors for two DrawCalls to be merged into one is whether both DrawCalls use the same texture.
+
+Cocos Creator provides **Dynamic Atlas**, which dynamically merges the textures into one large texture at project runtime. When a map is rendered, the Dynamic Atlas system automatically detects if the map has been merged into an atlas (collection of images). If not, the system merges the texture into the atlas if it meets the conditions for dynamic atlas.
+
+Dynamic atlas selects which textures are merged into a larger image in **rendering order**, which ensures that adjacent DrawCalls are merged into a single DrawCall (aka "batching").
+
+## Enable and Disable Dynamic Atlas
+
+During initialization, Cocos Creator sets different [CLEANUP_IMAGE_CACHE](%__APIDOC__%/en/interface/Macro?id=CLEANUP_IMAGE_CACHE) parameter for different platforms, and when `CLEANUP_IMAGE_CACHE` is disabled, dynamic atlas will be enabled by default.
+Enabling dynamic atlas will take up extra memory, and the size of the memory used varies by platform. It is currently disabled by default on mini games and native platforms, but it is recommended to turn it on if your project still has room in memory.
+
+**If you want to force dynamic atlas to be enabled**, please add the following code to your code:
+
+```ts
+macro.CLEANUP_IMAGE_CACHE = false;
+DynamicAtlasManager.instance.enabled = true;
+```
+
+> **Note**: write the code above in the outermost part of the project script, not in the `onLoad`/`start` class functions, to ensure that they take effect instantly during the project loading process. Otherwise, it may cause an error if the dynamic atlas is enabled only when part of the texture cache has been released.
+
+**To forcibly disable dynamic atlas**, control it directly by code:
+
+```ts
+dynamicAtlasManager.enabled = false;
+```
+
+## Texture Restrictions
+
+The dynamic atlas system limits the size of the texture that can be merged. By default, only textures with a width and height less than **512** can be entered into the dynamic atlas system. This limit can be modified by the developer as required with the following code.
+
+```ts
+dynamicAtlasManager.maxFrameSize = 512;
+```
+
+For details, look up `DynamicAtlasManager` in the [API documentation](%__APIDOC__%/en/).
diff --git a/versions/4.0/en/advanced-topics/engine-customization.md b/versions/4.0/en/advanced-topics/engine-customization.md
new file mode 100644
index 0000000000..4cece5090f
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/engine-customization.md
@@ -0,0 +1,203 @@
+# Engine Customization Workflow
+
+Cocos Creator has two engine kernels: C++ kernel and TypeScript kernel. The C++ kernel is used for native platforms, while the TypeScript kernel is used for web and mini-game platforms. On top of the engine kernels is the engine framework layer written in TypeScript, which aims to unify the differences between the two kernels and make development more convenient.
+
+
+
+## Getting the Engine Source Code
+
+
+
+### 1. Accessing the Cocos Engine Repository
+
+Cocos is an open-source engine, and you can obtain different versions of the engine source code from the official Cocos Engine repository. The repository links are as follows:
+
+- cocos/cocos-engine:[GitHub](https://github.com/cocos/cocos4/)
+
+Open the repository homepage, and you will see the content shown in the left sub-figure of the above image. You can decide which version to use based on your requirements.
+
+### 2. Selecting a Branch
+
+If you want to use the latest branch, select the "develop" branch as shown in the middle sub-figure of the image.
+
+>**Note:** This branch is the latest in-developing branch and may not guarantee stability.
+
+### Selecting a Tag
+
+If you want to use a tag (a stable branch) corresponding to a specific version of Cocos Creator, follow the steps shown in the right sub-figure of the image. Switch to the "Tags" tab and select the desired version. For example, if you are using Cocos Creator 3.7.3, select version 3.7.3.
+
+>**Note:** Different versions of Cocos Creator require corresponding engine branches or tags. Make sure the versions match.
+
+### 3. Clone/Download
+
+
+
+As shown in the image above, after selecting the appropriate branch or tag, you will be in the corresponding repository (1).
+
+Click on the "Code" button on the right (2) to open the code-getting panel.
+
+You can either copy the repository link (3) and clone it to local using Git, or choose **Download ZIP**(4) to download the source code as a ZIP file and extract it in your disk.
+
+>Don't forget to give a star to the Cocos Engine repository in the top right corner (5). Thank you!
+
+## Configuring Development Environment
+
+### 1. Placing the Engine Source Code in a Specified Directory
+
+Obtain the specific version of cocos-engine source code from the Cocos Engine repository according to your project's needs and place it in a suitable directory.
+
+- If the custom engine is only used for a specific project, it is recommended to put it in the project directory.
+- If multiple projects will share the same custom engine, place it in a suitable shared directory based on your project management approach.
+
+### 2. Downloading external
+
+The compilation of the Cocos native engine depends on the libraries in `cocos-engine/native/external/`. These libraries are several hundred megabytes in size and are not included by default in the source code package. You can obtain them in the following three ways:
+
+**The First Way:** Use git command-line
+
+```ts
+ cd cocos-engine/native
+ git clone https://github.com/cocos/cocos-engine-external external
+ cd external
+ git checkout -b branch_name tag
+```
+
+- branch_name:The new branch name
+- tag:The tag name corresponding to the third-party library. You can get it from the `checkout` field in `cocos-engine/native/external-config.json` file.
+
+> Example: If we want to use version 3.7.1-1, it can be written as `git checkout -b 3.7.3-1 3.7.3-1`
+
+**The Second Way:** Use gulp
+
+The following shell will only download the third-party libraries corresponding to the specific tag.
+
+```ts
+ cd cocos-engine/native
+ npm install
+ gulp init
+```
+
+> Whenever the used tag changes, you need to download it again. It requires downloading several hundred megabytes of content each time.
+
+**The Third Way:** Download the ZIP package
+
+If, for some reason, you cannot download the `external` source code package using `NodeJS` and `git commands`, you can directly download it from the [cocos-engine-external repository](https://github.com/cocos/cocos-engine-external) by following these steps.
+
+
+
+1. Select the corresponding tag. You can check which one to use from the `checkout` field of `cocos-engine/native/external-config.json`.
+2. Click the **Code** button on the right to open the code-getting panel.
+3. Click the **Download ZIP** button to download the source code as a ZIP package.
+4. Exact the package, rename it to `external`, and place it in the `cocos-engine/native` folder.
+
+> **Note:** The version of `external` and `cocos-engine` must match, otherwise, it may result in compilation errors.
+
+### 3. Installing Compilation Dependencies
+
+The compilation dependencies require `NodeJS`. Make sure you have installed `NodeJS v12.0` or above on your computer. If not, please download and install it from [https://nodejs.org/](https://nodejs.org/).
+
+After installation, navigate to the root directory of the custom engine and execute the following commands:
+
+```bash
+# Install gulp
+npm install -g gulp
+# Install the required modules
+npm install
+```
+
+### 4. Modifying the Engine Path
+
+Use the **Cocos Creator/File -> Preferences -> Engine Manager** tab to set the path to the engine source code. Note that **you need to restart the editor after modifying the engine path**.
+
+
+
+#### Specifying the TypeScript Engine
+
+By default, the `Use Built-in` option is selected, indicating that the built-in engine of Cocos Creator is being used. To use the custom engine, switch to the `Use Custom` tab and specify the path to the engine source code root directory.
+
+#### Specifying the Native(C++)Engine
+
+If you need to customize the engine functionality related to native platforms, you also need to check the `Use Custom` option under `Native Module`. It will automatically recognize the `native` folder under the custom engine's root directory as the path, which cannot be changed.
+
+#### Modifying the Storage Location
+
+
+
+By default, modifications to the engine path are saved as global configurations, which will affect all projects using the current version of Cocos Creator.
+
+Hover your mouse over the "Cocos Engine" text, and a settings button will appear in front of the text. Click on the button to select a storage location.
+
+#### Relaunching Cocos Creator
+
+After modifying the engine path, you need to restart Cocos Creator editor for the changes to take effect. You can either close Cocos Creator and open it again or click on the Relaunch button on the panel.
+
+**Note:** Once the custom engine is in working, the scene editor in Cocos Creator will also use the custom engine for rendering. By default, it uses the TypeScript kernel. If you want the editor to use the native engine for rendering as well, you need to enable the `Use native engine for scene editor` option in the **Preferences -> Laboratory** panel.
+
+
+
+## Modifying the TypeScript Engine
+
+If you only need to customize the engine functionality for web and mini-game platforms or modify the TypeScript modules of the engine (such as the UI system, animation system, etc.), you only need to compile the engine by clicking **Developer -> Compile the Engine** on the menu bar of Cocos Creator.
+
+
+
+This command will generate a bin folder under the engine directory and compile the engine source code there.
+
+## Modifying the Native (C++) Engine
+
+If you need to customize the engine functionality related to native platforms, in addition to modifying the TypeScript code, you may also need to modify the C++ code.
+
+To ensure that the native code can be compiled properly, make sure that the `Use Custom` option in the `Native Module` is selected.
+
+### Compiling in Cocos Creator
+
+After modifying the engine, open the **Build** panel, click **Build**, and after the build is complete, click **Make** to Compile.
+
+### Compiling in an IDE
+
+After configuring the custom engine path for the first time, you need to click the `Build` button in the **Build** panel to synchronize the relevant configuration to your IDE (such as Xcode, Android Studio, Visual Studio, etc.).
+
+The engine code used by the IDE project will then reference to the custom engine.
+
+From now on, each time when you modify the native engine code, you can compile it using IDE directly.
+
+## Rebuild the Native Engine Simulator
+
+Cocos Creator provides a feature to preview in a simulator based on the native engine.
+
+
+
+### Modified TypeScript Engine
+
+If you are using custom TypeScript engine, the native simulator will attempt to load the TS engine modules under `custom-engine-path/native/simulator/`.
+
+The first time you launch the simulator in this situation, you need to click **Developer-> Rebuild Native Simulator Engine** in the top menu bar, otherwise, the TS engine modules will not be loaded successfully.
+
+### Modified Native(C++) Engine
+
+If you have selected to use a custom native engine, Cocos Creator will launch the simulator located at `custom-engine-path/native/simulator/` when previewing in simulator.
+
+To avoid a large installation package, Cocos Creator excludes the native simulator project before publishing. Therefore, you need to follow these steps to configure the environment and rebuild it,otherwise, the simulator won't start.
+
+### Installing and Configuring CMake
+
+>Cocos Creator comes with its own CMake and has configured the paths, so you don't need to do additional configuration when building, compiling, and publishing your project.
+
+The compilation of the native simulator is not part of the build process, so you need to configure the CMake environment yourself.
+
+Since there are so many differences among different system, platforms, and versions, please refer to the [CMake official website](https://cmake.org/install/) for installing CMake and configuring the system environment variables.
+
+### Compilation
+
+After configuring `CMake`, navigate to the `custom-engine-path/native/` folder and execute the following commands.
+
+```bash
+# Install the required modules
+npm install
+# compile and generate native simulator
+gulp gen-simulator
+```
+
+After the compilation is complete, a simulator project and an executable application will be generated under the `custom-engine-path/native/simulator/` directory. You can then run the **Preview in Simulator**.
+
+Once the native simulator is successfully compiled and generated, if you only make changes to the TypeScript part, you only need to click **Developer->Rebuild the Native Simulator Engine** to make it in effect.
diff --git a/versions/4.0/en/advanced-topics/engine-customization/bin.png b/versions/4.0/en/advanced-topics/engine-customization/bin.png
new file mode 100644
index 0000000000..d459f2b6bb
Binary files /dev/null and b/versions/4.0/en/advanced-topics/engine-customization/bin.png differ
diff --git a/versions/4.0/en/advanced-topics/engine-customization/build-ts-engine.png b/versions/4.0/en/advanced-topics/engine-customization/build-ts-engine.png
new file mode 100644
index 0000000000..3877879b96
Binary files /dev/null and b/versions/4.0/en/advanced-topics/engine-customization/build-ts-engine.png differ
diff --git a/versions/4.0/en/advanced-topics/engine-customization/build.png b/versions/4.0/en/advanced-topics/engine-customization/build.png
new file mode 100644
index 0000000000..0a4673d45a
Binary files /dev/null and b/versions/4.0/en/advanced-topics/engine-customization/build.png differ
diff --git a/versions/4.0/en/advanced-topics/engine-customization/custom-engine-store-path.png b/versions/4.0/en/advanced-topics/engine-customization/custom-engine-store-path.png
new file mode 100644
index 0000000000..65665bef5f
Binary files /dev/null and b/versions/4.0/en/advanced-topics/engine-customization/custom-engine-store-path.png differ
diff --git a/versions/4.0/en/advanced-topics/engine-customization/custom-engine.png b/versions/4.0/en/advanced-topics/engine-customization/custom-engine.png
new file mode 100644
index 0000000000..ae880a4455
Binary files /dev/null and b/versions/4.0/en/advanced-topics/engine-customization/custom-engine.png differ
diff --git a/versions/4.0/en/advanced-topics/engine-customization/custom-native-engine.png b/versions/4.0/en/advanced-topics/engine-customization/custom-native-engine.png
new file mode 100644
index 0000000000..7ed3f1de28
Binary files /dev/null and b/versions/4.0/en/advanced-topics/engine-customization/custom-native-engine.png differ
diff --git a/versions/4.0/en/advanced-topics/engine-customization/custom-native-simulator.png b/versions/4.0/en/advanced-topics/engine-customization/custom-native-simulator.png
new file mode 100644
index 0000000000..b9e6adf35a
Binary files /dev/null and b/versions/4.0/en/advanced-topics/engine-customization/custom-native-simulator.png differ
diff --git a/versions/4.0/en/advanced-topics/engine-customization/custom-ts-engine.png b/versions/4.0/en/advanced-topics/engine-customization/custom-ts-engine.png
new file mode 100644
index 0000000000..7ed3f1de28
Binary files /dev/null and b/versions/4.0/en/advanced-topics/engine-customization/custom-ts-engine.png differ
diff --git a/versions/4.0/en/advanced-topics/engine-customization/download-external-zip.png b/versions/4.0/en/advanced-topics/engine-customization/download-external-zip.png
new file mode 100644
index 0000000000..2f9b226387
Binary files /dev/null and b/versions/4.0/en/advanced-topics/engine-customization/download-external-zip.png differ
diff --git a/versions/4.0/en/advanced-topics/engine-customization/download-repo-js.png b/versions/4.0/en/advanced-topics/engine-customization/download-repo-js.png
new file mode 100644
index 0000000000..e5338fbfad
Binary files /dev/null and b/versions/4.0/en/advanced-topics/engine-customization/download-repo-js.png differ
diff --git a/versions/4.0/en/advanced-topics/engine-customization/download-repo.png b/versions/4.0/en/advanced-topics/engine-customization/download-repo.png
new file mode 100644
index 0000000000..e7758ca928
Binary files /dev/null and b/versions/4.0/en/advanced-topics/engine-customization/download-repo.png differ
diff --git a/versions/4.0/en/advanced-topics/engine-customization/engine-core-architecture.png b/versions/4.0/en/advanced-topics/engine-customization/engine-core-architecture.png
new file mode 100644
index 0000000000..74fe96434f
Binary files /dev/null and b/versions/4.0/en/advanced-topics/engine-customization/engine-core-architecture.png differ
diff --git a/versions/4.0/en/advanced-topics/engine-customization/open-engine.png b/versions/4.0/en/advanced-topics/engine-customization/open-engine.png
new file mode 100644
index 0000000000..8f9e2c038b
Binary files /dev/null and b/versions/4.0/en/advanced-topics/engine-customization/open-engine.png differ
diff --git a/versions/4.0/en/advanced-topics/engine-customization/select-repo.png b/versions/4.0/en/advanced-topics/engine-customization/select-repo.png
new file mode 100644
index 0000000000..38559e4130
Binary files /dev/null and b/versions/4.0/en/advanced-topics/engine-customization/select-repo.png differ
diff --git a/versions/4.0/en/advanced-topics/engine-customization/use-native-engine-for-editor.png b/versions/4.0/en/advanced-topics/engine-customization/use-native-engine-for-editor.png
new file mode 100644
index 0000000000..124cc9aa80
Binary files /dev/null and b/versions/4.0/en/advanced-topics/engine-customization/use-native-engine-for-editor.png differ
diff --git a/versions/4.0/en/advanced-topics/hot-update-manager.md b/versions/4.0/en/advanced-topics/hot-update-manager.md
new file mode 100644
index 0000000000..3c99ef785c
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/hot-update-manager.md
@@ -0,0 +1,243 @@
+# Hot Update AssetsManager
+
+This document will fully cover the `AssetsManager` module for hot update, includes technical details and usage. As the requirements of the hot update process for developers may be different, and each developer may also face different problems. Developers need to fully understand the details of the hot update mechanism to be able to customize the workflow to meet their needs.
+
+This document is relatively long, it tries to introduce the hot update mechanism gradually, but will not introduce too much user level code. First, understand how to use the hot update mechanism to update a game, try the [simple tutorial](hot-update.md) example to get started.
+
+## Design goals and basic principles
+
+The hot update mechanism essentially downloads the required assets from the server to the client, and can execute new game logic so that new assets can be used by the game. This means two of the most central goals are: to download new assets, overwrite game logic and assets. At the same time, since the hot update mechanism was originally designed in Cocos2d-JS, we considered what kind of hot update mechanism was more suitable for Cocos's JavaScript user base. Finally, we decided to use a mechanic similar to how Web page update its content to update the game content. Let's take a look at the Web content update mechanic:
+
+1. The server has complete files of all the page content
+2. The browser requests a web page to cache its content locally
+3. When the browser re-request this page, it will query the version on server version by the last modified time (Last-Modified) or unique identification (Etag). If these two value are different, then download a new file to update the local cache, if not, continue to use the cache.
+
+The browser cache mechanism is more complex than the above description, but we can use similar basic idea. For game assets, it is possible to keep a copy of complete assets on the asset server. The client compare the version list with the server during updates, and download the different files and replace the cache. For the rest continues to use the client version or the cached file. So here's what we need to update the game:
+
+1. The server keeps the latest version of all the game assets (the developer can update the server at any time)
+2. The client sends request to get the asset different file list compare to server version
+3. Download all assets changed in the new version from the server
+4. Overwrite the old cache with the new assets and the files in the application package
+
+This is the whole hot update process. Of course, there are very many specific details we will introduce later. What the take away here is:
+
+**Cocos default hot update mechanism is not based on the patch update mechanism, the traditional hot update is often generate patches between multiple version of packages. Client need to download patches one by one according to the order of versions. Cocos's hot update mechanism generates a list of differences by updating the differences between the latest remote version and current local version directly.**
+
+This can naturally support cross-version update, such as the local version is A, remote version is C, then directly update the difference between A and C, do not need to generate A to B and B to C update patches. Therefore, in this design, we can upload new version of the game files separately to the server.
+
+## Hot update basic workflow
+
+After understanding the basic design above, take a look at a typical hot update process. Use the manifest description file to describe the asset file list and asset version that is stored locally or remotely. The manifest file definition is described later. The runtime environment assumes that the installer version is updated for the first time after the user has installed the app:
+
+
+
+The figure is divided into three parts, the middle is the hot update process, the left is the process of updating the AssetsManager to send the message to the user, the right is the middle output of each step. The bold words indicates the location of the middle output, such as in memory / temporary folder / cache folder.
+
+After reading this picture you may have a lot of questions. We will discuss details of the various steps that need to pay attention to or not easy to understand in the first place.
+
+## Technical details
+
+### Manifest format
+
+The manifest file is a json format that we use to compare local and remote asset differences, including master version information, engine version information, asset file lists, and asset information:
+
+```
+{
+ "packageUrl": The local cache root path of the remote asset
+ "remoteVersionUrl": [optional] the path of the remote version of the file used to determine whether the server has a new version of the assets
+ "remoteManifestUrl": Path of the remote asset manifest file, including version information and all asset information
+ "version": the version of the asset
+ "engineVersion": engine version
+ "assets": all asset lists
+ "key": the relative path of the asset (relative to the asset root)
+ "md5": The md5 hash represents the version information of the asset file
+ "compressed": [optional] If the value is true, the file is automatically downloaded after being extracted, currently only supports zip compression format
+ "size": [optional] The byte size of the file used to quickly get progress information
+ "searchPaths": A list of search paths that need to be added to FileUtils
+}
+```
+
+The manifest files can be generated by using the [Version generator script](https://github.com/cocos-creator/tutorial-hot-update/blob/master/version_generator.js) in the hot update example.
+
+It is important to note that the remote information (including `packageUrl`, `remoteVersionUrl`, `remoteManifestUrl`) is for the remote package. That is, the `manifest` only takes effect when installed or downloaded with a local package. It is possible to also update the remote package url during version update. In addition, `md5` key is only for file identification, it is necessary, use other algorithm or rule to generate the file identification, such as modified date. When client compare `manifest` with the remote version, as long as the md5 information is different, we think this file has changed.
+
+### The difference between the assets in the project and the published package
+
+Everyone in the creation of a Cocos Creator project, you can see it catalog under the assets of the catalog, which saved your scenes, scripts, prefab, etc., corresponding to the editor in the assets of the panel. But these engineering assets are not the same as the packaged assets, in the use of building a building to build the original version, we will find the directory to find res and src folder, these two folders are saved really let the game run up Of the game package within the assets. Where src contains all the scripts, res contains all the assets.
+
+The asset hot update should naturally update the built assets, not the project's assets directory.
+
+### Package assets, local cache assets and temporary assets
+
+When the player's game is installed on the user's phone, its game is in the form of `.ipa` (iOS) or `.apk` (Android), which, after installation, can not be modified or added Of any assets within the application package will always exist. So the hot update mechanism, we can only update the local cache to the phone's writable directory (application storage space or SD card specified directory), and through the FileUtils search path mechanism to complete the local cache on the package of assets coverage. At the same time in order to protect the reliability of the update, we will update the process will first put the new version of the assets into a temporary folder, only when the update is completed, will be replaced to the local cache folder. If the midrange interrupt update or update fails, the failed version will not pollute the existing local cache. This step is described in detail in the previous section of the flow chart:
+
+
+
+In the case of long-term updates, the local cache will always be replaced with the latest version, and the application package only until the user in the application store to update to the new version will be modified.
+
+### Progress information
+
+In the previous section of the flow chart, you can see the hot update manager has sent `UPDATE_PROGRESSION` message to the user. In the current version, the progress information received by the user contains:
+
+1. byte-level progress (percentage)
+2. File level progress (percentage)
+3. The number of bytes received
+4. The total number of bytes
+5. The number of files received
+6. The total number of documents
+
+```js
+function updateCb (event) {
+ switch (event.getEventCode ())
+ {
+ case native.EventAssetsManager.UPDATE_PROGRESSION:
+ log("Byte progression : " + event.getPercent() / 100);
+ log("File progression : " + event.getPercentByFile() / 100);
+ log("Total files : " + event.getTotalFiles());
+ log("Downloaded files : " + event.getDownloadedFiles());
+ log("Total bytes : " + event.getTotalBytes());
+ log("Downloaded bytes : " + event.getDownloadedBytes());
+ break;
+ }
+}
+```
+
+### Resume broken transfer
+
+Definitely a developer will ask, if the process of updating the network will be how? The answer is that the hot update manager supports resume broken transfer, and also supports file-level and byte-level breakpoints.
+
+So what exactly is it done? First of all, we use the manifest file to identify the status of each asset, such as not started, download, download success, in the hot update process, the file download will be identified to the memory of the manifest, when the number of files to download each The progress node (defaults to **10%** of a node) will serialize manifest in memory and save it to a temporary folder. The concrete steps are shown in the flowcharts of the multi-threaded concurrent download asset section:
+
+
+
+After the interruption, start the hot update process again, it will check whether there is an outstanding update in the temporary folder. After checking the version and the remote match, use the manifest in the temporary folder to continue the update as the Remote manifest. At this point, for the download status is completed, will not re-download, for the downloaded file, will try to send a request to the server (the server needs to support `Accept-Ranges`, or start from scratch).
+
+### Control concurrency
+
+Hot update manager provide control to download the number of concurrent API, the use of the following:
+
+```js
+assetsManager.setMaxConcurrentTask(10);
+```
+
+### Version comparison function
+
+A very important step in the hot update process is to compare the client and server versions, by default only when the primary version of the server is updated over the client major version. The engine implements a version of the comparison function, support the x.x.x.x four sequence versions of the comparison function (x is a pure number), do not conform to this version number mode will continue to use the string comparison function.
+
+In addition, we also allow users to use their own version of the contrast:
+
+```js
+// both versionA and versionB are string types.
+assetsManager.setVersionCompareHandle(function (versionA, versionB) {
+ var sub = parseFloat(versionA) - parseFloat(versionB);
+ // When the return value is greater than 0, versionA > versionB.
+ // When the return value is equal to 0, versionA = versionB
+ // When the return value is less then 0, versionA < versionB
+ return sub;
+});
+```
+
+### Verify file after downloaded
+
+During the download process, problems with the downloaded file contents may occur due to network problem or other network libraries. So we provide the user file verification interface, which is called by the Assets Manager after the file is downloaded (in the case of user implementation). If returning `true` indicates that the file is OK, returning `false` indicates that there is a problem with the file.
+
+```js
+assetsManager.setVerifyCallback(function (filePath, asset) {
+ var md5 = calculateMD5(filePath);
+ if (md5 === asset.md5)
+ return true;
+ else
+ return false;
+});
+```
+
+The asset version in manifest is recommended to use md5. You can determine whether the file is correct by calculating the md5 code of the downloaded file in the verify function and comparing it with the md5 of the asset. In addition to md5, the asset object also contains the following properties:
+
+| Property | Function Explanation |
+| :---- | :---- |
+| path | The relative path of the server side |
+| compressed | Whether it is compressed |
+| size | File state |
+| downloadState | Download size, includes `UNSTARTED`, `DOWNLOADING`, `SUCCESSED`, `UNMARKED` |
+
+### Error message handling and download retry
+
+In the left side of the flowchart, you can see a number of user messages that can be notified through the event listener of the Assets Manager. For details, you can refer to the [example](https://github.com/cocos-creator/tutorial-hot-update/blob/master/assets/hotupdate/HotUpdate.ts). The flowchart identifies the trigger and cause of all error messages, and you can handle them according to your system design.
+
+The most important thing is that when an exception occurs during the download process, such as a failed download, a failed decompression, or a failed verification, the `UPDATE_FAILED` event will be triggered. And a list of all assets that failed to download will be recorded in the Assets Manager and can be downloaded again as follows:
+
+```js
+assetsManager.downloadFailedAssets();
+```
+
+When the interface is called, it will restart the hot update process and only download the assets failed before. The entire process is the same as the normal hot update process.
+
+### The necessity of restart
+
+If you want to use hot updated assets, you need to restart the game.
+
+There are two reasons, the first is that the updated script requires a clean JS environment. The second is the assets configuration that used by `AssetManager` needs to be updated to the latest to load the scene and assets properly.
+
+1. Refresh of JS script
+
+ Before the hot update, all the scripts in the game have been executed, and all the classes, components, objects have already been stored in JS context. So if you load the script directly after the hot update without restarting the game, the classes and objects of the same name will be overwritten, but the objects created by the old scripts will still exist. Further, as a result of the overwriting, their dynamic state is also reset, causing the two versions of the objects to mix together, which comes with an overhead of memory usage.
+
+2. Refresh of asset configuration
+
+ Creator's scenes and assets depend on the [Asset Bundle](../asset/bundle.md). That is, the game will not be able to load the new scenes and assets without the Asset Bundle being reloaded and parsed by [Asset Manager](../asset/asset-manager.md).
+
+Enabling new assets relies on the search path mechanism of the Cocos engine. All files in the Cocos are read by FileUtils, which finds files in the priority order of the search path. So we add the hot update cache directory to the search path and promote it so that the assets in the cache directory are searched first. Here is the code example:
+
+```js
+import {NATIVE} from 'cc/env';
+// ...
+if (NATIVE) {
+ // Create AssetsManager
+ var assetsManager = new native.AssetsManager(manifestUrl, storagePath);
+ // The local manifest in the initialized AssetsManager is the manifest in the cache directory
+ var hotUpdateSearchPaths = assetsManager.getLocalManifest().getSearchPaths();
+ // The search path by default
+ var searchPaths = native.fileUtils.getSearchPaths();
+
+ // Insert hotUpdateSearchPaths to the beginning of searchPaths array
+ Array.prototype.unshift.apply(searchPaths, hotUpdateSearchPaths);
+
+ native.fileUtils.setSearchPaths(searchPaths);
+}
+```
+
+Note: that this code must be placed in `main.js` and executed before it require other script, otherwise it will still load the script from the application package.
+
+## Advanced Topics
+
+The above sections describe most of the implementation and usage of the Hot Update AssetsManager. But in some special scenarios, you may need some special tricks to avoid the problems caused by hot updates. But in some specific application scenes, you may need some special techniques to avoid problems caused by hot updates.
+
+### Iterative upgrade
+
+Hot update is a frequent requirement for game developers, and multiple hot updates may be released during the upgrade from one major version to another. So the following two questions are of more concern to developers:
+
+1. What happens during a local cache coverage?
+
+ When a local cached version already exists in the user's environment, the Assets Manager compares the cached version and the in-app version, and then uses the newer version as the local version. If the remote version is updated at this time, the Assets Manager uses a temporary folder to download the remote version during the update process. When the remote version is successfully updated, the contents of the temporary folder are copied to the local cache folder. If there are files of the same name in the local cache folder, they are overridden. And the other files are retained, because these files may still be valid, they just have not been modified in this release. Finally delete the temporary folder.
+
+ So, in theory, there's no problem with continuous hot update for minor version.
+
+2. How to clean the local cache during a game's major release?
+
+ During a package update, there are various ways to thoroughly clean up the local hot update cache, such as recording the current game version number, checking if it matches the saved version in `sys.localStorage`, and performing the following cleanup if they don't match:
+
+ ```js
+ // The version number previously saved in local Storage, if not, is considered as new version
+ var previousVersion = parseFloat(sys.localStorage.getItem('currentVersion'));
+ // game.currentVersion is the current version's number.
+ if (previousVersion < game.currentVersion) {
+ // The hot update cache directory. If there are multiple versions, you may need to record in a list and clean all.
+ native.fileUtils.removeDirectory(storagePath);
+ }
+ ```
+
+### Update engine
+
+Upgrading the engine version can have a huge impact on the hot update, and you may have noticed that there is a `src/cocos-js/cc.js` file in the native project, which is compiled by the JS engine and contains some interface encapsulations for the JS engine framework. In different versions of engine, its code will be quite different, and the bottom layer of C++ will also change simultaneously. Once the C++ engine version in the game pack does not match the engine version in the `src/cocos-js/cc.js`, it can cause serious problems and even prevent the game from running.
+
+It is recommended to publish the major version to app stores as much as possible after updating the engine. If you decide to use hot update, please carefully complete the test of updating the old version to the new version.
diff --git a/versions/4.0/en/advanced-topics/hot-update.md b/versions/4.0/en/advanced-topics/hot-update.md
new file mode 100644
index 0000000000..c654e4c083
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/hot-update.md
@@ -0,0 +1,151 @@
+# Assets Hot Update Tutorial
+
+## Preface
+
+In current Cocos Creator version, assets hot update workflow has not been fully integrated into the editor. But the engine itself has complete support for hot update system, so with some of the external script and tool the workflow is complete.
+
+The sample project for this document is available from [GitHub Repo](https://github.com/cocos-creator/tutorial-hot-update/tree/master).
+
+
+
+## Usage scenarios and design ideas
+
+Game developers are very familiar with the pattern that the game has been released in app market but each time user launch the game it will automatically look for updates from the server, to keep the client always updated. Of course, there are some other usage scenarios for hot update, but are not related to what we discuss here. We will mainly discuss how to implement hot update system in Cocos Creator.
+
+Hot update in Cocos Creator comes mainly from the `AssetsManager` module in the Cocos engine. It has a very important feature:
+
+**Server and client both keep a full list of the game asset (manifest)**, during hot update process, by comparing server and client asset manifest, the client should know what to download to get the latest content. This can naturally support cross-version updates, such as when client version is A, remote version is C, then we can directly update the assets from A to C. We do not need to generate A to B and B to C update package. Therefore, when we push new asset version to server, we can save new version files discretely on server, and during update the client will download each file needed separately.
+
+Please be aware that **hot update system is for native games only**, since Web game would always request assets from web server. So `AssetsManager` class exists only in the native namespace, please check runtime environment before implement these API.
+
+## Manifest file
+
+For different versions of file-level differences, AssetsManager uses a manifest file for version control. The client and server manifest files each contains an asset file list and version for each file. This allows comparing the version of each file to determine whether a file should be downloaded.
+
+The manifest file contains the following important information:
+
+1. The root path of remote assets
+2. Remote manifest file url
+3. Remote version file url (optionally)
+4. Major version number
+5. File list: index of file paths, including file version information. We recommend using the file md5 as the version number
+6. List of search path.
+
+The version file can be part of the contents of the manifest file and do not contain a list of files. But the manifest file may be large, each time client need to download the whole file for checking version update. So developer can provide a very small version file for version check only. `AssetsManager` will first check the version number provided by the version file to determine if it is necessary to continue downloading the manifest file and update it.
+
+## Implement hot update in the Cocos Creator project
+
+In this tutorial, we will provide a hot update workflow for Cocos Creator project. We have also offered `Downloader` JavaScript interface, so users are free to develop their own hot update solution.
+
+Before starting to explain in detail, developers can take a look at the directory structure of published native version of any game in Cocos Creator. The engine scripts will be packaged into the `src` directory, and other assets will be exported to the `assets` directory.
+
+Based on this project structure, the hot update process in this tutorial is simple:
+
+1. Generate the local manifest file based on the `assets` and `src` directories in the native published directory.
+2. Create a component script to be responsible for the hot update logic.
+3. After release of the game, if you need to update the version, you need to generate a set of remote asset versions, including the `assets` directory, `src` directory and manifest file. Then deploy these files to your server.
+4. When the hot update script detects that the server manifest version does not match local version, the hot update starts
+
+To show the hot update process, the example project used in the tutorial has a full version with 1.1.0 information saved in the `remote-assets` directory, and the default build of the project generates version 1.0.0. At the beginning of the game it will check whether there is a version of the remote update, if you find a remote version the user is prompted to update. When update is complete, the user re-enter the game and see the version 1.1.0 information.
+
+
+
+> **Note**: the project contains `remote-assets` is for debug mode, the developer must use the debug mode when building the test project, otherwise the release mode jsc file priority will be higher than `remote-assets` in the assets and cause the script to fail.
+
+### Use the version generator to generate the manifest file
+
+In the example project provided, [version_generator.js](https://github.com/cocos-creator/tutorial-hot-update/blob/master/version_generator.js) is a script file, which is a Nodejs script for generating the manifest file. Use it as follows:
+
+```bash
+> node version_generator.js -v 1.0.0 -u http://your-server-address/tutorial-hot-update/remote-assets/ -s native/package/ -d assets/
+```
+
+The following is a description of the parameters:
+
+- `-v` Specifies the major version number of the manifest file.
+- `-u` Specifies the url of the server remote package, which needs to be the same as the remote package url of the manifest file in the original release version, otherwise the update can not be detected.
+- `-s` local native published directory relative to the current path.
+- `-d` the path of the output manifest file.
+
+### Hot update component script
+
+In the example project, the implementation of the hot update component is located at [assets/hotupdate/HotUpdate.ts](https://github.com/cocos-creator/tutorial-hot-update/blob/master/assets/hotupdate/HotUpdate.ts), the developer can refer to this implementation, but also free to modify according to their own needs.
+
+In addition, the sample project is also equipped with a `Scene/Canvas/update` node for prompting to update and display the progress of the update.
+
+
+
+### Deploy to remote server
+
+In order to allow the game to detect remote versions, it is possible to simulate a remote server on the machine, there are a variety of server solutions (such as [SimpleHTTPServer](https://docs.python.org/2/library/simplehttpserver.html) for Python). We will not discuss detail here, developers can use their own preferred way. Once the remote server is up, modify the following places to allow the game to successfully find the remote package:
+
+1. `assets/project.manifest`: `packageUrl`, `remoteManifestUrl` and `remoteVersionUrl` in the client manifest file of the game
+2. `remote-assets/project.manifest`: `packageUrl`, `remoteManifestUrl` and `remoteVersionUrl` in the manifest file of the remote package
+3. `remote-assets/version.manifest`: `packageUrl`, `remoteManifestUrl` and `remoteVersionUrl` in the remote package's version file
+
+### Publish the original version
+
+After downloading the sample project, use Cocos Creator to open the project directly. Open **Build** panel, build for native platform, choose Windows/Mac as the target to test.
+
+> **Note**:
+> 1. Do not check MD5 Cache when building, otherwise it will cause the hot update to be invalid.
+> 2. Make sure to import editor plugin hot-update into the extensions folder (the demo project has imported the plugin).
+
+The editor plugin automatically adds the search path logic and fix code to `main.js` every time we build a successful native version:
+
+```js
+// Add the following code at the beginning of main.js
+(function () {
+ if (typeof window.jsb === 'object') {
+ var hotUpdateSearchPaths = localStorage.getItem('HotUpdateSearchPaths');
+ if (hotUpdateSearchPaths) {
+ var paths = JSON.parse(hotUpdateSearchPaths);
+ jsb.fileUtils.setSearchPaths(paths);
+
+ var fileList = [];
+ var storagePath = paths[0] || '';
+ var tempPath = storagePath + '_temp/';
+ var baseOffset = tempPath.length;
+
+ if (jsb.fileUtils.isDirectoryExist(tempPath) && !jsb.fileUtils.isFileExist(tempPath + 'project.manifest.temp')) {
+ jsb.fileUtils.listFilesRecursively(tempPath, fileList);
+ fileList.forEach(srcPath => {
+ var relativePath = srcPath.substr(baseOffset);
+ var dstPath = storagePath + relativePath;
+
+ if (srcPath[srcPath.length] == '/') {
+ jsb.fileUtils.createDirectory(dstPath)
+ }
+ else {
+ if (jsb.fileUtils.isFileExist(dstPath)) {
+ jsb.fileUtils.removeFile(dstPath)
+ }
+ jsb.fileUtils.renameFile(srcPath, dstPath);
+ }
+ })
+ jsb.fileUtils.removeDirectory(tempPath);
+ }
+ }
+ }
+})();
+```
+
+> **Note**: `fileUtils` is located in the traditional `jsb` namespace instead of `native`, and currently, the script compile system only supports importing `native` objects via `import` in TypeScript.
+
+This step must be done because the essence of the hot update is to replace the files in the original game package with a remotely downloaded file. The search path in Cocos engine just meet this demand, it can be used to specify the remote package download url as the default search path, so the game will run the process of downloading a good remote version. In addition, the search path is used in the last update process using `localStorage` (which conforms to the WEB standard [Local Storage API](https://developer.mozilla.org/en/docs/Web/API/Window/localStorage)) to store on the user's machine. The `HotUpdateSearchPaths` key is specified in `HotUpdate.js`, and the name used for the save and read process must match.
+
+In addition, if encountering this warning during the opening of the project, ignore: `loader for [.manifest] not exists!`.
+
+### Run the example project
+
+If everything is alright, run the native version of the sample project. A new version will be detected, suggesting that the update will automatically restart the game after the game, then enter the table scene.
+
+
+
+## Conclusion
+
+The above is a hot update solution, Cocos Creator in the future version to provide more mature hot update process, directly integrated into the editor. Of course, the underlying Downloader API will also be provided to allow users to freely implement their own hot update scheme and to build a complete visual workflow in the editor through the plug-in mechanism. This tutorial and sample project is for your reference and we encourage developers to customize their own workflows. If you have questions and communication also welcome feedback to [Forum](https://discuss.cocos2d-x.org/c/creator).
+
+## Next Step
+
+[AssetsManager Document](hot-update-manager.md)
diff --git a/versions/4.0/en/advanced-topics/hot-update/am-part1.png b/versions/4.0/en/advanced-topics/hot-update/am-part1.png
new file mode 100644
index 0000000000..bb03431e1f
Binary files /dev/null and b/versions/4.0/en/advanced-topics/hot-update/am-part1.png differ
diff --git a/versions/4.0/en/advanced-topics/hot-update/am-part2.png b/versions/4.0/en/advanced-topics/hot-update/am-part2.png
new file mode 100644
index 0000000000..72b95c4e1d
Binary files /dev/null and b/versions/4.0/en/advanced-topics/hot-update/am-part2.png differ
diff --git a/versions/4.0/en/advanced-topics/hot-update/assets-manager.png b/versions/4.0/en/advanced-topics/hot-update/assets-manager.png
new file mode 100644
index 0000000000..eb9840499b
Binary files /dev/null and b/versions/4.0/en/advanced-topics/hot-update/assets-manager.png differ
diff --git a/versions/4.0/en/advanced-topics/hot-update/editor.png b/versions/4.0/en/advanced-topics/hot-update/editor.png
new file mode 100644
index 0000000000..89a4aa7d8b
Binary files /dev/null and b/versions/4.0/en/advanced-topics/hot-update/editor.png differ
diff --git a/versions/4.0/en/advanced-topics/hot-update/table.png b/versions/4.0/en/advanced-topics/hot-update/table.png
new file mode 100644
index 0000000000..bb0527bc63
Binary files /dev/null and b/versions/4.0/en/advanced-topics/hot-update/table.png differ
diff --git a/versions/4.0/en/advanced-topics/hot-update/title.jpg b/versions/4.0/en/advanced-topics/hot-update/title.jpg
new file mode 100644
index 0000000000..a86dcc07d4
Binary files /dev/null and b/versions/4.0/en/advanced-topics/hot-update/title.jpg differ
diff --git a/versions/4.0/en/advanced-topics/hot-update/update.png b/versions/4.0/en/advanced-topics/hot-update/update.png
new file mode 100644
index 0000000000..8b886d5622
Binary files /dev/null and b/versions/4.0/en/advanced-topics/hot-update/update.png differ
diff --git a/versions/4.0/en/advanced-topics/http.md b/versions/4.0/en/advanced-topics/http.md
new file mode 100644
index 0000000000..838969083d
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/http.md
@@ -0,0 +1,65 @@
+# HTTP Request
+
+In some cases, it may be necessary to make requests to a server to fetch data. In Cocos Creator, you can use the fetch method, which is part of JavaScript.
+
+The prototype is defined as follows.
+
+```ts
+declare function fetch(input: RequestInfo | URL, init?: RequestInit): Promise;
+```
+
+## Setting Up a Test Sever
+
+First, set up a simple HTTP server using a backend language you are familiar with. Non-backend developers can skip this section. In this example, we'll use Golang to set up the server. Here is an example code:
+
+```go
+package main
+
+import (
+"fmt"
+"log"
+"net/http"
+)
+
+func handler(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintf(w, "http request received")
+}
+
+func main() {
+ http.HandleFunc("/", handler)
+ log.Fatal(http.ListenAndServe(":8080", nil))
+}
+```
+
+The above code will set up a network server listening on port 8080.
+
+## Making an HTTP Request
+
+In Cocos Creator, you can use the `fetch` method to make requests to the server. In this example, we'll use the `GET` method to request data from the server and expect the server to respond with text data. Here's an example code:
+
+```ts
+import { _decorator, Component } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass('HttpTest')
+export class HttpTest extends Component {
+ start() {
+
+ fetch("http://127.0.0.1:8080").then((response: Response) => {
+ return response.text()
+ }).then((value) => {
+ console.log(value);
+ })
+ }
+}
+```
+
+After running the scene, the following log will be printed:
+
+```bash
+> http request received.
+```
+
+You can also use `response.json()` to retrieve the response in JSON format.
+
+You can refer to the [MDN Web Docs](https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch) for more detailed information.
diff --git a/versions/4.0/en/advanced-topics/index.md b/versions/4.0/en/advanced-topics/index.md
new file mode 100644
index 0000000000..200cc82a3d
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/index.md
@@ -0,0 +1,16 @@
+# Advanced Topics
+
+- [Submit Code to Cocos Engine Repository](../submit-pr/submit-pr.md)
+- [User Data Storage](data-storage.md)
+- [Custom loading Wasm/Asm files and modules](wasm-asm-load.md)
+- [Converting Native Code to Wasm/Asm Files Using Emscripten](wasm-asm-create.md)
+- [Engine Customization Workflow](engine-customization.md)
+- [Web Preview Customization Workflow](../editor/preview/browser.md)
+- [Dynamic Atlas](dynamic-atlas.md)
+- [Mangle Engine Internal Properties](mangle-properties.md)
+- [Hot Update Tutorial](hot-update.md)
+- [AssetManager for Hot Update](hot-update-manager.md)
+- [HTTP Request](http.md)
+- [WebSocket Introduction](websocket-introduction.md)
+ - [WebSocket Client](websocket.md)
+ - [WebSocket Server](websocket-server.md)
diff --git a/versions/4.0/en/advanced-topics/java-reflection.md b/versions/4.0/en/advanced-topics/java-reflection.md
new file mode 100644
index 0000000000..83b37d556a
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/java-reflection.md
@@ -0,0 +1,253 @@
+# JavaScript and Android Communication with Reflection
+
+## Calling Java Static Methods from JavaScript
+
+In an Android native application created with Cocos Creator, we can directly call Java static methods from JavaScript using the Java reflection mechanism. The method is defined as follows.
+
+```js
+import { native } from 'cc';
+var o = native.reflection.callStaticMethod(className, methodName, methodSignature, parameters...)
+```
+
+- className: the name of the Java class.
+- methodName: the name of the static method.
+- methodSignature: the signature of the method, to indicate a unique method.
+- parameters: the list of parameters.
+
+Now, let's take the `Test` class under the `com.cocos.game` package as an example.
+
+```java
+// package "com.cocos.game";
+
+public class Test {
+
+ public static void hello (String msg) {
+ System.out.println (msg);
+ }
+
+ public static int sum (int a, int b) {
+ return a + b;
+ }
+
+ public static int sum (int a) {
+ return a + 2;
+ }
+}
+```
+
+### className
+
+The `className` should include the package path. If we want to call a static method in the `Test` class mentioned above, the `className` should be "com/cocos/game/Test".
+
+> **Note**: Here we use a `/` instead of a `.` in Java package name.
+
+### methodName
+
+The `methodName` is simply the name of the method. For example, if we want to call the `sum` method, the `methodName` parameter should be "sum".
+
+### methodSignature
+
+Since Java supports method overloading, the method signature is used to specify the parameter types and return type, ensuring a unique method is invoked.
+
+The format of the method signature is: **(parameter types)return type**.
+
+Cocos Creator currently supports the following 4 Java type signatures:
+
+| Java Type | Signature |
+| :------ | :----- |
+| int | I |
+| float | F |
+| boolean | Z |
+| String | Ljava/lang/String; |
+
+> **Note**: the signature of `String` type is `Ljava/lang/String;`, don't miss the `;` in the end.
+
+Here are some examples:
+
+- `()V` represents a method with no parameters and no return value.
+- `(I)V` represents a method with one parameter of type int and no return value.
+- `(I)I` represents a method with one parameter of type int and a return value of type int.
+- `(IF)Z` represents a method with two parameters, one of type int and one of type float, and a return value of type boolean.
+- `(ILjava/lang/String;F)Ljava/lang/String;` represents a method with three parameters, one of type int, one of type String, and one of type float, and a return value of type String.
+
+### parameters
+
+The parameters passed should match the method signature. It supports number, boolean, and string types.
+
+### Examples
+
+Here are some examples of calling static methods in the Test class:
+
+```js
+if(sys.os == sys.OS.ANDROID && sys.isNative){
+ // call hello
+ native.reflection.callStaticMethod("com/cocos/game/Test", "hello", "(Ljava/lang/String;)V", "this is a message from JavaScript");
+
+ // call the first sum
+ var result = native.reflection.callStaticMethod("com/cocos/game/Test", "sum", "(II)I", 3, 7);
+ log(result); // 10
+
+ // call the second sum
+ var result = native.reflection.callStaticMethod("com/cocos/game/Test", "sum", "(I)I", 3);
+ log(result); // 5
+}
+```
+
+The `sys.isNative` is used to check if it's running on a native platform, and the `sys.os` is used to determine the current operating system. Since the communication mechanisms vary across different platforms, it is recommended to perform the check before call `native.reflection.callStaticMethod`.
+
+After running the code, you can see the corresponding output.
+
+## Calling JavaScript from Java
+
+In addition to JavaScript calling Java, the engine also provides a mechanism for Java to call JavaScript.
+
+By using the `CocosJavascriptJavaBridge.evalString` method provided by the engine, you can execute JavaScript code. It's important to note that since JavaScript code in Cocos Engine is executed on the GL thread, we need to use `CocosHelper.runOnGameThread` to ensure that the thread is correct.
+
+Next, we will add a button to the Alert dialog and execute a piece of JavaScript code in its response function.
+
+```java
+alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ // Must execute in GL thread
+ CocosHelper.runOnGameThread(new Runnable() {
+ @Override
+ public void run() {
+ CocosJavascriptJavaBridge.evalString("cc.log(\"Javascript Java bridge!\")");
+ }
+ });
+ }
+});
+```
+
+Next, let's take a look at how to call JavaScript code in different situations.
+
+### Calling Global Function
+
+We can add a new global function in the script using the following code:
+
+```js
+window.callByNative = function(){
+ //to do
+}
+```
+
+>`window` is the global object in the Cocos Engine script environment. If you want a variable, function, object, or class to be globally accessible, you need to add it as a property of `window`. You can access it using `window.variableName` or `variableName` directly.
+
+Then, you can call it like this:
+
+```java
+CocosHelper.runOnGameThread(new Runnable() {
+ @Override
+ public void run() {
+ CocosJavascriptJavaBridge.evalString("window.callByNative()");
+ }
+});
+```
+
+Or:
+
+```js
+CocosHelper.runOnGameThread(new Runnable() {
+ @Override
+ public void run() {
+ CocosJavascriptJavaBridge.evalString("callByNative()");
+ }
+});
+```
+
+### Calling Static Function of an Class
+
+Suppose there is an object in the TypeScript script with the following static function:
+
+```ts
+export class NativeAPI{
+ public static callByNative(){
+ //to do
+ }
+}
+//Register NativeAPI as a global class, otherwise it cannot be called in Objective-C.
+window.NativeAPI = NativeAPI;
+```
+
+Then you can call it like this:
+
+```java
+CocosHelper.runOnGameThread(new Runnable() {
+ @Override
+ public void run() {
+ CocosJavascriptJavaBridge.evalString("NativeAPI.callByNative()");
+ }
+});
+```
+
+### Calling Singleton Function
+
+If the script code implements a singleton object that can be globally accessed:
+
+```ts
+export class NativeAPIMgr{
+ private static _inst:NativeAPIMgr;
+
+ public static get inst():NativeAPIMgr{
+ if(!this._inst){
+ this._inst = new NativeAPIMgr();
+ }
+ return this._inst;
+ }
+
+ public static callByNative(){
+ //to do
+ }
+}
+
+//Register NativeAPIMgr as a global class, otherwise it cannot be called in Objective-C.
+window.NativeAPIMgr = NativeAPIMgr;
+```
+
+You can call it like this:
+
+```java
+CocosHelper.runOnGameThread(new Runnable() {
+ @Override
+ public void run() {
+ CocosJavascriptJavaBridge.evalString("NativeAPIMgr.inst.callByNative()");
+ }
+});
+```
+
+### Calling with Parameters
+
+The above mentioned ways of calling JS from Java all support parameter passing. However, the parameters only support the three basic types: `string`, `number`, and `boolean`.
+
+Taking the global function as an example:
+
+```js
+window.callByNative = function(a:string, b:number, c:bool){
+ //to do
+}
+```
+
+You can call it like this:
+
+```java
+CocosHelper.runOnGameThread(new Runnable() {
+ @Override
+ public void run() {
+ CocosJavascriptJavaBridge.evalString("window.callByNative('test',1,true)");
+ }
+});
+```
+
+## Calling JavaScript from C++
+
+If you want to call `evalString` in C++, you can refer to the following approach to ensure that `evalString` is executed in the GL thread of the engine:
+
+```c++
+CC_CURRENT_ENGINE()->getScheduler()->performFunctionInCocosThread([=]() {
+ se::ScriptEngine::getInstance()->evalString(script.c_str());
+});
+```
+
+## Thread Safety
+
+As you can see in the code above, `CocosHelper.runOnGameThread` and `CC_CURRENT_ENGINE()->getScheduler()->performFunctionInCocosThread` are used. This is to ensure that the code is executed in the correct thread. For more details, please refer to the [Thread Safety](./thread-safety.md) documentation.
diff --git a/versions/4.0/en/advanced-topics/js-java-bridge.md b/versions/4.0/en/advanced-topics/js-java-bridge.md
new file mode 100644
index 0000000000..f652c9ff07
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/js-java-bridge.md
@@ -0,0 +1,159 @@
+# JavaScript and Java Communication using JsbBridge
+
+## Background
+
+In [JavaScript and Android Communication with Reflection](./java-reflection.md), We not only need to strictly declare package names and function signatures but also need to carefully verify the number of parameters to ensure proper operation. The steps involved are quite complex.
+
+Therefore, we provide an additional method to simplify the communication between the script and the native. This method acts as a channel or bridge, and we named it `JsbBridge`, which stands for a bridge between scripts and the native app through JSB binding.
+
+> **Note**: Both methods can be used effectively, and developers can choose the one that suits their needs based on their specific requirements.
+
+## JsbBridge Mechanism
+
+### JavaScript API
+
+In the script layer, there are only two interfaces: sendToNative and onNative, defined as follows:
+
+```js
+// JavaScript
+export namespace bridge{
+ /**
+ * Send to native with at least one argument.
+ */
+ export function sendToNative(arg0: string, arg1?: string): void;
+ /**
+ * Save your own callback controller with a JavaScript function,
+ * Use 'jsb.bridge.onNative = (arg0: String, arg1: String | null)=>{...}'
+ * @param args : received from native
+ */
+ export function onNative(arg0: string, arg1?: string | null): void;
+}
+```
+
+As the names suggest, `sendToNative` is used to invoke code in the native layer, while `onNative` is used to respond to calls from the native layer.
+
+When using these interfaces, please note the following:
+
+- Since this feature is still in the experimental stage, it only supports the transmission of `string` data. If you need to transmit objects with multiple parameters, consider converting them to `Json` format for transmission and parse them before using.
+- `onNative` Only one function is recorded at a time for `onNative`, and setting the property again will override the previously set `onNative` method.
+- The `sendToNative` method is a one-way communication and does not have return value. It does not inform JavaScript of the success or failure of the operation. Developers need to handle the operation status themselves.
+
+### Java API
+
+In Java, there are also two corresponding interfaces: `sendToScript` and `ICallback.onScript`, defined as follows:
+
+```JAVA
+// JAVA
+public class JsbBridge {
+ public interface ICallback{
+ /**
+ * Applies this callback to the given argument.
+ *
+ * @param arg0 as input
+ * @param arg1 as input
+ */
+ void onScript(String arg0, String arg1);
+ }
+ /** Add a callback which you would like to apply
+ * @param f ICallback, the method which will be actually applied. multiple calls will override
+ * */
+ public static void setCallback(ICallback f);
+ /**
+ * Java dispatch Js event, use native c++ code
+ * @param arg0 input values
+ */
+ public static void sendToScript(String arg0, String arg1);
+ public static void sendToScript(String arg0);
+}
+```
+
+Among them, `sendToScript` is used to invoke code in the script layer, while `onScript` is used to respond to calls from the script layer.
+
+We need to implement the `ICallback` interface and use `setCallback` to register and respond to the specific behavior of `onScript`.
+
+## Basic Usage
+
+### Calling Java from JavaScript
+
+Suppose we have implemented Java interface for opening an advertisement. When the player clicks the button to open the advertisement, it should be triggered by the corresponding Java interface through JavaScript.
+
+We need to first implement an `ICallback` interface to respond to the operation and register it using `JsbBridge.setCallback`. The code is as follows:
+
+```JAVA
+JsbBridge.setCallback(new JsbBridge.ICallback() {
+ @Override
+ public void onScript(String arg0, String arg1) {
+ //TO DO
+ if(arg0.equals("open_ad")){
+ //call openAd method.
+ }
+ }
+});
+```
+
+> In actual projects, the above code is usually called directly or indirectly in the `onCreate` method of `AppActivity.java` to ensure that it can respond to all calls from the script layer.
+
+In the JavaScript script, we can call it as follows:
+
+```ts
+import { native } from 'cc'
+public static onclick(){
+ native.bridge.sendToNative('open_ad', defaultAdUrl);
+}
+```
+
+### Calling JavaScript from Java
+
+Suppose that after our advertisement finishes playing, we need to notify the JavaScript layer. We can do it as follows.
+
+First, in JavaScript, use `onNative` to respond to the event:
+
+```ts
+native.bridge.onNative = (arg0:string, arg1: string):void=>{
+ if(arg0 == 'ad_close'){
+ if(arg1 == "finished") {
+ //ad playback completed.
+ }
+ else{
+ //ad cancel.
+ }
+ }
+ return;
+}
+```
+
+> In actual projects, you can place the above code in the `onload` function of a script component that needs to be loaded when the program starts to ensure early listening to events from the native layer.
+
+Then, in Java, call it as follows:
+
+```JAVA
+JsbBridge.sendToScript("ad_close", "finished");
+```
+
+Through the above operations, we can notify JavaScript about the playback result of the advertisement.
+
+## Best Practices
+
+JsbBridge provides two string-type parameters, `arg0` and `arg1`, to pass information, which can be allocated according to different needs.
+
+### 1. Both arg0 and arg1 used as parameters
+
+If the communication requirements are relatively simple and do not require categorization, you can use `arg0` and `arg1` as parameters.
+
+### 2. arg0 used as command type, arg1 used as a parameter
+
+If the communication requirements are relatively complex, you can use arg0 as a command type to process different commands, and arg1 can be used as a parameter.
+
+### 3. arg0 used as a command type, arg1 used as a JSON string
+
+For particularly complex requirements where simple string-type parameters are not sufficient, you can convert the objects that need to be passed into a string using `JSON.stringify` and pass them through `arg1`. When using them, you can restore them to objects using `JSON.parse` for further processing.
+
+> Since it involves serialization and deserialization operations of JSON, this usage is not recommended for frequent calls.
+
+## Thread Safety
+
+Note that if the related code involves native UI, you need to consider thread safety issues. For more details, please refer to:[Thread Safety](./thread-safety.md)。
+
+## Sample: Multiple Event Calls
+
+Cocos provides the [native-script-bridge](https://github.com/cocos/cocos-example-projects/tree/v3.8/native-script-bridge) example, which developers can download for reference use as needed.
diff --git a/versions/4.0/en/advanced-topics/js-oc-bridge.md b/versions/4.0/en/advanced-topics/js-oc-bridge.md
new file mode 100644
index 0000000000..84e33916a8
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/js-oc-bridge.md
@@ -0,0 +1,151 @@
+# JavaScript and Objective-C Communication using JsbBridge
+
+## Background
+
+[JavaScript and iOS/macOS Communication with Reflection](./oc-reflection.md), We need to carefully verify the number of parameters to ensure proper operation. The steps involved are quite complex.
+
+Therefore, we provide an additional method to simplify the communication between the script and the native. This method acts as a channel or bridge, and we named it `JsbBridge`, which stands for a bridge between scripts and the native app through JSB binding.
+
+> **Note**: Both methods can be used effectively, and developers can choose the one that suits their needs based on their specific requirements.
+
+## JsbBridge Mechanism
+
+### JavaScript API
+
+```js
+// JavaScript
+export namespace bridge{
+ /**
+ * Send to native with at least one argument.
+ */
+ export function sendToNative(arg0: string, arg1?: string): void;
+ /**
+ * Save your own callback controller with a JavaScript function,
+ * Use 'jsb.bridge.onNative = (arg0: String, arg1: String | null)=>{...}'
+ * @param args : received from native
+ */
+ export function onNative(arg0: string, arg1?: string | null): void;
+}
+```
+
+As the names suggest, `sendToNative` is used to invoke code in the native layer, while `onNative` is used to respond to calls from the native layer.
+
+When using these interfaces, please note the following:
+
+- Since this feature is still in the experimental stage, it only supports the transmission of `string` data. If you need to transmit objects with multiple parameters, consider converting them to `Json` format for transmission and parse them before using.
+- `onNative` Only one function is recorded at a time for `onNative`, and setting the property again will override the previously set `onNative` method.
+- The `sendToScript` method is a one-way communication and does not have return value. It does not inform JavaScript of the success or failure of the operation. Developers need to handle the operation status themselves.
+
+### Objective-C API
+
+In `Objective-C`, there are also two corresponding interfaces: `sendToScript` and `callByScript`, defined as follows:
+
+```objc
+//Objective-c
+typedef void (^ICallback)(NSString*, NSString*);
+
+@interface JsbBridge : NSObject
+
++(instancetype)sharedInstance;
+-(bool)setCallback:(ICallback)cb;
+-(bool)callByScript:(NSString*)arg0 arg1:(NSString*)arg1;
+-(void)sendToScript:(NSString*)arg0 arg1:(NSString*)arg1;
+-(void)sendToScript:(NSString*)arg0;
+
+@end
+```
+
+Among them, `sendToScript` is used to invoke code in the script layer, while `callByScript` is used to respond to calls from the script layer.
+
+We need to implement the `ICallback` interface and use `setCallback` to register and respond to the specific behavior of `callByScript`.
+
+## Basic Usage
+
+### Calling Objective-C from JavaScript
+
+Suppose we have written an Objective-C interface to open an advertisement, and when the player clicks the button to open the advertisement, it should be triggered by JavaScript calling the corresponding Objective-C interface.
+
+First, we need to implement an `ICallback` interface to respond to the operation, and then register it with `JsbBridge` using the `setCallback` method.
+
+Here is the Objective-C code:
+
+```ObjC
+#include "platform/apple/JsbBridge.h"
+
+static ICallback cb = ^void (NSString* _arg0, NSString* _arg1){
+ if([_arg0 isEqual:@"open_ad"]){
+ //open Ad
+ }
+};
+
+JsbBridge* m = [JsbBridge sharedInstance];
+[m setCallback:cb];
+```
+
+In JavaScript, we can call it like this:
+
+```ts
+import { native } from 'cc'
+public static onclick(){
+ native.bridge.sendToNative('open_ad', defaultAdUrl);
+}
+```
+
+### Calling JavaScript from Objective-C
+
+Suppose that after our advertisement finishes playing, we need to notify the JavaScript layer. We can do it as follows.
+
+First, in JavaScript, use `onNative` to respond to the event:
+
+```ts
+native.bridge.onNative = (arg0:string, arg1: string):void=>{
+ if(arg0 == 'ad_close'){
+ if(arg1 == "finished") {
+ //ad playback completed.
+ }
+ else{
+ //ad cancel.
+ }
+ }
+ return;
+}
+```
+
+> In actual projects, you can place the above code in the `onload` function of a script component that needs to be loaded when the program starts to ensure early listening to events from the native layer.
+
+Then, in Objective-C, call it as follows:
+
+```ObjC
+#include "platform/apple/JsbBridge.h"
+
+JsbBridge* m = [JsbBridge sharedInstance];
+[m sendToScript:@"ad_close" arg1:@"finished"];
+```
+
+Through the above operations, we can notify JavaScript about the playback result of the advertisement.
+
+## Best Practices
+
+JsbBridge provides two string-type parameters, `arg0` and `arg1`, to pass information, which can be allocated according to different needs.
+
+### 1. Both arg0 and arg1 used as parameters
+
+If the communication requirements are relatively simple and do not require categorization, you can use `arg0` and `arg1` as parameters.
+
+### 2. arg0 used as command type, arg1 used as a parameter
+
+If the communication requirements are relatively complex, you can use arg0 as a command type to process different commands, and arg1 can be used as a parameter.
+
+### 3. arg0 used as a command type, arg1 used as a JSON string
+
+For particularly complex requirements where simple string-type parameters are not sufficient, you can convert the objects that need to be passed into a string using `JSON.stringify` and pass them through `arg1`. When using them, you can restore them to objects using `JSON.parse` for further processing.
+
+> Since it involves serialization and deserialization operations of JSON, this usage is not recommended for frequent calls.
+
+## Thread Safety
+
+Note that if the related code involves native UI, you need to consider thread safety issues. For more details, please refer to:[Thread Safety](./thread-safety.md)。
+
+## Sample: Multiple Event Calls
+
+Cocos provides the [native-script-bridge](https://github.com/cocos/cocos-example-projects/tree/v3.8/native-script-bridge) example, which developers can download for reference use as needed.
diff --git a/versions/4.0/en/advanced-topics/jsb-auto-binding.md b/versions/4.0/en/advanced-topics/jsb-auto-binding.md
new file mode 100644
index 0000000000..a779bd0ca3
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/jsb-auto-binding.md
@@ -0,0 +1,380 @@
+# Using JSB Auto Binding
+
+> This article is republished from [Tencent Online Education Department Technical Blog](https://oedx.github.io/2019/07/03/cocos-creator-js-binding-auto/)
+> Author: kevinxzhang
+
+Creator provides `native.reflection.callStaticMethod` method to support the interface of calling Native side (Android/iOS/Mac) directly from TypeScript side, but after much practice, we found that the performance of this interface is very low under a lot of frequent calls, especially on Android side, such as calling the interface implemented on Native side for printing logs. And it is easy to cause some native crashes, such as `local reference table overflow` and other problems. Throughout the implementation of Cocos native code, basically all interface methods are implemented based on the JSB approach, so this article mainly explains the JSB auto-binding logic to help you quickly implement the `callStaticMethod` to JSB transformation process.
+
+## Background
+
+For those who have used Cocos Creator (or CC for convenience), `native.reflection.callStaticMethod` is certainly no stranger to providing the ability to call the Native side from the TypeScript side. For example, if we want to call the Native implementation of the log printing and persistence interface, we can easily do so in JavaScript as follows:
+
+```javascript
+import {NATIVE} from 'cc/env';
+
+if (NATIVE && sys.os == sys.OS.IOS) {
+ msg = this.buffer_string + '\n[cclog][' + clock + '][' + tag + ']' + msg;
+ native.reflection.callStaticMethod("ABCLogService", "log:module:level:", msg, 'cclog', level);
+ return;
+} else if (NATIVE && sys.os == sys.OS.ANDROID) {
+ msg = this.buffer_string + '\n[cclog][' + clock + '][' + tag + ']' + msg;
+ native.reflection.callStaticMethod("com/example/test/CommonUtils", "log", "(ILjava/lang/String;Ljava/lang/String;)V", level, 'cclog', msg);
+ return;
+}
+```
+
+It is very simple to use and can be called cross-platform in one line of code, a little look at its implementation shows that the C++ layer is implemented in the Android side by way of jni, and the iOS side is called dynamically by way of runtime. However, in order to take into account the generality and support all methods, the Android side does not have a caching mechanism for jni-related objects, which can lead to serious performance problems when a large number of calls are made in a short period of time. Previously we encountered more cases is printing log in the downloader, some application scenarios trigger a large number of download operations in a short period of time, resulting in `local reference table overflow` crashes, or even interface lag on low-end machines that cannot be loaded out.
+
+Fixing this problem requires a JSB modification for log calls, along with a caching mechanism related to jni to optimize performance. jSB binding is simply the process of converting objects between the C++ and script layers, and forwarding script layer function calls to the C++ layer.
+
+JSB binding is usually done in two ways: **manual binding** and **automatic binding**. The manual binding method can be found in the [Using JSB Manual Binding](jsb-manual-binding.md) documentation.
+- The advantage of manual binding is that it is flexible and customizable; the disadvantage is the necessity to write all the code yourself, especially the conversion between C++ type and TypeScript type, which can easily lead to memory leaks and some pointers or objects not being freed.
+- Auto-binding will save a lot of trouble, which directly generates the relevant code through a script in one click, and subsequently, if there are new codes or changes, simply re-execute the script once. Auto-binding is perfect for cases where it is not necessary to do strong customization and then need to finish JSB quickly. The following is a step-by-step explanation of how to implement automatic JSB binding.
+
+## Environment Configuration and Auto-Binding Demonstration
+
+### Environment Configuration
+
+Auto-binding, to put it simply, is a matter of executing a python script to automatically generate the corresponding `.cpp` and `.h` files. First,make sure that the computer has a python runtime environment. Example of how to install it on a Mac:
+
+1. To install python 3.0, download the installation package from the python website:
+
+
+
+2. Install some of the python dependencies via pip3:
+
+ ```shell
+ sudo pip3 install pyyaml==5.4.1
+ sudo pip3 install Cheetah3
+ ```
+
+3. Install the NDK, which is definitely essential when it comes to C++. It is recommended to install the [Android NDK r21e](https://github.com/android/ndk/wiki/Unsupported-Downloads#r16b) version, set the `PYTH_profile` in `~/.bash_ profile`, then set `PYTHON_ROOT` and `NDK_ROOT` in `~/.bash_profile`, because these two environment variables will be used directly in the python file that will be executed later.
+
+ ```shell
+ export NDK_ROOT=/Users/kevin/android-ndk-r21e
+ export PYTHON_BIN=python3
+ ```
+
+In Windows, directly install the modules by referring to the above, and remember to configure the environment variables at the end.
+
+### Auto-Binding Demonstration
+
+Here's a demonstration of how the files under the cocos engine, i.e. the **cocos/bindings/auto** directory (shown below) are automatically generate:
+
+
+
+In fact, the beginning of these file names that there are some specific rules for naming these files, so how are these files generated? First, open a terminal, `cd` to the **tools/tojs** directory, and then run `./genbindings.py`.
+
+
+
+After about a minute or so of running, the following message will appear, indicating that it has been successfully generated:
+
+
+
+After the above steps, all the files under **cocos/bindings/auto** will be automatically generated, which is very convenient.
+
+The following is an example of how the TypeScript layer prints logs by calling the Native layer log method through JSB, and how to implement the auto-binding tool to generate the corresponding auto-binding files based on the C++ code written.
+
+## Writing the C++ layer implementation
+
+C++ is the bridge between TypeScript and Native layers. To implement JSB calls, the first step is to prepare the header files and implementation for the C++ layer, here we create a `test` folder in `cocos` directory to store the relevant files:
+
+
+
+`ABCJSBBridge.h`, declares an `abcLog` function for the TypeScript layer to call the logging, and because the logging method will certainly be used in many places in the TypeScript layer, a singleton pattern is used here, providing `getInstance()` to get the current instance of the class.
+
+```cpp
+#pragma once
+
+#include
+
+namespace abc
+{
+ class JSBBridge
+ {
+ public:
+ void abcLog(const std::string& msg);
+ /**
+ * Returns a shared instance of the director.
+ * @js _getInstance
+ */
+ static JSBBridge* getInstance();
+
+ /** @private */
+ JSBBridge();
+ /** @private */
+ ~JSBBridge();
+ bool init();
+ };
+}
+```
+
+The following is the corresponding implementation of `ABCJSBBridge.cpp`:
+
+```cpp
+#include
+#include "ABCJSBBridge.h"
+
+namespace abc
+{
+ // singleton stuff
+ static JSBBridge *s_SharedJSBBridge = nullptr;
+
+ JSBBridge::JSBBridge()
+ {
+ CC_LOG_ERROR("Construct JSBBridge %p", this);
+ init();
+ }
+
+ JSBBridge::~JSBBridge()
+ {
+ CC_LOG_ERROR("Destruct JSBBridge %p", this);
+ s_SharedJSBBridge = nullptr;
+ }
+
+ JSBBridge* JSBBridge::getInstance()
+ {
+ if (!s_SharedJSBBridge)
+ {
+ CC_LOG_ERROR("getInstance JSBBridge ");
+ s_SharedJSBBridge = new (std::nothrow) JSBBridge();
+ CCASSERT(s_SharedJSBBridge, "FATAL: Not enough memory for create JSBBridge");
+ }
+
+ return s_SharedJSBBridge;
+ }
+
+ bool JSBBridge::init(void)
+ {
+ CC_LOG_ERROR("init JSBBridge ");
+ return true;
+ }
+
+ void JSBBridge::abcLog(const std::string& msg)
+ {
+ CC_LOG_ERROR("%s", msg.c_str());
+ }
+}
+```
+
+## JSB Configuration Scripting
+
+Find the `genbindings.py` script in the **tools/tojs** directory, copy it and rename it to `genbindings_test.py`, then modify the `genbindings_test.py` module configuration to keep only the cocos2dx_test module.
+
+
+
+The next step is to add a custom configuration file `cocos2dx_test.ini` to the **tools/tojs** directory, which is actually similar to the other `.ini` files under **tools/tojs**, mainly to let the auto-binding tool know which APIs to bind and in what way. Refer directly to Cocos' existing `.ini` file to write this, here is the contents of `cocos2dx_test.ini`:
+
+```ini
+[cocos2dx_test]
+# the prefix to be added to the generated functions. You might or might not use this in your own
+# templates
+prefix = cocos2dx_test
+
+# create a target namespace (in javascript, this would create some code like the equiv. to `ns = ns || {}`)
+# all classes will be embedded in that namespace
+target_namespace = abc
+
+macro_judgement =
+
+android_headers =
+
+android_flags = -target armv7-none-linux-androideabi -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -DANDROID -D__ANDROID_API__=14 -gcc-toolchain %(gcc_toolchain_dir)s --sysroot=%(androidndkdir)s/platforms/android-14/arch-arm -idirafter %(androidndkdir)s/sources/android/support/include -idirafter %(androidndkdir)s/sysroot/usr/include -idirafter %(androidndkdir)s/sysroot/usr/include/arm-linux-androideabi -idirafter %(clangllvmdir)s/lib64/clang/5.0/include -I%(androidndkdir)s/sources/cxx-stl/llvm-libc++/include
+
+clang_headers =
+clang_flags = -nostdinc -x c++ -std=c++17 -fsigned-char -mfloat-abi=soft -U__SSE__
+
+cocos_headers = -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/platform/android -I%(cocosdir)s/external/sources
+
+cocos_flags = -DANDROID -DCC_PLATFORM=3 -DCC_PLATFORM_MAC_IOS=1 -DCC_PLATFORM_MAC_OSX=4 -DCC_PLATFORM_WINDOWS=2 -DCC_PLATFORM_ANDROID=3
+
+
+cxxgenerator_headers =
+
+# extra arguments for clang
+extra_arguments = %(android_headers)s %(clang_headers)s %(cxxgenerator_headers)s %(cocos_headers)s %(android_flags)s %(clang_flags)s %(cocos_flags)s %(extra_flags)s
+
+# what headers to parse
+headers = %(cocosdir)s/cocos/test/ABCJSBBridge.h
+
+# cpp_headers = network/js_network_manual.h
+
+# what classes to produce code for. You can use regular expressions here. When testing the regular
+# expression, it will be enclosed in "^$", like this: "^Menu*$".
+classes = JSBBridge
+
+# what should we skip? in the format ClassName::[function function]
+# ClassName is a regular expression, but will be used like this: "^ClassName$" functions are also
+# regular expressions, they will not be surrounded by "^$". If you want to skip a whole class, just
+# add a single "*" as functions. See bellow for several examples. A special class name is "*", which
+# will apply to all class names. This is a convenience wildcard to be able to skip similar named
+# functions from all classes.
+skip = JSBBridge::[init]
+
+rename_functions =
+
+rename_classes =
+
+# for all class names, should we remove something when registering in the target VM?
+remove_prefix =
+
+# classes for which there will be no "parent" lookup
+classes_have_no_parents = JSBBridge
+
+# base classes which will be skipped when their sub-classes found them.
+base_classes_to_skip = Clonable
+
+# classes that create no constructor
+# Set is special and we will use a hand-written constructor
+abstract_classes = JSBBridge
+```
+
+In fact, the annotations inside are also very detailed, and here are a few of the main properties and their meanings:
+
+
+| Property | Description |
+|:--- | :--- |
+| prefix | Define the name of the function inside the generated binding file. The combination of function name is `js + prefix + the function name in the header file`. For example, if we define `JSBBridge_ abcLog` in the header file and set the `prefix` to `cocos2dx test`, the function name in the final binding file will be `js_cocos2dx_test_JSBBridge_abcLog`. |
+| target_namespace | The target namespace in the script, e.g.: `cc`, `spine`, etc. |
+| headers | List of headers to be bound, separated by spaces, headers will be scanned recursively. |
+| cpp_headers | List of header files that need to be included in the binding code but do not need to be scanned by the binding tool. |
+| classes | List of class names to be bound, separated by spaces. |
+| abstract_classes | When configured as an abstract class, its constructors will not be bound, separated by spaces. |
+
+Once the above configuration is done, `cd` to the `tools/tojs` directory and run `./genbindings_test.py` to automatically generate the bindings file. Notice the two bindings under `cocos/bindings/auto`:
+
+
+
+Open the generated `jsb_cocos2dx_test_auto.cpp`:
+
+```cpp
+#include "cocos/bindings/auto/jsb_cocos2dx_test_auto.h"
+#include "cocos/bindings/manual/jsb_conversions.h"
+#include "cocos/bindings/manual/jsb_global.h"
+#include "test/ABCJSBBridge.h"
+
+#ifndef JSB_ALLOC
+#define JSB_ALLOC(kls, ...) new (std::nothrow) kls(__VA_ARGS__)
+#endif
+
+#ifndef JSB_FREE
+#define JSB_FREE(ptr) delete ptr
+#endif
+se::Object* __jsb_abc_JSBBridge_proto = nullptr;
+se::Class* __jsb_abc_JSBBridge_class = nullptr;
+
+static bool js_cocos2dx_test_JSBBridge_abcLog(se::State& s) // NOLINT(readability-identifier-naming)
+{
+ auto* cobj = SE_THIS_OBJECT(s);
+ SE_PRECONDITION2(cobj, false, "js_cocos2dx_test_JSBBridge_abcLog : Invalid Native Object");
+ const auto& args = s.args();
+ size_t argc = args.size();
+ CC_UNUSED bool ok = true;
+ if (argc == 1) {
+ HolderType arg0 = {};
+ ok &= sevalue_to_native(args[0], &arg0, s.thisObject());
+ SE_PRECONDITION2(ok, false, "js_cocos2dx_test_JSBBridge_abcLog : Error processing arguments");
+ cobj->abcLog(arg0.value());
+ return true;
+ }
+ SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
+ return false;
+}
+SE_BIND_FUNC(js_cocos2dx_test_JSBBridge_abcLog)
+
+static bool js_cocos2dx_test_JSBBridge_getInstance(se::State& s) // NOLINT(readability-identifier-naming)
+{
+ const auto& args = s.args();
+ size_t argc = args.size();
+ CC_UNUSED bool ok = true;
+ if (argc == 0) {
+ abc::JSBBridge* result = abc::JSBBridge::getInstance();
+ ok &= nativevalue_to_se(result, s.rval(), nullptr /*ctx*/);
+ SE_PRECONDITION2(ok, false, "js_cocos2dx_test_JSBBridge_getInstance : Error processing arguments");
+ SE_HOLD_RETURN_VALUE(result, s.thisObject(), s.rval());
+ return true;
+ }
+ SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 0);
+ return false;
+}
+SE_BIND_FUNC(js_cocos2dx_test_JSBBridge_getInstance)
+
+bool js_register_cocos2dx_test_JSBBridge(se::Object* obj) // NOLINT(readability-identifier-naming)
+{
+ auto* cls = se::Class::create("JSBBridge", obj, nullptr, nullptr);
+
+ cls->defineFunction("abcLog", _SE(js_cocos2dx_test_JSBBridge_abcLog));
+ cls->defineStaticFunction("getInstance", _SE(js_cocos2dx_test_JSBBridge_getInstance));
+ cls->install();
+ JSBClassType::registerClass(cls);
+
+ __jsb_abc_JSBBridge_proto = cls->getProto();
+ __jsb_abc_JSBBridge_class = cls;
+
+ se::ScriptEngine::getInstance()->clearException();
+ return true;
+}
+bool register_all_cocos2dx_test(se::Object* obj)
+{
+ // Get the ns
+ se::Value nsVal;
+ if (!obj->getProperty("abc", &nsVal))
+ {
+ se::HandleObject jsobj(se::Object::createPlainObject());
+ nsVal.setObject(jsobj);
+ obj->setProperty("abc", nsVal);
+ }
+ se::Object* ns = nsVal.toObject();
+
+ js_register_cocos2dx_test_JSBBridge(ns);
+ return true;
+}
+```
+
+Doesn't it look familiar? It's exactly the same as Cocos' existing `.cpp` files, even including the registration functions and class definitions that are all automatically generated.
+
+## Cocos Compilation Configuration
+
+Although we have generated the bindings after the above step, the TypeScript layer can't be used directly because we still need to configure the generated bindings into the `CMakeLists.txt` file to be compiled with other C++ files, which is the last part of the `CMakeLists.txt` compilation configuration.
+
+1. Open the `CMakeLists.txt` file and add the initial `ABCJSBBridge.h` and `ABCJSBBridge.cpp` to it, as well as the `jsb_cocos2dx_test_auto.h` and `jsb_cocos2dx_test_auto.cpp` files generated by the automatic bindings:
+
+ 
+
+2. Open `cocos/bindings/manual/jsb_module_register.cpp` and add the registration code for the cocos2dx_test module:
+
+ 
+
+
+After the above configuration, call it directly from the TypeScript layer like this:
+
+``` typescript
+import { _decorator, Component, Node } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass('Test')
+export class Test extends Component {
+ start () {
+ // @ts-ignore
+ abc.JSBBridge.getInstance().abcLog("JSB binding test success")
+ }
+}
+```
+
+## Restrictions on Auto-Binding
+
+Auto-binding relies on the [Bindings Generator tool](https://github.com/cocos-creator/bindings-generator). The Bindings Generator tool can Bind public methods and public properties of C++ classes to the scripting layer. The automatic binding tool, although very powerful, has a few limitations:
+1. It can only generate bindings for classes, not structs, independent functions, etc.
+2. It is not possible to generate `Delegate` type APIs, because objects in scripts cannot inherit from the `Delegate` class in C++ and override the `Delegate` functions in it.
+3. The child class overrides the API of the parent class while overriding this API.
+4. Part of the API implementation is not fully reflected in its API definition.
+5. The API is actively called by C++ at runtime.
+
+**NOTICE:**
+Since 3.6 the types of parameters and return values involved in auto-binding need to be bound as well, or the conversion methods `sevalue_to_native`/`nativevalue_to_se` need to be provided, otherwise they will be saved at compile time. Before 3.5, it was reported as a runtime error.
+
+## Summary
+
+In summary, automatic binding of JSBs only requires the developer to write the relevant C++ implementation class, a configuration file, and then execute a single command to complete the entire binding process. If there is no special customization, it is still a lot more efficient than manual binding. The actual work can be done on a case-by-case basis by first using the auto-binding feature, and then manually modifying the generated binding file to achieve half the result with twice the effort.
+
diff --git a/versions/4.0/en/advanced-topics/jsb-bridge-wrapper.md b/versions/4.0/en/advanced-topics/jsb-bridge-wrapper.md
new file mode 100644
index 0000000000..edf02be9f4
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/jsb-bridge-wrapper.md
@@ -0,0 +1,191 @@
+# JsbBridgeWrapper - An Event Mechanism based on JsbBridge
+
+> **Note**: After v3.6.0, `jsb` module is about to be deprecated, APIs will be moved to the `native` module of namespace `cc`.
+
+## An eventify system based on JsbBridge
+
+`JsbBridgeWrapper` is an eventify system based on `JsbBridge`, which is more convenient and easier to use. Developers can trigger multiple events without manually implementing one. But it is not mthread safe. If you're working on a complex situation, it is still recommended to implement the eventify system by yourself.
+
+### JsbBridgeWrapper interface introduction
+
+```js
+/**
+ * Listener for jsbBridgeWrapper's event.
+ * It takes one argument as string which is transferred by jsbBridge.
+ */
+export type OnNativeEventListener = (arg: string) => void;
+export namespace jsbBridgeWrapper {
+ /** If there's no event registered, the wrapper will create one */
+ export function addNativeEventListener(eventName: string, listener: OnNativeEventListener);
+ /**
+ * Dispatch the event registered on Objective-C, Java etc.
+ * No return value in JS to tell you if it works.
+ */
+ export function dispatchEventToNative(eventName: string, arg?: string);
+ /**
+ * Remove all listeners relative.
+ */
+ export function removeAllListenersForEvent(eventName: string);
+ /**
+ * Remove the listener specified
+ */
+ export function removeNativeEventListener(eventName: string, listener: OnNativeEventListener);
+ /**
+ * Remove all events, use it carefully!
+ */
+ export function removeAllListeners();
+}
+```
+
+`OnNativeEventListener` is the type of callback to register here, yet you can also code with anonymous function, for example:
+
+```js
+import { native } from 'cc'
+// When event ‘A’ is triggered, the function ‘this.A’ will be applied
+native.jsbBridgeWrapper.addNativeEventListener("A", (usr: string) => {
+ this.A(usr);
+});
+```
+
+### Platform implementations
+
+JsbBridgeWrapper has different implementations on different platforms.
+
+As for Objective-C and Java, you will see `JsbBridgeWrapper` with a similar declaration.
+
+- [Objective-C](https://github.com/cocos/cocos4/blob/v4.0.0/native/cocos/platform/apple/JsbBridgeWrapper.h):
+
+ ```objc
+ // In Objective-C
+ typedef void (^OnScriptEventListener)(NSString*);
+
+ @interface JsbBridgeWrapper : NSObject
+ /**
+ * Get the instance of JsbBridgetWrapper
+ */
+ + (instancetype)sharedInstance;
+ /**
+ * Add a listener to specified event, if the event does not exist, the wrapper will create one. Concurrent listener will be ignored
+ */
+ - (void)addScriptEventListener:(NSString*)eventName listener:(OnScriptEventListener)listener;
+ /**
+ * Remove listener for specified event, concurrent event will be deleted. Return false only if the event does not exist
+ */
+ - (bool)removeScriptEventListener:(NSString*)eventName listener:(OnScriptEventListener)listener;
+ /**
+ * Remove all listener for event specified.
+ */
+ - (void)removeAllListenersForEvent:(NSString*)eventName;
+ /**
+ * Remove all event registered. Use it carefully!
+ */
+ - (void)removeAllListeners;
+ /**
+ * Dispatch the event with argument, the event should be registered in javascript, or other script language in future.
+ */
+ - (void)dispatchEventToScript:(NSString*)eventName arg:(NSString*)arg;
+ /**
+ * Dispatch the event which is registered in javascript, or other script language in future.
+ */
+ - (void)dispatchEventToScript:(NSString*)eventName;
+ @end
+
+ ```
+- [JAVA](https://github.com/cocos/cocos-engine/blob/v3.5.0/native/cocos/platform/android/java/src/com/cocos/lib/JsbBridgeWrapper.java) or [Huawei HarmonyOS](https://github.com/cocos/cocos-engine/blob/v3.5.0/native/cocos/platform/ohos/libcocos/src/main/java/com/cocos/lib/JsbBridgeWrapper.java):
+
+ ```JAVA
+ // In JAVA
+ public class JsbBridgeWrapper {
+ public interface OnScriptEventListener {
+ void onScriptEvent(String arg);
+ }
+ /**
+ * Add a listener to specified event, if the event does not exist, the wrapper will create one. Concurrent listener will be ignored
+ */
+ public void addScriptEventListener(String eventName, OnScriptEventListener listener);
+ /**
+ * Remove listener for specified event, concurrent event will be deleted. Return false only if the event does not exist
+ */
+ public boolean removeScriptEventListener(String eventName, OnScriptEventListener listener);
+ /**
+ * Remove all listener for event specified.
+ */
+ public void removeAllListenersForEvent(String eventName);
+ /**
+ * Remove all event registered. Use it carefully!
+ */
+ public void removeAllListeners() {
+ this.eventMap.clear();
+ }
+ /**
+ * Dispatch the event with argument, the event should be registered in javascript, or other script language in future.
+ */
+ public void dispatchEventToScript(String eventName, String arg);
+ /**
+ * Dispatch the event which is registered in javascript, or other script language in future.
+ */
+ public void dispatchEventToScript(String eventName);
+ }
+ ```
+
+## Basic usage
+
+### Register JS event, and using Objective-C/JAVA to trigger JavaScript event
+
+We can still do with the simple demand: Change the label content with native callback result. once the native event is triggered, it will return the specified text to JavaScript. Before that, we should add an event listener for `changeLabelContent`.
+
+#### Register JS event
+
+```js
+public changeLabelContent(user: string): void {
+ console.log("Hello " + user + " I'm K");
+ this.labelForContent!.string = "Hello " + user + " ! I'm K";
+}
+native.jsbBridgeWrapper.addNativeEventListener("changeLabelContent", (usr: string) => {
+ this.changeLabelContent(usr);
+});
+```
+
+#### Dispatch event to JS
+
+Once `changeLabelContent` event is triggered, label content will change to composition of specified strings. Before that, we should register the native event.
+
+- Objective-C code sample:
+
+ ```Objc
+ // Objective-C
+ JsbBridgeWrapper* m = [JsbBridgeWrapper sharedInstance];
+ OnScriptEventListener requestLabelContent = ^void(NSString* arg){
+ JsbBridgeWrapper* m = [JsbBridgeWrapper sharedInstance];
+ [m dispatchEventToScript:@"changeLabelContent" arg:@"Charlotte"];
+ };
+ [m addScriptEventListener:@"requestLabelContent" listener:requestLabelContent];
+ ```
+
+- JAVA code sample:
+
+ ```JAVA
+ // JAVA
+ JsbBridgeWrapper jbw = JsbBridgeWrapper.getInstance();
+ jbw.addScriptEventListener("requestLabelContent", arg ->{
+ System.out.print("@JAVA: here is the argument transport in" + arg);
+ jbw.dispatchEventToScript("changeLabelContent","Charlotte");
+ });
+ ```
+
+ > **Note**: You can also use anonymous function in JAVA too.
+
+#### Dispatch event to native
+
+The return value here is set to a const value, when JsbBridgeWrapper in Objective-C/JAVA receives the event notification of `requestLabelContent`, it will trigger `changeLabelContent` with a return value.
+
+The final step, add a button to start our test. the code example is as follows:
+
+```js
+// Button click event for SAY HELLO
+public sayHelloBtn() {
+ native.jsbBridgeWrapper.dispatchEventToNative("requestLabelContent");
+}
+```
+
+The effect is same as the test case of JsbBridge, click the `SAY HELLO` button, the label content will become a welcome message. Also, example case of JsbBridge is updated in repository.
diff --git a/versions/4.0/en/advanced-topics/jsb-manual-binding.md b/versions/4.0/en/advanced-topics/jsb-manual-binding.md
new file mode 100644
index 0000000000..3cd448c45b
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/jsb-manual-binding.md
@@ -0,0 +1,398 @@
+# JSB Manual Binding
+
+> This article is republished from [Tencent Online Education Department Technical Blog](https://oedx.github.io/2019/05/29/cocos-creator-js-binding-manual/)
+> Author: xepherjin
+
+## Background
+
+The overall JS/Native communication call structure in the ABCmouse project has always been based on the `callStaticMethod <-> evalString` approach. The `callStaticMethod` method makes it possible to call `Java/Objective-C` static methods directly in JavaScript through the reflection mechanism. With the `evalString` method, we can execute JS code, so that we can communicate with each other.
+
+
+
New ABCmouse application architecture: communication with evalString based on callStaticMethod
+
+Although it is easier to add new business logic after encapsulating the interface in the upper layer based on this approach. However, over-reliance on evalString often brings some pitfalls. As an example on the Android side.
+
+```js
+CocosJavascriptJavaBridge.evalString("window.sample.testEval('" + param + "',JSON.stringify(" + jsonObj + "))");
+```
+
+For common parameter structures, this works fine, however, based on real-world scenarios, we find that controlling the **quotes** is particularly important. As the code shows, in order to ensure that JS code is executed correctly, we must be clear about the use of `'` and `"` when concatenating strings, which can lead to `evalString` failures if we are not careful. We know from a lot of feedback on the official Cocos forums that this is a very easy place to get into trouble. On the other hand, for our project, the uncertainties caused by over-reliance on `evalString` are often difficult to control, and we can't just try/catch` to solve them. Fortunately, after global business troubleshooting, the majority of the project is currently in the project, so after reviewing the official documentation, we decided to bypass `evalString` and communicate directly based on JSB binding.
+
+Here is an example of downloader access. In our project, the downloader is implemented separately on the Android and iOS sides. In the previous version, the downloader calls and callbacks were based on the `callStaticMethod <-> evalString` approach.
+
+Each call to download needs to be executed like this.
+
+```ts
+import {NATIVE} from 'cc/env';
+
+if(NATVE && sys.os == sys.OS.IOS) {
+ jsb.reflection.callStaticMethod('ABCFileDownloader', 'downloadFileWithUrl:cookie:savePath:', url, cookies, savePath);
+} else if(NATVE && sys.os == sys.OS.ANDROID) {
+ jsb.reflection.callStaticMethod("com/tencent/abcmouse/downloader/ABCFileDownloader", "downloadFileWithUrl", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", url, cookies, savePath);
+}
+```
+
+A successful or unsuccessful download requires the execution of a JS by splicing together a statement like the following.
+
+```java
+StringBuilder sb = new StringBuilder(JS_STRING_ON_DOWNLOAD_FINISH + "(");
+sb.append("'" + success + "',");
+sb.append("'" + url + "',");
+sb.append("'" + savePath + "',");
+sb.append("'" + msg + "',");
+sb.append("'" +code + "')");
+CocosJavascriptJavaBridge.evalString(sb.toString());
+```
+
+Whether it is a call or a callback are cumbersome and error-prone splicing, all the data had to be converted into a string ~ ~ (emmmmm also not beautiful) ~ ~, and also take into account the `evalString` implementation efficiency issues. If only a few business scenarios in the use of still barely acceptable, but when the business is increasingly complex and large, if you have to write this, and there is no detailed documentation to regulate constraints, its post-maintenance costs can be imagined.
+
+When using JSB transformation, we call only a few lines of code and do not need to distinguish between platforms, not to worry about the above-mentioned splicing hidden problems, compared to the logic is much clearer.
+
+```js
+jsb.fileDownloader.requestDownload(url, savePath, cookies, options, (success, url, savePath, msg, code) => {
+ // do whatever you want
+});
+```
+
+So the next step is to take the simplest downloader binding process as an example, and I'll take you through the general process of JSB manual binding.
+**(Although Cocos Creator is very user-friendly and provides automatic binding configuration files, you can generate target files directly with some configurations, which reduces a lot of work. However, to complete the manual binding process by hand will help to understand the whole process of binding more comprehensively and help to deepen the understanding. (On the other hand, when there are special needs that cannot be met by automatic binding, manual binding is often more flexible)**
+
+## Pre-work
+
+Before we start, we need to know about the ScriptEngine abstraction layer, related APIs and other related knowledge, this part can be skipped if you already know from the Cocos Creator documentation and go straight to the **Practice** part.
+
+### Abstract layer
+
+
+
+In version 1.7, the abstraction layer was designed as a separate module with no relationship to the engine, and the management of the JS engine was moved from `ScriptingCore` to the `se::ScriptEngine` class, with `ScriptingCore` being retained in the hope that It is hoped that it will act as an adapter by passing some of the engine's events to the wrapper layer. This abstraction layer provides wrappers for a variety of optional JS execution engines such as JavaScriptCore, SpiderMonkey, V8, ChakraCore, etc. Most of the work of JSB is actually setting up C++ callbacks for JS-related operations and associating C++ objects in the callback functions. It actually contains the following two main types.
+
+- Register JS functions (including global functions, class constructors, class destructors, class member functions, class static member functions) and bind a C++ callback
+- Register JS object property read and write accessors, and bind separate read and write C++ callbacks
+
+Given that the definition of key methods varies across JS engines, the Cocos team uses **macros** to smooth out this difference in callback function definitions and parameter types, which you can read in detail in the Cocos Creator documentation at the end of this article.
+** It's worth mentioning that the ScriptEngine layer was designed by the Cocos team to be a standalone module that doesn't depend on the Cocos engine at all. **We developers can port all the source code of the abstraction layer under **cocos/bindings/jswrapper** and use it directly in other projects.
+
+### SE Types
+
+All types of the C++ abstraction layer are under the `se` namespace, which stands for ScriptEngine.
+
+- **se::ScriptEngine**
+
+ It is the administrator of the JS engine and is in charge of JS engine initialization, destruction, restart, Native module registration, loading scripts, forced garbage collection, JS exception cleanup, and whether to enable the debugger. It is a single instance, and the corresponding instance can be obtained via `se::ScriptEngine::getInstance()`.
+
+- **se::Value**
+
+ JS variables have six types `object`, `number`, `string`, `boolean`, `null`, `undefined`, so `se::Value` uses union to contain `object`, `number`, `string`, `boolean`, and `null`. string`, `boolean`. The non-valued types: `null`, `undefined` can be directly represented by the private variable `_type`.
+
+ If `se::Value` stores the base data type, such as `number`, `string`, `boolean`, it stores a copy of the value directly internally. The storage of `object` is special in that it is a weak reference to a JS object via `se::Object*`.
+
+- **se::Object**
+
+ Inherits from the `se::RefCounter` reference counter manager class, which holds a weak reference to a JS object. If we need to use the corresponding `se::Object` of the current object in the binding callback, we just need to get it with `s.thisObject()`. where s is of type `se::State`.
+
+- **se::Class**
+
+ After a Class type is created, there is no need to manually free memory, it is automatically handled by the wrapper layer. `se::Class` provides some APIs for defining class creation, static/dynamic member functions, property reading and writing, etc., which will be introduced later in the practice. The full contents can be found in the Cocos Creator documentation.
+
+- **se::State**
+
+ It is an environment in the binding callback where we can get the current C++ pointer, `se::Object` object pointer, parameter list, return value reference through `se::State`.
+
+### Macro
+
+As mentioned earlier, the abstraction layer uses macros to smooth out the differences in key function definitions and parameter types across JS engines, so that developers use one function definition regardless of the underlying engine.
+
+For example, all JS to C++ callback functions in the abstraction layer are defined as
+
+```cpp
+bool foo(se::State& s)
+{
+ ...
+ ...
+}
+SE_BIND_FUNC(foo) // Here is an example of the definition of a callback function
+```
+
+After we write the callback function, we need to remember to wrap the callback function using the `SE_BIND_XXX` series of macros. The full set of `SE_BIND_XXX` macros is currently shown below.
+
+- `SE_BIND_PROP_GET`: Wraps a JS object property read callback function
+- `SE_BIND_PROP_SET`: wraps a JS object property write callback function
+- `SE_BIND_FUNC`: wraps a JS function that can be used as a global function, class member function, or class static function
+- `SE_DECLARE_FUNC`: declares a JS function, usually used in the `.h` header file
+- `SE_BIND_CTOR`: wraps a JS constructor
+- `SE_BIND_SUB_CLS_CTOR`: wraps the constructor of a JS subclass that can inherit
+- `SE_BIND_FINALIZE_FUNC`: wraps a JS object callback function after it has been reclaimed by GC
+- `SE_DECLARE_FINALIZE_FUNC`: declares a callback function for a JS object after it has been reclaimed by GC
+- `_SE`: the name of the wrapper callback function, escaped to the definition of the callback function recognized by each JS engine, note that the first character is an underscore, similar to the _T("xxx") used under Windows to wrap Unicode or MultiBytes strings
+
+In our simplified example, only `SE_DECLARE_FUNC`, `SE_BIND_FUNC` will be used.
+
+### Type conversion helper functions
+
+The type conversion helper functions are located in **cocos/bindings/manual/jsb_conversions.h** and contain methods for interconverting `se::Value` to C++ types. The two main ones are as follows:
+
+- `bool sevalue_to_native(const se::Value &from, T *to, se::Object * /*ctx*/)`, from `se::Value` to a C++ type
+- `bool nativevalue_to_se(const T &from, se::Value& out, se::Object * /*ctx*/)`, from C++ type to `se::Value`
+
+> The third argument can be passed directly as `nullptr` in most cases, currently only the `function` type has a dependency on `ctx`.
+
+## Practices
+
+Before we get started, we need to clarify the process of JSB binding, which is simply the process of implementing some class libraries in the C++ layer, and then calling the corresponding methods on the JS side after some specific processing. Because JS is the main business language, we are limited in what we can do with Native functionality, such as file, network, and other related operations.
+
+SkeletonRenderer` in the Cocos Creator documentation, for example, if you call the `spine.SkeletonRenderer` constructor with the `new` operator in JSB, you will actually call the `js_spine_SkeletonRenderer _constructor` function. In this C++ function, memory is allocated for the skeleton object, it is added to the auto-recycle pool, and then the JS-level `_ctor` function is called to complete the initialization. The `_ctor` function calls different init functions depending on the type and number of arguments, and these init functions are also C++ function bindings.
+
+```cpp
+#define SE_BIND_CTOR(funcName, cls, finalizeCb) \
+ void funcName##Registry(const v8::FunctionCallbackInfo& _v8args) \
+ { \
+ v8::Isolate* _isolate = _v8args.GetIsolate(); \
+ v8::HandleScope _hs(_isolate); \
+ bool ret = true; \
+ se::ValueArray args; \
+ se::internal::jsToSeArgs(_v8args, &args); \
+ se::Object* thisObject = se::Object::_createJSObject(cls, _v8args.This()); \
+ thisObject->_setFinalizeCallback(_SE(finalizeCb)); \
+ se::State state(thisObject, args); \
+ ret = funcName(state); \
+ if (!ret) { \
+ SE_LOGE("[ERROR] Failed to invoke %s, location: %s:%d\n", #funcName, __FILE__, __LINE__); \
+ } \
+ se::Value _property; \
+ bool _found = false; \
+ _found = thisObject->getProperty("_ctor", &_property); \
+ if (_found) _property.toObject()->call(args, thisObject); \
+ }
+```
+
+The methodological correspondence of the three layers is as follows.
+
+| Javascript | JSB | Cocos Creator |
+| :--------- | :-----| :----------- |
+| jsb.SkeletonRenderer.initWithSkeleton | js_spine_SkeletonRenderer_initWithSkeleton | spine::SkeletonRenderer::initWithSkeleton |
+| jsb.SkeletonRenderer.initWithUUID | js_spine_SkeletonRenderer_initWithUUID | spine::SkeletonRenderer::initWithUUID |
+
+The timing of this call process is as follows.
+
+
+
Call timing diagram (quoted from Cocos Creator documentation)
+
+The process is similar to the one above. First, we need to define the interface and the fields, let's draw up the simplest downloader `FileDownloader`, which has the `download(url, path, callback)` interface, and in the `callback` we need to get the `code`, `msg`. And to make it easy to use, we mount it under the `jsb` object, so we can call it simply with the following code:
+
+```js
+jsb.fileDownloader.download(url, path, (msg, code) => {
+ // do whatever you want
+});
+```
+
+Once the interface is defined, we can start coding the C++ part. First of all, let's take a look at `FileDownloader.h`, which is a public header file for Android/iOS. Then Android/iOS implement their own specific download implementations (skipped here), and `reqCtx` is used to store the callback correspondence.
+
+```cpp
+class FileDownloader {
+ public:
+ typedef std::function ResultCallback;
+ static FileDownloader* getInstance();
+ static void destroyInstance();
+ void download(const std::string& url,
+ const std::string& savePath,
+ const ResultCallback& callback);
+ void onDownloadResult(const std::string msg, const int code);
+ ... ...
+ protected:
+ static FileDownloader* s_sharedFileDownloader;
+ std::unordered_map reqCtx;
+};
+```
+
+Next we proceed to the most critical part of the binding.
+Since the downloader is functionally classified as a network module, we can choose to implement our `FileDownloader` bindings in the existing `jsb_cocos_network_auto` in the Cocos source code. Declare the JS function in `jsb_cocos_network_auto.h` as follows
+
+```cpp
+SE_DECLARE_FUNC(js_network_FileDownloader_download); // Declare member functions, download calls
+SE_DECLARE_FUNC(js_network_FileDownloader_getInstance); // Declare static functions to get a single instance
+```
+
+Then register `FileDownloader` and the two newly declared functions to the JS virtual machine in `jsb_cocos_network_auto.cpp`. Start by writing the corresponding two method implementations and leave them blank, and then fill in the blanks when the registration logic is complete.
+
+```cpp
+static bool js_network_FileDownloader_download(se::State &s) { // The method name is the same as when it was declared
+ // TODO
+}
+
+SE_BIND_FUNC(js_network_FileDownloader_download); // Wrapping the method
+
+static bool js_network_FileDownloader_getInstance(se::State& s) { // The method name is the same as when it was declared
+ // TODO
+}
+
+SE_BIND_FUNC(js_network_FileDownloader_getInstance); // Wrapping the method
+```
+
+Now let's start writing the registration logic and add a new registration method to collect all the registration logic for `FileDownloader`.
+
+```cpp
+bool js_register_network_FileDownloader(se::Object* obj) {
+ auto cls = se::Class::create("FileDownloader", obj, nullptr, nullptr);
+ cls->defineFunction("download", _SE(js_network_FileDownloader_download));
+ cls->defineStaticFunction("getInstance", _SE(js_network_FileDownloader_getInstance));
+ cls->install();
+ JSBClassType::registerClass(cls);
+ se::ScriptEngine::getInstance()->clearException();
+ return true;
+}
+```
+
+Let's see what important things are done in this method.
+
+1. Call the `se::Class::create(className, obj, parentProto, ctor)` method to create a Class named `FileDownloader`. After successful registration, an instance can be created in the JS layer by `let xxx = new FileDownloader() After registration, you can create an instance in the JS layer by `let xxx = new FileDownloader() ;`. 2.
+2. Call the `defineFunction(name, func)` method to define a member function `download` and bind its implementation to the wrapped `js_network_FileDownloader_download`.
+3. call the `defineStaticFunction(name, func)` method, which defines a static member function `getInstance` and binds its implementation to the wrapped `js_network_FileDownloader_getInstance`.
+4. call the `install()` method to register itself to the JS virtual machine.
+5. Call the `JSBClassType::registerClass` method to map the generated class to a C++-level class (internally implemented via `std::unordered_map`).
+
+With these steps, we have completed the crucial registration part, but of course don't forget to add the `js_register_network_FileDownloader` call to the registration portal of the `network` module: `js_register_network_FileDownloader`.
+
+```cpp
+bool register_all_cocos_network(se::Object* obj)
+{
+ // Get the ns
+ se::Value nsVal;
+ if (!obj->getProperty("jsb", &nsVal))
+ {
+ se::HandleObject jsobj(se::Object::createPlainObject());
+ nsVal.setObject(jsobj);
+ obj->setProperty("jsb", nsVal);
+ }
+ se::Object* ns = nsVal.toObject();
+
+ ... ...
+ // Set the Class registration generated earlier to a property of jsb so that we can pass
+ // let downloader = new jsb.FileDownloader();
+ // Get the instance
+ js_register_network_FileDownloader(ns);
+ return true;
+}
+```
+
+With this step done, our class has been successfully bound, so now we come back to refine the methods we left blank.
+
+First is `getInstance()`.
+
+```cpp
+static bool js_network_FileDownloader_getInstance(se::State& s)
+{
+ const auto& args = s.args();
+ size_t argc = args.size();
+ CC_UNUSED bool ok = true;
+ if (argc == 0) {
+ FileDownloader* result = FileDownloader::getInstance(); // C++ 单例
+ ok &= nativevalue_to_se(result, s.rval(), nullptr);
+ SE_PRECONDITION2(ok, false, "js_network_FileDownloader_getInstance : Error processing arguments");
+ return true;
+ }
+ SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 0);
+ return false;
+}
+```
+
+As mentioned earlier, we can get C++ pointer, `se::Object` object pointer, parameter list, return value reference through `se::State`. The logic is sorted out as follows.
+
+1. `args()` gets all the arguments (vector of `se::Value`) brought by JS.
+2. the number of arguments, because here `getInstance()` does not need additional arguments, so the argument is 0.
+3. `native_ptr_to_seval()` is used to get a `se::Value` at the binding level based on a C++ object pointer and assign the return value to `rval()` to the JS level.
+
+At this point, the binding layer logic of `getInstance()` is all done and we can already get the instance via `let downloader = jsb.FileDownloader.getInstance()`.
+
+Next is `download()`.
+
+```cpp
+static bool js_network_FileDownloader_download(se::State &s) {
+ FileDownloader *cobj = (FileDownloader *) s.nativeThisObject();
+ SE_PRECONDITION2(cobj, false,
+ "js_network_FileDownloader_download : Invalid Native Object");
+ const auto &args = s.args();
+ size_t argc = args.size();
+ CC_UNUSED bool ok = true;
+ if (argc == 3) {
+ std::string url;
+ std::string path;
+ ok &= sevalue_to_native(args[0], &url, nullptr); // Converted to ::string url
+ ok &= sevalue_to_native(args[1], &path, nullptr); // Converted to ::string path
+ std::function callback;
+ do {
+ if (args[2].isObject() && args[2].toObject()->isFunction())
+ {
+ se::Value jsThis(s.thisObject());
+ // Get JS callbacks
+ se::Value jsFunc(args[2]);
+ // If the target class is a singleton, it cannot be associated with se::Object::attachObject
+ // You must use se::Object::root and do not care about unroot. The unroot operation will trigger the destruct of jsFunc with the destruction of the lambda, and the unroot operation will be performed in the destructor of se::Object.
+ // If s.thisObject->attachObject(jsFunc.toObject); is used, the corresponding func and target will never be freed and a memory leak will occur.
+ jsFunc.toObject()->root();
+ auto lambda = [=](const std::string& msg,
+ const int code) -> void {
+ se::ScriptEngine::getInstance()->clearException();
+ se::AutoHandleScope hs;
+ CC_UNUSED bool ok = true;
+ se::ValueArray args;
+ args.resize(2);
+ ok &= nativevalue_to_se(msg, args[0], nullptr);
+ ok &= nativevalue_to_se(code, args[1], nullptr);
+ se::Value rval;
+ se::Object* thisObj = jsThis.isObject() ? jsThis.toObject() : nullptr;
+ se::Object* funcObj = jsFunc.toObject();
+ // Execute JS method callbacks
+ bool succeed = funcObj->call(args, thisObj, &rval);
+ if (!succeed) {
+ se::ScriptEngine::getInstance()->clearException();
+ }
+ };
+ callback = lambda;
+ }
+ else
+ {
+ callback = nullptr;
+ }
+ } while(false);
+ SE_PRECONDITION2(ok, false, "js_network_FileDownloader_download : Error processing arguments");
+ cobj->download(url, path, callback);
+ return true;
+ }
+ SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int) argc, 3);
+ return false;
+}
+```
+
+1. Get the url, path parameters and the original jsFunc after C++ conversion by `seval_to_std_string` method.
+2. Manually construct the callback function to convert msg and code to `se::Value`. 3.
+3. execute the JS method for callback via `funcObj->call`.
+
+Finally, given the risk of memory release, we also need to do the relevant recycling in the `close()` method in `Application.cpp`.
+
+```cpp
+network::FileDownloader::destroyInstance();
+```
+
+================================================
+
+The above is the whole binding process, after compiling to Android/iOS environment respectively, we will be able to make download calls via `jsb.fileDownloader.download()`.
+(PS: Be sure to remember to perform `NATIVE` macro judgment before use, because the non-JSB environment can not be used)
+
+```typescript
+import {NATIVE} from 'cc/env';
+...
+if(NATIVE) {
+ // JSB Related Logic
+}
+
+```
+
+## Summary
+
+Let's now summarize the detailed process of manual binding transformation. In general, the transformation process for commonly used JSBs is roughly as follows.
+- Determine the method interface and JS/Native public fields
+- Declare header files and implement Android JNI and OC specific business code respectively
+- Write abstraction layer code to register the necessary classes and corresponding methods in the JS virtual machine
+- Mount the bound class in a specified object (like a namespace) in JS
diff --git a/versions/4.0/en/advanced-topics/jsb-optimizations.md b/versions/4.0/en/advanced-topics/jsb-optimizations.md
new file mode 100644
index 0000000000..bd8e71becd
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/jsb-optimizations.md
@@ -0,0 +1,872 @@
+# Optimization of Cross-Language Invocation
+
+## Introduction
+
+In the native implementation of Cocos Creator version 3.6.0, we have made improvements in the native (CPP) code. This mainly involves the implementation of the node tree (Scene, Node), assets (Asset and its subclasses), material system (Material, Pass, ProgramLib), 3D renderer (including Model, SubModel), and 2D renderer (Batch2D, RenderEntity) in CPP. And these functionalities are exposed to the JS through binding techniques.
+
+As known to all, in Cocos Creator 3.x, developers can only use TypeScript (TS) scripts to develop game logic. Although we have implemented more engine code in CPP, developers cannot directly use CPP for game logic development. Therefore, we use the Script Engine Wrapper API (referred to as SE API) to bind and expose the types implemented in the CPP to JS. The interfaces exposed to JS remain consistent with those in the web environment.
+
+The primary benefit of moving core code to the native is that the execution performance of engine code running on native platforms is improved, especially on platforms that do not support JIT compilation (such as iOS). However, before the official release of version 3.6.0, we also faced a series of side effects resulting from the "elevation of the native level". The main issue was that the number of JSB calls (interactions between JS and CPP languages) increased significantly compared to previous versions. This directly offset the benefits brought by the elevation of the native level and even resulted in poorer performance compared to the previous version(v3.5). This article will introduce some optimization methods to reduce JSB calls. If developers encounter similar issues with excessive JSB calls in their own CPP code, we hope this article can provide some optimization insights.
+
+## Shared Memory
+
+For properties in Node that require frequent synchronization, we utilize shared memory between CPP and JS to avoid JSB calls. To facilitate the sharing of CPP memory with JS, we have encapsulated the bindings::NativeMemorySharedToScriptActor helper class.
+
+bindings/utils/BindingUtils.h
+
+```c++
+namespace cc::bindings {
+
+class NativeMemorySharedToScriptActor final {
+public:
+ NativeMemorySharedToScriptActor() = default;
+ ~NativeMemorySharedToScriptActor();
+
+ void initialize(void *ptr, uint32_t byteLength);
+ void destroy();
+
+ inline se::Object *getSharedArrayBufferObject() const { return _sharedArrayBufferObject; }
+
+private:
+ se::Object *_sharedArrayBufferObject{nullptr};
+
+ CC_DISALLOW_COPY_MOVE_ASSIGN(NativeMemorySharedToScriptActor)
+};
+
+} // namespace cc::bindings
+```
+
+bindings/utils/BindingUtils.h
+
+```c++
+#include "bindings/utils/BindingUtils.h"
+#include "bindings/jswrapper/SeApi.h"
+
+namespace cc::bindings {
+
+NativeMemorySharedToScriptActor::~NativeMemorySharedToScriptActor() {
+ destroy();
+}
+
+void NativeMemorySharedToScriptActor::initialize(void* ptr, uint32_t byteLength) {
+ CC_ASSERT_NULL(_sharedArrayBufferObject);
+ // The callback of freeing buffer is empty since the memory is managed in native,
+ //The external array buffer just holds a reference to the memory.
+ _sharedArrayBufferObject = se::Object::createExternalArrayBufferObject(ptr, byteLength, [](void* /*contents*/, size_t /*byteLength*/, void* /*userData*/) {});
+ // Root this object to prevent it from being garbage collected (GC), we will invoke `unroot` in the destroy function.
+ _sharedArrayBufferObject->root();
+}
+
+void NativeMemorySharedToScriptActor::destroy() {
+ if (_sharedArrayBufferObject != nullptr) {
+ _sharedArrayBufferObject->unroot();
+ _sharedArrayBufferObject->decRef();
+ _sharedArrayBufferObject = nullptr;
+ }
+}
+
+} // namespace cc::bindings
+```
+
+bindings/jswrapper/v8/Object.h
+
+```c++
+using BufferContentsFreeFunc = void (*)(void *contents, size_t byteLength, void *userData);
+static Object *createExternalArrayBufferObject(void *contents, size_t byteLength, BufferContentsFreeFunc freeFunc, void *freeUserData = nullptr);
+```
+
+bindings/jswrapper/v8/Object.cpp
+
+```c++
+/* static */
+Object *Object::createExternalArrayBufferObject(void *contents, size_t byteLength, BufferContentsFreeFunc freeFunc, void *freeUserData /* = nullptr*/) {
+ Object *obj = nullptr;
+ std::shared_ptr backingStore = v8::ArrayBuffer::NewBackingStore(contents, byteLength, freeFunc, freeUserData);
+ v8::Local jsobj = v8::ArrayBuffer::New(__isolate, backingStore);
+
+ if (!jsobj.IsEmpty()) {
+ obj = Object::_createJSObject(nullptr, jsobj);
+ }
+ return obj;
+}
+```
+
+Analysis of the code above reveals that NativeMemorySharedToScriptActor calls the v8::ArrayBuffer::NewBackingStore and v8::ArrayBuffer::New functions to create an External type of ArrayBuffer. It is named "External" because its memory is not allocated and managed internally by V8. Instead, its memory is entirely managed by the code out of V8. When the ArrayBuffer object is garbage collected, the freeFunc callback function is triggered. In Node, the memory that needs to be shared consists of several contiguous properties in the Node. The creation and release of this memory are entirely handled by CPP Node itself, and the destruction of CPP Node instances is controlled by the GC. Therefore, when NativeMemorySharedToScriptActor::initialize internally calls se::Object::createExternalArrayBufferObject, it passes an empty implementation of the callback function.
+
+Node.h
+
+```c++
+class Node : public CCObject {
+ ......
+ inline se::Object *_getSharedArrayBufferObject() const { return _sharedMemoryActor.getSharedArrayBufferObject(); } // NOLINT
+ ......
+ bindings::NativeMemorySharedToScriptActor _sharedMemoryActor;
+ ......
+ // Shared memory with JS
+ // NOTE: TypeArray created in node.jsb.ts _ctor should have the same memory layout
+ uint32_t _eventMask{0}; // Uint32: 0
+ uint32_t _layer{static_cast(Layers::LayerList::DEFAULT)}; // Uint32: 1
+ uint32_t _transformFlags{0}; // Uint32: 2
+ index_t _siblingIndex{0}; // Int32: 0
+ uint8_t _activeInHierarchy{0}; // Uint8: 0
+ uint8_t _active{1}; // Uint8: 1
+ uint8_t _isStatic{0}; // Uint8: 2
+ uint8_t _padding{0}; // Uint8: 3
+ ......
+};
+```
+
+Node.cpp
+
+```c++
+Node::Node(const ccstd::string &name) {
+#define NODE_SHARED_MEMORY_BYTE_LENGTH (20)
+ static_assert(offsetof(Node, _padding) + sizeof(_padding) - offsetof(Node, _eventMask) == NODE_SHARED_MEMORY_BYTE_LENGTH, "Wrong shared memory size");
+ _sharedMemoryActor.initialize(&_eventMask, NODE_SHARED_MEMORY_BYTE_LENGTH);
+#undef NODE_SHARED_MEMORY_BYTE_LENGTH
+
+ _id = idGenerator.getNewId();
+ if (name.empty()) {
+ _name.append("New Node");
+ } else {
+ _name = name;
+ }
+}
+```
+
+In the Node constructor, `_sharedMemoryActor.initialize(&_eventMask, NODE_SHARED_MEMORY_BYTE_LENGTH);` is called to set the first 20 bytes starting from the `_eventMask` property as shared memory.
+
+node.jsb.ts
+
+> **Note**: All files ending with `.jsb.ts` will be replaced with their corresponding versions without the `.jsb` extension during the packaging process. For example, `node.jsb.ts` will replace `node.ts`. You can refer to the `cc.config.json` file in the root directory of the engine for more details. It contains the corresponding `overrides` field, such as `"cocos/scene-graph/node.ts": "cocos/scene-graph/node.jsb.ts"`.
+
+```ts
+// The _ctor callback function in JS is triggered during the final stage of the `var node = new Node();` process in JS, i.e., after the CPP Node object is created. Therefore, the ArrayBuffer returned by the _getSharedArrayBufferObject binding function must exist.
+nodeProto._ctor = function (name?: string) {
+ ......
+ // Get the CPP shared ArrayBuffer object through the _getSharedArrayBufferObject binding method
+ const sharedArrayBuffer = this._getSharedArrayBufferObject();
+ // Uint32Array with 3 elements, offset from the start: eventMask, layer, dirtyFlags
+ this._sharedUint32Arr = new Uint32Array(sharedArrayBuffer, 0, 3);
+ // Int32Array with 1 element, offset from the 12th byte: siblingIndex
+ this._sharedInt32Arr = new Int32Array(sharedArrayBuffer, 12, 1);
+ // Uint8Array with 3 elements, offset from the 16th byte: activeInHierarchy, active, static
+ this._sharedUint8Arr = new Uint8Array(sharedArrayBuffer, 16, 3);
+ //
+
+ this._sharedUint32Arr[1] = Layers.Enum.DEFAULT; // this._sharedUint32Arr[1] represents the layer
+ ......
+};
+```
+
+By using shared memory, it also means that we cannot pass the values to be set from JS to CPP through JSB binding functions. Therefore, we need to define corresponding getter/setter functions in the `.jsb.ts` file. These functions will internally modify the shared memory by directly manipulating the TypedArray.
+
+```ts
+Object.defineProperty(nodeProto, 'activeInHierarchy', {
+ configurable: true,
+ enumerable: true,
+ get (): Readonly {
+ return this._sharedUint8Arr[0] != 0; // Uint8, 0: activeInHierarchy
+ },
+ set (v) {
+ this._sharedUint8Arr[0] = (v ? 1 : 0); // Uint8, 0: activeInHierarchy
+ },
+});
+
+Object.defineProperty(nodeProto, '_activeInHierarchy', {
+ configurable: true,
+ enumerable: true,
+ get (): Readonly {
+ return this._sharedUint8Arr[0] != 0; // Uint8, 0: activeInHierarchy
+ },
+ set (v) {
+ this._sharedUint8Arr[0] = (v ? 1 : 0); // Uint8, 0: activeInHierarchy
+ },
+});
+
+Object.defineProperty(nodeProto, 'layer', {
+ configurable: true,
+ enumerable: true,
+ get () {
+ return this._sharedUint32Arr[1]; // Uint32, 1: layer
+ },
+ set (v) {
+ this._sharedUint32Arr[1] = v; // Uint32, 1: layer
+ if (this._uiProps && this._uiProps.uiComp) {
+ this._uiProps.uiComp.setNodeDirty();
+ this._uiProps.uiComp.markForUpdateRenderData();
+ }
+ this.emit(NodeEventType.LAYER_CHANGED, v);
+ },
+});
+
+Object.defineProperty(nodeProto, '_layer', {
+ configurable: true,
+ enumerable: true,
+ get () {
+ return this._sharedUint32Arr[1]; // Uint32, 1: layer
+ },
+ set (v) {
+ this._sharedUint32Arr[1] = v; // Uint32, 1: layer
+ },
+});
+
+Object.defineProperty(nodeProto, '_eventMask', {
+ configurable: true,
+ enumerable: true,
+ get () {
+ return this._sharedUint32Arr[0]; // Uint32, 0: eventMask
+ },
+ set (v) {
+ this._sharedUint32Arr[0] = v; // Uint32, 0: eventMask
+ },
+});
+
+Object.defineProperty(nodeProto, '_siblingIndex', {
+ configurable: true,
+ enumerable: true,
+ get () {
+ return this._sharedInt32Arr[0]; // Int32, 0: siblingIndex
+ },
+ set (v) {
+ this._sharedInt32Arr[0] = v; // Int32, 0: siblingIndex
+ },
+});
+
+nodeProto.getSiblingIndex = function getSiblingIndex() {
+ return this._sharedInt32Arr[0]; // Int32, 0: siblingIndex
+};
+
+Object.defineProperty(nodeProto, '_transformFlags', {
+ configurable: true,
+ enumerable: true,
+ get () {
+ return this._sharedUint32Arr[2]; // Uint32, 2: _transformFlags
+ },
+ set (v) {
+ this._sharedUint32Arr[2] = v; // Uint32, 2: _transformFlags
+ },
+});
+
+Object.defineProperty(nodeProto, '_active', {
+ configurable: true,
+ enumerable: true,
+ get (): Readonly {
+ return this._sharedUint8Arr[1] != 0; // Uint8, 1: active
+ },
+ set (v) {
+ this._sharedUint8Arr[1] = (v ? 1 : 0); // Uint8, 1: active
+ },
+});
+
+Object.defineProperty(nodeProto, 'active', {
+ configurable: true,
+ enumerable: true,
+ get (): Readonly {
+ return this._sharedUint8Arr[1] != 0; // Uint8, 1: active
+ },
+ set (v) {
+ this.setActive(!!v);
+ },
+});
+
+Object.defineProperty(nodeProto, '_static', {
+ configurable: true,
+ enumerable: true,
+ get (): Readonly {
+ return this._sharedUint8Arr[2] != 0;
+ },
+ set (v) {
+ this._sharedUint8Arr[2] = (v ? 1 : 0);
+ },
+});
+```
+
+### Performance Comparison Results
+
+
+
+## Avoiding Parameters Passing
+
+If JSB function calls involve parameters, V8 internally needs to validate the reasonableness of the parameters. These validation tasks can also impact the performance of the calls. For JSB functions that may be frequently called in Node, we avoid passing floating-point parameters by reusing a global Float32Array.
+
+scene-graph/utils.jsb.ts
+
+```ts
+import { IMat4Like, Mat4 } from '../core/math';
+
+declare const jsb: any;
+
+// For optimizing getPosition, getRotation, getScale
+export const _tempFloatArray = new Float32Array(jsb.createExternalArrayBuffer(20 * 4));
+
+export const fillMat4WithTempFloatArray = function fillMat4WithTempFloatArray (out: IMat4Like) {
+ Mat4.set(out,
+ _tempFloatArray[0], _tempFloatArray[1], _tempFloatArray[2], _tempFloatArray[3],
+ _tempFloatArray[4], _tempFloatArray[5], _tempFloatArray[6], _tempFloatArray[7],
+ _tempFloatArray[8], _tempFloatArray[9], _tempFloatArray[10], _tempFloatArray[11],
+ _tempFloatArray[12], _tempFloatArray[13], _tempFloatArray[14], _tempFloatArray[15]
+ );
+};
+//
+```
+
+The above code defines a global `_tempFloatArray` that is used to store number or composite types (such as Vec3, Vec4, Mat4, etc.) parameters.
+
+node.jsb.ts
+
+```ts
+// ......
+// Set the FloatArray to the CPP code
+Node._setTempFloatArray(_tempFloatArray.buffer);
+// ......
+// Reimplement the setPosition function in JS with parameters
+nodeProto.setPosition = function setPosition(val: Readonly | number, y?: number, z?: number) {
+ if (y === undefined && z === undefined) {
+ // When both y and z are undefined, it means the first parameter is of type Vec3
+ _tempFloatArray[0] = 3;
+ const pos = val as Vec3;
+ // Assign the new pos to the FloatArray and this._lpos cache
+ this._lpos.x = _tempFloatArray[1] = pos.x;
+ this._lpos.y = _tempFloatArray[2] = pos.y;
+ this._lpos.z = _tempFloatArray[3] = pos.z;
+ } else if (z === undefined) {
+ // If z is undefined, there are only 2 parameters x and y
+ _tempFloatArray[0] = 2;
+ this._lpos.x = _tempFloatArray[1] = val as number;
+ this._lpos.y = _tempFloatArray[2] = y as number;
+ } else {
+ _tempFloatArray[0] = 3;
+ this._lpos.x = _tempFloatArray[1] = val as number;
+ this._lpos.y = _tempFloatArray[2] = y as number;
+ this._lpos.z = _tempFloatArray[3] = z as number;
+ }
+ this._setPosition(); // This is a native binding function without parameters
+};
+```
+
+jsb_scene_manual.cpp
+
+```ts
+namespace {
+
+/**
+ * Helper class for operating on the shared global FloatArray
+ */
+class TempFloatArray final {
+public:
+ TempFloatArray() = default;
+ ~TempFloatArray() = default;
+
+ inline void setData(float* data) { _data = data; }
+
+ ......
+
+ inline const float& operator[](size_t index) const { return _data[index]; }
+ inline float& operator[](size_t index) { return _data[index]; }
+
+private:
+ float* _data{ nullptr };
+
+ CC_DISALLOW_ASSIGN(TempFloatArray)
+};
+
+TempFloatArray tempFloatArray;
+
+} // namespace
+```
+
+```c++
+static bool js_scene_Node_setTempFloatArray(se::State& s) // NOLINT(readability-identifier-naming)
+{
+ const auto& args = s.args();
+ size_t argc = args.size();
+ CC_UNUSED bool ok = true;
+ if (argc == 1) {
+ uint8_t* buffer = nullptr;
+ args[0].toObject()->getArrayBufferData(&buffer, nullptr);
+ // Initialize the associated data of TempFloatArray
+ tempFloatArray.setData(reinterpret_cast(buffer));
+ return true;
+ }
+ SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
+ return false;
+}
+SE_BIND_FUNC(js_scene_Node_setTempFloatArray)
+```
+
+```c++
+bool register_all_scene_manual(se::Object* obj) // NOLINT(readability-identifier-naming)
+{
+ ......
+ __jsb_cc_Node_proto->defineFunction("_setPosition", _SE(js_scene_Node_setPosition));
+ __jsb_cc_Node_proto->defineFunction("_setScale", _SE(js_scene_Node_setScale));
+ __jsb_cc_Node_proto->defineFunction("_setRotation", _SE(js_scene_Node_setRotation));
+ __jsb_cc_Node_proto->defineFunction("_setRotationFromEuler", _SE(js_scene_Node_setRotationFromEuler));
+ __jsb_cc_Node_proto->defineFunction("_rotateForJS", _SE(js_scene_Node_rotateForJS));
+ ......
+}
+```
+
+```c++
+// Binding for node._setPosition() without parameters
+static bool js_scene_Node_setPosition(void* s) // NOLINT(readability-identifier-naming)
+{
+ auto* cobj = reinterpret_cast(s);
+ auto argc = static_cast(tempFloatArray[0]);
+ if (argc == 2) {
+ // Get the parameters from tempFloatArray
+ cobj->setPositionInternal(tempFloatArray[1], tempFloatArray[2], true);
+ } else {
+ cobj->setPositionInternal(tempFloatArray[1], tempFloatArray[2], tempFloatArray[3], true);
+ }
+ return true;
+}
+SE_BIND_FUNC_FAST(js_scene_Node_setPosition) // Note that the new SE_BIND_FUNC_FAST macro is used here
+```
+
+Node.h
+
+```c++
+ inline void setPositionInternal(float x, float y, bool calledFromJS) { setPositionInternal(x, y, _localPosition.z, calledFromJS); }
+ void setPositionInternal(float x, float y, float z, bool calledFromJS);
+```
+
+bindings/jswrapper/v8/HelperMacros.h
+
+```c++
+#define SE_BIND_FUNC(funcName) \
+ void funcName##Registry(const v8::FunctionCallbackInfo &_v8args) { \
+ JsbInvokeScope(#funcName); \
+ jsbFunctionWrapper(_v8args, funcName, #funcName); \
+ }
+
+#define SE_BIND_FUNC_FAST(funcName) \
+ void funcName##Registry(const v8::FunctionCallbackInfo &_v8args) { \
+ auto *thisObject = static_cast(_v8args.This()->GetAlignedPointerFromInternalField(0)); \
+ auto *nativeObject = thisObject != nullptr ? thisObject->getPrivateData() : nullptr; \
+ funcName(nativeObject); \
+ }
+```
+
+bindings/jswrapper/v8/HelperMacros.cpp
+
+```c++
+// The SE_BIND_FUNC macro calls the jsbFunctionWrapper function, which performs additional tasks internally.
+SE_HOT void jsbFunctionWrapper(const v8::FunctionCallbackInfo &v8args, se_function_ptr func, const char *funcName) {
+ bool ret = false;
+ v8::Isolate *isolate = v8args.GetIsolate();
+ v8::HandleScope scope(isolate);
+ bool needDeleteValueArray{false};
+ se::ValueArray &args = se::gValueArrayPool.get(v8args.Length(), needDeleteValueArray);
+ se::CallbackDepthGuard depthGuard{args, se::gValueArrayPool._depth, needDeleteValueArray};
+ se::internal::jsToSeArgs(v8args, args);
+ se::Object *thisObject = se::internal::getPrivate(isolate, v8args.This());
+ se::State state(thisObject, args);
+ ret = func(state);
+ if (!ret) {
+ SE_LOGE("[ERROR] Failed to invoke %s\n", funcName);
+ }
+ se::internal::setReturnValue(state.rval(), v8args);
+}
+```
+
+The internal implementation of the `SE_BIND_FUNC_FAST` macro is extremely fast because it is very simple. It immediately triggers the callback function once it obtains the private data, without any se-related API calls. This avoids the conversion between `se::Value` and `jsvalue` and also bypasses parameter validation by V8. You can compare it with the standard implementation of the `SE_BIND_FUNC` macro.
+
+Furthermore, you may wonder why we don't share the position, rotation, and scale information directly through the approach described in the 'Shared Memory' section, but using `_setPosition()`, `_setRotation()`, and `_setScale()` JSB methods without parameters. The reason is that this JSB calls cannot be removed. Let's take a look at the implementation of `Node::setPosition()`:
+
+```c++
+class Node : public CCObject {
+ ......
+ inline void setPosition(const Vec3 &pos) { setPosition(pos.x, pos.y, pos.z); }
+ inline void setPosition(float x, float y) { setPosition(x, y, _localPosition.z); }
+ inline void setPosition(float x, float y, float z) { setPositionInternal(x, y, z, false); }
+ inline void setPositionInternal(float x, float y, bool calledFromJS) { setPositionInternal(x, y, _localPosition.z, calledFromJS); }
+ void setPositionInternal(float x, float y, float z, bool calledFromJS);
+
+ ......
+ inline uint32_t getChangedFlags() const {
+ return _hasChangedFlagsVersion == globalFlagChangeVersion ? _hasChangedFlags : 0;
+ }
+ inline void setChangedFlags(uint32_t value) {
+ _hasChangedFlagsVersion = globalFlagChangeVersion;
+ _hasChangedFlags = value;
+ }
+ ......
+};
+```
+
+```c++
+void Node::setPositionInternal(float x, float y, float z, bool calledFromJS) {
+ _localPosition.set(x, y, z);
+ invalidateChildren(TransformBit::POSITION);
+
+ if (_eventMask & TRANSFORM_ON) {
+ emit(TransformBit::POSITION);
+ }
+
+ if (!calledFromJS) {
+ notifyLocalPositionUpdated();
+ }
+}
+```
+
+`setPosition` not only assigns a value to `_localPosition`, but it also needs to trigger the invocation of the `invalidateChildren` function. `invalidateChildren` is a recursive function that internally traverses all child nodes and modifies other properties such as `_transformFlags`, `_hasChangedFlagsVersion`, and `_hasChangedFlags`. Therefore, we cannot remove `setPosition` through the "shared memory" approach mentioned in the first section.
+
+### Performance Comparison Results
+
+
+
+## Caching Properties
+
+Caching properties in the JS can help avoid accessing the C++ interface through getters and reduce JSB(JavaScript Bindings) calls.
+
+node.jsb.ts
+
+```ts
+Object.defineProperty(nodeProto, 'position', {
+ configurable: true,
+ enumerable: true,
+ get (): Readonly {
+ return this._lpos;
+ },
+ set (v: Readonly) {
+ this.setPosition(v as Vec3);
+ },
+});
+
+nodeProto.getPosition = function getPosition (out?: Vec3): Vec3 {
+ if (out) {
+ return Vec3.set(out, this._lpos.x, this._lpos.y, this._lpos.z);
+ }
+ return Vec3.copy(new Vec3(), this._lpos);
+};
+
+nodeProto._ctor = function (name?: string) {
+ ......
+ this._lpos = new Vec3();
+ this._lrot = new Quat();
+ this._lscale = new Vec3(1, 1, 1);
+ this._euler = new Vec3();
+ .......
+};
+```
+
+### Performance Comparison Results
+
+
+
+## Node Synchronization
+
+In the user's logic code, it is common to use the following pattern:
+
+```ts
+const children = node.children;
+for (let i = 0; i < children.length; ++i) {
+ const child = children[i];
+ // do something with child
+}
+```
+
+The `.children` getter may be called frequently, which can result in excessive JSB (JavaScript Bindings) calls. The getter for `children` is bound uniquely because it represents a JS array, while in CPP it corresponds to the type `ccstd::vector _children;`. As a result, there is no straightforward way to synchronize data between JS Array and CPP's std::vector. If the `.children` getter is called using JSB each time, it will generate a temporary JS Array using `se::Object::createArrayObject`, and then convert each CPP child to JS child using `nativevalue_to_se` and assign it to the JS Array. This incurs a heavy conversion overhead and generates temporary arrays that need to be garbage collected, adding additional pressure to the GC.
+
+To address this issue, we cache the `_children` property in the JS. When `_children` is modified in the CPP, we use the event system to notify the JS code's `_children` to update its content. This is achieved by listening to `ChildAdded` and `ChildRemoved` events.
+
+Let's illustrate this with the example of `node.addChild(child);`:
+
+```c++
+class Node : public CCObject {
+ ......
+ inline void addChild(Node *node) { node->setParent(this); }
+
+ inline void removeChild(Node *node) const {
+ auto idx = getIdxOfChild(_children, node);
+ if (idx != -1) {
+ node->setParent(nullptr);
+ }
+ }
+ inline void removeFromParent() {
+ if (_parent) {
+ _parent->removeChild(this);
+ }
+ }
+ void removeAllChildren();
+ ......
+};
+```
+
+```c++
+void Node::setParent(Node* parent, bool isKeepWorld /* = false */) {
+ ......
+ onSetParent(oldParent, isKeepWorld);
+ emit(oldParent);
+ if (oldParent) {
+ if (!(oldParent->_objFlags & Flags::DESTROYING)) {
+ index_t removeAt = getIdxOfChild(oldParent->_children, this);
+ if (removeAt < 0) {
+ return;
+ }
+ // Remove the child from the old parent node
+ oldParent->_children.erase(oldParent->_children.begin() + removeAt);
+ oldParent->updateSiblingIndex();
+ oldParent->emit(this);
+ }
+ }
+ if (newParent) {
+ ......
+ // Add the child to the new parent node
+ newParent->_children.emplace_back(this);
+ _siblingIndex = static_cast(newParent->_children.size() - 1);
+ newParent->emit(this);
+ }
+ onHierarchyChanged(oldParent);
+}
+```
+
+After calling `addChild`, the `Node::_children` in the CPP is modified, it triggers the `emit` event. This event is listened to during Node initialization, as seen in the code snippet in `jsb_scene_manual.cpp`.
+
+```c++
+// jsb_scene_manual.cpp
+static void registerOnChildAdded(cc::Node *node, se::Object *jsObject) {
+ node->on(
+ [jsObject](cc::Node * /*emitter*/, cc::Node *child) {
+ se::AutoHandleScope hs;
+ se::Value arg0;
+ nativevalue_to_se(child, arg0);
+ // Call the private JS function _onChildAdded
+ se::ScriptEngine::getInstance()->callFunction(jsObject, "_onChildAdded", 1, &arg0);
+ });
+}
+
+static bool js_scene_Node_registerOnChildAdded(se::State &s) // NOLINT(readability-identifier-naming)
+{
+ auto *cobj = SE_THIS_OBJECT(s);
+ SE_PRECONDITION2(cobj, false, "Invalid Native Object");
+
+ auto *jsObject = s.thisObject();
+
+ registerOnChildAdded(cobj, jsObject);
+ return true;
+}
+SE_BIND_FUNC(js_scene_Node_registerOnChildAdded) // NOLINT(readability-identifier-naming)
+
+bool register_all_scene_manual(se::Object *obj) // NOLINT(readability-identifier-naming)
+{
+ ......
+ __jsb_cc_Node_proto->defineFunction("_registerOnChildAdded", _SE(js_scene_Node_registerOnChildAdded));
+ ......
+}
+```
+
+node.jsb.ts
+
+```ts
+Object.defineProperty(nodeProto, 'children', {
+ configurable: true,
+ enumerable: true,
+ get () {
+ return this._children;
+ },
+ set (v) {
+ this._children = v;
+ },
+});
+
+nodeProto._onChildRemoved = function (child) {
+ this.emit(NodeEventType.CHILD_REMOVED, child);
+};
+
+// This function is called by the CPP's registerOnChildAdded function
+nodeProto._onChildAdded = function (child) {
+ this.emit(NodeEventType.CHILD_ADDED, child);
+};
+
+nodeProto.on = function (type, callback, target, useCapture: any = false) {
+ switch (type) {
+ ......
+ case NodeEventType.CHILD_ADDED:
+ if (!(this._registeredNodeEventTypeMask & REGISTERED_EVENT_MASK_CHILD_ADDED_CHANGED)) {
+ this._registerOnChildAdded(); // Call the JSB method to register the listener
+ this._registeredNodeEventTypeMask |= REGISTERED_EVENT_MASK_CHILD_ADDED_CHANGED;
+ }
+ break;
+ ......
+ default:
+ break;
+ }
+ this._eventProcessor.on(type, callback, target, useCapture);
+};
+
+nodeProto._ctor = function (name?: string) {
+ ......
+ this._children = [];
+
+ // Use the on interface to listen for CHILD_ADDED and CHILD_REMOVED events
+ this.on(NodeEventType.CHILD_ADDED, (child) => {
+ // Synchronize the this._children array in the JS
+ this._children.push(child);
+ });
+
+ this.on(NodeEventType.CHILD_REMOVED, (child) => {
+ const removeAt = this._children.indexOf(child);
+ if (removeAt < 0) {
+ errorID(1633);
+ return;
+ }
+ this._children.splice(removeAt, 1);
+ });
+
+ ......
+};
+```
+
+### Performance Comparison Results
+
+
+
+## Parameter Array Object Pool
+
+Up to version 3.6.0, Cocos Creator engine does not have an efficient memory pool implementation. When using the se (Script Engine Wrapper) for JS -> CPP interactions, temporary `se::ValueArray args(argCount)` objects need to be created. `se::ValueArray` is a `ccstd::vector` typedef, which leads to a significant amount of temporary memory allocations and deallocations, greatly impacting performance. This issue was not exposed in previous versions because the native code was relatively low-level and had fewer JSB calls. However, in version 3.6.0, with the increased native level hierarchy and JSB calls, this problem became more severe.
+
+To address this issue, we came up with a solution: using an object pool to reuse `se::ValueArray` objects. The implementation of the object pool, `se::ValueArrayPool`, is relatively simple and is outlined below:
+
+bindings/jswrapper/ValueArrayPool.h
+
+```c++
+// CallbackDepthGuard class for resetting se::Value objects in a se::ValueArray after use
+// If the se::ValueArray is allocated with `new`, it will handle the `delete` process
+class CallbackDepthGuard final {
+public:
+ CallbackDepthGuard(ValueArray &arr, uint32_t &depth, bool needDelete)
+ : _arr(arr), _depth(depth), _needDelete(needDelete) {
+ ++_depth;
+ }
+
+ ~CallbackDepthGuard() {
+ --_depth;
+ for (auto &e : _arr) {
+ e.setUndefined();
+ }
+ if (_needDelete) {
+ delete &_arr;
+ }
+ }
+
+private:
+ ValueArray &_arr;
+ uint32_t &_depth;
+ const bool _needDelete{false};
+};
+
+class ValueArrayPool final {
+public:
+ // The maximum number of arguments for a bound function is 20
+ // If there are more than 20 arguments, consider refactoring the function parameters
+ static const uint32_t MAX_ARGS = 20;
+
+ ValueArrayPool();
+
+ ValueArray &get(uint32_t argc, bool &outNeedDelete);
+
+ uint32_t _depth{0};
+
+private:
+ void initPool(uint32_t index);
+ ccstd::vector> _pools;
+};
+
+extern ValueArrayPool gValueArrayPool;
+```
+
+bindings/jswrapper/ValueArrayPool.cpp
+
+```c++
+ValueArrayPool gValueArrayPool;
+
+// Define the maximum depth as 5. If the depth exceeds this value, the object pool will not be used.
+#define SE_DEFAULT_MAX_DEPTH (5)
+
+ValueArrayPool::ValueArrayPool() {
+ _pools.resize(SE_DEFAULT_MAX_DEPTH);
+ for (uint32_t i = 0; i < SE_DEFAULT_MAX_DEPTH; ++i) {
+ initPool(i);
+ }
+}
+
+ValueArray &ValueArrayPool::get(uint32_t argc, bool &outNeedDelete) {
+ // If the depth is greater than the size of the object pool, directly create a new ValueArray object.
+ if (SE_UNLIKELY(_depth >= _pools.size())) {
+ outNeedDelete = true;
+ auto *ret = ccnew ValueArray();
+ ret->resize(argc);
+ return *ret;
+ }
+
+ outNeedDelete = false;
+ CC_ASSERT_LE(argc, MAX_ARGS);
+ // Retrieve a ValueArray object from the object pool.
+ auto &ret = _pools[_depth][argc];
+ CC_ASSERT(ret.size() == argc);
+ return ret;
+}
+
+// Initialize pool
+void ValueArrayPool::initPool(uint32_t index) {
+ auto &pool = _pools[index];
+ uint32_t i = 0;
+ for (auto &arr : pool) {
+ arr.resize(i);
+ ++i;
+ }
+}
+```
+
+Let's look at the implementation of jsbFunctionWrapper function:
+
+```c++
+SE_HOT void jsbFunctionWrapper(const v8::FunctionCallbackInfo &v8args, se_function_ptr func, const char *funcName) {
+ bool ret = false;
+ v8::Isolate *isolate = v8args.GetIsolate();
+ v8::HandleScope scope(isolate);
+
+ /* Original code
+ se::ValueArray args;
+ args.reserve(10);
+ */
+
+ // Optimized implementation - Start
+ bool needDeleteValueArray{false};
+ // Retrieve a se::ValueArray from the global object pool, note that needDeleteValueArray is an output parameter
+ se::ValueArray &args = se::gValueArrayPool.get(v8args.Length(), needDeleteValueArray);
+ // Define a "callback depth guard" variable depthGuard, which automatically cleans up the object pool when it's destroyed
+ se::CallbackDepthGuard depthGuard{args, se::gValueArrayPool._depth, needDeleteValueArray};
+ // Optimized implementation - End
+
+ se::internal::jsToSeArgs(v8args, args);
+ se::Object *thisObject = se::internal::getPrivate(isolate, v8args.This());
+ se::State state(thisObject, args);
+ ret = func(state);
+ if (!ret) {
+ SE_LOGE("[ERROR] Failed to invoke %s\n", funcName);
+ }
+ se::internal::setReturnValue(state.rval(), v8args);
+}
+```
+
+### Performance Comparison Results
+
+
+
+## Conclusion
+
+The main optimization techniques employed in Cocos Creator 3.6.0 native engine are as follows:
+
+1. Implementing the engine's core modules in the native(C++) to leverage the performance of C++ code execution.
+2. Minimizing the frequency of cross-language interactions (JS <-> CPP) through the following five methods:
+ - Shared memory: Improving performance by reducing memory copies.
+ - Avoiding parameter passing: Using member variables instead of frequent parameter passing.
+ - Caching properties: Storing frequently accessed properties in cache to avoid redundant retrieval.
+ - Node synchronization: Synchronizing node changes through an event listening mechanism during node operations.
+ - Parameter array object pool: Reusing parameter array objects using an object pool to reduce memory allocation and deallocation overhead.
+
+By implementing these optimization measures, we have improved the performance of the Cocos Creator engine. These optimization techniques significantly reduce the overhead of cross-language interactions and enhance the overall performance and responsiveness of the engine.
diff --git a/versions/4.0/en/advanced-topics/jsb-sebind.md b/versions/4.0/en/advanced-topics/jsb-sebind.md
new file mode 100644
index 0000000000..966588726f
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/jsb-sebind.md
@@ -0,0 +1,567 @@
+# `sebind` Tutorial
+
+Before `sebind`, both manual and automatic bindings required more steps for developers to complete the binding and required more knowledge of JSB. `sebind` takes advantage of C++ templates to minimize intermediate code.
+
+## A simple example
+
+We will define an object `simpleMath` in the global space, and add a `lerp` function.
+
+```js
+let v = simpleMath.lerp(a, b, t);
+```
+The function is implemented in C++.
+
+### Preparation
+
+We need to create a Cocos Creator project, save a scene, and create a new build task for any native platform. This example uses the Windows platform.
+
+### Step 1: Add the binding code
+
+In the `native/engine/common/Classes` directory, create a new file `HelloSEBind.cpp` and write the following code:
+
+```c++
+// HelloSEBind.cpp
+#include "bindings/sebind/sebind.h"
+
+namespace {
+struct Empty {}; // act as a namespace
+float lerp(float a, float b, float t) { return (1 - t) * a + t * b; }
+} // namespace
+
+bool jsb_register_simple_math(se::Object *globalThis) {
+
+ sebind::class_ demoMathClass("simpleMath");
+ {
+ // invoke through simpleMath.lerp(a, b, t);
+ demoMathClass.staticFunction("lerp", &lerp).install(globalThis);
+ }
+ return true;
+}
+```
+
+Include the file `HelloSEBind.cpp` to `native/engine/common/CMakeLists.txt`
+
+```cmake
+
+# ...
+
+list(APPEND CC_COMMON_SOURCES
+ ${CMAKE_CURRENT_LIST_DIR}/Classes/Game.h
+ ${CMAKE_CURRENT_LIST_DIR}/Classes/Game.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/Classes/HelloSEBind.cpp # new file
+)
+```
+### Step 2: Register to `ScriptEngine`
+
+Edit `Game.cpp`, located in the `native/engine/common/Classes` directory
+
+```c++
+// ...
+
+// declare registry function
+extern bool jsb_register_simple_math(se::Object *); // #1
+
+Game::Game() = default;
+
+
+int Game::init() {
+
+// ...
+ _xxteaKey = SCRIPT_XXTEAKEY;
+
+ // add callback to script engine
+ auto *seengine = se::ScriptEngine::getInstance(); // #2
+ seengine->addRegisterCallback(jsb_register_simple_math); // #3
+
+ BaseGame::init();
+ //....
+```
+
+### Step 3: Verification
+
+Start the program in Debug mode, and connect with Chrome devtools:
+
+
+
+Done.
+
+Compared to the previous approachs, the use of the `SE` APIs is greatly reduced, and so is the amount of code.
+
+## A more complex binding example
+
+`sebind` does interface binding on a class-by-class basis. Each JS class requires the construction of a corresponding `sebind::class_` instance. All class bindings are done through the methods provided by `sebind::class_`.
+
+In the following, we will familiarize ourselves with the `sebind` binding process by exporting the sample code for the `User` class.
+
+> **Note**: The sample code is only used to illustrate the usage of `sebind`, the internal interface design and implementation is not useful in practice.
+
+```c++
+class User {
+private:
+ static int userCount;
+
+public:
+ // static methods
+ static int doubleUserCount() { return 2 * userCount; }
+ // static attributes
+ static int getUserCount() { return userCount; }
+ static void setUserCount(int v) { userCount = v; }
+
+ // constructors with different parameters
+ User() { userCount++; }
+ User(const std::string &name_) : User() { name = name_; }
+ User(const std::string &name_, const std::string &token)
+ : User() {
+ name = name_;
+ _token = token;
+ }
+ User(const std::string &name_, const std::string &token, int credit)
+ : User(name, token) {
+ _credit = credit;
+ name = name_;
+ _token = token;
+ }
+
+
+ ~User() = default;
+
+ // attributes
+ std::string getToken() const { return _token; }
+ void setToken(const std::string &t) { _token = t; }
+
+ // override function
+ std::string toString() const { return name + ":" + _token; }
+ std::string toString(const std::string &tag) const {
+ return "[" + tag + "]:" + name + ":" + _token;
+ }
+
+ // function args with bound type
+ std::string mergeName1(User &other) { return name + "|" + other.name; }
+ std::string mergeName2(User *other) { return name + "|" + other->name; }
+ std::string mergeName3(const std::shared_ptr &other) {
+ return name + "|" + other->name;
+ }
+ // public fields
+ std::string name{"unset"};
+
+private:
+ std::string _token{"unset"};
+ int _credit{-1};
+};
+
+int User::userCount = 0;
+
+} // namespace
+
+```
+#### Instantiate `sebind::class_`
+
+Relates a C++ class to a specified JS class name
+
+```c++
+sebind::class_ userClass("User");
+```
+
+#### Bind constructors
+
+```c++
+ userClass.constructor<>() // JS: new User
+ .constructor() // JS: new User("Jone")
+ .constructor() // JS: new User("Jone", "343453")
+ .constructor() //JS: new User("Jone", "343453", 5678)
+```
+
+There are 4 constructor patterns declared here, with 0,1,2,3 parameters. Each template parameter corresponds to the constructor's parameter type.
+When calling `new User(...)` will trigger the corresponding C++ constructor depending on the number of arguments
+
+> **Note**: If you don't declare any `constructor`, `sebind:class_` will use the default parameterless constructor.
+
+We can also define common functions as constructors, for example:
+
+```c++
+User *createUser(int credit) {
+ return = new User("Lambda", "ctor", credit);
+}
+
+// ...
+.constructor(&createUser) // JS: new User(234)
+```
+
+The return value needs to be a `User*` type. This is equivalent to declaring the constructor `constructor(credit:number)` in JS.
+
+#### Exporting member properties
+
+Export a C++ public field as a JS property
+
+```c++
+.property("name", &User::name) // JS: user.name
+```
+
+You can also define `getter`/`setter` functions as properties. Here the `getter` function needs to have a return value, and no parameters. The `setter` function takes one argument.
+
+```c++
+.property("token", &User::getToken, &User::setToken) // JS: user.token
+```
+
+> **Note**: `getter`/`setter` can not be both `nullptr`.
+
+Common functions, with `User*` as the first argument, can be used as member functions. For example:
+
+```c++
+std::string tokenLong_get(User *u) {
+ return "token[" + u->getToken() + "]";
+}
+void tokenLong_set(User *u, const std::string &s) {
+ u->setToken("token[" + u->getToken() + "]");
+}
+//...
+.property("tokenPrefix", &tokenLong_get, &tokenLong_set) // JS: user.tokenPrefix
+```
+
+#### Export Member Functions
+
+Exporting C++ member functions to JS.
+
+```c++
+.function("mergeName1", &User::mergeName1) // JS: user1.mergeName1(user2)
+.function("mergeName2", &User::mergeName2) // JS: user2.mergeName1(user2)
+.function("mergeName3", &User::mergeName3) // JS: user3.mergeName1(user2)
+```
+
+Instances of bound types in JS can be passed as arguments to C++ bound functions. C++ functions can take instances of bound objects by *reference*, *pointer* or *smart pointer*. Here, if `User` inherits `cc::RefCounted`, we can use `cc::IntrusivePtr` to hold it. If we don't inherit `cc::RefCounted`, as is the case now, we can also hold it with `std::shared_ptr`. After holding with `shared_ptr/IntrusivePtr`, the associated JS object is GC'd, and the object held at the C++ level will not be destroyed.
+
+> **Note**: The binding type needs to be registered with the macro `JSB_REGISTER_OBJECT_TYPE(User);` before calling the sebind APIs. Only then will the subsequent `jsb_conversions` method handle the type conversion correctly.
+
+If a function is overloaded, we need to specify the specific type of the function pointer with `static_cast`.
+
+```c++
+.function("toString", static_cast(&User::toString)) ///JS: (new User).toString()
+.function("toString", static_cast(&User::toString)) //JS: (new User).toString("1111")
+```
+
+Similar to constructors, overloaded functions are matched based on the number of arguments, and the same number of arguments should be avoided. If you need to determine the type of parameters at runtime, you can refer to bind [`SE` functions](#manual-type-conversion).
+
+#### Exporting static methods of a class
+
+Exporting static functions of a C++ class
+
+```c++
+.staticFunction("doubleUserCount", &User::doubleUserCount) // JS: User.doubleUserCount()
+```
+It is also possible to export common functions as class static functions
+
+```c++
+int static_add(int a, int b) { return a + b; }
+///...
+.staticFunction("add", &static_add) //JS: User.add(1,2)
+```
+
+#### Export Class Static Properties
+
+Export a C++ class static function as a static property of a JS class.
+
+```c++
+.staticProperty("userCount", &User::getUserCount, &User::setUserCount) //JS: User.userCount
+```
+or common functions
+```c++
+int gettime() { return time(nullptr); }
+/// ...
+.staticProperty("time", &gettime, nullptr) //JS: User.time
+```
+
+#### Registering A Destruct Callback
+
+Register a callback for when the bound object is GC'd.
+
+```c++
+.finalizer([](User *usr) {
+ std::cout << "release " << usr->name << std::endl;
+})
+```
+
+#### Export the class to JS global namespace
+
+Mounts the `User` class to the `globalThis` object, completing the export. `User` class can be accessed globally in the JS script.
+
+```c++
+.install(globalThis);
+```
+
+#### Class Inheritance
+
+Specify the parent class's prototype in the second parameter of the `sebind::class_` constructor. Here the `SuperUser` class inherits from the `User` class.
+
+```c++
+sebind::class_ superUser("SuperUser", userClass.prototype());
+{
+ superUser.constructor()
+ .function(
+ "superName", +[](User *user) { return user->name + ".super";
+ }) // JS: (new SuperUser("Mok")).superName()
+ .install(globalThis);
+}
+```
+
+> **Note**: that the static methods of the parent class are not inherited by the child class.
+
+## Other Uses
+
+### Calling JS functions in C++
+
+Since 3.6.1, with `sebind::bindFunction` you can bind `se::Value` to `std::function` in C++, without having to deal with parameter conversions. Similarly, you can use `sebind::callFunction` to call JS functions directly.
+
+For example:
+```c++
+demo.staticFunction(
+ "add",
+ +[](const se::Value &func, int a, int b) {
+ // bind js function as a std::function
+ auto addFunc = sebind::bindFunction(func);
+ // ..
+ // invoke std::function
+ auto result = addFunc(a, b);
+
+ // call JS function with automatic arguments assembling
+ auto result2 = sebind::callFunction(func, a, b);
+ auto result3 = sebind::callFunction(func, 6, 8);
+
+ // argument type computing
+ auto result4 = sebind::callFunction(func, a, b);
+ auto result5 = sebind::callFunction(func, 6, 8);
+
+ std::cout << "result 1 " << result << std::endl;
+ std::cout << "result 2 " << result2 << std::endl;
+ });
+```
+
+### Binding abstract classes
+
+`sebind::class_` requires a constructor to be provided, but the constructor for the abstract class is not available. Resolve this conflict by providing an empty constructor to enable registration of the abstract type.
+
+For example:
+
+```c++
+
+class AbstractClass {
+public:
+ virtual bool tick() = 0;
+};
+
+class SubClass : public AbstractClass {
+public:
+ bool tick() override { return true; }
+};
+
+AbstractClass *fakeConstructor() {
+ assert(false); // Abstract class cannot be instantiated
+ return nullptr;
+}
+
+//..
+sebind::class_ base("AbstractBase");
+
+base.constructor<>(&fakeConstructor) // add constructor
+ .function("tick", &AbstractClass::tick)
+ .install(globalThis);
+
+sebind::class_ sub("SubClass", base.prototype());
+sub.install(globalThis);
+```
+
+### Manual Type Conversion
+
+`sebind` supports binding traditional `SE` functions to perform the conversion manually. For example:
+
+```c++
+bool jsb_sum(se::State &state) {
+ double result = 0;
+ auto &args = state.args();
+ for (int i = 0; i < args.size(); i++) {
+ result += (args[i].isNumber() ? args[i].toDouble() : 0);
+ }
+ state.rval().setDouble(result);
+ return true;
+}
+///
+.staticFunction("sum", &jsb_sum) // JS: User.sum(1,2,3,4,5)
+```
+
+This allows for variable-length parameters and flexible parameter conversions. It's more flexible than automatic conversions and requires developers to be more familiar with the `SE API`.
+
+### Requirng JS `this` Object within constructor
+
+Requring the corresponding JS `this` object in a C++ constructor is a common requirement, and simplifies access from C++ to JS.
+
+All we need to do is specify the placeholder `sebind::ThisObject` in the argument type of the `constructor` and declare the argument type of the corresponding constructor as `se::Object *`.
+
+```c++
+// constructor
+User(se::Object *self, const std::string &name_) {
+ self->setProperty("fromNative", se::Value(true));
+ name = name_;
+}
+/// ...
+superUser.constructor() // JS: new SuperUser("Jone")
+```
+
+> **Note**: Common functions are not supported here for now.
+
+When calling the corresponding constructor in JS, all `sebind::ThisObject` parameters should be ignored.
+
+
+
+
+
+Full content of *HelloSEBind.cpp*
+
+
+```c++
+
+#include "bindings/sebind/sebind.h"
+#include
+
+namespace {
+
+
+struct Empty {}; // act as a namespace
+float lerp(float a, float b, float t) { return (1 - t) * a + t * b; }
+
+class User {
+ static int userCount;
+
+public:
+ static int doubleUserCount() { return 2 * userCount; }
+ static int getUserCount() { return userCount; }
+ static void setUserCount(int v) { userCount = v; }
+
+ User() { userCount++; }
+ // User(const std::string &name_) : User() { name = name_; }
+ User(const std::string &name_, const std::string &token) : User() {
+ name = name_;
+ _token = token;
+ }
+ User(const std::string &name_, const std::string &token, int credit)
+ : User(name, token) {
+ _credit = credit;
+ name = name_;
+ _token = token;
+ }
+
+ User(se::Object *self, const std::string &name_) {
+ self->setProperty("fromNative", se::Value(true));
+ name = name_;
+ }
+
+ ~User() { userCount--; }
+
+ std::string getToken() const { return _token; }
+ void setToken(const std::string &t) { _token = t; }
+ std::string toString() const { return name + ":" + _token; }
+ std::string toString(const std::string &tag) const {
+ return "[" + tag + "]:" + name + ":" + _token;
+ }
+
+ std::string mergeName1(User &other) { return name + "|" + other.name; }
+ std::string mergeName2(const std::shared_ptr &other) {
+ return name + "|" + other->name;
+ }
+ std::string mergeName3(User *other) { return name + "|" + other->name; }
+
+ std::string name{"unset"};
+
+private:
+ std::string _token{"unset"};
+ int _credit{-1};
+};
+
+int User::userCount = 0;
+
+class UserExt : public User {
+public:
+ using User::User;
+};
+
+/////////////////////////////////////////////////////
+
+User *createUser(int credit) { return new User("Lambda", "ctor", credit); }
+
+std::string tokenLong_get(User *u) { return "token[" + u->getToken() + "]"; }
+void tokenLong_set(User *u, const std::string &s) {
+ u->setToken("token[" + u->getToken() + "]");
+}
+
+int static_add(int a, int b) { return a + b; }
+
+bool jsb_sum(se::State &state) {
+ double result = 0;
+ auto &args = state.args();
+ for (int i = 0; i < args.size(); i++) {
+ result += (args[i].isNumber() ? args[i].toDouble() : 0);
+ }
+ state.rval().setDouble(result);
+ return true;
+}
+
+int gettime() { return time(nullptr); }
+
+
+} // namespace
+
+JSB_REGISTER_OBJECT_TYPE(User);
+
+bool jsb_register_simple_math(se::Object *globalThis) {
+
+ sebind::class_ demoMathClass("simpleMath");
+ {
+ // invoke through simpleMath.lerp(a, b, t);
+ demoMathClass.staticFunction("lerp", &lerp).install(globalThis);
+ }
+
+ sebind::class_ userClass("User");
+ {
+
+ userClass
+ .constructor<>()
+ .constructor()
+ .constructor()
+ .constructor()
+ // .constructor(&createUser)
+ .property("name", &User::name)
+ .property("token", &User::getToken, &User::setToken)
+ .property("tokenPrefix", &tokenLong_get, nullptr)
+ .function("mergeName1", &User::mergeName1)
+ // .function("mergeName2", &User::mergeName2)
+ .function("mergeName3", &User::mergeName3)
+ .function("toString",
+ static_cast(&User::toString))
+ .function("toString",
+ static_cast(
+ &User::toString))
+ .staticFunction("doubleUserCount", &User::doubleUserCount)
+ .staticProperty("userCount", &User::getUserCount, &User::setUserCount)
+ .staticProperty("time", &gettime, nullptr)
+ .staticFunction("sum", &jsb_sum)
+ .finalizer([](User *usr) {
+ std::cout << "release " << usr->name << std::endl;
+ })
+ .install(globalThis);
+ }
+
+ sebind::class_ superUser("SuperUser", userClass.prototype());
+ {
+ superUser.constructor()
+ .function(
+ "superName", +[](UserExt *user) { return user->name + ".super"; })
+ .install(globalThis);
+ }
+
+ return true;
+}
+```
+
+
+
+
+
+
diff --git a/versions/4.0/en/advanced-topics/jsb-swig.md b/versions/4.0/en/advanced-topics/jsb-swig.md
new file mode 100644
index 0000000000..e8d691f2a9
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/jsb-swig.md
@@ -0,0 +1,71 @@
+# Introduction
+
+From Cocos Creator 3.7.0, we switch the approach of generating JS binding code from [bindings-generator](https://github.com/cocos/cocos4/tree/d08a11244d2a31da1aac7af7d2aa8f1b6152e30c/native/tools/bindings-generator) to [Swig](https://www.swig.org). Swig has many benefits in generating glue code by parsing its custom `interface` file (IDL) which is compatible with `C++`. For more about why we switch to Swig, you could refer to [this issue](https://github.com/cocos/cocos-engine/issues/10792) .
+
+## Generate JS Binding Code for Engine
+
+In 3.8 and later versions, developers no longer need to manually trigger the generation of binding code because CMake will automatically call the SWIG command during the build process to generate the binding code.
+
+Please note that if the generation process fails, you should pay attention to the output logs in the console.
+
+However, if you add or remove `.i` files for the engine, you need to regenerate the project to ensure that the updated references to the `.i` files are taken into account and that the updated binding code is generated.
+
+## Generate JS Bindings Code for Developer's Project
+
+- Make sure you have installed NodeJS (`>= v8.9.4`)
+
+- Open Terminal (macOS/Linux) or Command Line Tool (Windows)
+
+- Create a directory for generated code, e.g. `/Users/abc/my-project/native/engine/common/Classes/bindings/auto`
+
+- Write a JS configuration file
+
+ - Create the JS configruation file, e.g. `/Users/abc/my-project/tools/swig-config/swig-config.js` with the following content
+
+ ```js
+ 'use strict';
+ const path = require('path');
+
+ // Developer's custom module configuration
+ // configList is required
+ const configList = [
+ [ 'your_module_interface_0.i', 'jsb_your_module_interface_0_auto.cpp' ],
+ [ 'your_module_interface_1.i', 'jsb_your_module_interface_1_auto.cpp' ],
+ // ......
+ ];
+
+ const projectRoot = path.resolve(path.join(__dirname, '..', '..'));
+ // interfaceDir is optional
+ const interfacesDir = path.join(projectRoot, 'tools', 'swig-config');
+ // bindingsOutDir is optional
+ const bindingsOutDir = path.join(projectRoot, 'native', 'engine', 'common', 'Classes', 'bindings', 'auto');
+
+ module.exports = {
+ interfacesDir, // optional, if it isn't exported, the items in configList should be absolute or relative to current directory of swig-config.js
+ bindingsOutDir, // optional, if it isn't exported, the items in configList should be absolute or relative to current directory of swig-config.js
+ configList // required
+ };
+ ```
+
+ - Run the following command
+
+ ```bash
+ # If current workspace is not in '/Users/abc/my-project/tools/swig-config'
+ $ node < Engine Root Path >/native/tools/swig-config/genbindings.js -c /Users/abc/my-project/tools/swig-config/swig-config.js
+ ```
+
+ ```bash
+ # If you have already navigate to '/Users/abc/my-project/tools/swig-config' directory, you could run the command without -c argument like:
+ $ cd /Users/abc/my-project/tools/swig-config
+ $ node < Engine Root Path >/native/tools/swig-config/genbindings.js
+ ```
+
+## Swig Interface File
+
+- There is a [swig-interface-template.i](https://github.com/cocos/cocos4/blob/1f928364f4cad22681e7830c53dc7da71a87d11f/native/tools/swig-config/swig-interface-template.i) in `engine/native/tools/swig-config` directory, just copy and rename it to some place in your project. There some comments demonstrate how to configure your module in `.i` file. You could also reference engine internal `.i` files in `engine/native/tools/swig-config`, for instance, `scene.i` or `assets.i` for a quick start.
+- If you're using `Visual Studio Code`, you could install `SWIG Language` extension which was developed by `Hong-She Liang` for highlight syntax support.
+- For more details of writing `.i` file, please visit [tutorial](#tutorial) section.
+
+## Tutorial
+
+Visit [The Tutorial of Swig Workflow in Cocos Creator](jsb/swig/tutorial/index.md), which includes binding a new module in engine or user's project step by step.
diff --git a/versions/4.0/en/advanced-topics/jsb-web-difference.md b/versions/4.0/en/advanced-topics/jsb-web-difference.md
new file mode 100644
index 0000000000..1fc98f67de
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/jsb-web-difference.md
@@ -0,0 +1,90 @@
+# The differences between Pure JS and JS-Binding objects
+
+Cocos Creator Engine uses `V8` to export CPP classes to Javascript, we call it `JS-Binding`. There're some differences between Pure JS and JS-Binding objects. If your application needs to run on all platforms, especially on native platforms, it's better not to use some APIs that behave differently between `Web` and `Native` platforms. If you have to use them, you need to write some platform specified code like `if (NATIVE) {...} else {...}` .
+
+## Properties
+
+The properties of pure JS objects are assigned to instance, but they're assigned to `prototype` for JS-Binding objects.
+
+### Pure JS objects
+
+```typescript
+class MyClass {
+ constructor() {
+ this.a = 'a';
+ this.b = false;
+ this.c = 100;
+ }
+};
+
+const myobj = new MyClass();
+const ownA = myobj.hasOwnProperty('a');
+console.log(`ownA: ${ownA}`); // ownA: true
+```
+
+### JS-Binding objects
+
+```c++
+// C++ class
+class MyClass {
+public:
+ std::string a;
+ bool b;
+ int32_t c;
+};
+
+// The snippet of JS-Binding glue code.
+bool js_register_cc_MyClass(se::Object* obj) {
+ auto* cls = se::Class::create("MyClass", obj, nullptr, _SE(js_new_cc_MyClass));
+ cls->defineStaticProperty("__isJSB", se::Value(true), se::PropertyAttribute::READ_ONLY | se::PropertyAttribute::DONT_ENUM | se::PropertyAttribute::DONT_DELETE);
+
+ cls->defineProperty("a", _SE(js_cc_MyClass_a_get), _SE(js_cc_MyClass_a_set));
+ cls->defineProperty("b", _SE(js_cc_MyClass_b_get), _SE(js_cc_MyClass_b_set));
+ cls->defineProperty("c", _SE(js_cc_MyClass_c_get), _SE(js_cc_MyClass_c_set));
+
+ cls->defineFinalizeFunction(_SE(js_delete_cc_MyClass));
+ cls->install();
+ JSBClassType::registerClass(cls);
+
+ __jsb_cc_MyClass_proto = cls->getProto();
+ __jsb_cc_MyClass_class = cls;
+ se::ScriptEngine::getInstance()->clearException();
+ return true;
+}
+//
+```
+
+```typescript
+const myobj = new jsb.MyClass();
+const ownA = myobj.hasOwnProperty('a');
+console.log(`ownA: ${ownA}`); // ownA: false
+const protoOwnA = myobj.__proto__.hasOwnProperty('a');
+console.log(`protoOwnA: ${protoOwnA}`); // protoOwnA: true
+```
+
+So if you have written some JS code depends on `hasOwnProperty`, you need to keep in mind of the above difference since it may cause your application to work correctly on Web platform, but be broken on Native platform.
+
+### Possible Solution
+
+If the application needs to run on Native platform, while checking whether a property exists on a JS-Binding object, you need to check its `__proto__` either. For example:
+
+```typescript
+function doSomething(v) {
+ // ......
+}
+
+function foo() {
+ for (const key in myObj) {
+ if (myObj.hasOwnProperty('a')) {
+ doSomething(myObj['a']);
+ } else if (NATIVE) {
+ if (myObj.__proto__.hasOwnProperty('a')) {
+ doSomething(myObj['a']);
+ }
+ }
+ }
+}
+```
+
+
+
diff --git a/versions/4.0/en/advanced-topics/jsb/100.png b/versions/4.0/en/advanced-topics/jsb/100.png
new file mode 100644
index 0000000000..49fddd9197
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/100.png differ
diff --git a/versions/4.0/en/advanced-topics/jsb/110.png b/versions/4.0/en/advanced-topics/jsb/110.png
new file mode 100644
index 0000000000..b83f27e9a2
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/110.png differ
diff --git a/versions/4.0/en/advanced-topics/jsb/111.png b/versions/4.0/en/advanced-topics/jsb/111.png
new file mode 100644
index 0000000000..6b4e659937
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/111.png differ
diff --git a/versions/4.0/en/advanced-topics/jsb/112.png b/versions/4.0/en/advanced-topics/jsb/112.png
new file mode 100644
index 0000000000..90baa96c38
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/112.png differ
diff --git a/versions/4.0/en/advanced-topics/jsb/JSB2.0-Architecture.png b/versions/4.0/en/advanced-topics/jsb/JSB2.0-Architecture.png
new file mode 100644
index 0000000000..c7b115ed21
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/JSB2.0-Architecture.png differ
diff --git a/versions/4.0/en/advanced-topics/jsb/auto-file.png b/versions/4.0/en/advanced-topics/jsb/auto-file.png
new file mode 100644
index 0000000000..4777dc508d
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/auto-file.png differ
diff --git a/versions/4.0/en/advanced-topics/jsb/binding-file.png b/versions/4.0/en/advanced-topics/jsb/binding-file.png
new file mode 100644
index 0000000000..ca182f89c9
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/binding-file.png differ
diff --git a/versions/4.0/en/advanced-topics/jsb/called-injs.png b/versions/4.0/en/advanced-topics/jsb/called-injs.png
new file mode 100644
index 0000000000..ee07044673
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/called-injs.png differ
diff --git a/versions/4.0/en/advanced-topics/jsb/cancel-output_dir.png b/versions/4.0/en/advanced-topics/jsb/cancel-output_dir.png
new file mode 100644
index 0000000000..c118a809e2
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/cancel-output_dir.png differ
diff --git a/versions/4.0/en/advanced-topics/jsb/error-1.png b/versions/4.0/en/advanced-topics/jsb/error-1.png
new file mode 100644
index 0000000000..d25b0fd6f5
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/error-1.png differ
diff --git a/versions/4.0/en/advanced-topics/jsb/error-2.png b/versions/4.0/en/advanced-topics/jsb/error-2.png
new file mode 100644
index 0000000000..6778af5cb1
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/error-2.png differ
diff --git a/versions/4.0/en/advanced-topics/jsb/generate-binding-file.png b/versions/4.0/en/advanced-topics/jsb/generate-binding-file.png
new file mode 100644
index 0000000000..57282f7503
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/generate-binding-file.png differ
diff --git a/versions/4.0/en/advanced-topics/jsb/generate-file-complete.png b/versions/4.0/en/advanced-topics/jsb/generate-file-complete.png
new file mode 100644
index 0000000000..caf7eea7f6
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/generate-file-complete.png differ
diff --git a/versions/4.0/en/advanced-topics/jsb/generate-file.png b/versions/4.0/en/advanced-topics/jsb/generate-file.png
new file mode 100644
index 0000000000..5d1363e0f9
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/generate-file.png differ
diff --git a/versions/4.0/en/advanced-topics/jsb/infrastructure.png b/versions/4.0/en/advanced-topics/jsb/infrastructure.png
new file mode 100644
index 0000000000..7b7f6a2c65
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/infrastructure.png differ
diff --git a/versions/4.0/en/advanced-topics/jsb/jsb_process.jpg b/versions/4.0/en/advanced-topics/jsb/jsb_process.jpg
new file mode 100644
index 0000000000..b4e9c0f273
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/jsb_process.jpg differ
diff --git a/versions/4.0/en/advanced-topics/jsb/opt-1.jpg b/versions/4.0/en/advanced-topics/jsb/opt-1.jpg
new file mode 100644
index 0000000000..3529892643
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/opt-1.jpg differ
diff --git a/versions/4.0/en/advanced-topics/jsb/opt-2.jpg b/versions/4.0/en/advanced-topics/jsb/opt-2.jpg
new file mode 100644
index 0000000000..1e3599ac7c
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/opt-2.jpg differ
diff --git a/versions/4.0/en/advanced-topics/jsb/opt-3.jpg b/versions/4.0/en/advanced-topics/jsb/opt-3.jpg
new file mode 100644
index 0000000000..4dbaf1927f
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/opt-3.jpg differ
diff --git a/versions/4.0/en/advanced-topics/jsb/opt-4.jpg b/versions/4.0/en/advanced-topics/jsb/opt-4.jpg
new file mode 100644
index 0000000000..355f57f538
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/opt-4.jpg differ
diff --git a/versions/4.0/en/advanced-topics/jsb/opt-5.jpg b/versions/4.0/en/advanced-topics/jsb/opt-5.jpg
new file mode 100644
index 0000000000..b5a9c45165
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/opt-5.jpg differ
diff --git a/versions/4.0/en/advanced-topics/jsb/store-file.png b/versions/4.0/en/advanced-topics/jsb/store-file.png
new file mode 100644
index 0000000000..bd2a0b0f75
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/store-file.png differ
diff --git a/versions/4.0/en/advanced-topics/jsb/swig/tutorial/MyRefCompileError.jpg b/versions/4.0/en/advanced-topics/jsb/swig/tutorial/MyRefCompileError.jpg
new file mode 100644
index 0000000000..dee74edb03
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/swig/tutorial/MyRefCompileError.jpg differ
diff --git a/versions/4.0/en/advanced-topics/jsb/swig/tutorial/another-module-compile-error.jpg b/versions/4.0/en/advanced-topics/jsb/swig/tutorial/another-module-compile-error.jpg
new file mode 100644
index 0000000000..bc3fb929a8
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/swig/tutorial/another-module-compile-error.jpg differ
diff --git a/versions/4.0/en/advanced-topics/jsb/swig/tutorial/index.md b/versions/4.0/en/advanced-topics/jsb/swig/tutorial/index.md
new file mode 100644
index 0000000000..477bcb86ac
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/jsb/swig/tutorial/index.md
@@ -0,0 +1,1144 @@
+# The Tutorial of Swig Workflow in Cocos Creator
+
+## How to Bind a New Module in Engine
+
+### Add a new module interface file
+
+- Add a new module interface file to `native/tools/swig-config` directory, e.g. `new-engine-module.i`
+
+- Copy the content in [swig-interface-template.i](https://github.com/cocos/cocos4/blob/1f928364f4cad22681e7830c53dc7da71a87d11f/native/tools/swig-config/swig-interface-template.i) to new-engine-module.i
+
+- Add necessary configuration, you refer to the existed `.i` files in `native/tools/swig-config` directory or refer to [the following section](#How to Bind a New Module in Developer's Project)
+
+### Modify `engine/native/cocos/CMakeLists.txt`
+
+```cmake
+######## auto
+cocos_source_files(
+ NO_WERROR NO_UBUILD ${SWIG_OUTPUT}/jsb_cocos_auto.cpp # Add this line
+ ${SWIG_OUTPUT}/jsb_cocos_auto.h # Add this line
+ NO_WERROR NO_UBUILD ${SWIG_OUTPUT}/jsb_cocos_auto.cpp
+ ${SWIG_OUTPUT}/jsb_cocos_auto.h
+ ......
+```
+
+### Register the new module to Script Engine
+
+Open `jsb_module_register.cpp` and do the following modifications
+
+```c++
+......
+#if CC_USE_PHYSICS_PHYSX
+ #include "cocos/bindings/auto/jsb_physics_auto.h"
+#endif
+#include "cocos/bindings/auto/jsb_new_engine_module_auto.h" // Add this line
+
+bool jsb_register_all_modules() {
+ se::ScriptEngine *se = se::ScriptEngine::getInstance();
+ ......
+ se->addRegisterCallback(register_all_my_new_engine_module); // Add this line
+
+ se->addAfterCleanupHook([]() {
+ cc::DeferredReleasePool::clear();
+ JSBClassType::cleanup();
+ });
+ return true;
+}
+```
+
+## How to Bind a New Module in Developer's Project
+
+Suppose we have a Cocos Creator project located at `/Users/james/NewProject` directory.
+
+Build a native project in Cocos Creator's build panel, we get `/Users/james/NewProject/native` directory.
+
+### Bind a simple class
+
+#### Create a simple class
+
+Create a header file in `/Users/james/NewProject/native/engine/common/Classes/MyObject.h` , its content is
+
+```c++
+// MyObject.h
+#pragma once
+#include "cocos/cocos.h"
+namespace my_ns {
+class MyObject {
+public:
+ MyObject() = default;
+ MyObject(int a, bool b) {}
+ virtual ~MyObject() = default;
+ void print() {
+ CC_LOG_DEBUG("==> a: %d, b: %d\n", _a, (int)_b);
+ }
+
+ float publicFloatProperty{1.23F};
+private:
+ int _a{100};
+ bool _b{true};
+};
+} // namespace my_ns {
+```
+
+#### Write an interface file
+
+Create an interface called `my-module.i` file in `/Users/james/NewProject/tools/swig-config`
+
+```c++
+// my-module.i
+%module(target_namespace="my_ns") my_module
+
+// Insert code at the beginning of generated header file (.h)
+%insert(header_file) %{
+#pragma once
+#include "bindings/jswrapper/SeApi.h"
+#include "bindings/manual/jsb_conversions.h"
+
+#include "MyObject.h" // Add this line
+%}
+
+// Insert code at the beginning of generated source file (.cpp)
+%{
+#include "bindings/auto/jsb_my_module_auto.h"
+%}
+
+%include "MyObject.h"
+```
+
+#### Write a swig config file
+
+Create a file called swig-config.js in `/Users/james/NewProject/tools/swig-config`
+
+```js
+// swig-config.js
+'use strict';
+const path = require('path');
+const configList = [
+ [ 'my-module.i', 'jsb_my_module_auto.cpp' ],
+];
+
+const projectRoot = path.resolve(path.join(__dirname, '..', '..'));
+const interfacesDir = path.join(projectRoot, 'tools', 'swig-config');
+const bindingsOutDir = path.join(projectRoot, 'native', 'engine', 'common', 'bindings', 'auto');
+// includeDirs means header search path for Swig parser
+const includeDirs = [
+ path.join(projectRoot, 'native', 'engine', 'common', 'Classes'),
+];
+
+module.exports = {
+ interfacesDir,
+ bindingsOutDir,
+ includeDirs,
+ configList
+};
+```
+
+#### Generate bindings for project
+
+```bash
+$ cd /Users/james/NewProject/tools/swig-config
+$ node < Engine Root >/native/tools/swig-config/genbindings.js
+```
+
+If succeed, the files ( `jsb_my_module_auto.cpp/.h` ) contain JS binding code will be generated at `/Users/james/NewProject/native/engine/bindings/auto` directory
+
+#### Modify project's CMakeLists.txt
+
+- Open `/Users/james/NewProject/native/engine/common/CMakeLists.txt`, add `MyObject.h` and its binding code
+
+ ```cmake
+ include(${COCOS_X_PATH}/CMakeLists.txt)
+
+ list(APPEND CC_COMMON_SOURCES
+ ${CMAKE_CURRENT_LIST_DIR}/Classes/Game.h
+ ${CMAKE_CURRENT_LIST_DIR}/Classes/Game.cpp
+ ############### Add the following lines ##############
+ ${CMAKE_CURRENT_LIST_DIR}/Classes/MyObject.h
+ ${CMAKE_CURRENT_LIST_DIR}/bindings/auto/jsb_my_module_auto.h
+ ${CMAKE_CURRENT_LIST_DIR}/bindings/auto/jsb_my_module_auto.cpp
+ ########################################################
+ )
+ ```
+
+- Modify `/Users/james/NewProject/native/engine/mac/CMakeLists.txt`
+
+ ```cmake
+ cmake_minimum_required(VERSION 3.8)
+ # ......
+ cc_mac_before_target(${EXECUTABLE_NAME})
+ add_executable(${EXECUTABLE_NAME} ${CC_ALL_SOURCES})
+ ############### Add the following lines ##############
+ target_include_directories(${EXECUTABLE_NAME} PRIVATE
+ ${CC_PROJECT_DIR}/../common
+ )
+ ########################################################
+ cc_mac_after_target(${EXECUTABLE_NAME})
+ ```
+
+
+#### Open project
+
+macOS: `/Users/james/NewProject/build/mac/proj/NewProject.xcodeproj `
+
+Windows: `< A specific directory >/NewProject/build/win64/proj/NewProject.sln`
+
+#### Register the new module to Script Engine
+
+Modify `Game.cpp` :
+
+```c++
+#include "Game.h"
+#include "bindings/auto/jsb_my_module_auto.h" // Add this line
+//......
+int Game::init() {
+ // ......
+ se::ScriptEngine::getInstance()->addRegisterCallback(register_all_my_module); // Add this line
+ BaseGame::init();
+ return 0;
+}
+// ......
+```
+
+#### Test binding
+
+- Add a `my-module.d.ts` file in the root of project directory to make TS compiler know our binding class.
+
+ ```ts
+ // my-module.d.ts
+ declare namespace my_ns {
+ class MyObject {
+ constructor();
+ constructor(a: number, b: number);
+
+ publicFloatProperty : number;
+ print() : void;
+ }
+ }
+ ```
+
+- Modify `/Users/james/NewProject/temp/tsconfig.cocos.json` file
+
+ ```js
+ {
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "compilerOptions": {
+ "target": "ES2015",
+ "module": "ES2015",
+ "strict": true,
+ "types": [
+ "./temp/declarations/cc.custom-macro",
+ "./temp/declarations/jsb",
+ "./temp/declarations/cc",
+ "./temp/declarations/cc.env",
+ "./my-module" // Add this line
+ ],
+ // ......
+ "forceConsistentCasingInFileNames": true
+ }
+ }
+ ```
+
+- Open NewProject in Cocos Creator, create a cube object in scene and attach a script to cube, the script's content is
+
+ ```ts
+ import { _decorator, Component } from 'cc';
+ const { ccclass } = _decorator;
+
+ @ccclass('MyComponent')
+ export class MyComponent extends Component {
+ start() {
+ const myObj = new my_ns.MyObject();
+ myObj.print(); // Invoke native print method
+ console.log(`==> myObj.publicFloatProperty: ${myObj.publicFloatProperty}`); // Get property defined in native
+ }
+ }
+ ```
+
+- Run project, if succeed, you could find the following logs in console
+
+ ```
+ 17:31:44 [DEBUG]: ==> a: 100, b: 1
+ 17:31:44 [DEBUG]: D/ JS: ==> myObj.publicFloatProperty: 1.2300000190734863
+ ```
+
+#### Section Conclusion
+
+In this section, we have learned how to use `Swig` tool to bind a simple class, export its public methods and properties to JS. This section also cover the entire flow of binding native classes. Start from next section, we will focus on using more `Swig` features to satisfy more needs of JS bindings, for example:
+
+- How to import depended header files
+- How to ignore classes, methods, properties
+- How to rename classes, methods, properties
+- How to define attributes which bind c++ getter and setter as a JS property
+- How to configure C++ modules in .i file
+
+### Import depended header files
+
+Suppose we let MyObject class be inherited from MyRef class. But we don't want to bind MyRef class.
+
+```c++
+// MyRef.h
+#pragma once
+namespace my_ns {
+class MyRef {
+public:
+ MyRef() = default;
+ virtual ~MyRef() = default;
+ void addRef() { _ref++; }
+ void release() { --_ref; }
+private:
+ unsigned int _ref{0};
+};
+} // namespace my_ns {
+```
+
+```c++
+// MyObject.h
+#pragma once
+#include "cocos/cocos.h"
+#include "MyRef.h"
+namespace my_ns {
+// MyObject inherits from MyRef
+class MyObject : public MyRef {
+public:
+ MyObject() = default;
+ MyObject(int a, bool b) {}
+ virtual ~MyObject() = default;
+ void print() {
+ CC_LOG_DEBUG("==> a: %d, b: %d\n", _a, (int)_b);
+ }
+
+ float publicFloatProperty{1.23F};
+private:
+ int _a{100};
+ bool _b{true};
+};
+} // namespace my_ns {
+```
+
+When Swig parses MyObject.h, it will not know what `MyRef` is, it will output a warning in console.
+
+```bash
+.../Classes/MyObject.h:7: Warning 401: Nothing known about base class 'MyRef'. Ignored.
+```
+
+It's simple to fix this issue, we need to let Swig know that MyRef exists by using `%import` directive.
+
+```c++
+// ......
+// Insert code at the beginning of generated source file (.cpp)
+%{
+#include "bindings/auto/jsb_my_module_auto.h"
+%}
+
+%import "MyRef.h" // Add this line to fix the warning
+%include "MyObject.h"
+```
+
+Although Swig doesn't report the error now, the binding code will not be compiled, the error is:
+
+
+
+We fix this in the next section by `%ignore` directive.
+
+### Ignore classes, methods, properties
+
+#### Ignore classes
+
+In last section, we got a compile error in `js_register_my_ns_MyObject`. Since MyRef should not be bound, we could use`%ignore` directive to ignore it.
+
+```c++
+// my-module.i
+// ......
+%ignore my_ns::MyRef; // Add this line
+%import "MyRef.h"
+%include "MyObject.h"
+```
+
+Generate binding again, it compiles ok.
+
+```c++
+// jsb_my_module_auto.cpp
+bool js_register_my_ns_MyObject(se::Object* obj) {
+ auto* cls = se::Class::create("MyObject", obj, nullptr, _SE(js_new_MyObject)); // parentProto will be set to nullptr
+ cls->defineProperty("publicFloatProperty", _SE(js_my_ns_MyObject_publicFloatProperty_get), _SE(js_my_ns_MyObject_publicFloatProperty_set));
+ cls->defineFunction("print", _SE(js_my_ns_MyObject_print));
+ // ......
+}
+```
+
+#### Ignore methods and properties
+
+We add a new method `methodToBeIgnored` and a new property `propertyToBeIgnored` to `MyObject` class.
+
+```c++
+// MyObject.h
+#pragma once
+#include "cocos/cocos.h"
+#include "MyRef.h"
+namespace my_ns {
+// MyObject inherits from MyRef
+class MyObject : public MyRef {
+public:
+// .....
+ void methodToBeIgnored() {} // Add this line
+ float propertyToBeIgnored{345.123F}; // Add this line
+// ......
+ float publicFloatProperty{1.23F};
+private:
+ int _a{100};
+ bool _b{true};
+};
+} // namespace my_ns {
+
+```
+
+Re-generate bindings, we'll get `methodToBeIgnored` and `propertyToBeIgnored` bound.
+
+```c++
+// jsb_my_module_auto.cpp
+bool js_register_my_ns_MyObject(se::Object* obj) {
+ auto* cls = se::Class::create("MyObject", obj, nullptr, _SE(js_new_MyObject));
+ cls->defineProperty("propertyToBeIgnored", _SE(js_my_ns_MyObject_propertyToBeIgnored_get), _SE(js_my_ns_MyObject_propertyToBeIgnored_set)); // this property should not be bound
+ cls->defineProperty("publicFloatProperty", _SE(js_my_ns_MyObject_publicFloatProperty_get), _SE(js_my_ns_MyObject_publicFloatProperty_set));
+ cls->defineFunction("print", _SE(js_my_ns_MyObject_print));
+ cls->defineFunction("methodToBeIgnored", _SE(js_my_ns_MyObject_methodToBeIgnored)); // this method should not be bound
+ // ......
+}
+```
+
+Modify `my-module.i` to skip binding them.
+
+```c++
+// my-module.i
+// ......
+
+%ignore my_ns::MyRef;
+%ignore my_ns::MyObject::methodToBeIgnored; // Add this line
+%ignore my_ns::MyObject::propertyToBeIgnored; // Add this line
+
+%import "MyRef.h"
+%include "MyObject.h"
+```
+
+Re-generate bindings, they're ignored now.
+
+```c++
+// jsb_my_module_auto.cpp
+bool js_register_my_ns_MyObject(se::Object* obj) {
+ auto* cls = se::Class::create("MyObject", obj, nullptr, _SE(js_new_MyObject));
+ cls->defineProperty("publicFloatProperty", _SE(js_my_ns_MyObject_publicFloatProperty_get), _SE(js_my_ns_MyObject_publicFloatProperty_set));
+ cls->defineFunction("print", _SE(js_my_ns_MyObject_print));
+// ......
+}
+```
+
+### Rename classes, methods, properties
+
+Swig has defined a directive called `%rename` to rename classes, methods or properties. To demonstrate, we modify MyObject again.
+
+```c++
+// MyObject.h
+#pragma once
+#include "cocos/cocos.h"
+#include "MyRef.h"
+namespace my_ns {
+// MyObject inherits from MyRef
+class MyObject : public MyRef {
+public:
+// ......
+ void methodToBeRenamed() { // Add this method
+ CC_LOG_DEBUG("==> hello MyObject::methodToBeRenamed");
+ }
+ int propertyToBeRenamed{1234}; // Add this property
+
+ float publicFloatProperty{1.23F};
+private:
+ int _a{100};
+ bool _b{true};
+};
+} // namespace my_ns {
+```
+
+Generate bindings, we get:
+
+```c++
+// jsb_my_module_auto.cpp
+bool js_register_my_ns_MyObject(se::Object* obj) {
+ auto* cls = se::Class::create("MyObject", obj, nullptr, _SE(js_new_MyObject));
+ cls->defineProperty("propertyToBeRenamed", _SE(js_my_ns_MyObject_propertyToBeRenamed_get), _SE(js_my_ns_MyObject_propertyToBeRenamed_set));
+ cls->defineProperty("publicFloatProperty", _SE(js_my_ns_MyObject_publicFloatProperty_get), _SE(js_my_ns_MyObject_publicFloatProperty_set));
+
+ cls->defineFunction("print", _SE(js_my_ns_MyObject_print));
+ cls->defineFunction("methodToBeRenamed", _SE(js_my_ns_MyObject_methodToBeRenamed));
+```
+
+If we want to rename `propertyToBeRenamed` to `coolProperty` and rename `methodToBeRenamed` to `coolMethod`, modify `my-module.i` as follows:
+
+```c++
+// my-module.i
+// ......
+%ignore my_ns::MyRef;
+%ignore my_ns::MyObject::methodToBeIgnored;
+%ignore my_ns::MyObject::propertyToBeIgnored;
+%rename(coolProperty) my_ns::MyObject::propertyToBeRenamed; // Add this line
+%rename(coolMethod) my_ns::MyObject::methodToBeRenamed; // Add this line
+
+%import "MyRef.h"
+%include "MyObject.h"
+```
+
+If we want to rename `MyObject` class to `MyCoolObject`, I guess you have already known how to do. Yes, add this line:
+
+```c++
+%rename(MyCoolObject) my_ns::MyObject;
+```
+
+Re-generate bindings, get the correct name exported to JS.
+
+```c++
+// jsb_my_module_auto.cpp
+// MyCoolObject, coolProperty, coolMethod are all what we want now.
+bool js_register_my_ns_MyObject(se::Object* obj) {
+ auto* cls = se::Class::create("MyCoolObject", obj, nullptr, _SE(js_new_MyCoolObject));
+ cls->defineProperty("coolProperty", _SE(js_my_ns_MyCoolObject_coolProperty_get), _SE(js_my_ns_MyCoolObject_coolProperty_set));
+ cls->defineProperty("publicFloatProperty", _SE(js_my_ns_MyCoolObject_publicFloatProperty_get), _SE(js_my_ns_MyCoolObject_publicFloatProperty_set));
+ cls->defineFunction("print", _SE(js_my_ns_MyCoolObject_print));
+ cls->defineFunction("coolMethod", _SE(js_my_ns_MyCoolObject_coolMethod));
+ // ......
+}
+```
+
+Test it, update `my-module.d.ts` and `MyComponent.ts`. The code example is as follows:
+
+```c++
+// my-module.d.ts
+declare namespace my_ns {
+class MyCoolObject {
+ constructor();
+ constructor(a: number, b: number);
+
+ publicFloatProperty : number;
+ print() : void;
+ coolProperty: number;
+ coolMethod() : void;
+}
+}
+```
+
+```ts
+// MyComponent.ts
+import { _decorator, Component } from 'cc';
+const { ccclass } = _decorator;
+
+@ccclass('MyComponent')
+export class MyComponent extends Component {
+ start() {
+ const myObj = new my_ns.MyCoolObject(); // Renamed to MyCoolObject
+ myObj.print();
+ console.log(`==> myObj.publicFloatProperty: ${myObj.publicFloatProperty}`);
+ // Add the follow lines
+ console.log(`==> old: myObj.coolProperty: ${myObj.coolProperty}`);
+ myObj.coolProperty = 666;
+ console.log(`==> new: myObj.coolProperty: ${myObj.coolProperty}`);
+ myObj.coolMethod();
+ }
+}
+```
+
+Build and run project, get log:
+
+```
+17:53:28 [DEBUG]: ==> a: 100, b: 1
+17:53:28 [DEBUG]: D/ JS: ==> myObj.publicFloatProperty: 1.2300000190734863
+17:53:28 [DEBUG]: D/ JS: ==> old: myObj.coolProperty: 1234
+17:53:28 [DEBUG]: D/ JS: ==> new: myObj.coolProperty: 666
+17:53:28 [DEBUG]: ==> hello MyObject::methodToBeRenamed
+```
+
+### Define an attribute
+
+`%attribute` directive is used for bind C++ getter and setter functions as a JS property.
+
+#### Usage
+
+1. Define an attribute (JS property) without `setter`
+
+ ```c++
+ %attribute(your_namespace::your_class_name, cpp_member_variable_type, js_property_name, cpp_getter_function_name)
+ ```
+
+2. Define an attribute (JS property) with `getter` and `setter`
+
+ ```c++
+ %attribute(your_namespace::your_class_name, cpp_member_variable_type, js_property_name, cpp_getter_function_name, cpp_setter_function_name)
+ ```
+
+3. Define an attribute (JS property) without `getter`
+
+ ```c++
+ %attribute_writeonly(your_namespace::your_class_name, cpp_member_variable_type, js_property_name, cpp_setter_function_name)
+ ```
+
+#### Demo
+
+To demonstrate, we add two new methods for MyObject class.
+
+```c++
+// MyObject.h
+#pragma once
+#include "cocos/cocos.h"
+#include "MyRef.h"
+namespace my_ns {
+// MyObject inherits from MyRef
+class MyObject : public MyRef {
+public:
+// ......
+ void setType(int v) { _type = v; CC_LOG_DEBUG("==> setType: v: %d", v); } // Add this line
+ int getType() const { return _type; } // Add this line
+
+ float publicFloatProperty{1.23F};
+private:
+ int _a{100};
+ bool _b{true};
+ int _type{333};
+};
+} // namespace my_ns {
+```
+
+```c++
+// my-module.i
+// ......
+%attribute(my_ns::MyObject, int, type, getType, setType); // Add this line
+
+%import "MyRef.h"
+%include "MyObject.h"
+```
+
+```c++
+// jsb_my_module_auto.cpp
+bool js_register_my_ns_MyObject(se::Object* obj) {
+// ......
+ cls->defineProperty("type", _SE(js_my_ns_MyCoolObject_type_get), _SE(js_my_ns_MyCoolObject_type_set));
+// ......
+}
+```
+
+```ts
+// MyComponent.ts
+import { _decorator, Component } from 'cc';
+const { ccclass } = _decorator;
+
+@ccclass('MyComponent')
+export class MyComponent extends Component {
+ start() {
+ const myObj = new my_ns.MyCoolObject();
+ myObj.print();
+ console.log(`==> myObj.publicFloatProperty: ${myObj.publicFloatProperty}`);
+ console.log(`==> old: myObj.coolProperty: ${myObj.coolProperty}`);
+ myObj.coolProperty = 666;
+ console.log(`==> new: myObj.coolProperty: ${myObj.coolProperty}`);
+ myObj.coolMethod();
+ console.log(`==> old: myObj.type: ${myObj.type}`);
+ myObj.type = 888;
+ console.log(`==> new: myObj.type: ${myObj.type}`);
+ }
+}
+```
+
+Build and run project
+
+```
+18:09:53 [DEBUG]: ==> a: 100, b: 1
+18:09:53 [DEBUG]: D/ JS: ==> myObj.publicFloatProperty: 1.2300000190734863
+18:09:53 [DEBUG]: D/ JS: ==> old: myObj.coolProperty: 1234
+18:09:53 [DEBUG]: D/ JS: ==> new: myObj.coolProperty: 666
+18:09:53 [DEBUG]: ==> hello MyObject::methodToBeRenamed
+18:09:53 [DEBUG]: D/ JS: ==> old: myObj.type: 333
+18:09:53 [DEBUG]: ==> setType: v: 888 // Cool, C++ setType is invoked
+18:09:53 [DEBUG]: D/ JS: ==> new: myObj.type: 888 // Cool, C++ getType is invoked, 888 is return from C++
+```
+
+#### %attribute_writeonly directive
+
+`%attribute_writeonly` directive is an extension we added in swig `Cocos` backend, it's used for the purpose that C++ class only has a `set` function and there isn't a `get` function.
+
+In `native/tools/swig-config/cocos.i`, there are:
+
+```c++
+%attribute_writeonly(cc::ICanvasRenderingContext2D, float, width, setWidth);
+%attribute_writeonly(cc::ICanvasRenderingContext2D, float, height, setHeight);
+%attribute_writeonly(cc::ICanvasRenderingContext2D, float, lineWidth, setLineWidth);
+%attribute_writeonly(cc::ICanvasRenderingContext2D, ccstd::string&, fillStyle, setFillStyle);
+%attribute_writeonly(cc::ICanvasRenderingContext2D, ccstd::string&, font, setFont);
+```
+
+This is the similar functionality in JS:
+
+```javascript
+Object.defineProperty(MyNewClass.prototype, 'width', {
+ configurable: true,
+ enumerable: true,
+ set(v) {
+ this._width = v;
+ },
+ // No get() for property
+});
+```
+
+#### Reference type
+
+If C++ `get` function returns a reference data type or `set` function accesses a reference data type, don't forget to add `&` suffix in %attribute or %attribute_writeonly directives. The following `ccstd::string&` is an example.
+
+```c++
+%attribute_writeonly(cc::ICanvasRenderingContext2D, ccstd::string&, fillStyle, setFillStyle);
+```
+
+If `&` is missing, a temporary `ccstd::string` instance will be created while the binding function is invoked.
+
+#### %arg() directive
+
+Sometimes, the type of C++ variable is a describled by C++ template, for instance:
+
+```c++
+class MyNewClass {
+ public:
+ const std::map& getConfig() const { return _config; }
+ void setConfig(const std::map &config) { _config = config; }
+ private:
+ std::map _config;
+};
+```
+
+We may write an `%attribute` in `.i` file like:
+
+```c++
+%attribute(MyNewClass, std::map&, config, getConfig, setConfig);
+```
+
+You will get an error while invoking `node genbindings.js`.
+
+```
+Error: Macro '%attribute_custom' expects 7 arguments
+```
+
+This is because `swig` doesn't know how to deal with comma (`,`) in `std::map&`, it will split it to two parts:
+
+1. std::map&
+
+Therefore, this line of %attribute directive will be parsed with 6 arguments instead of 5.
+
+To avoid making `swig` confused, we need to use `%arg` directive to tell `swig` that `std::map&` is a complete declaration.
+
+```c++
+%attribute(MyNewClass, %arg(std::map&), config, getConfig, setConfig);
+```
+
+Re-run `node genbindings.js`, the error will no longer be reported.
+
+#### Don't add `const`
+
+In the above sample, `%arg(std::map&)` is used as a C++ data type in %attribue directive. You may consider to add a `const` prefix before `std::map` like `%arg(const std::map&)`. If you do that, you will make a readyonly `config` property which only binds `MyNewClass::getConfig`. That's obviously not what we expect. If we need a readonly property, just don't assign a `set` function.
+
+```c++
+// Don't assign setConfig means the property doesn't need a setter.
+%attribute(MyNewClass, %arg(std::map&), config, getConfig);
+```
+
+So to keep things simple, never add `const` prefix while writing a `%attribute` directive.
+
+### Configure C++ modules in .i file
+
+Sometimes, whether to compile a class depends on whether a macro is enabled. For example, we add a `MyFeatureObject` class in `MyObject.h`
+
+```c++
+// MyObject.h
+#pragma once
+#include "cocos/cocos.h"
+#include "MyRef.h"
+
+#ifndef USE_MY_FEATURE
+#define USE_MY_FEATURE 1 // Enable USE_MY_FEATURE
+#endif
+
+namespace my_ns {
+
+#if USE_MY_FEATURE
+class MyFeatureObject {
+public:
+ void foo() {
+ CC_LOG_DEBUG("==> MyFeatureObject::foo");
+ }
+};
+#else
+class MyFeatureObject;
+#endif
+
+// MyObject inherits from MyRef
+class MyObject : public MyRef {
+public:
+//......
+ MyFeatureObject* getFeatureObject() {
+#if USE_MY_FEATURE // getFeatureObject only returns valid value when USE_MY_FEATURE is enabled
+ if (_featureObject == nullptr) {
+ _featureObject = new MyFeatureObject();
+ }
+#endif
+ return _featureObject;
+ }
+private:
+ int _a{100};
+ bool _b{true};
+ int _type{333};
+ MyFeatureObject* _featureObject{nullptr}; // Add this line
+};
+} // namespace my_ns {
+```
+
+```c++
+// my-module.i
+// ......
+%rename(MyCoolObject) my_ns::MyObject;
+
+%attribute(my_ns::MyObject, int, type, getType, setType);
+
+%module_macro(USE_MY_FEATURE) my_ns::MyFeatureObject; // Add this line to let Swig know the generated code for MyFeatureObject needs to be wrapped by USE_MY_FEATURE macro
+%module_macro(USE_MY_FEATURE) my_ns::MyObject::getFeatureObject; // Add this line to let Swig know the generated code for MyObject::getFeatureObject should be wrapped by USE_MY_FEATURE macro
+
+#define USE_MY_FEATURE 1 // Must be 1 to trick Swig that we need to generate binding code
+// even this macro is disabled in C++. NOTE: this line should be after %module_macro
+
+%import "MyRef.h"
+%include "MyObject.h"
+```
+
+```c++
+// my-module.d.ts
+declare namespace my_ns {
+class MyFeatureObject {
+ foo() : void;
+}
+
+class MyCoolObject {
+ constructor();
+ constructor(a: number, b: number);
+
+ publicFloatProperty : number;
+ print() : void;
+ coolProperty: number;
+ coolMethod() : void;
+ type: number;
+ getFeatureObject() : MyFeatureObject;
+}
+}
+```
+
+```ts
+// MyComponent.ts
+import { _decorator, Component } from 'cc';
+const { ccclass } = _decorator;
+
+@ccclass('MyComponent')
+export class MyComponent extends Component {
+ start() {
+ const myObj = new my_ns.MyCoolObject();
+ myObj.print();
+ console.log(`==> myObj.publicFloatProperty: ${myObj.publicFloatProperty}`);
+ console.log(`==> old: myObj.coolProperty: ${myObj.coolProperty}`);
+ myObj.coolProperty = 666;
+ console.log(`==> new: myObj.coolProperty: ${myObj.coolProperty}`);
+ myObj.coolMethod();
+ console.log(`==> old: myObj.type: ${myObj.type}`);
+ myObj.type = 888;
+ console.log(`==> new: myObj.type: ${myObj.type}`);
+ const featureObj = myObj.getFeatureObject();
+ console.log(`==> featureObj: ${featureObj}`);
+ if (featureObj) {
+ featureObj.foo();
+ }
+ }
+}
+```
+
+After generating bindings, the binding code is as follows:
+
+```c++
+#if USE_MY_FEATURE // NOTE THAT, all binding code of MyFeatureObject is wrapped by USE_MY_FEATURE macro
+
+se::Class* __jsb_my_ns_MyFeatureObject_class = nullptr;
+se::Object* __jsb_my_ns_MyFeatureObject_proto = nullptr;
+SE_DECLARE_FINALIZE_FUNC(js_delete_my_ns_MyFeatureObject)
+
+static bool js_my_ns_MyFeatureObject_foo(se::State& s)
+{
+// ......
+}
+// ......
+bool js_register_my_ns_MyFeatureObject(se::Object* obj) {
+ auto* cls = se::Class::create("MyFeatureObject", obj, nullptr, _SE(js_new_my_ns_MyFeatureObject));
+// ......
+}
+
+#endif // USE_MY_FEATURE
+
+// ......
+static bool js_my_ns_MyCoolObject_getFeatureObject(se::State& s)
+{
+#if USE_MY_FEATURE // getFeatureObject function is also wrapped by USE_MY_FEATURE
+// ......
+ ok &= nativevalue_to_se(result, s.rval(), s.thisObject() /*ctx*/);
+ SE_PRECONDITION2(ok, false, "MyCoolObject_getFeatureObject, Error processing arguments");
+ SE_HOLD_RETURN_VALUE(result, s.thisObject(), s.rval());
+#endif // USE_MY_FEATURE
+ return true;
+}
+SE_BIND_FUNC(js_my_ns_MyCoolObject_getFeatureObject)
+
+// ......
+bool register_all_my_module(se::Object* obj) {
+ // Get the ns
+ se::Value nsVal;
+ if (!obj->getProperty("my_ns", &nsVal, true))
+ {
+ se::HandleObject jsobj(se::Object::createPlainObject());
+ nsVal.setObject(jsobj);
+ obj->setProperty("my_ns", nsVal);
+ }
+ se::Object* ns = nsVal.toObject();
+ /* Register classes */
+#if USE_MY_FEATURE
+ js_register_my_ns_MyFeatureObject(ns); // js_register_my_ns_MyFeatureObject is wrapped by USE_MY_FEATURE
+#endif // USE_MY_FEATURE
+ js_register_my_ns_MyObject(ns);
+ return true;
+}
+```
+
+Build and run the project, the output is as follows:
+
+```
+18:32:20 [DEBUG]: D/ JS: ==> featureObj: [object Object] // featureObj is valid if USE_MY_FEATURE macro is enabled
+18:32:20 [DEBUG]: ==> MyFeatureObject::foo // Invoke C++ foo method
+```
+
+When we don't need `MyFeatureObject`, assign the macro to 0, the code is as follows:
+
+```c++
+// MyObject.h
+#pragma once
+#include "cocos/cocos.h"
+#include "MyRef.h"
+
+#ifndef USE_MY_FEATURE
+#define USE_MY_FEATURE 0 // Disable USE_MY_FEATURE
+#endif
+```
+
+Build and run the project, the following output can be seen.
+
+```
+18:54:00 [DEBUG]: D/ JS: ==> featureObj: undefined // getFeatureObject returns undefined if USE_MY_FEATURE is disabled.
+```
+
+### Multiple swig modules configuration
+
+Let's create another header file `MyAnotherObject.h`.
+
+```c++
+// MyAnotherObject.h
+#pragma once
+namespace my_another_ns {
+struct MyAnotherObject {
+ float a{135.246};
+ int b{999};
+};
+} // namespace my_another_ns {
+```
+
+Update `MyObject.h`:
+
+```c++
+// MyObject.h
+//......
+class MyObject : public MyRef {
+public:
+// ......
+ void helloWithAnotherObject(const my_another_ns::MyAnotherObject &obj) {
+ CC_LOG_DEBUG("==> helloWithAnotherObject, a: %f, b: %d", obj.a, obj.b);
+ }
+// ......
+};
+} // namespace my_ns {
+```
+
+Create `/Users/james/NewProject/tools/swig-config/another-module.i`
+
+```c++
+// another-module.i
+%module(target_namespace="another_ns") another_module
+
+// Insert code at the beginning of generated header file (.h)
+%insert(header_file) %{
+#pragma once
+#include "bindings/jswrapper/SeApi.h"
+#include "bindings/manual/jsb_conversions.h"
+
+#include "MyAnotherObject.h" // Add this line
+%}
+
+// Insert code at the beginning of generated source file (.cpp)
+%{
+#include "bindings/auto/jsb_another_module_auto.h"
+%}
+
+%include "MyAnotherObject.h"
+```
+
+Modify `/Users/james/NewProject/tools/swig-config/swig-config.js`
+
+```c++
+'use strict';
+
+const path = require('path');
+
+const configList = [
+ [ 'my-module.i', 'jsb_my_module_auto.cpp' ],
+ [ 'another-module.i', 'jsb_another_module_auto.cpp' ], // Add this line
+];
+
+const projectRoot = path.resolve(path.join(__dirname, '..', '..'));
+const interfacesDir = path.join(projectRoot, 'tools', 'swig-config');
+const bindingsOutDir = path.join(projectRoot, 'native', 'engine', 'common', 'bindings', 'auto');
+const includeDirs = [
+ path.join(projectRoot, 'native', 'engine', 'common', 'Classes'),
+];
+
+module.exports = {
+ interfacesDir,
+ bindingsOutDir,
+ includeDirs,
+ configList
+};
+```
+
+Modify `/Users/james/NewProject/native/engine/common/CMakeLists.txt`
+
+```cmake
+# /Users/james/NewProject/native/engine/common/CMakeLists.txt
+list(APPEND CC_COMMON_SOURCES
+ ${CMAKE_CURRENT_LIST_DIR}/Classes/Game.h
+ ${CMAKE_CURRENT_LIST_DIR}/Classes/Game.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/Classes/MyObject.h
+ ${CMAKE_CURRENT_LIST_DIR}/Classes/MyAnotherObject.h # Add this line
+ ${CMAKE_CURRENT_LIST_DIR}/bindings/auto/jsb_my_module_auto.h
+ ${CMAKE_CURRENT_LIST_DIR}/bindings/auto/jsb_my_module_auto.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/bindings/auto/jsb_another_module_auto.h # Add this line
+ ${CMAKE_CURRENT_LIST_DIR}/bindings/auto/jsb_another_module_auto.cpp # Add this line
+)
+```
+
+Generate bindings again.
+
+Update `Game.cpp`:
+
+```c++
+#include "Game.h"
+#include "bindings/auto/jsb_my_module_auto.h"
+#include "bindings/auto/jsb_another_module_auto.h" // Add this line
+//......
+
+int Game::init() {
+//......
+ se::ScriptEngine::getInstance()->addRegisterCallback(register_all_my_module);
+ se::ScriptEngine::getInstance()->addRegisterCallback(register_all_another_module); // Add this line
+//
+ BaseGame::init();
+ return 0;
+}
+```
+
+Build and compile, but the following errors will be reported:
+
+
+
+Since MyObject class depends on MyAnotherObject which is defined on another module. We need to update `my-module.i` and add `#include "bindings/auto/jsb_another_module_auto.h"`.
+
+```c++
+// my-module.i
+%module(target_namespace="my_ns") my_module
+
+// Insert code at the beginning of generated header file (.h)
+%insert(header_file) %{
+#pragma once
+#include "bindings/jswrapper/SeApi.h"
+#include "bindings/manual/jsb_conversions.h"
+
+#include "MyObject.h"
+%}
+
+// Insert code at the beginning of generated source file (.cpp)
+%{
+#include "bindings/auto/jsb_my_module_auto.h"
+#include "bindings/auto/jsb_another_module_auto.h" // Add this line
+%}
+
+// ......
+```
+
+Compile project. It should compile success now.
+
+Next, we update .d.ts
+
+```ts
+// my-module.d.ts
+declare namespace my_ns {
+class MyFeatureObject {
+ foo() : void;
+}
+
+class MyCoolObject {
+ constructor();
+ constructor(a: number, b: number);
+
+ publicFloatProperty : number;
+ print() : void;
+ coolProperty: number;
+ coolMethod() : void;
+ type: number;
+ getFeatureObject() : MyFeatureObject;
+ helloWithAnotherObject(obj: another_ns.MyAnotherObject) : void; // Add this line
+}
+}
+
+// Add the following lines
+declare namespace another_ns {
+class MyAnotherObject {
+ a: number;
+ b: number;
+}
+}
+```
+
+We add some more test code of reading the properties of `MyAnotherObject.`
+
+```ts
+// MyComponent.ts
+import { _decorator, Component } from 'cc';
+const { ccclass } = _decorator;
+
+@ccclass('MyComponent')
+export class MyComponent extends Component {
+ start() {
+ const myObj = new my_ns.MyCoolObject();
+ // ......
+ const anotherObj = new another_ns.MyAnotherObject(); // Add this line
+ myObj.helloWithAnotherObject(anotherObj); // Add this line
+ }
+}
+```
+
+Build and run project, the following output should be seen.
+
+```
+15:05:36 [DEBUG]: ==> helloWithAnotherObject, a: 135.246002, b: 999
+```
diff --git a/versions/4.0/en/advanced-topics/jsb/v8-win32-debug.jpg b/versions/4.0/en/advanced-topics/jsb/v8-win32-debug.jpg
new file mode 100644
index 0000000000..40b6aac3cd
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/v8-win32-debug.jpg differ
diff --git a/versions/4.0/en/advanced-topics/jsb/v8-win32-memory.jpg b/versions/4.0/en/advanced-topics/jsb/v8-win32-memory.jpg
new file mode 100644
index 0000000000..54f8ba2a7c
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/v8-win32-memory.jpg differ
diff --git a/versions/4.0/en/advanced-topics/jsb/v8-win32-profile.jpg b/versions/4.0/en/advanced-topics/jsb/v8-win32-profile.jpg
new file mode 100644
index 0000000000..3297816571
Binary files /dev/null and b/versions/4.0/en/advanced-topics/jsb/v8-win32-profile.jpg differ
diff --git a/versions/4.0/en/advanced-topics/mangle-properties.md b/versions/4.0/en/advanced-topics/mangle-properties.md
new file mode 100644
index 0000000000..9f5985ddd8
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/mangle-properties.md
@@ -0,0 +1,72 @@
+# Mangle Engine Internal Properties
+
+To help users further reduce game package size, the Cocos Engine team has introduced engine internal property mangling functionality starting from version 3.8.6. This feature can mangle properties in the engine's TypeScript code, effectively reducing game package size without compromising game performance.
+
+> Note: This feature currently does not support native platforms.
+
+## Enable Engine Property Mangling During Build
+
+
+
+## Generate Mangle Configuration
+
+During the build process, an `engine-mangle-config.json` file will be generated in the project root directory. If users want to quickly generate this configuration file, they can start a build and interrupt the build task after the configuration file is generated in the project root directory.
+
+## Mangle Configuration Fields
+
+By default, this feature mangles private properties in the engine's TypeScript code. If you need to mangle public and protected properties, you'll need to configure this in the configuration file.
+
+| Field | Description |
+| :-------------- | :----------- |
+| mangleProtected | Whether to mangle protected properties (default is false) |
+| mangleList | Add engine properties that need to be mangle |
+| dontMangleList | Add engine properties that should not be mangle |
+
+### Configuration Example
+
+#### "Profiler._meshRenderer" is a custom added property, while others are default mangle configurations.
+
+```json
+{
+ "COMMON": {
+ "mangleProtected": false,
+ "mangleList": [
+ "UITransform._sortSiblings",
+ "UITransform._cleanChangeMap",
+ "Node._findComponents",
+ "Node._findChildComponent",
+ "Node._findChildComponents",
+ "Node.idGenerator",
+ "Node._stacks",
+ "Node._stackId",
+ "Node._setScene",
+ "EffectAsset._layoutValid",
+ "EffectAsset._effects",
+ "ReflectionProbe.DEFAULT_CUBE_SIZE",
+ "ReflectionProbe.DEFAULT_PLANER_SIZE",
+ "WebGLDeviceManager.setInstance",
+ "WebGL2DeviceManager.setInstance",
+ "CanvasPool",
+
+ ],
+ "dontMangleList": [
+ "Component",
+ "Profiler._meshRenderer"
+ ]
+ },
+ "MINIGAME": {
+ "extends": "COMMON",
+ "mangleList": [],
+ "dontMangleList": []
+ },
+ "WECHAT": {
+ "extends": "MINIGAME",
+ "mangleList": [],
+ "dontMangleList": []
+ }
+}
+```
+
+## Important Notes
+
+When this feature is enabled and debug mode is active during packaging, it will slightly increase the size of the debug package.
\ No newline at end of file
diff --git a/versions/4.0/en/advanced-topics/mangle-properties/open-mangle-properties.png b/versions/4.0/en/advanced-topics/mangle-properties/open-mangle-properties.png
new file mode 100644
index 0000000000..a6e41befec
Binary files /dev/null and b/versions/4.0/en/advanced-topics/mangle-properties/open-mangle-properties.png differ
diff --git a/versions/4.0/en/advanced-topics/memory-leak-detector.md b/versions/4.0/en/advanced-topics/memory-leak-detector.md
new file mode 100644
index 0000000000..5e5c53024f
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/memory-leak-detector.md
@@ -0,0 +1,57 @@
+# Native Engine Memory Leak Detection System
+
+The native engine is developed using the C++ language. In order to facilitate game & engine developers to quickly find memory leaks, Cocos Creator provides a **memory leak detection system** since v3.4.0.
+
+Compared with other memory leak detection tools, the built-in memory leak detection tool in Cocos Creator has the following advantages:
+
+- **Cross-platform**: support Windows/Android/Mac/iOS platforms.
+- **Ease of use**: no need to download additional tools and perform complex configurations. Support output of stack information at memory leaks, which is convenient for quickly locating leaks.
+- **Consistency**: the usage process of each platform is almost the same: start the game from the IDE -> run for a period of time -> close the game -> view the IDE output log.
+- **Real-time**: although the frame rate of the game in the profiling mode has dropped, it still maintains the real-time running frame rate.
+- **Accuracy**: theoretically zero false positives.
+
+## Usage steps
+
+1. The memory leak detection system is disabled by default. To enable it, you need to modify the value of the macro `USE_MEMORY_LEAK_DETECTOR` in the `engine/native/cocos/base/Config.h` file of the engine directory to **1**.
+
+ ```c++
+ #ifndef USE_MEMORY_LEAK_DETECTOR
+ #define USE_MEMORY_LEAK_DETECTOR 1
+ #endif
+ ```
+
+2. The Android platform requires one additional step as a result of the different implementation mechanisms amongst platforms:
+
+ Add a line of code `set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -finstrument-functions")` to the `native/engine/android/CMakeLists.txt` file in the project directory, as follows:
+
+ ```
+ set(CC_PROJ_SOURCES)
+ set(CC_COMMON_SOURCES)
+ set(CC_ALL_SOURCES)
+
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -finstrument-functions")
+ ```
+
+3. Start the game from the IDE corresponding to the native platform (such as Visual Studio, Android Studio, Xcode), and close the game after running for a period of time. If there is any memory leak, the detailed information of the memory leak will be output in the output window of the IDE at this time.
+
+ - **Windows platform**
+
+ 
+
+ In the Release version, if more friendly stack information is needed, right-click the executable project-properties, open the project properties page, and make the following settings:
+
+ - Linker -> Debugging -> Generate Debug Info: Generate Debug Information(/DEBUG)
+
+ - C/C++ -> Optimization -> Optimization: Disabled(/Od)\
+
+ - C/C++ -> Optimization -> Inline Function Expansion:Disabled(/Ob0)
+
+ - **Android platform**
+
+ 
+
+ - **Mac/iOS platform**
+
+ 
+
+4. Fix the leak according to the information output by the Native platform IDE, and repeat until there is no leak.
diff --git a/versions/4.0/en/advanced-topics/memory-leak-detector/androidstudio.png b/versions/4.0/en/advanced-topics/memory-leak-detector/androidstudio.png
new file mode 100644
index 0000000000..ba37bb8981
Binary files /dev/null and b/versions/4.0/en/advanced-topics/memory-leak-detector/androidstudio.png differ
diff --git a/versions/4.0/en/advanced-topics/memory-leak-detector/visualstudio.png b/versions/4.0/en/advanced-topics/memory-leak-detector/visualstudio.png
new file mode 100644
index 0000000000..87c3998f88
Binary files /dev/null and b/versions/4.0/en/advanced-topics/memory-leak-detector/visualstudio.png differ
diff --git a/versions/4.0/en/advanced-topics/memory-leak-detector/xcode.png b/versions/4.0/en/advanced-topics/memory-leak-detector/xcode.png
new file mode 100644
index 0000000000..cd9b357773
Binary files /dev/null and b/versions/4.0/en/advanced-topics/memory-leak-detector/xcode.png differ
diff --git a/versions/4.0/en/advanced-topics/native-plugins/brief.md b/versions/4.0/en/advanced-topics/native-plugins/brief.md
new file mode 100644
index 0000000000..a75143e986
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/native-plugins/brief.md
@@ -0,0 +1,111 @@
+# Native Plugins
+
+> **Note**:
+>
+> * Please use the native plugin feature in CocosCreator 3.6.3 and above.
+> * The native plugin feature is not yet adapted for HarmonyOS related platforms.
+
+Native plugins are part of the editor plugin system. Developers can use native plugins to call script binding interfaces (such as sebind) to extend the capability of JS scripts calling C++ interfaces, which is very beneficial for solving script performance bottlenecks and reusing existing codebases.
+
+## Relationship with Existing Plugin System
+
+Native plugins can exist independently of editor plugins. Users can use native plugins by copying them to specified directories.
+
+At the same time, native plugins also serve as a supplement to the existing editor plugin system, extending the capabilities of the game runtime. They leverage the capabilities of editor plugins to manage native plugins, such as: download/on-off switching/version upgrade and other functions.
+
+### Plugin Structure
+
+Each plugin has a plugin description file `cc_plugin.json` in its root directory, which is a standard JSON file.
+
+When building native projects, the build system will recursively search for all `cc_plugin.json` files from the project's `extensions` and `native` directories to locate native plugins. Once `cc_plugins.json` is found in a directory, it will not search subdirectories further.
+
+## Installing Dependencies
+
+In a few environments where the editor is not installed, [NodeJS](https://nodejs.org/en/download/) version 8.0 or above needs to be installed to support plugin configuration parsing. Developers can set the NodeJS environment variable `PATH`, or specify it by setting `NODE_EXECUTABLE` in `CMakeLists.txt`.
+
+You can also set the environment variable `NODE_EXECUTABLE` to the full path of node. Starting from version 3.6.2, if CMake still cannot locate nodejs, you can directly set `NODE_EXECUTABLE` in `native/engine/common/localCfg.cmake`.
+
+## Basic Directory Structure Example
+
+```
+├── cc_plugin.json
+├── android
+│ ├── arm64-v8a
+│ ├── armeabi-v7a
+│ ├── x86
+│ └── x86_64
+│__ google-play
+│ ├── arm64-v8a
+│ ├── armeabi-v7a
+│ ├── x86
+│ └── x86_64
+├── ios
+│ ├── include
+│ └── lib
+├── mac
+│ ├── include
+│ └── lib
+│── windows
+│ ├── include
+│ └── lib
+```
+
+The file `cc_plugin.json` provides the necessary information for loading plugins and serves as the identifier for native plugins. Each supported native platform corresponds to a directory, which contains at least one `-Config.cmake` file. The build system uses CMake's [`find_package`](https://cmake.org/cmake/help/latest/command/find_package.html#id7) mechanism to locate or link to the required library files.
+
+If there are cross-platform source files or CMake configurations in the plugin, these files can be merged into the top-level directory. For details, please refer to the [example project](https://github.com/PatriceJiang/ccplugin_tutorial/tree/main/NewProject/native/plugins/hello_cocos).
+
+## Description File `cc_plugin.json` Format
+
+```ts
+{
+ "name": string; // Required: Plugin name
+ "version": string; // Required: Plugin version
+ "engine-version":string; // Required: Corresponding engine version range
+ "author": string; // Required: Plugin author
+ "description": string; // Required: Plugin description
+ "platforms":string[]; // Optional: Supported platform list, defaults to all native platforms if not specified. Includes windows, android, google-play, mac, ios
+ "disabled":true; // Optional: Disable plugin
+ "disable-by-platforms":string[]; // Optional: Disable plugin on specified platforms
+ "modules": [{ // Required: Libraries included in the plugin
+ "target":string; // Required: Corresponding `find_package` name, must be consistent with the first parameter of `CC_PLUGIN_ENTRY`
+ "depends": string|string[]; // Optional: Dependencies on other module names
+ "platforms":string[]; // Optional: Re-specify supported native platforms
+ }]
+
+}
+```
+
+`engine-version` can specify version ranges and exclude specific versions. Code example as follows:
+
+```ts
+"engine-version": ">=3.3 <= 3.6.0 !3.5.2|| 4.x"
+```
+
+### File Example
+
+```json
+{
+ "name":"hello-cocos-demo",
+ "version":"1.0.0",
+ "author":"cocos",
+ "engine-version":">=3.6.3",
+ "disabled":false,
+ "modules":[
+ {
+ "target":"hello_cocos_glue"
+ }
+ ],
+ "platforms":["windows", "android", "mac", "ios", "google-play"]
+}
+```
+## Creating Native Plugins
+
+Cocos native projects use CMake for management. Native plugins are managed through the search paths/directories of find_package, so as long as the directory conforms to CMake find_package search rules, the plugin can be loaded correctly. Therefore, the development process of native plugins involves providing CMake configurations and related resources, as well as writing cc_plugin.json. For related examples, please refer to [Native Plugin Creation and Usage Example](./tutorial.md).
+
+## Installing and Disabling Native Plugins
+
+Download the pre-built plugin package from the [Native Plugin Creation and Usage Example](https://github.com/zhefengzhang/cocos-native-plugins), then select a folder and copy it to the `extensions` or `native` directory according to your project requirements.
+
+If you want to disable the plugin, or disable it only on specific platforms, you can modify the `disabled` and `disable-by-platforms` fields in cc_plugin.json.
+
+> **Note**: Native plugins require CMake 3.12+. Android needs to [specify CMake version](https://developer.android.com/studio/projects/install-ndk#vanilla_cmake) as 3.18.1. Other platforms use the built-in CMake in the editor, so the version number does not need to be specified.
diff --git a/versions/4.0/en/advanced-topics/native-plugins/doc/images/1_2_save_emtpy_scene.png b/versions/4.0/en/advanced-topics/native-plugins/doc/images/1_2_save_emtpy_scene.png
new file mode 100644
index 0000000000..1b0cdd7053
Binary files /dev/null and b/versions/4.0/en/advanced-topics/native-plugins/doc/images/1_2_save_emtpy_scene.png differ
diff --git a/versions/4.0/en/advanced-topics/native-plugins/doc/images/1_3_create_windows_build.png b/versions/4.0/en/advanced-topics/native-plugins/doc/images/1_3_create_windows_build.png
new file mode 100644
index 0000000000..b0ad424636
Binary files /dev/null and b/versions/4.0/en/advanced-topics/native-plugins/doc/images/1_3_create_windows_build.png differ
diff --git a/versions/4.0/en/advanced-topics/native-plugins/doc/images/1_create_empty_project.png b/versions/4.0/en/advanced-topics/native-plugins/doc/images/1_create_empty_project.png
new file mode 100644
index 0000000000..b9fb948ee2
Binary files /dev/null and b/versions/4.0/en/advanced-topics/native-plugins/doc/images/1_create_empty_project.png differ
diff --git a/versions/4.0/en/advanced-topics/native-plugins/doc/images/2_1_link_error.png b/versions/4.0/en/advanced-topics/native-plugins/doc/images/2_1_link_error.png
new file mode 100644
index 0000000000..14d679daf9
Binary files /dev/null and b/versions/4.0/en/advanced-topics/native-plugins/doc/images/2_1_link_error.png differ
diff --git a/versions/4.0/en/advanced-topics/native-plugins/doc/images/2_1_vs_project.png b/versions/4.0/en/advanced-topics/native-plugins/doc/images/2_1_vs_project.png
new file mode 100644
index 0000000000..566a607565
Binary files /dev/null and b/versions/4.0/en/advanced-topics/native-plugins/doc/images/2_1_vs_project.png differ
diff --git a/versions/4.0/en/advanced-topics/native-plugins/doc/images/2_3_debug_url.png b/versions/4.0/en/advanced-topics/native-plugins/doc/images/2_3_debug_url.png
new file mode 100644
index 0000000000..d44f661a3e
Binary files /dev/null and b/versions/4.0/en/advanced-topics/native-plugins/doc/images/2_3_debug_url.png differ
diff --git a/versions/4.0/en/advanced-topics/native-plugins/doc/images/2_3_empty_window.png b/versions/4.0/en/advanced-topics/native-plugins/doc/images/2_3_empty_window.png
new file mode 100644
index 0000000000..1f4ca1f600
Binary files /dev/null and b/versions/4.0/en/advanced-topics/native-plugins/doc/images/2_3_empty_window.png differ
diff --git a/versions/4.0/en/advanced-topics/native-plugins/doc/images/2_4_devtool.png b/versions/4.0/en/advanced-topics/native-plugins/doc/images/2_4_devtool.png
new file mode 100644
index 0000000000..6756351ddc
Binary files /dev/null and b/versions/4.0/en/advanced-topics/native-plugins/doc/images/2_4_devtool.png differ
diff --git a/versions/4.0/en/advanced-topics/native-plugins/doc/images/2_5_devtool.png b/versions/4.0/en/advanced-topics/native-plugins/doc/images/2_5_devtool.png
new file mode 100644
index 0000000000..6d9dd69bd6
Binary files /dev/null and b/versions/4.0/en/advanced-topics/native-plugins/doc/images/2_5_devtool.png differ
diff --git a/versions/4.0/en/advanced-topics/native-plugins/doc/images/3_1_android_build.png b/versions/4.0/en/advanced-topics/native-plugins/doc/images/3_1_android_build.png
new file mode 100644
index 0000000000..0aa1a08654
Binary files /dev/null and b/versions/4.0/en/advanced-topics/native-plugins/doc/images/3_1_android_build.png differ
diff --git a/versions/4.0/en/advanced-topics/native-plugins/tutorial.md b/versions/4.0/en/advanced-topics/native-plugins/tutorial.md
new file mode 100644
index 0000000000..8ac117fe7b
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/native-plugins/tutorial.md
@@ -0,0 +1,387 @@
+# Native Plugin Creation Example
+
+If you want to use third-party native libraries in native projects, you can follow the steps in this article.
+
+This article requires some understanding of native project compilation and generation. Developers can learn about it through the [CMake official website](https://cmake.org/). We have also prepared a [Native Plugin Creation and Usage Example](https://github.com/zhefengzhang/cocos-native-plugins) for reference.
+
+## Creating Native Plugins
+
+### Compiling Dependent Libraries or Static Libraries
+
+Use the compilation tools provided by the application platform to compile c or cpp files into .lib or .a files. In the [Native Plugin Creation and Usage Example](https://github.com/zhefengzhang/cocos-native-plugins) repository, the hello_cocos.cpp file in the src folder has been compiled into .lib and .a files and added to the plugin directories of various platforms. The jni directory in the repository provides the configuration and code used when compiling .a files with the `ndk-build` command on the Android platform for developers' reference. Please compile for other platforms yourself.
+
+### Windows Configuration for Plugin Development Project
+
+In this example, we will introduce hello_cocos.lib as a plugin on the Windows platform, integrate it into the engine, and make it available for use in TS/JS. Other platforms will use hello_cocos.a as an example. If you want to use other libraries, please compile them for the corresponding platform in advance.
+
+- Create a project using Cocos Creator 3.6.3 or higher
+
+ Start CocosCreator and execute `Create Empty Project` in the specified directory.
+
+ 
+
+- Create and save an empty scene
+
+ 
+
+- Export the native project through the **Build & Publish** panel and build it to generate the `native/` directory
+
+ Here we create a new build task for Windows.
+
+ 
+
+ Execute **Build**, which will also generate the `native/` directory.
+
+ View the contents of the directory through the console (Windows CMD or PowerShell or similar software):
+
+ ```console
+ $ tree native/ -L 2
+ native/
+ └── engine
+ ├── common
+ └── win64
+
+ ```
+
+- Create a directory for plugin storage in `native/`
+
+ ```console
+ mkdir -p native/native-plugin/
+ ```
+
+### Adding Native Plugin Support for Windows
+
+- Add Windows platform-related subdirectories:
+
+ ```console
+ mkdir -p native/native-plugin/windows/
+ ```
+
+- Copy the pre-compiled dependency library `hello_cocos.lib` and header files to the corresponding directory:
+
+ ```console
+ $ tree native/native-plugin/
+
+ native/native-plugin/
+ ├── include
+ │ └── hello_cocos.h
+ └── windows
+ └── lib
+ ├── hello_cocos.lib
+ └── hello_cocosd.lib
+ ```
+
+- Add files `hello_cocos_glue.cpp`, `CMakeLists.txt` and `hello_cocos_glue-config.cmake`:
+
+ ```console
+ mkdir native/native-plugin/src
+ touch native/native-plugin/src/hello_cocos_glue.cpp
+ touch native/native-plugin/src/CMakeLists.txt
+ touch native/native-plugin/hello_cocos_glue-config.cmake
+ ```
+
+ Current plugin directory contents:
+
+ ```console
+ $ tree native/native-plugin/
+ native/native-plugin/
+ ├── include
+ │ └── hello_cocos.h
+ ├── src
+ │ ├── CMakeLists.txt
+ │ └── hello_cocos_glue.cpp
+ └── windows
+ ├── hello_cocos_glue-config.cmake
+ └── lib
+ ├── hello_cocos.lib
+ └── hello_cocosd.lib
+ ```
+
+- Edit `hello_cocos_glue-config.cmake` to add declarations for `hello_cocos.lib` and imported content:
+
+ ```cmake
+ set(_hello_cocos_GLUE_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+ add_library(hello_cocos STATIC IMPORTED GLOBAL)
+ set_target_properties(hello_cocos PROPERTIES
+ IMPORTED_LOCATION ${_hello_cocos_GLUE_DIR}/lib/hello_cocos.lib
+ IMPORTED_LOCATION_DEBUG ${_hello_cocos_GLUE_DIR}/lib/hello_cocosd.lib
+ )
+
+ include(${_hello_cocos_GLUE_DIR}/../src/CMakeLists.txt)
+ ```
+
+- Edit `native/native-plugin/src/CMakeLists.txt` and add the following content:
+
+ ```cmake
+ set(_hello_cocos_GLUE_SRC_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+ add_library(hello_cocos_glue ${_hello_cocos_GLUE_SRC_DIR}/hello_cocos_glue.cpp)
+
+ target_link_libraries(hello_cocos_glue
+ hello_cocos
+ ${ENGINE_NAME} # cocos_engine
+ )
+
+ target_include_directories(hello_cocos_glue PRIVATE
+ ${_hello_cocos_GLUE_SRC_DIR}/../include
+ )
+ ```
+
+- Create configuration file `cc_plugin.json` in directory `native/native-plugin/`
+
+ ```json
+ {
+ "name":"hello-cocos-demo",
+ "version":"1.0.0",
+ "author":"cocos",
+ "engine-version":">=3.6.3",
+ "disabled":false,
+ "modules":[
+ {
+ "target":"hello_cocos_glue"
+ }
+ ],
+ "platforms":["windows"]
+ }
+ ```
+
+ The files required for the native plugin have now been created, but they cannot be compiled yet. The file `hello_cocos_glue.cpp` needs to register the plugin's initialization function.
+
+ Execute **Build** again to trigger the update of the Visual Studio project.
+
+- Open the sln file in directory `build/windows/proj/` with Visual Studio
+
+ - A `plugin_registry` target is automatically generated for initializing all enabled plugins:
+
+ 
+
+ - Directly running the target will result in similar error reports:
+
+ 
+
+- Edit `hello_cocos_glue.cpp`
+
+ ```c++
+ #include "hello_cocos.h"
+ #include "bindings/sebind/sebind.h"
+ #include "plugins/bus/EventBus.h"
+ #include "plugins/Plugins.h"
+
+ // export c++ methods to JS
+ static bool register_demo(se::Object *ns) {
+
+ sebind::class_ klass("Demo");
+
+ klass.constructor()
+ .function("hello", &Demo::hello);
+ klass.install(ns);
+ return true;
+ }
+
+ void add_demo_class() {
+ using namespace cc::plugin;
+ static Listener listener(BusType::SCRIPT_ENGINE);
+ listener.receive([](ScriptEngineEvent event) {
+ if (event == ScriptEngineEvent::POST_INIT) {
+ se::ScriptEngine::getInstance()->addRegisterCallback(register_demo);
+ }
+ });
+ }
+
+ /**
+ * Regist a new cc plugin entry function
+ * first param: should match the name in cc_plugin.json
+ * second param: callback when engine initialized
+ */
+ CC_PLUGIN_ENTRY(hello_cocos_glue, add_demo_class);
+ ```
+
+ After compiling again, there are no more errors, and the project can now be compiled and run correctly.
+
+- Run the target project:
+
+ 
+
+- To verify whether our native plugin has been loaded, we need to connect to devtools:
+
+ From the `Output` panel, obtain the debugging connection.
+
+ 
+
+ Open the browser, enter the debugging link address from the image above, and type the following code in the console:
+
+ ```javascript
+ new Demo("World").hello("Cocos")
+ ```
+
+ 
+
+ Based on the output, it can be confirmed that our interface has been successfully exported through the native plugin.
+
+### Adding Native Plugin Support for Android
+
+- Add Android build task
+
+- Create Android-related native plugin directory
+
+ ```console
+ mkdir native/native-plugin/android
+ ```
+
+- Copy pre-compiled dependency libraries and header files to the corresponding directory, create `hello_cocos_glue-config.cmake`
+
+ Android directory status:
+
+ ```console
+ $ tree native/native-plugin/android/
+ native/native-plugin/android/
+ ├── hello_cocos_glue-config.cmake
+ ├── arm64-v8a
+ │ └── lib
+ │ └── libhello_cocos.a
+ └── armeabi-v7a
+ └── lib
+ └── libhello_cocos.a
+
+ ```
+
+- Edit `hello_cocos_glue-config.cmake`
+
+ ```cmake
+ set(_hello_cocos_GLUE_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+ add_library(hello_cocos STATIC IMPORTED GLOBAL)
+ set_target_properties(hello_cocos PROPERTIES
+ IMPORTED_LOCATION ${_hello_cocos_GLUE_DIR}/${ANDROID_ABI}/lib/libhello_cocos.a
+ )
+
+ include(${_hello_cocos_GLUE_DIR}/../src/CMakeLists.txt)
+ ```
+
+- Update `cc_plugin.json`, add `android` to the `platforms` field
+
+ ```json
+ {
+ "name":"hello-cocos-demo",
+ "version":"1.0.0",
+ "author":"cocos",
+ "engine-version":">=3.6.3",
+ "disabled":false,
+ "modules":[
+ {
+ "target":"hello_cocos_glue"
+ }
+ ],
+ "platforms":["windows", "android"]
+ }
+
+ ```
+
+- Add new Android build task
+
+ 
+
+After building, you can open the project with Android Studio and use devtool for debugging verification.
+
+### Adding Native Plugin Support for iOS
+
+- Add iOS build task
+
+- Create iOS-related native plugin directory
+
+ ```
+ mkdir -p native/native-plugin/ios/lib
+ ```
+
+- Copy pre-compiled dependency libraries and header files to the corresponding directory, create `hello_cocos_glue-config.cmake`, edit according to the following example:
+
+ ```cmake
+ set(_hello_cocos_GLUE_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+
+ add_library(hello_cocos STATIC IMPORTED GLOBAL)
+ set_target_properties(hello_cocos PROPERTIES
+ IMPORTED_LOCATION ${_hello_cocos_GLUE_DIR}/lib/libhello_cocos.a
+ )
+
+ include(${_hello_cocos_GLUE_DIR}/../src/CMakeLists.txt)
+ ```
+
+### Adding Native Plugin Support for MacOS
+
+- Add MacOS build task
+
+- Create MacOS-related native plugin directory
+
+ ```console
+ mkdir -p native/native-plugin/mac/lib
+ ```
+
+- Copy pre-compiled dependency libraries and header files to the corresponding directory, create `hello_cocos_glue-config.cmake`
+
+ ```cmake
+ set(_hello_cocos_GLUE_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+ add_library(hello_cocos STATIC IMPORTED GLOBAL)
+ set_target_properties(hello_cocos PROPERTIES
+ IMPORTED_LOCATION ${_hello_cocos_GLUE_DIR}/lib/libhello_cocos.a
+ )
+
+ include(${_hello_cocos_GLUE_DIR}/../src/CMakeLists.txt)
+ ```
+
+- Update `cc_plugin.json`, add `iOS` and `mac` to the `platforms` field
+
+ ```json
+ {
+ "name":"hello-cocos-demo",
+ "version":"1.0.0",
+ "author":"cocos",
+ "engine-version":">=3.6.3",
+ "disabled":false,
+ "modules":[
+ {
+ "target":"hello_cocos_glue"
+ }
+ ],
+ "platforms":["windows", "android", "iOS", "mac"]
+ }
+
+ ```
+
+At this point, a native plugin that supports Android, Windows, MacOS, and iOS has been developed.
+
+The final contents of the native plugin directory are as follows:
+
+```console
+$ tree native/native-plugin/
+native/native-plugin
+├── cc_plugin.json
+├── include
+│ └── hello_cocos.h
+├── src
+│ ├── CMakeLists.txt
+│ └── hello_cocos_glue.cpp
+├── android
+│ ├── hello_cocos_glue-config.cmake
+│ ├── arm64-v8a
+│ │ └── lib
+│ │ └── libhello_cocos.a
+│ └── armeabi-v7a
+│ └── lib
+│ └── libhello_cocos.a
+├── ios
+│ ├── hello_cocos_glue-config.cmake
+│ └── lib
+│ └── libhello_cocos.a
+├── mac
+│ ├── hello_cocos_glue-config.cmake
+│ └── lib
+│ └── libhello_cocos.a
+└── windows
+ ├── hello_cocos_glue-config.cmake
+ └── lib
+ ├── hello_cocos.lib
+ └── hello_cocosd.lib
+```
\ No newline at end of file
diff --git a/versions/4.0/en/advanced-topics/native-profiler/add-stats.png b/versions/4.0/en/advanced-topics/native-profiler/add-stats.png
new file mode 100644
index 0000000000..2ff1942433
Binary files /dev/null and b/versions/4.0/en/advanced-topics/native-profiler/add-stats.png differ
diff --git a/versions/4.0/en/advanced-topics/native-profiler/enable-profiler.png b/versions/4.0/en/advanced-topics/native-profiler/enable-profiler.png
new file mode 100644
index 0000000000..e218692666
Binary files /dev/null and b/versions/4.0/en/advanced-topics/native-profiler/enable-profiler.png differ
diff --git a/versions/4.0/en/advanced-topics/native-profiler/profiler.png b/versions/4.0/en/advanced-topics/native-profiler/profiler.png
new file mode 100644
index 0000000000..67a0ca8621
Binary files /dev/null and b/versions/4.0/en/advanced-topics/native-profiler/profiler.png differ
diff --git a/versions/4.0/en/advanced-topics/native-scene-culling.md b/versions/4.0/en/advanced-topics/native-scene-culling.md
new file mode 100644
index 0000000000..80a96bf5a7
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/native-scene-culling.md
@@ -0,0 +1,39 @@
+# Native Scene Culling
+
+Creator supports native scene culling starting from v3.4.0, including **Octree Scene Culling** and **Occlusion Query Culling** for native platforms only.
+
+## Octree Scene Culling
+
+Generally, the engine culls models that are not in the viewing frustum (the visible range of the camera) by checking whether the bounding boxes of the models are in the viewing frustum one by one, which is slower. If octree culling is enabled, the models that are not in the viewing frustum can be quickly culled by the octree.
+
+This feature is disabled by default, to enable it, select the scene root node **Scene** in the **Hierarchy** panel, then notice the **Octree Scene Culling** option in the **Inspector** panel, and check **Enabled**.
+
+
+
+When octree culling is enabled, the whole world's bounding box (e.g. the white bordered cube in the scene above) will be displayed in the **Scene** panel.
+
+The properties of **Octree Scene Culling** are described as follows:
+
+| Property | Description |
+| :-- | :-- |
+| Enabled | Check this option to enable Octree Scene Culling, only for native platforms. |
+| World MinPos | The minimum vertex coordinates of the world bounding box (objects beyond the bounding box are not rendered). |
+| World MaxPos | The maximum vertex coordinates of the world bounding box (objects beyond the bounding box are not rendered). |
+| Depth | Depth of the octree, the default value is 8. If the scene is small, it is recommended not to set this value too large, otherwise it may consume memory. |
+
+## Occlusion Query Culling
+
+**Occlusion Query Culling** is off by default, if it is on, the GFX backend will perform an occlusion query through the graphics API and if the object is occluded, only the simplified bounding box and material will be used to render the object to improve performance.
+
+This feature can be turned on with code that says
+
+```ts
+director.root.pipeline.setOcclusionQueryEnabled(true);
+```
+
+> **Note**: GLES 2.0 does not support occlusion query culling, and some GLES 3.0 devices do not support it without the `GL_EXT_occlusion_query_boolean` extension.
+
+## Performance optimization suggestions
+
+- If most of the objects in the scene are visible, it is recommended not to enable **Octree Scene Culling** and **Occlusion Query Culling**.
+- Performance may vary slightly from device to device, so decide whether to turn on the corresponding culling function after comparing performance tests.
diff --git a/versions/4.0/en/advanced-topics/native-scene-culling/octree-scene-culling.png b/versions/4.0/en/advanced-topics/native-scene-culling/octree-scene-culling.png
new file mode 100644
index 0000000000..c537849390
Binary files /dev/null and b/versions/4.0/en/advanced-topics/native-scene-culling/octree-scene-culling.png differ
diff --git a/versions/4.0/en/advanced-topics/native-secondary-development.md b/versions/4.0/en/advanced-topics/native-secondary-development.md
new file mode 100644
index 0000000000..0b2ea34ecc
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/native-secondary-development.md
@@ -0,0 +1,150 @@
+# Native Platform Secondary Development Guide
+
+If you need to integrate third-party SDK libraries or modify, add or remove C++, Objective-C, or Java code files, the following information can help you do it faster.
+
+## Native Project Directories
+
+When you click the **Build** button, three native platform-related folders are generated.
+
+There is 3 directories related to native project.
+
+### Common Directory
+
+Location: `native/engine/common`
+
+This directory is used to store common content such as engine library configurations and some third-party libraries that are used by all platforms.
+
+> The code in this directory is mostly written in C/C++.
+
+### Native Platforms Directories
+
+Location: `native/engine/`
+
+This directory is used to store platform-specific content. For example:
+
+- native/engine/android
+- native/engine/ios
+- native/engine/win64
+- native/engine/mac
+
+> `win64` is used for Windows, and `win32` is no longer supported. Only `win64` applications are supported for release by Cocos Creator.
+
+### Project Directory
+
+Location: `build/`
+
+This directory contains the final generated native projects used for compilation, debugging, and publishing. For example:
+
+- build/android
+- build/ios
+- build/windows
+- build/mac
+
+During each build, the engine combines the common directory, the native platform directory, and the resources and scripts from the Cocos Creator project to generate the project directory.
+
+The code and related configurations in the project directory reference the files in the corresponding native platform directory and the common directory. If you make changes to the corresponding parts in the IDE, the files in the referenced directories will be modified accordingly.
+
+**Note:** The `native/engine/ios/info.plist` and `native/engine/mac/info.plist` files copied due to the mechanism of `CMake`. If you want to modify `info.plist`, please be cautious.
+
+The project directory contains the following contents:
+- `assets`: `data` A symbolic link to the data directory, used for compatibility across platforms.
+- `data`: The contents generated from the resources and scripts in the Cocos Creator project.
+- `proj`: The native platform project for the current build, used for compilation, debugging, and publishing in the corresponding platform's IDE (e.g., Xcode, Android Studio).
+- `cocos.compile.config.json`: The build options configuration used for this build.
+
+## Native Project Customization
+
+Sometimes, due to project requirements, we may need to modify, add, or remove native platform-related source code files, integrate third-party SDKs, or modify project configurations. These tasks are referred to as project customization development.
+
+Below, we will categorize different scenarios and explain how to perform the operations.
+
+### Modifying Engine Code
+
+Please refer to the [Engine Customization Workflow](./engine-customization.md)。
+
+### Modifying Project Code
+
+If you need to modify project-related code, simply locate the corresponding files and make the necessary changes. Once modified, you can compile the project without any additional configuration.
+
+### Adding/Removing Code Files
+
+Adding or removing code files involves modifying the build configuration, which may differ for different programming languages and platforms. Let's categorize them as follows.
+
+#### Adding/Removing C++ Files
+
+If you need to add or remove project-related C++ files, you need to modify the corresponding `CMakeLists.txt` file.
+
+If the C++ files to be added or removed are in the `native/engine/common/` directory, you need to modify `native/engine/common/CMakeLists.txt`.
+
+```bat
+list(APPEND CC_COMMON_SOURCES
+ ${CMAKE_CURRENT_LIST_DIR}/Classes/Game.h
+ ${CMAKE_CURRENT_LIST_DIR}/Classes/Game.cpp
+)
+```
+
+As shown in the code above, find the corresponding location and add or remove your own source code.
+
+If the code files to be added or removed are platform-specific C++ files, you need to modify `native/engine//CMakeLists.txt`. Refer to the code below:
+
+```bat
+include(${CC_PROJECT_DIR}/../common/CMakeLists.txt)
+
+//Add your own C++ files here
+list(APPEND CC_PROJ_SOURCES
+ ${CMAKE_CURRENT_LIST_DIR}/MyTest2.hpp
+ ${CMAKE_CURRENT_LIST_DIR}/MyTest2.cpp
+)
+```
+
+#### Adding/Removing Objective-C Files
+
+The management of Objective-C files in the iOS/macOS native projects generated by Cocos Creator is exactly the same as for C++. Please refer to the previous content.
+
+#### Adding/Removing Java Files
+
+Java is based on a path-based package management mechanism, so adding or removing Java files does not require any special handling.
+
+### Integrating C++/OC Libraries
+
+If the library you want to integrate is written in C++ or Objective-C, place the SDK in the `native/engine/common/` or `native/engine//` directory depending on the situation, and modify the corresponding `CMakeLists.txt` in the respective directory.
+
+Libraries written by Objective-C should only be placed in the platform-specific directory and should not be placed in `native/engine/common/`, as it may cause compilation errors on other native platforms.
+
+Most C++ SDKs provide their own `CMakeLists.txt`, so you can integrate them by including the files.
+
+For CMake configuration, you can refer to the existing `CMakeLists.txt` in the project for modification. For more details on using CMake, you can refer to [Introduce to CMake Usage](../advanced-topics/cmake-learning.md).
+
+### Integrating Jar Libraries
+
+If the library you want to integrate is written by Java and specific to the Android platform, simply place it in the corresponding `native/engine/android/` directory and configure `native/android/build.gradle`.
+
+## Interacting with Native
+
+For newly created native methods or newly integrated native SDKs that you want to export for use in script code, you can use the following approaches.
+
+### Using JsbBridge
+
+If you need to call simple and infrequent functions, you can use the `JsbBridge` mechanism for communication.
+
+- [JavaScript and Java Communication using JsbBridge](js-java-bridge.md)
+- [JavaScript and Objective-C Communication using JsbBridge](js-oc-bridge.md)
+
+### Using JSB Auto Binding
+
+For frequent C++ function calls or batch C++ API exports to the script layer, it is recommended to use the [JSB Automatic Binding]((jsb-auto-binding.md)) mechanism for script-native interaction.
+
+### Using Reflection
+
+Communication based on the reflection mechanism in Java and Objective-C can also be used for convenient script-native interaction. However, due to stricter review rules on iOS, there is a risk of review failure when using reflection mechanisms on iOS.
+
+- [JavaScript and Android Communication with Reflection](java-reflection.md)
+- [JavaScript and iOS/macOS Communication with Reflection](oc-reflection.md)
+
+## Source Code Version Control
+
+If your team uses source code version control software for collaborative work, the `native/` directory should be included in the version control.
+
+All project customization work should be done in the `/` directory as much as possible, so that the `build/` directory can be deleted at any time and does not need to be included in the source code version control.
+
+For special project requirements that cannot be achieved within the `native/` directory, modifications to the content under the `build/` directory are required. In this case, the corresponding folders should be included in version control based on the requirements.
diff --git a/versions/4.0/en/advanced-topics/oc-reflection.md b/versions/4.0/en/advanced-topics/oc-reflection.md
new file mode 100644
index 0000000000..64b79df487
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/oc-reflection.md
@@ -0,0 +1,230 @@
+# JavaScript and iOS/macOS Communication with Reflection
+
+## Calling Objective-C from JavaScript
+
+In Cocos Creator, there is a cross-language communication method based on language reflection, which allows JavaScript to directly call Objective-C functions. The method prototype is as follows:
+
+```js
+var result = native.reflection.callStaticMethod(className, methodName, arg1, arg2, .....);
+```
+
+In the `native.reflection.callStaticMethod method`, by passing the Objective-C class name, method name, and arguments, you can directly call the Objective-C static method and obtain the return value.
+
+> **Note**:
+> 1. Only static methods of accessible classes can be called
+>
+> 2. In March 2017, Apple App Store issued warnings to some applications that used risky methods. Among them, `respondsToSelector` and `performSelector` are included, which are core APIs used in the reflection mechanism. Please pay attention to Apple's official stance on this issue. Related discussions can be found at: [JSPatch](https://github.com/bang590/JSPatch/issues/746)、[React-Native](https://github.com/facebook/react-native/issues/12778)、[Weex](https://github.com/alibaba/weex/issues/2875)。
+
+To reduce the risk of rejection during app review, it is recommended to [JavaScript and Objective-C Communication using JsbBridge](./js-oc-bridge.md).
+
+### Class Name and Static Methods
+
+The class name in the parameter does not require a path; you only need to pass the class name as it is in Objective-C. For example, if you create a class called `NativeOcClass` in any file in your project directory, you just need to import it into your project.
+
+Once again, it's important to note that it only supports call the static methods of Objective-C classes from JavaScript.
+
+### Method with Parameters
+
+When it comes to method names, pay attention to their exact syntax. You need to provide the complete method name, especially when a method has parameters. The colons `:` in the method name should also be included.
+
+Here's an example of a method with parameters:
+
+```objc
+import
+@interface NativeOcClass : NSObject
++(BOOL)callNativeUIWithTitle:(NSString *) title andContent:(NSString *)content;
+@end
+```
+
+Example of calling a method with parameters:
+
+```js
+if(sys.isNative && (sys.os == sys.OS.IOS || sys.os == sys.OS.OSX)){
+ var ret = native.reflection.callStaticMethod("NativeOcClass",
+ "callNativeUIWithTitle:andContent:",
+ "cocos2d-js",
+ "Yes! you call a Native UI from Reflection");
+}
+```
+
+The `sys.isNative` is used to check if it's running on a native platform, and the `sys.os` is used to determine the current operating system. Since the communication mechanisms vary across different platforms, it is recommended to perform the check before call `native.reflection.callStaticMethod`.
+
+> **Note**: The method name should be `callNativeUIWithTitle:andContent:`, don't forget the **:** at the end.
+
+### Method without Parameters
+
+If a method does not have any parameters, then you don't need to include the colons `:`, the `methodName` remains the same as in Objective-C.
+
+Here's an example of a method without parameters:
+
+```objc
++(NSString *)callNativeWithReturnString;
+```
+
+Example of calling a method without parameters:
+
+```js
+var ret = native.reflection.callStaticMethod("NativeOcClass",
+ "callNativeWithReturnString");
+```
+
+### Return Values
+
+Here's the Objective-C implementation of the method that shows a native dialog. It sets the title and content to the passed parameters and returns a boolean value.
+
+```objc
++(BOOL)callNativeUIWithTitle:(NSString *) title andContent:(NSString *)content{
+ UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title message:content delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
+ [alertView show];
+ return true;
+}
+```
+
+At this point, you can receive the returned value (true) from Objective-C in the variable `ret`.
+
+### Type Conversion
+
+When dealing with float, int, and bool parameters in Objective-C implementation, you should use the following types for conversion:
+
+- **Use NSNumber for float and int**
+- **Use BOOL for bool**
+
+For example, in the code snippet below, we pass two float numbers to calculate their sum. We use `NSNumber` as the parameter type instead of int and float.
+
+```objc
++(float) addTwoNumber:(NSNumber *)num1 and:(NSNumber *)num2{
+ float result = [num1 floatValue]+[num2 floatValue];
+ return result;
+}
+```
+
+Currently, the parameters and return values support the following types:
+
+- `int`
+- `float`
+- `bool`
+- `string`
+
+Other types are not supported at the moment.
+
+If you're not familiar with how to add Objective-C files to your project, you can refer to the [Native Platform Secondary Development Guide](native-secondary-development.md)。
+
+## Calling JavaScript in Objective-C
+
+In a Cocos Creator native project, we can also execute JavaScript code in C++ or Objective-C using the `evalString` method.
+
+Here's an example of how to call JavaScript code:
+
+```c++
+CC_CURRENT_ENGINE()->getScheduler()->performFunctionInCocosThread([=](){
+ se::ScriptEngine::getInstance()->evalString(script.c_str());
+});
+```
+
+> **Note**: Unless you are certain that the current thread is the main thread ( Cocos Thread ), you need to use the performFunctionInCocosThread method to dispatch the function to the main thread for execution.
+
+### Global Function
+
+We can add a new global function in the script using the following code:
+
+```js
+window.callByNative = function(){
+ //to do
+}
+```
+
+>`window` is the global object in the Cocos Engine script environment. If you want a variable, function, object, or class to be globally accessible, you need to add it as a property of `window`. You can access it using `window.variableName` or `variableName` directly.
+
+Then, you can call it like this:
+
+```c++
+CC_CURRENT_ENGINE()->getScheduler()->performFunctionInCocosThread([=](){
+ se::ScriptEngine::getInstance()->evalString("window.callByNative()");
+});
+```
+
+Or:
+
+```c++
+CC_CURRENT_ENGINE()->getScheduler()->performFunctionInCocosThread([=](){
+ se::ScriptEngine::getInstance()->evalString("callByNative()");
+});
+```
+
+### Calling Static Function of an Class
+
+Suppose there is an object in the TypeScript script with the following static function:
+
+```ts
+export class NativeAPI{
+ public static callByNative(){
+ //to do
+ }
+}
+//Register NativeAPI as a global class, otherwise it cannot be called in Objective-C.
+window.NativeAPI = NativeAPI;
+```
+
+We can call it like this:
+
+```c++
+CC_CURRENT_ENGINE()->getScheduler()->performFunctionInCocosThread([=](){
+ se::ScriptEngine::getInstance()->evalString("NativeAPI.callByNative()");
+});
+```
+
+### Calling Singleton Function
+
+If the script code implements a singleton object that can be globally accessed:
+
+```ts
+export class NativeAPIMgr{
+ private static _inst:NativeAPIMgr;
+
+ public static get inst():NativeAPIMgr{
+ if(!this._inst){
+ this._inst = new NativeAPIMgr();
+ }
+ return this._inst;
+ }
+
+ public static callByNative(){
+ //to do
+ }
+}
+
+//Register NativeAPIMgr as a global class, otherwise it cannot be called in Objective-C.
+window.NativeAPIMgr = NativeAPIMgr;
+```
+
+We can call it like this.
+
+```c++
+CC_CURRENT_ENGINE()->getScheduler()->performFunctionInCocosThread([=](){
+ se::ScriptEngine::getInstance()->evalString("NativeAPIMgr.inst.callByNative()");
+});
+```
+
+### Calling with Parameters
+
+The above mentioned ways of calling JS from Java all support parameter passing. However, the parameters only support the three basic types: `string`, `number`, and `boolean`.
+
+Taking the global function as an example:
+
+```js
+window.callByNative = function(a:string, b:number, c:bool){
+ //to do
+}
+```
+
+You can call it like this:
+
+```c++
+CC_CURRENT_ENGINE()->getScheduler()->performFunctionInCocosThread([=](){
+ se::ScriptEngine::getInstance()->evalString("window.callByNative('test',1,true)");
+});
+```
+
+## Thread Safety
+
+As you can see in the code above, `CC_CURRENT_ENGINE()->getScheduler()->performFunctionInCocosThread` is used. This is to ensure that the code is executed in the correct thread. For more details, please refer to the [Thread Safety](./thread-safety.md) documentation.
diff --git a/versions/4.0/en/advanced-topics/profiler.md b/versions/4.0/en/advanced-topics/profiler.md
new file mode 100644
index 0000000000..53e60fb8dd
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/profiler.md
@@ -0,0 +1,101 @@
+# Native Performance Profiler
+
+The performance profiler is a tool for performance analysis and statistics that is currently only available on native platforms.
+
+## Default statistics
+
+- The performance profiler is shown as follows:
+
+ 
+
+- Different from the old version of `Profiler` in the lower left corner, the new version of `Profiler` provides more detailed game performance and memory statistics, and supports expansion. Developers can freely add performance and memory data that they care about. The default data is as follows:
+
+ 1. Core statistics `CoreStats`, including:
+ - frame rate
+ - render time per frame
+ - GFX backend
+ - Whether to enable multithreading
+ - Whether to enable occlusion query
+ - Whether to enable shadow maps
+ - Screen Resolution
+
+ 2. Object count statistics `ObjectStats`, including:
+ - number of render calls
+ - Number of instantiations
+ - Number of triangles
+ - Number of 2D rendering batches
+ - Number of rendered models
+ - Number of cameras
+
+ 3. Memory usage statistics `MemoryStats`, including:
+ - Vertex buffer size for DebugRenderer
+ - Native font memory size
+ - Video memory occupied by textures
+ - The video memory occupied by Buffer
+ - GeometryRenderer vertex buffer size
+
+ 4. Performance Statistics `PerformanceStats`, showing the logical thread call stack, contains for each profiled code segment:
+ - total execution time per frame
+ - Maximum time for a single execution per frame
+ - total number of executions per frame
+ - average execution time per frame
+ - Total historical execution time
+ - The maximum time of a single execution in history
+ - Total number of historical executions
+ - The average time of a single execution in history
+
+## How to use
+
+- In the main menu of the editor: **Project** -> **Project Settings** -> **Feature cropping**, check **Debug Renderer**, this option is closed by default, you need to open it to display the debug information:
+
+ 
+
+- Change the macro definition of `CC_USE_PROFILER` to `1` in `native/cocos/base/Config.h`, and then change it back to `0` after the performance and memory optimization is completed. At this time, the performance profiler is completely closed and will not Cause any side effects on the code:
+
+ ```c++
+ #ifndef CC_USE_PROFILER
+ #define CC_USE_PROFILER 0
+ #endif
+ ```
+
+- If you want to add the statistical information of `ObjectStats`, such as counting the number of rendered models per frame (need to be called in a function such as update for each frame):
+
+ The following macros are defined in [native/cocos/profiler/Profiler.h](https://github.com/cocos/cocos4/blob/v4.0.0/native/cocos/profiler/Profiler.h). Developers can use it as needed.
+
+ ```c++
+ void RenderScene::update(uint32_t stamp) {
+ ...
+ CC_PROFILE_OBJECT_UPDATE(Models, _models.size());
+ }
+ ```
+
+ - `CC_PROFILE_OBJECT_UPDATE` for updating statistics
+ - `CC_PROFILE_OBJECT_INC` for incrementing statistics
+ - `CC_PROFILE_OBJECT_DEC` for decrementing statistics
+
+- If you want to add `MemoryStats` statistics, such as counting the memory usage of `GeometryRenderer` vertex buffer:
+
+ ```c++
+ void GeometryVertexBuffer::init(gfx::Device *device,
+ uint32_t maxVertices, const gfx::AttributeList &attributes) {
+ ...
+ CC_PROFILE_MEMORY_INC(GeometryVertexBuffer, static_cast(_maxVertices * sizeof(T)));
+ }
+ ```
+
+ - `CC_PROFILE_MEMORY_UPDATE` for updating memory usage (bytes)
+ - `CC_PROFILE_MEMORY_INC` for incrementing memory usage (bytes)
+ - `CC_PROFILE_MEMORY_DEC` for decrementing memory usage (bytes)
+
+- If you want to add `PerformanceStats` statistics, such as the execution time (in milliseconds) of the `ForwardPipeline::render` function:
+
+ ```c++
+ void ForwardPipeline::render(const ccstd::vector &cameras) {
+ CC_PROFILE(ForwardPipelineRender);
+ ...
+ }
+ ```
+
+- After the above modification, compile and run, you can see the new statistics on the screen:
+
+ 
diff --git a/versions/4.0/en/advanced-topics/sebind/devtool-test.png b/versions/4.0/en/advanced-topics/sebind/devtool-test.png
new file mode 100644
index 0000000000..20f59eb095
Binary files /dev/null and b/versions/4.0/en/advanced-topics/sebind/devtool-test.png differ
diff --git a/versions/4.0/en/advanced-topics/sebind/thisobject_placeholder.png b/versions/4.0/en/advanced-topics/sebind/thisobject_placeholder.png
new file mode 100644
index 0000000000..b1a11679cd
Binary files /dev/null and b/versions/4.0/en/advanced-topics/sebind/thisobject_placeholder.png differ
diff --git a/versions/4.0/en/advanced-topics/supported-versions.md b/versions/4.0/en/advanced-topics/supported-versions.md
new file mode 100644
index 0000000000..1186730303
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/supported-versions.md
@@ -0,0 +1,22 @@
+# Features and System Versions
+
+## Modules and System Versions
+
+| Module | Android | iOS |
+| :-- | :--- | :-- |
+| VULKAN | API Level 24(7.0) | - |
+| Google Play Instant | API Level 23(6.0) | - |
+| TBB | API Level 21(5.0) | 10.0 |
+| TaskFlow | API Level 18(4.3) | 12.0 |
+| Deferred Rendering Pipeline | API Level 21(5.0) | 10.0 |
+
+## C++ 与与最低支持的系统版本
+
+| Cocos Creator | C++ | Android | iOS |
+| :-- | :--- | :-- | :-- |
+| 3.0 | C++14 | API Level 18(4.3) | 10.0 |
+| 3.1~3.3.1 | C++17 | API Level 21(5.0) | 11.0 |
+| 3.3.2 ~ 3.5.1 | C++14 | API Level 18 (4.3) | 10.0 |
+| 3.6.0 以上 | C++17 | API Level 21(5.0) | 11.0
+
+> **Note**: Enabling the `TaskFlow` will automatically enable C++17 support for compilation, and `TaskFlow` requires iOS 12+ for its required features.
diff --git a/versions/4.0/en/advanced-topics/thread-safety.md b/versions/4.0/en/advanced-topics/thread-safety.md
new file mode 100644
index 0000000000..b7ab23ec00
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/thread-safety.md
@@ -0,0 +1,78 @@
+# Thread Safety
+
+In a native application built with Cocos Creator, there are at least two threads: the **GL Thread** and **Native UI Thread**。
+- **GL Thread**: Executes rendering-related code of the Cocos Engine and JavaScript code.
+- **UI Thread**: Handles the creation, response, and update of the platform's native UI.
+
+Therefore, we need to be aware of the following two issues:
+1. When code in the **UI thread** needs to call code in the **GL thread**, we need to handle thread safety.
+2. When code in the **GL thread** needs to call code in the **UI thread**, we need to handle thread safety.
+
+Now let's take a look at how to handle thread safety in different situations.
+
+## Executing on the UI Thread
+
+When we write Java methods on the Android platform that involve UI-related operations, and they are called in the GL thread, we need to use the `app.runOnUiThread` method to execute the code on the UI thread, ensuring thread safety.
+
+Let's take an example of displaying an Alert dialog on Android.
+
+```java
+public class AppActivity extends CocosActivity {
+
+ private static AppActivity app = null;
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ app = this;
+ }
+
+ public static void showAlertDialog(final String title,final String message) {
+ app.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ AlertDialog alertDialog = new AlertDialog.Builder(app).create();
+ alertDialog.setTitle(title);
+ alertDialog.setMessage(message);
+ alertDialog.setIcon(R.drawable.icon);
+ alertDialog.show();
+ }
+ });
+ }
+}
+```
+
+In this example, the showAlert method creates and displays an Alert dialog. By using app.runOnUiThread, we ensure that the code runs on the UI thread, preventing any thread safety issues.
+
+## Executing on the GL Thread
+
+When code running on the UI thread needs to call code in the GL thread, we need to use `CocosHelper.runOnGameThread` to ensure thread safety.
+
+Let's take an example of a button event response:
+
+```java
+alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ // Must run on GL Thread
+ CocosHelper.runOnGameThread(new Runnable() {
+ @Override
+ public void run() {
+ CocosJavascriptJavaBridge.evalString("cc.log(\"Javascript Java bridge!\")");
+ }
+ });
+ }
+});
+```
+
+## Objective-C / C++
+
+If you are writing Objective-C or C++ code and want to ensure thread safety, you can use the `CC_CURRENT_ENGINE()->getScheduler()->performFunctionInCocosThread` method to execute the code on the GL thread.
+
+Here's an example:
+
+```c++
+CC_CURRENT_ENGINE()->getScheduler()->performFunctionInCocosThread([=](){
+ //TO DO
+});
+```
+
+Please note that the above code is in C++. If you want to call it from Objective-C code, you need to use the `*.mm` file extension for your Objective-C code file.
diff --git a/versions/4.0/en/advanced-topics/wasm-asm-create.md b/versions/4.0/en/advanced-topics/wasm-asm-create.md
new file mode 100644
index 0000000000..c2c05346b9
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/wasm-asm-create.md
@@ -0,0 +1,110 @@
+# Converting Native Code to Wasm/Asm Files Using Emscripten
+
+## Installing Emscripten on Windows
+
+1. **Download emsdk:** Clone the emsdk repository by running the git command: `git clone https://github.com/emscripten-core/emsdk.git`
+
+ > **Note:** You need to have git installed on your computer to run git commands. If not installed, download and install it from [git official website](https://git-scm.com/).
+
+2. **Choose an emsdk version:** The latest version of emsdk is 4.0.10, but testing has revealed unexpected compatibility issues. We recommend using version 3.1.41, which is the version used by the engine team when compiling Spine module wasm files.
+
+3. **Install emsdk dependencies:** In the emsdk root directory, run the command: `./emsdk install 3.1.41`. This will automatically install the required runtime libraries for emsdk.
+
+ > **Notes:**
+ > * When switching emsdk versions, you need to both switch the source code version and reinstall the runtime libraries. Simply append the version number string after `./emsdk install`.
+ >
+ > * To install the latest version of emsdk dependencies, append `latest` after `./emsdk install`.
+ >
+ > * If downloads fail during dependency installation, try using a VPN to accelerate the connection.
+
+4. **Configure system environment variables for emsdk:** In the emsdk root directory, run the command: `./emsdk_env.bat` to automatically configure the required system environment variables for emsdk runtime libraries.
+
+5. **Verify emsdk environment variables:** Open the upstream/emscripten/.emscripten file in the emsdk directory and check if LLVM_ROOT and BINARYEN_ROOT match the following reference paths:
+
+ ```python
+ LLVM_ROOT = 'D:\\git\\emsdk\\upstream\\bin'
+ BINARYEN_ROOT = 'D:\\git\\emsdk\\upstream'
+ ```
+
+ If they don't match, manually modify them to point to the local paths where llvm tools and binaryen tools can be found.
+
+6. **Activate emsdk environment:** In the emsdk root directory, run the command: `./emsdk activate --system` to activate the emsdk environment. After this, you can use the `emcc` command in command line windows.
+
+ > **Notes:**
+ > * Adding `--system` makes the emsdk environment available in all command line windows. Otherwise, you would need to run `./emsdk activate` each time you open a new command line window.
+ >
+ > * Older versions typically used `./emsdk activate --global` for global activation.
+
+7. **Verify successful emsdk installation:** Run the command: `emcc --version` in a command line window. If you see output like `emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.41`, the installation was successful.
+
+## Generating Wasm Files
+
+1. **Create a C code file:** Create a Cocos.c file in any directory with the following content:
+
+ ```C
+ #include
+
+ int main() {
+ printf("Hello World\n");
+ }
+ ```
+
+2. **Convert C code to Wasm/Asm file:** In the root directory where Cocos.c is located (assuming it's in D:\) run the command: `emcc D:\Cocos.c -s WASM=1`. After execution, the wasm file will be generated in the current directory.
+
+ > **Notes:**
+ >
+ > * Adding `-s WASM=1` specifies generation of wasm files. Using `-s WASM=0` generates Asm files for platforms without WebAssembly support.
+ >
+ > * When generating Asm files, if the native code requires large memory initialization, a .mem file will also be generated and needs to be loaded.
+ >
+ > * For more command line parameters, run `emcc --help` or search for related documentation online.
+
+## Loading Wasm/Asm Files
+
+Refer to [Custom Loading of Wasm/Asm Files and Modules](./wasm-asm-load.md) for instructions on loading Wasm/Asm files.
+
+## Compiling Cocos Engine's Spine Wasm (Available for 3.8.0 ~ 3.8.4 engine versions)
+
+1. **Install CMake:** Download and install from [CMake official website](https://cmake.org/)
+
+2. **Configure CMake system environment variables:** Add `C:\Program Files\CMake\bin` to your system environment variables.
+
+3. **Install MinGW:** Download the package containing `win32-seh-ucrt` from [MinGW releases page](https://github.com/niXman/mingw-builds-binaries/releases), then extract it to your computer.
+
+4. **Configure MinGW system environment variables:** Add `C:\mingw64\bin` to your system environment variables.
+
+5. **Navigate to Spine Wasm C++ code folder:** Open a command line tool and use cd to enter the Cocos engine folder containing Spine Wasm C++ code:
+
+ ```cmd
+ cd D:\CocosCreator\Creator\3.8.3\resources\resources\3d\engine-native\cocos\editor-support\spine-wasm
+ ```
+
+ > **Note:** This is a reference path - modify it according to your actual installation path.
+
+6. **Generate CMakeFiles:** Run the command `emcmake cmake -B ./build` to generate CMakeFiles in the build folder.
+
+7. **Enter build folder:** Use cd to enter the build folder: `cd ./build`.
+
+8. **Generate Spine Wasm files:** Run the command `emmake make`. You should now see spine.js and spine.wasm generated in the build folder.
+
+ 
+
+9. **Modify emcc commands in CMakeLists.txt:** The CMakeLists.txt file is located in the spine-wasm folder. Open it and modify the `emcc` command parameters to change the final output.
+
+ > **Note:**
+ >
+ > * To compile a Debug version, set CMAKE_BUILD_TYPE to Debug in CMakeLists.txt, remove the -O3 optimization option from emcc commands, and add the -g compilation option.
+
+10. **Update Cocos Engine's Built-in Spine Wasm:** Copy the generated spine Wasm and spine.js files to the folder at relative path `engine-native/external/emscripten/spine`, rename spine.js to spine.wasm.js, and replace the old file.
+
+ > **Note:** You need to restart the editor after switching between debug and release modes.
+
+11. **Update Editor's Cached spine.wasm.js:** Delete spine.wasm.js in the editor's cache folder at relative path `resources\3d\engine\bin\.cache`, then restart the editor.
+
+## Compiling Cocos Engine's Spine Wasm (For engine versions 3.8.5 and above)
+
+Refer to the content in [Spine WASM Compilation Guide](https://github.com/cocos/cocos4/blob/v4.0.0/native/cocos/editor-support/spine-wasm/README.md).
+
+## Debugging Debug Version of Spine Wasm
+
+Use Google Chrome and install the [C/C++ DevTools Support extension](https://chromewebstore.google.com/detail/cc++-devtools-support-dwa/pdcpmagijalfljmkmjngeonclgbbannb). After installation, you can open and debug Spine Wasm C++ related code files in the Chrome DevTools console.
diff --git a/versions/4.0/en/advanced-topics/wasm-asm-load.md b/versions/4.0/en/advanced-topics/wasm-asm-load.md
new file mode 100644
index 0000000000..7fcb60d460
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/wasm-asm-load.md
@@ -0,0 +1,264 @@
+# Custom Loading of Wasm/Asm Files and Modules
+
+The CocosCreator engine provides interfaces for manually loading Wasm/Asm modules such as Spine and Box2D. However, if users want to load custom Wasm/Asm files and modules, they need to implement the loading logic themselves within their project.
+
+> #### Note: This article does not cover how to create Wasm/Asm files but focuses on loading them in CocosCreator.
+
+1. Add support for Wasm/Asm files in loaders and parsers. Insert the following example code outside the script's class or translate it into JavaScript and include it as a JS plugin in the project.
+
+ ```js
+ // Determine if the current platform supports loading wasm files. The Cocos engine currently does not support loading wasm files on iOS platforms.
+ if (sys.hasFeature(sys.Feature.WASM) || sys.os !== sys.OS.IOS) {
+ if (sys.isNative) {
+ //@ts-ignore
+ assetManager.downloader.register('.wasm', assetManager.downloader._downloaders[".bin"]);
+ //@ts-ignore
+ assetManager.parser.register('.wasm', assetManager.parser._parsers[".bin"]);
+ }
+ else if (sys.isBrowser || sys.platform === sys.Platform.WECHAT_GAME) {
+ //@ts-ignore
+ assetManager.downloader.register('.wasm', assetManager.downloader._downloadArrayBuffer);
+ //@ts-ignore
+ assetManager.downloader.register('.mem', assetManager.downloader._downloadArrayBuffer);
+ }
+ } else {
+ if (sys.isNative) {
+ //@ts-ignore
+ assetManager.downloader.register('.mem', assetManager.downloader._downloaders[".bin"]);
+ //@ts-ignore
+ assetManager.parser.register('.mem', assetManager.parser._parsers[".bin"]);
+ }
+ }
+ ```
+
+* Both wasm and mem files are binary files, so the built-in binary file loading functions of the engine are used as download and parsing functions for these formats.
+
+2. Modify the tsconfig.json file in the project to add `CommonJS` module support, enabling dynamic imports of JS scripts.
+
+ ```json
+ {
+ /* Base configuration. Do not edit this field. */
+ "extends": "./temp/tsconfig.cocos.json",
+
+ /* Add your custom configuration here. */
+ "compilerOptions": {
+ "strict": false,
+ "module": "CommonJS"
+ }
+ }
+ ```
+
+3. Import Wasm/Asm files into the resource manager of the CocosCreator editor and place both .wasm and .mem files in the same bundle folder. Below is an example of the file distribution structure for reference:
+
+ 
+
+ 
+
+4. Add the wasmOrAsmLoadTest function to import Wasm/Asm module scripts. Add success and failure callbacks, invoking the loading of Wasm/Asm binary files in the success callback.
+
+ > #### Note: The third parameter received by the loadWasmOrAsm function is the resource Uuid of the Wasm/Asm file in the editor. Developers should replace it with the Uuid of resources in their own projects.
+
+ ```js
+ wasmOrAsmLoadTest () {
+ if (sys.hasFeature(sys.Feature.WASM) || sys.os !== sys.OS.IOS) {
+ import('./effekseer.js').then(({ default: wasmFactory })=> {
+ this.loadWasmOrAsm("wasmFiles", "effekseer", "44cacb3c-e901-455d-b3e1-1c38a69718e1").then((wasmFile)=>{
+ //TODO: Initialize wasm file
+
+ }, (err)=> {
+ console.error("wasm load failed", err);
+ })
+ });
+ } else {
+ import('./effekseer.asm.js').then(({ default: asmFactory })=> {
+ this.loadWasmOrAsm("wasmFiles", "effekseer.asm", "3400003e-dc3c-43c1-8757-3e082429125a").then((asmFile)=> {
+ //TODO: Initialize asm file
+
+ }, (err)=> {
+ console.error("asm load failed", err);
+ });
+ });
+ }
+ }
+ ```
+
+5. Add the loadWasmOrAsm method, which is used to load Wasm/Asm binary files.
+
+ ```js
+ loadWasmOrAsm (bundleName, fileName, editorWasmOrAsmUuid): Promise {
+ return new Promise((resolve, reject) => {
+ if (EDITOR) {
+ // Loading resources via UUID is more convenient in the editor; cannot load through bundles.
+ if (editorWasmOrAsmUuid) {
+ assetManager.loadAny(editorWasmOrAsmUuid, (err, file: Asset)=> {
+ if (!err) {
+ //@ts-ignore
+ resolve(file);
+ } else {
+ reject(err);
+ }
+ })
+ }
+ } else {
+ if (bundleName && fileName) {
+ assetManager.loadBundle(bundleName, (err, bundle)=>{
+ if (!err) {
+ bundle.load(fileName, Asset, (err2: any, file: Asset) => {
+ if (!err2) {
+ //@ts-ignore
+ resolve(file);
+ } else {
+ reject(err2);
+ }
+ })
+ } else {
+ reject(err);
+ }
+ })
+ }
+ }
+ })
+ }
+ ```
+
+6. Write Wasm initialization code. After the Wasm binary file is loaded, call the instantiateWasm function to complete initialization.
+
+ ```js
+ initWasm (wasmFactory, file): Promise {
+ var self = this;
+ return new Promise((resolve, reject) => {
+ wasmFactory({
+ instantiateWasm (importObject, receiveInstance) {
+ self.instantiateWasm(file, importObject).then((result) => {
+ receiveInstance(result.instance, result.module);
+ }).catch((err) => reject(err));
+ }
+ }).then((instance: any)=>{
+ resolve(instance);
+ }).catch((err) => reject(err));
+ });
+ }
+
+ instantiateWasm (wasmFile: Asset, importObject: WebAssembly.Imports): Promise {
+ if (sys.isBrowser || sys.isNative) {
+ //@ts-ignore
+ return WebAssembly.instantiate(wasmFile._file, importObject);
+ } else if (sys.platform === sys.Platform.WECHAT_GAME){
+ //@ts-ignore
+ return CCWebAssembly.instantiate(wasmFile.nativeUrl, importObject)
+ }
+ }
+ ```
+
+7. Add a call to the initWasm function in the wasmOrAsmLoadTest function to complete the loading of Wasm.
+
+ ```js
+ wasmOrAsmLoadTest () {
+ if (sys.hasFeature(sys.Feature.WASM) || sys.os !== sys.OS.IOS) {
+ import('./effekseer.js').then(({ default: wasmFactory })=> {
+ this.loadWasmOrAsm("wasmFiles", "effekseer", "44cacb3c-e901-455d-b3e1-1c38a69718e1").then((wasmFile)=>{
+ this.initWasm(wasmFactory, wasmFile).then((instance: any)=> {
+ Effekseer = instance;
+ Effekseer._myFunction();
+ console.log("effekseer wasm module inited", Effekseer);
+ }, (err) => {
+ console.error("effekseer wasm module init failed", err);
+ });
+
+ }, (err)=> {
+ console.error("wasm load failed", err);
+ })
+ });
+ } else {
+ import('./effekseer.asm.js').then(({ default: asmFactory })=> {
+ this.loadWasmOrAsm("wasmFiles", "effekseer.asm", "3400003e-dc3c-43c1-8757-3e082429125a").then((asmFile)=> {
+ //TODO: Initialize asm file
+
+ }, (err)=> {
+ console.error("asm load failed", err);
+ });
+ });
+ }
+ }
+ ```
+
+* After Wasm is loaded, you should see the following output in the browser console in this example:
+
+ 
+
+ 8. Write asm initialization code. First, add constants for the memory size of the asm module, then add the initAsm function to initialize the Asm module.
+
+ ```js
+ // Add constants for the memory size of the asm module, used during asm module initialization.
+ const PAGESIZE = 65536; // 64KiB
+
+ // Number of pages in the wasm memory
+ // TODO: Make this configurable by the user.
+ const PAGECOUNT = 32 * 16;
+
+ // Total memory size of the wasm memory
+ const MEMORYSIZE = PAGESIZE * PAGECOUNT; // 32 MiB
+ ```
+
+ ```js
+ initAsm (asmFactory, file): Promise {
+ const asmMemory: any = {};
+ asmMemory.buffer = new ArrayBuffer(MEMORYSIZE);
+ const module = {
+ asmMemory,
+ memoryInitializerRequest: {
+ //@ts-ignore
+ response: file._file,
+ status: 200,
+ } as Partial,
+ };
+ return asmFactory(module);
+ }
+ ```
+
+9. Add a call to the initAsm function in the wasmOrAsmLoadTest function to complete the loading of Asm.
+
+ ```js
+ wasmOrAsmLoadTest () {
+ if (sys.hasFeature(sys.Feature.WASM) || sys.os !== sys.OS.IOS) {
+ import('./effekseer.js').then(({ default: wasmFactory })=> {
+ this.loadWasmOrAsm("wasmFiles", "effekseer", "44cacb3c-e901-455d-b3e1-1c38a69718e1").then((wasmFile)=>{
+ this.initWasm(wasmFactory, wasmFile).then((instance: any)=> {
+ Effekseer = instance;
+ Effekseer._myFunction();
+ console.log("effekseer wasm module inited", Effekseer);
+ }, (err) => {
+ console.error("effekseer wasm module init failed", err);
+ });
+
+ }, (err)=> {
+ console.error("wasm load failed", err);
+ })
+ });
+ } else {
+ import('./effekseer.asm.js').then(({ default: asmFactory })=> {
+
+ this.loadWasmOrAsm("wasmFiles", "effekseer.asm", "3400003e-dc3c-43c1-8757-3e082429125a").then((asmFile)=> {
+ this.initAsm(asmFactory, asmFile).then((instance: any)=>{
+ Effekseer = instance;
+ Effekseer._myFunction();
+ console.log("effekseer asm module inited", Effekseer);
+ }, (err) => {
+ console.error("effekseer asm module init failed", err);
+ });
+
+ }, (err)=> {
+ console.error("asm load failed", err);
+ });
+ });
+ }
+ }
+ ```
+
+* After Asm is loaded, you should see the following output in the browser console in this example:
+
+ 
+
+### Example Project Repository Address
+
+[GitHub Repository Address](https://github.com/cocos/cocos-awesome-tech-solutions/tree/3.8.x-release/demo/Creator3.8.6_WasmOrAsmLoad)
diff --git a/versions/4.0/en/advanced-topics/web-socket/http.png b/versions/4.0/en/advanced-topics/web-socket/http.png
new file mode 100644
index 0000000000..add0572dd3
Binary files /dev/null and b/versions/4.0/en/advanced-topics/web-socket/http.png differ
diff --git a/versions/4.0/en/advanced-topics/web-socket/web-socket.png b/versions/4.0/en/advanced-topics/web-socket/web-socket.png
new file mode 100644
index 0000000000..5d643cb619
Binary files /dev/null and b/versions/4.0/en/advanced-topics/web-socket/web-socket.png differ
diff --git a/versions/4.0/en/advanced-topics/websocket-introduction.md b/versions/4.0/en/advanced-topics/websocket-introduction.md
new file mode 100644
index 0000000000..4fae540a26
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/websocket-introduction.md
@@ -0,0 +1,24 @@
+# WebSocket Introduction
+
+Often when developing web applications or games, for data security or other goals, user data needs to be stored in a web back-end server, and browsers generally only support the HTTP protocol.
+
+The HTTP (HyperText Transfer Protocol) protocol [^1] is an application layer transport protocol based on the TCP protocol and is used by requesting data from the client (web browser or via [API](http.md)) to the server, which stores the data in the HTTP protocol response and returns it to the client.
+
+
+
+In the early days of the HTTP protocol (before 1.1), one request corresponded to one network connection, which meant that each time an HTTP request was made, the client and server had to re-establish a TCP connection, which was a waste of resources. After HTTP/1.1, the HTTP protocol can be merged by keep-alive, so that multiple requests (Request) and responses (Respnose) can be merged. However, the HTTP protocol at this time is still one request for one response.
+
+Usually, such communication is sufficient for the server to passively accept the return data from the client's request. In specific cases, such as when the server needs to push data to the client, the client needs to poll the request, i.e., the client keeps requesting data from the server through timing or other loops. The HTTP protocol itself carries a large HTTP header and the constant polling behavior can cause waste of resources and bandwidth on the client and server side.
+
+To solve this problem, the W3C Advisory Committee developed the WebSocket protocol in 2008, and in 2011, WebSocket became the browser standard, which means that all browsers support WebSocket.
+
+The HTTP/1.1 protocol can be upgraded to the Websocket protocol by upgrading the connection [^2], after which both the client and the server can actively push the required data to each other. This solves the problem of real-time client-server interaction.
+
+
+
+WebSocket transfers can optionally use Binary or String to increase the specificity and security of the private protocol.
+
+To use Websocket within Cocos Creator, see [Using WebSocket Server](websocket-server.md) and [WebSocket Client](websocket.md).
+
+[^1]: [The WebSocket Protocol](https://www.rfc-editor.org/rfc/rfc6455)
+[^2]: [HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP)
diff --git a/versions/4.0/en/advanced-topics/websocket-server.md b/versions/4.0/en/advanced-topics/websocket-server.md
new file mode 100644
index 0000000000..b896802010
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/websocket-server.md
@@ -0,0 +1,102 @@
+# WebSocket Server
+
+Developers can launch a WebSocket Server during the game and provide an **RPC interface**. By improving and calling these **RPC interfaces**, developers can monitor the internal state of the game process and increase the ability to manage the game process state.
+
+## How To Enable
+
+The **WebSocket Server** is disabled by default. To enable it, need to check the editor's main menu **Project -> Project Settings -> Feature Cropping** , and enable the **WebSocket Server** configuration setting.
+
+## How to use WebSocket
+
+Refer to the example code below:
+
+```ts
+// In the native platform's Release mode or in Web / WeChat Mini Games and other platforms, WebSocketServer may not be defined.
+if (typeof WebSocketServer === "undefined") {
+ console.error("WebSocketServer is not enabled!");
+ return;
+}
+
+let s = new WebSocketServer();
+s.onconnection = function (conn) {
+ conn.onmessage = function (data) {
+ conn.send(data, (err) => {});
+ }
+ conn.onclose = function () {
+ console.log("connection gone!");
+ };
+};
+
+s.onclose = function () {
+ console.log("server is closed!");
+}
+s.listen(8080, (err) => {
+ if (!err);
+ console.log("server booted!");
+});
+```
+
+## API
+
+The interface is defined as follows
+
+```typescript
+/**
+ * Server object
+ */
+class WebSocketServer {
+ /**
+ * Close the server
+ */
+ close(cb?: WsCallback): void;
+ /**
+ * Listen and launch the service
+ */
+ listen(port: number, cb?: WsCallback): void;
+ /**
+ * Handle new requests
+ */
+ set onconnection(cb: (client: WebSocketServerConnection) => void);
+ /**
+ * Set up the server shutdown callback
+ */
+ set onclose(cb: WsCallback);
+ /**
+ * Gets all the connection objects
+ */
+ get connections(): WebSocketServerConnection[];
+}
+
+/**
+ * The client connection object in the server
+ */
+class WebSocketServerConnection {
+ /**
+ * Close the connection
+ */
+ close(code?: number, reason?: string): void;
+ /**
+ * Send the data
+ */
+ send(data: string|ArrayBuffer, cb?: WsCallback): void;
+
+ set ontext(cb: (data: string) => void);
+ set onbinary(cb: (data: ArrayBuffer) => void);
+ set onmessage(cb: (data: string|ArrayBuffer) => void);
+ set onconnect(cb: () => void;);
+ set onclose(cb: WsCallback);
+ set onerror(cb: WsCallback);
+
+ get readyState(): number;
+}
+
+interface WsCallback {
+ (err?: string): void;
+}
+```
+
+> **Note**: After v3.7.0, `ondata` callback has been deprecated, please use `onmessage` to instead.
+
+## Reference links
+
+The interface design refers to the [nodejs-websocket](https://www.npmjs.com/package/nodejs-websocket#server) server.
diff --git a/versions/4.0/en/advanced-topics/websocket.md b/versions/4.0/en/advanced-topics/websocket.md
new file mode 100644
index 0000000000..17132e363a
--- /dev/null
+++ b/versions/4.0/en/advanced-topics/websocket.md
@@ -0,0 +1,15 @@
+# WebSocket Client
+
+The native environment supports the [Web Standard](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket) WebSocket interface.
+
+## Differences
+
+Prior to version 3.5, the WebSocket API on Android and Windows was implemented using [libwebsockets](https://github.com/warmcat/libwebsockets). It requires the developer to specify the CA file path with the third parameter.
+
+```ts
+this.wsInstance = new WebSocket('wss://echo.websocket.org', [], caURL);
+````
+
+See [demo code](https://github.com/cocos/cocos-test-projects/blob/07f5671e18ef3ed4494d8cba6c2f9499766467a6/assets/cases/network/NetworkCtrl.ts#L113-L120). CA certificates can be downloaded from [here](https://curl.se/docs/caextract.html).
+
+After version 3.5, certificates are no longer mandatory on Android.
diff --git a/versions/4.0/en/animation/animation-auxiliary-curve.md b/versions/4.0/en/animation/animation-auxiliary-curve.md
new file mode 100644
index 0000000000..832a92df35
--- /dev/null
+++ b/versions/4.0/en/animation/animation-auxiliary-curve.md
@@ -0,0 +1,49 @@
+# The Auxillary Curve
+
+The Auxillary Curve is a new feature in Cocos Creator 3.8, and you can read the [Auxillary Curve](./marionette/procedural-animation/auxiliary-curve/index.md) to help understanding the basic concepts.
+
+Please make sure the **Animation Auxillary Curve** option is enabled in the **Laboratory** page of the **Preference** panel.
+
+
+
+In this section, we will introduce to you how to use the auxillary curve in the animation editor. Auxillary curve is a part of a curve editor, the basic curve options can be refer to [Curve Editor](./curve-editor.md).
+
+Select the node with the animation component (Animation, SkeletalAnimation or AnimationController). Click on the button in the figure below to enter the editing mode.
+
+
+
+The Auxiliary Curves section in the figure below shows the auxiliary curves.
+
+
+
+## Adding and Removing Curves
+
+Clicking the "+" button on an auxiliary curve in the animation editor will add an auxiliary curve to the current animation.
+
+
+
+The name of the auxiliary curve can be modified after it has been added. It can also be changed later by clicking on the auxiliary curve with the right mouse button and using the Rename menu in the popup menu.
+
+
+
+In the popup menu, click the Remove menu to remove the currently selected auxiliary curve or rename the curve.
+
+## New Keyframe
+
+Keyframes can be added by clicking the right mouse button on the right side of the Auxiliary Curve Editor.
+
+
+
+After creating a keyframe, the pop-up menu with a right-click on the keyframe allows you to adjust the information of the keyframe or interpolation.
+
+
+
+| Menu | Description |
+| :--- | :--- |
+| Delete | Delete this keyframe | Duplicate | Auxiliary keyframe.
+| Copy | Auxiliary keyframe, after copying, you can paste the information of the keyframe when clicking other keyframes or blank space |
+| Paste | Copy the previously copied keyframe to the mouse clicked position or replace the information of the selected keyframe |
+| Edit | Click the popup box to change the time and value of the current keyframe. 
+| Flag tangent | When clicked, the tangent line of the curve at that point will switch to horizontal mode 
+| Interpolation Mode | See [Linear Interpolation Mode](./curve-editor.md#Interpolation%20Mode) |
+| Tangent weight mode | See [Tangent weight mode](./curve-editor.md#Tangent%20Weight%20Mode) |
diff --git a/versions/4.0/en/animation/animation-auxiliary-curve/add-curve.png b/versions/4.0/en/animation/animation-auxiliary-curve/add-curve.png
new file mode 100644
index 0000000000..46af0aad67
Binary files /dev/null and b/versions/4.0/en/animation/animation-auxiliary-curve/add-curve.png differ
diff --git a/versions/4.0/en/animation/animation-auxiliary-curve/create-key-frame.png b/versions/4.0/en/animation/animation-auxiliary-curve/create-key-frame.png
new file mode 100644
index 0000000000..c4fb841c31
Binary files /dev/null and b/versions/4.0/en/animation/animation-auxiliary-curve/create-key-frame.png differ
diff --git a/versions/4.0/en/animation/animation-auxiliary-curve/edit-pop.png b/versions/4.0/en/animation/animation-auxiliary-curve/edit-pop.png
new file mode 100644
index 0000000000..80d1da9650
Binary files /dev/null and b/versions/4.0/en/animation/animation-auxiliary-curve/edit-pop.png differ
diff --git a/versions/4.0/en/animation/animation-auxiliary-curve/enable.png b/versions/4.0/en/animation/animation-auxiliary-curve/enable.png
new file mode 100644
index 0000000000..312fa506ac
Binary files /dev/null and b/versions/4.0/en/animation/animation-auxiliary-curve/enable.png differ
diff --git a/versions/4.0/en/animation/animation-auxiliary-curve/flat.png b/versions/4.0/en/animation/animation-auxiliary-curve/flat.png
new file mode 100644
index 0000000000..1981efb9ff
Binary files /dev/null and b/versions/4.0/en/animation/animation-auxiliary-curve/flat.png differ
diff --git a/versions/4.0/en/animation/animation-auxiliary-curve/keyframe-menu.png b/versions/4.0/en/animation/animation-auxiliary-curve/keyframe-menu.png
new file mode 100644
index 0000000000..fd35e3cf65
Binary files /dev/null and b/versions/4.0/en/animation/animation-auxiliary-curve/keyframe-menu.png differ
diff --git a/versions/4.0/en/animation/animation-auxiliary-curve/menu.png b/versions/4.0/en/animation/animation-auxiliary-curve/menu.png
new file mode 100644
index 0000000000..0499bf0f25
Binary files /dev/null and b/versions/4.0/en/animation/animation-auxiliary-curve/menu.png differ
diff --git a/versions/4.0/en/animation/animation-auxiliary-curve/overview.png b/versions/4.0/en/animation/animation-auxiliary-curve/overview.png
new file mode 100644
index 0000000000..ca0b76b2f6
Binary files /dev/null and b/versions/4.0/en/animation/animation-auxiliary-curve/overview.png differ
diff --git a/versions/4.0/en/animation/animation-auxiliary-curve/right-menu.png b/versions/4.0/en/animation/animation-auxiliary-curve/right-menu.png
new file mode 100644
index 0000000000..7fec349e70
Binary files /dev/null and b/versions/4.0/en/animation/animation-auxiliary-curve/right-menu.png differ
diff --git a/versions/4.0/en/animation/animation-auxiliary-curve/start-edit.png b/versions/4.0/en/animation/animation-auxiliary-curve/start-edit.png
new file mode 100644
index 0000000000..3fbc6f8dcc
Binary files /dev/null and b/versions/4.0/en/animation/animation-auxiliary-curve/start-edit.png differ
diff --git a/versions/4.0/en/animation/animation-clip.md b/versions/4.0/en/animation/animation-clip.md
new file mode 100644
index 0000000000..1d6be67f44
--- /dev/null
+++ b/versions/4.0/en/animation/animation-clip.md
@@ -0,0 +1,29 @@
+# Animation Clip
+
+An Animation Clip is an asset containing animation data, which is one of the core elements of the animation system. By attaching an Animation Clip on the [Animation Component](animation-comp.md), this animation data can be applied to the node where the Animation Component is located.
+
+Currently, Creator supports importing Skeletal Animation assets produced by external art tools or by creating a new Animation Clip asset directly inside Creator.
+
+## Animations created inside Creator
+
+New Animation Clips can be created, edited, and previewed directly through the **Animation** panel, please refer to the [Animation Editor](animation.md) documentation for details.
+
+This can also be done by scripting, please refer to the [Using Animation Curves](use-animation-curve.md) documentation for details.
+
+## Externally imported skeleton animations
+
+Externally imported animations include the following:
+
+1. Skeletal Animations produced by third-party art tools.
+
+2. Skeletal Animations that come with the model after it is imported.
+
+When a model that contains animations is imported, the animation contained in the model will be imported at the same time. This animation is used in the same way as the internal new assets, and the crop of skeletal animation can be referred to [Introduction to the animation module of model assets](../asset/model/mesh.md) documentation.
+
+Starting with v3.4, Cocos Creator has introduced the new Marionette animation system which implements a skeletal animation flow controlled by a state machine, please refer to the [Marionette Animation System](./marionette/index.md) documentation.
+
+For additional details about Skeletal Animation settings, please refer to the [Skeletal Animation](skeletal-animation.md) documentation.
+
+> **Note**: skeletal animations imported externally cannot be viewed and edited in the **Animation** panel. The nodes are locked, and can only be edited in external art tools.
+>
+> 
diff --git a/versions/4.0/en/animation/animation-clip/skeletal-animation.png b/versions/4.0/en/animation/animation-clip/skeletal-animation.png
new file mode 100644
index 0000000000..06dcb920f1
Binary files /dev/null and b/versions/4.0/en/animation/animation-clip/skeletal-animation.png differ
diff --git a/versions/4.0/en/animation/animation-comp.md b/versions/4.0/en/animation/animation-comp.md
new file mode 100644
index 0000000000..022d3e148d
--- /dev/null
+++ b/versions/4.0/en/animation/animation-comp.md
@@ -0,0 +1,25 @@
+# Animation Component Reference
+
+The Animation component can drive node and component properties on their nodes and children in an animated manner, including properties in user-defined scripts.
+
+
+
+There are several ways to add Animation components:
+
+1. Add an Animation component in the **Animation** panel, review the [Creating Animation Components and Animation Clips](animation-create.md) documentation for details.
+2. Select the node to be animated in the **Hierarchy** panel, and then select **Add Component -> Animation -> Animation** in the **Inspector** panel to add an Animation component to the node.
+3. Added via script, review the [Controlling Animation with Scripts](animation-component.md) documentation for details.
+
+## Animation Component Properties
+
+| Property | Description |
+| :-- | :------ |
+| Clips | The added animation clip asset, default is empty, support adding multiple. The AnimationClip added here can be edited directly in the **Animation** panel. |
+| DefaultClip | The default animation clip. If this option is attached with the **PlayOnLoad** property checked, then the animation will automatically play the content of the Default Clip when it is loaded.
+| PlayOnLoad | Boolean type. If this option is checked, the content of the Default Clip will be played automatically after the animation is loaded.
+
+## Detailed Description
+
+If an animation needs to contain multiple nodes, usually one creates a new node as the **root node** of the animation, and then the Animation component will be attached to the root node. All the other children nodes under this root node will be automatically entered into this animation clip and displayed in the **Node List** area of the **Animation** panel. For details, please refer to the [Get Familiar with the Animation Panel - Node list](animation-editor.md#2-node-list) documentation.
+
+The Animation component also provides some common animation control functions. To control animations using scripts, please refer to the [Controlling Animation with Scripts](animation-component.md) documentation.
diff --git a/versions/4.0/en/animation/animation-component.md b/versions/4.0/en/animation/animation-component.md
new file mode 100644
index 0000000000..c77d4279b8
--- /dev/null
+++ b/versions/4.0/en/animation/animation-component.md
@@ -0,0 +1,179 @@
+# Controlling Animation with Scripts
+
+## Animation Component
+
+The Animation Component manages a set of animation states that control the play, pause, resume, stop, switch, etc. of each animation. The Animation Component creates a corresponding [Animation State](animation-state.md) object for each Animation Clip. The Animation State is used to control the Animation Clips that need to be used on the object.
+
+In the Animation Component, Animation States are identified by name, and the default name of each animation state is the name of its Animation Clip.
+
+Adding an Animation Component to a node in a script is done in the following way:
+
+```ts
+import { Animation, Node } from 'cc';
+
+function (node: Node) {
+ const animationComponent = node.addComponent(Animation);
+}
+```
+
+### Playing and switching animations
+
+#### Playing animations
+
+The Animation Component controls the playback of the specified animation via the [play()](%__APIDOC__%/en/class/Animation?id=play) API, e.g:
+
+```ts
+// Play the animation state 'idle'
+animationComponent.play('idle');
+```
+
+If no specific animation is specified and `defaultClip` is set when using `play` to play an animation, the `defaultClip` animation will be played. If the `playOnLoad` of the Animation Component is also set to `true`, the Animation Component will automatically play the contents of `defaultClip` on the first run.
+
+```ts
+// The defaultClip animation will be played if the defaultClip is set without specifying the animation to be played
+animationComponent.play();
+```
+
+#### Switching animation
+
+When using the `play` interface to play an animation, if there are other animations playing at the same time, the other animations will be stopped immediately. This switch is very abrupt, and in some cases we want the switch to be a "fade in and fade out" effect, use [crossFade()](%__APIDOC__%/en/class/Animation?id=crossFade) to smoothly complete the switch within the specified period. For example:
+
+```ts
+// Play the animation state 'walk'
+animationComponent.play('walk');
+
+/* ... */
+
+// Smoothly switch from walk to run animation in 0.3 seconds
+animationComponent.crossFade('run', 0.3);
+```
+
+This fade-in and fade-out mechanism of `crossFade()` makes it possible for more than one Animation State to be playing at the same moment. Therefore, the Animation Component has no concept of the **current animation**.
+
+Even so, the Animation Component provides `pause()`, `resume()`, and `stop()` methods that pause, resume, and stop all the animation states being played while also pausing, resuming, and stopping the animation switching.
+
+**Notes:Only take effect on REALTIME Mode spine Animation**
+
+For more details about the control interface related to the Animation Component, please refer to the [Class Animation](%__APIDOC__%/en/class/Animation).
+
+## Animation State
+
+The Animation Component only provides some simple control functions, which are mostly sufficient and easy to use, but for more animation information and animation control interfaces, review the [Animation State](animation-state.md) documentation.
+
+## Frame Events
+
+The **Animation** panel supports visual editing of [event frames](animation-event.md), or frame events can be added directly to the script.
+
+The `events` of an `AnimationClip` contain all the frame events of this animation, each with the following properties:
+
+```ts
+{
+ frame: number;
+ func: string;
+ params: any[];
+}
+```
+
+- `frame`: the point in time when the event will be triggered, in seconds. For example, `0.618` means the event will be triggered when the animation reaches the 0.618th second. For the conversion between timeline scale units, please refer to the [Scale Unit Display of the Timeline](animation-editor.md#scale-unit-display-of-the-timeline) documentation.
+- `func`: indicates the name of the function that will be called back when the event is triggered. When the event is triggered, the animation system will search **all the components in the animation root node**, if there is a component that implements the function specified in `func` of the animation event, it will call it and pass in the parameters in `params`.
+
+For example, if an event frame is added at 0.5s of the animation timeline:
+
+
+
+The code implemented in the script is as follows:
+
+```ts
+{
+ frame: 0.5;
+ func: 'onTrigger';
+ params: [ 0 ];
+}
+```
+
+### Example
+
+The following code indicates that the default Animation Clip of the Animation Component of the node where the `MyScript` script component is located will call the `onTriggered()` method of the `MyScript` component when it reaches the 0.5 second mark and pass the parameter `0`.
+
+```ts
+import { Animation, Component, _decorator } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass("MyScript")
+class MyScript extends Component {
+ public start() {
+ const animation = this.node.getComponent(Animation);
+ if (animation && animation.defaultClip) {
+ const { defaultClip } = animation;
+ defaultClip.events = [
+ {
+ frame: 0.5, // Triggers the event on the 0.5 second
+ func: 'onTriggered', // The name of the function to call when the event is triggered
+ params: [ 0 ], // Parameters passed to `func`
+ }
+ ];
+
+ animation.clips = animation.clips;
+ }
+ }
+
+ public onTriggered(arg: number) {
+ console.log('I am triggered!', arg);
+ }
+}
+```
+
+## Animation Events
+
+In addition to the callbacks provided by the frame events in the **Animation** panel, the animation system also provides a way to call back animation events. The currently supported callback events include:
+
+- `PLAY`: triggered when playback starts
+- `STOP`: triggered when playback is stopped
+- `PAUSE`: triggered when playback is paused
+- `RESUME`: triggered when playback is resumed
+- `LASTFRAME`: if the animation loop is greater than 1, triggered when the animation reaches the last frame.
+- `FINISHED`: trigger when the animation is finished.
+
+These events are defined in `Animation.EventType` and the code examples is as follows.
+
+SkeletalAnimation:
+
+```ts
+import { _decorator, Component, Node, SkeletalAnimation, Animation, SkeletalAnimationState } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass('SkeletonAnimationEvent')
+export class SkeletonAnimationEvent extends Component {
+ start() {
+
+ let skeletalAnimation = this.node.getComponent(SkeletalAnimation);
+ skeletalAnimation.on(Animation.EventType.FINISHED, this.onAnimationFinished, this);
+ }
+
+ onAnimationFinished(type:Animation.EventType, state:SkeletalAnimationState){
+
+ }
+}
+```
+
+Animation:
+
+```ts
+import { _decorator, Component, Node, Animation, AnimationState } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass('AnimationEvent')
+export class AnimationEvent extends Component {
+
+ start() {
+ let animation = this.node.getComponent(Animation);
+ animation.on(Animation.EventType.FINISHED, this.onAnimationEvent, this)
+ }
+
+ onAnimationEvent(type: Animation.EventType, state: AnimationState) {
+
+ }
+}
+```
+
+For more details, please refer to the [Animation.EventType](%__APIDOC__%/en/namespace/Animation?id=EventType) API.
diff --git a/versions/4.0/en/animation/animation-create.md b/versions/4.0/en/animation/animation-create.md
new file mode 100644
index 0000000000..bda9c2c92f
--- /dev/null
+++ b/versions/4.0/en/animation/animation-create.md
@@ -0,0 +1,43 @@
+# Creating Animation Components and Animation Clips
+
+Before using the **Animation** panel to create animation, select the node to add animation to in the **Hierarchy** panel or the **Scene** panel, then add the [Animation Component](./animation-comp.md) and mount the **Animation Clip** on the component to edit the animation data, and the edited animation data will be saved in the current Animation Clip. The animation data of the nodes that do not have a Clip mounted cannot be edited.
+
+If the currently selected node does not have an Animation Component, the **Add Animation Component** button will be displayed on the interface of the **Animation** panel, click it to add **Animation Component** on the **Inspector** panel.
+
+
+
+Go ahead and click the **Create a new AnimationClip file** button in the **Animation** panel and name it (e.g.: `animation`).
+
+
+
+An animation clip (`animation.anim`) is automatically created in the **Assets** panel and mounted to the `DefaultClip` property of the Animation component:
+
+
+
+The above briefly describes how to create Animation components and animation clips in the **Animation** panel, for more information about the creation and properties of Animation components, please refer to the [Animation Component](./animation-comp.md) documentation. For additional information on how to create animation clips, please refer to the end of this article.
+
+Next, click **Enter animation editing mode** to start [edit-animation-clip](edit-animation-clip.md). The newly created empty Animation Clip is displayed in the animation editor as follows:
+
+
+
+## Attaching new animation clips
+
+An Animation Component can have multiple Animation Clips attached to it. To additionally create and attach a new animation clip on the object of an existing Animation Clip, there are several ways to do so:
+
+1. Click the **+** button at the top left of the **Assets** panel, or right-click on a blank area and select **Animation Clip**, which will generate an animation clip file (default name `animation`) in the **Assets** panel.
+
+ Next, select the corresponding node in the **Hierarchy** panel, find the Animation Component (`cc.Animation`) in the **Inspector** panel, and change the value of the `Clips` property. For example, if only one clip file is attached, and to add another one, change the original **1** to **2**.
+
+ 
+
+ Finally, drag the Animation Clip just created in the **Assets** panel to the `cc.AnimationClip` selection box in the above image.
+
+2. Find the Animation component (`cc.Animation`) in the **Inspector** panel and change the value of the `Clips` property.
+
+ Next, click the **Find** button behind the new empty `cc.AnimationClip` selection box, and click the **Create** button at the top right of the pop-up search window to automatically create an Animation Clip in the **Assets** panel and mount it to the `cc.AnimationClip` selection box.
+
+ 
+
+3. To create the Animation Clip dynamically by using a script, please refer to the [use-animation-curve](use-animation-curve.md) documentation for details.
+
+The Animation Clips to edit can be switched from the **Clips** drop-down list in the top left corner of **Animation** panel.
diff --git a/versions/4.0/en/animation/animation-create/add-clip.png b/versions/4.0/en/animation/animation-create/add-clip.png
new file mode 100644
index 0000000000..a028d15c4f
Binary files /dev/null and b/versions/4.0/en/animation/animation-create/add-clip.png differ
diff --git a/versions/4.0/en/animation/animation-create/add-component.png b/versions/4.0/en/animation/animation-create/add-component.png
new file mode 100644
index 0000000000..b61266c623
Binary files /dev/null and b/versions/4.0/en/animation/animation-create/add-component.png differ
diff --git a/versions/4.0/en/animation/animation-create/add-new-clip.png b/versions/4.0/en/animation/animation-create/add-new-clip.png
new file mode 100644
index 0000000000..9f7cbba5f5
Binary files /dev/null and b/versions/4.0/en/animation/animation-create/add-new-clip.png differ
diff --git a/versions/4.0/en/animation/animation-create/add-new-clip2.png b/versions/4.0/en/animation/animation-create/add-new-clip2.png
new file mode 100644
index 0000000000..93c05e0268
Binary files /dev/null and b/versions/4.0/en/animation/animation-create/add-new-clip2.png differ
diff --git a/versions/4.0/en/animation/animation-create/animation-component.png b/versions/4.0/en/animation/animation-create/animation-component.png
new file mode 100644
index 0000000000..f778df4aba
Binary files /dev/null and b/versions/4.0/en/animation/animation-create/animation-component.png differ
diff --git a/versions/4.0/en/animation/animation-create/empty-clip.png b/versions/4.0/en/animation/animation-create/empty-clip.png
new file mode 100644
index 0000000000..7e985ddf20
Binary files /dev/null and b/versions/4.0/en/animation/animation-create/empty-clip.png differ
diff --git a/versions/4.0/en/animation/animation-create/mount-clip.png b/versions/4.0/en/animation/animation-create/mount-clip.png
new file mode 100644
index 0000000000..b605e29a7e
Binary files /dev/null and b/versions/4.0/en/animation/animation-create/mount-clip.png differ
diff --git a/versions/4.0/en/animation/animation-curve.md b/versions/4.0/en/animation/animation-curve.md
new file mode 100644
index 0000000000..f5de8843df
--- /dev/null
+++ b/versions/4.0/en/animation/animation-curve.md
@@ -0,0 +1,30 @@
+# Curve Editing View
+
+After creating the basic animation clip, one can **control how the keyframes change over time between keyframes by editing the animation curve**. An animation curve is actually a linear track made up of individual keyframes connected on the current property track, with each keyframe being a control point on this curve path. Under the curve editing view, the change of keyframe values is more visually noticed, and keyframe value changes can be adjusted more delicately.
+
+
+
+Click the switch view button on the side of the properties list to switch to the curve editing view.
+
+After switching to the curve editing view, you can see that the line markers will be displayed on the property list, and the line markers will not be displayed on the property tracks that do not support curve editing, and the curves will not be displayed normally when the corresponding property track is selected. When the corresponding curve is displayed in the curve editing area, the line marker will show the corresponding curve color, and the name of the currently selected curve will be displayed in the property menu area.
+
+
+
+## Getting to know the curve editor
+
+The **Animation** panel has a built-in curve editor for animation curves, which is actually the same as the particle curve editor. On top of the general curve editor, the **Animation** panel has some customization to better support curve keyframe editing.
+
+For general functions of the curve editor, please refer to the [Curve Editor](./curve-editor.md) documentation for more information.
+
+In addition to general curve editing operations, the curve editor area within the **Animation** panel supports the following functions.
+
+- To show all keyframes, click the button above the curve editor area , or press the F shortcut to quickly scale the current view area to show all keyframes.
+- Shortcuts and handling of all keyframes in the keyframe view of the **Animation** panel, such as double-clicking on the keyframe time line to move to the keyframe position, copy and paste shortcuts, etc.
+- Copy and paste in curve editing area is shared with keyframe view mode, so you can paste copied keyframe data with each other in different display views.
+- The number of intervals used for the interval alignment keyframe function of the curve editor will be synchronized with the number of intervals in the menu bar of the **Animation** panel.
+
+### Bezier Curve Preset
+
+There are some standard Bezier curve presets built into the animation editor. After entering the curve editing view, click the curve preset panel in the sidebar to show the curve presets. Click the curve to select the curve clip, and then click the preset on the curve preset panel you can applying the curve preset. After applying the preset, the interpMode of the keyframes at both ends of the curve clip will be adjusted to curve mode by default, and the weightMode of the keyframes will be modified to a state where the left and right sides of the curve clip can be stretched freely to achieve the same effect as the curve preset.
+
+
diff --git a/versions/4.0/en/animation/animation-curve/add-keyframe-to-curve.png b/versions/4.0/en/animation/animation-curve/add-keyframe-to-curve.png
new file mode 100644
index 0000000000..c327b1f885
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/add-keyframe-to-curve.png differ
diff --git a/versions/4.0/en/animation/animation-curve/add-keyframe.png b/versions/4.0/en/animation/animation-curve/add-keyframe.png
new file mode 100644
index 0000000000..816239da4e
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/add-keyframe.png differ
diff --git a/versions/4.0/en/animation/animation-curve/animation-curve-preset.gif b/versions/4.0/en/animation/animation-curve/animation-curve-preset.gif
new file mode 100644
index 0000000000..3f7a16801c
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/animation-curve-preset.gif differ
diff --git a/versions/4.0/en/animation/animation-curve/change-preset.gif b/versions/4.0/en/animation/animation-curve/change-preset.gif
new file mode 100644
index 0000000000..e5ca97aef6
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/change-preset.gif differ
diff --git a/versions/4.0/en/animation/animation-curve/constant.png b/versions/4.0/en/animation/animation-curve/constant.png
new file mode 100644
index 0000000000..e0b397f328
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/constant.png differ
diff --git a/versions/4.0/en/animation/animation-curve/cubic.png b/versions/4.0/en/animation/animation-curve/cubic.png
new file mode 100644
index 0000000000..d0cfaff2f6
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/cubic.png differ
diff --git a/versions/4.0/en/animation/animation-curve/curve-btn.png b/versions/4.0/en/animation/animation-curve/curve-btn.png
new file mode 100644
index 0000000000..36eda835b4
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/curve-btn.png differ
diff --git a/versions/4.0/en/animation/animation-curve/edit-key.png b/versions/4.0/en/animation/animation-curve/edit-key.png
new file mode 100644
index 0000000000..997827d5aa
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/edit-key.png differ
diff --git a/versions/4.0/en/animation/animation-curve/interopMode-key.gif b/versions/4.0/en/animation/animation-curve/interopMode-key.gif
new file mode 100644
index 0000000000..74dac4f745
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/interopMode-key.gif differ
diff --git a/versions/4.0/en/animation/animation-curve/interopMode.png b/versions/4.0/en/animation/animation-curve/interopMode.png
new file mode 100644
index 0000000000..ae1a9d40ab
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/interopMode.png differ
diff --git a/versions/4.0/en/animation/animation-curve/linear.png b/versions/4.0/en/animation/animation-curve/linear.png
new file mode 100644
index 0000000000..d88fa70b5c
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/linear.png differ
diff --git a/versions/4.0/en/animation/animation-curve/main.png b/versions/4.0/en/animation/animation-curve/main.png
new file mode 100644
index 0000000000..78333b342f
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/main.png differ
diff --git a/versions/4.0/en/animation/animation-curve/move-keys.gif b/versions/4.0/en/animation/animation-curve/move-keys.gif
new file mode 100644
index 0000000000..0eb5726707
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/move-keys.gif differ
diff --git a/versions/4.0/en/animation/animation-curve/preset.gif b/versions/4.0/en/animation/animation-curve/preset.gif
new file mode 100644
index 0000000000..3ed087067a
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/preset.gif differ
diff --git a/versions/4.0/en/animation/animation-curve/save-curve.gif b/versions/4.0/en/animation/animation-curve/save-curve.gif
new file mode 100644
index 0000000000..2550586434
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/save-curve.gif differ
diff --git a/versions/4.0/en/animation/animation-curve/scale-keys.gif b/versions/4.0/en/animation/animation-curve/scale-keys.gif
new file mode 100644
index 0000000000..369a73cce1
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/scale-keys.gif differ
diff --git a/versions/4.0/en/animation/animation-curve/select-key.gif b/versions/4.0/en/animation/animation-curve/select-key.gif
new file mode 100644
index 0000000000..92f57f44cf
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/select-key.gif differ
diff --git a/versions/4.0/en/animation/animation-curve/select-preset.gif b/versions/4.0/en/animation/animation-curve/select-preset.gif
new file mode 100644
index 0000000000..77afdc90b4
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/select-preset.gif differ
diff --git a/versions/4.0/en/animation/animation-curve/show-all-keys.png b/versions/4.0/en/animation/animation-curve/show-all-keys.png
new file mode 100644
index 0000000000..828928e7c9
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/show-all-keys.png differ
diff --git a/versions/4.0/en/animation/animation-curve/show-line.png b/versions/4.0/en/animation/animation-curve/show-line.png
new file mode 100644
index 0000000000..eb269b990d
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/show-line.png differ
diff --git a/versions/4.0/en/animation/animation-curve/tangentWeightMode-key.gif b/versions/4.0/en/animation/animation-curve/tangentWeightMode-key.gif
new file mode 100644
index 0000000000..278837b6a1
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/tangentWeightMode-key.gif differ
diff --git a/versions/4.0/en/animation/animation-curve/tangentWeightMode.png b/versions/4.0/en/animation/animation-curve/tangentWeightMode.png
new file mode 100644
index 0000000000..ee15949957
Binary files /dev/null and b/versions/4.0/en/animation/animation-curve/tangentWeightMode.png differ
diff --git a/versions/4.0/en/animation/animation-editor.md b/versions/4.0/en/animation/animation-editor.md
new file mode 100644
index 0000000000..cfda69fcb2
--- /dev/null
+++ b/versions/4.0/en/animation/animation-editor.md
@@ -0,0 +1,178 @@
+# Get Familiar with the Animation Panel
+
+The **Animation** panel is used to edit and preview the animation clip of the currently selected node. When editing animation data or related properties, it will take effect immediately after mouse focus leaves.
+
+The **Animation** panel is already included in the default layout of Cocos Creator, or open the **Animation** panel by clicking **Panel -> Animation -> Animation Editor** in the main menu above the editor.
+
+## Panel Introduction
+
+The **Animation** panel can be divided into the following main sections.
+
+
+
+1. **Toolbar**: some common function buttons, such as play/pause/stop animation, add event frame, save animation, quit editing, etc.
+2. **Node List**: used to display/set the currently selected node and its child nodes.
+3. **Animation timeline and Keyframe Preview**: used to display/set the event frames added to the current node (and its children) and the preview of all keyframes on the added animation property.
+4. **Animation Property List**: used to display/set all animation properties included in the currently edited animation clip for the currently selected node.
+5. **Animation Property Keyframe Preview**: used to display/set all keyframes on each animation property of the currently selected node.
+6. **Related properties of the current animation clip**: used to set the playback mode, playback speed, etc. of the current animation clip.
+
+For specific content, please refer to the following introduction.
+
+### 1. Menu Toolbar
+
+The function buttons in the **Menu toolbar** are, from left to right.
+
+| Icon | Description | Shortcut |
+| :---- | :--- | :--- |
+|  | Toggle animation clips. When multiple animation clips are attached on the Animation component, this button can be used to toggle between clips. | - |
+|  | Moves the red time control line to the beginning of the current animation clip | Ctrl/Cmd + ← |
+|  | Move time control line to previous frame | ← |
+|  | Play/pause current animation | Ctrl/Cmd + P |
+|  | Move the time control line to the next frame | → |
+|  | Move the time control line to the end of the current animation clip | Ctrl/Cmd + → |
+|  | Click to stop the current animation, the time control line will move to the first frame after stopping | Ctrl/Cmd + S |
+|  | The scale unit of the timeline are displayed in three ways: **Time: 0-00** **Frame: 0** **Time (s): 0 s** See the **Scale Units of the Timeline** section below for details. | - |
+| | Used to set the spacing size between keyframes when multiple keyframes are generated at the same time. | - |
+|  | Spacing the selected keyframes at the same time. The selected keyframes will be spaced according to the first frame, using the value in the **Spacing** input box as the spacing size.
+|  | Add event frame, click this button to add an event frame above the current timeline | - |
+|  | Save the currently edited animation data. | - |
+|  | Click this button to jump to the official manual section on the **Animation** panel | Ctrl/Cmd + S |
+|  | Open the shortcuts panel, which supports custom shortcuts. See the **Shortcuts** section below for details | - |
+| | Exit animation editing mode | Ctrl + Q |
+
+### 2. Node list
+
+
+
+This area shows the currently selected animation nodes and their children, arranged in a way that corresponds to the node tree in the **Hierarchy** panel. Click on the top  button to hide/show nodes without animation data, or just type the node name in the input box to quickly find the node.
+
+Currently, it is possible to right-click on a node to clear, migrate, copy and paste node data. For details, please refer to the [Common operations on node data](edit-animation-clip.md#common-operations-on-node-data) documentation.
+
+
+
+### 3. Animation timeline and keyframe preview
+
+
+
+The animation timeline is mainly used to display/set the custom [event frames](animation-event.md) added to the current node, the [keyframes](edit-animation-clip.md) (blue diamond) of all animation properties added to the node (and its children) and to show the preview.
+
+The time control line (red vertical line) indicates the time the current animation is at, and the currently selected time can be changed in several ways:
+
+- Drag and drop the time control line directly
+- Double click on the keyframe
+- Using the relevant move control buttons in the menu toolbar
+- Use shortcut keys, which can be found in the **Shortcuts** section below
+- Click anywhere in the upper area of the animation timeline
+
+ 
+
+If the time control line is moved, the nodes in the **Scene** panel will also move accordingly to the animation track.
+
+
+
+#### Scale unit display of the timeline
+
+The  button in the **Toolbar** can be used to toggle the way the scale unit of the timeline is displayed. The value in the input box will change with the movement of the time control line. Manual input is supported, and the time control line will be automatically positioned to the corresponding position after the input is finished.
+
+The following three display methods are currently supported:
+
+- **Time: 0-00** (default): the animation timeline scale is displayed as a combination of seconds and frames. The value in front of the input box means **seconds**, and the value after it means **frames**, for example `01-05` means 1 second and 5 frames.
+
+ 
+
+- **Frame: 0**: display the scale of the animation timeline in terms of frames.
+
+ 
+
+- **Time(s): 0 s**: display the scale of the animation timeline in seconds.
+
+ 
+
+The frame rate (Sample) is generally used to indicate how many frames a second is to be divided into, which can be adjusted in the **Sample** option at the bottom of the **Animation** panel. This is affected to a different extent when the scale unit of the timeline is displayed in different ways.
+
+When the scale unit is set to **Frame**, it is in frames and is not affected by the frame rate.
+When set to **Time** or **Time(s)**, the same scale represents a different point in time as the frame rate changes, and the conversion between the two is calculated as follows:
+
+| Frame Rate (Sample) | Time: 00-00 | Time (s): 0 s |
+| :-- | :--------- | :------------ |
+| 30 | 01-05 | 1 + 5/30 = 1.17 s |
+| 10 | 01-05 | 1 + 5/10 = 1.5 s |
+
+For example, if the frame rate is set to 30 and a keyframe is added to the `01-05` scale, the keyframe will be at frame 35 after the animation starts. Changing the frame rate to 10, the total number of frames where the keyframe is located does not change, it is still at frame 35 after the start of the animation, and the scale reading at the keyframe location becomes `03-05`, which translates to exactly 3 times the previous time (s).
+
+#### Changing the animation timeline scale
+
+If the **Animation** panel display is too small and needs to be enlarged for more keyframes to be displayed within the editor, Just simply scroll the mouse wheel in either **Animation Timeline** and **Animation Property Keyframe Preview** area to scale the timeline up or down.
+
+
+
+#### Moving the animation timeline display area
+
+Drag and drop the middle/right mouse button in any area of the **Animation Timeline** or **Animation Property Keyframe preview** to see the hidden keyframes on the left/right side of the animation timeline that are outside the display area.
+
+
+
+### 4. List of animation property
+
+
+
+This area is mainly used to display/add/set the animation property of the currently selected node in the current Animation Clip. The animation properties include the node's own properties, component properties (including those in user-defined script components), and the animation properties are added by clicking the **+** button in the upper right corner. Component properties are prefixed with the name of the component, e.g.: `cc.Sprite.spriteFrame`.
+
+Right-click on the animation property or click  button to the right of the animation property to select **Remove Prop Track**, **Clear Keyframe Data**, or **Copy Prop Track**. For details, please refer to the [Common operations on animation property data](edit-animation-clip.md#Common-operations-on-animation-property-data) documentation.
+
+
+
+### 5. Keyframe preview of the animation property
+
+
+
+This area is mainly used to display the specific keyframe settings of the currently selected node on each animation property, and is also the main area for keyframe editing. Keyframes can be added by right-clicking on the animation property on the right side. This area also supports the ability to move, copy, and paste keyframes by checking and tapping on them. For details, please refer to the [Common keyframe operations](edit-animation-clip.md#common-keyframe-operations) documentation.
+
+When clicking on a keyframe, it will turn from blue to white and information about it will be displayed above the area, and double-clicking on the keyframe will move the time control line to its location.
+
+
+
+### 6. Related properties of the current animation clip
+
+The properties of the current Animation Clip that can be set directly on the **Animation** panel include: **WrapMode**, **Sample**, **Speed** and **Duration**. For details, please refer to the [Animation Clip Properties Settings](edit-animation-clip.md#animation-clip-properties-settings) documentation.
+
+## Adjusting the Layout of the Animation Panel
+
+The dividers between the node list and the timeline, and between the property list and the timeline are available for dragging and dropping to change the layout. By dragging and dropping it is possible to freely adjust the **Animation** panel to a layout effect suitable for editing.
+
+
+
+## Shortcut keys
+
+Click on the menu toolbar's  button in the menu toolbar to open the shortcuts panel:
+
+
+
+Shortcuts can be customized in the **Animation** panel. Directly click the shortcut key combination of the function to be modified. A prompt will appear as shown below.
+
+
+
+### Default shortcut key summary
+
+Function | Shortcut | Description
+:--- | :----- | :---
+Enter/exit **Animation** panel | Ctrl/Cmd + E | -
+Save animation data | Ctrl/Cmd + S | -
+Move forward one frame | ← | Ignore current operation if already at frame 0. Move the time control line when the keyframe is not selected, move the keyframe when the keyframe is selected.
+Move back one frame | → | Move the time control line when the keyframe is not selected, move the keyframe when the keyframe is selected.
+Move to the first frame | Ctrl/Cmd + ← | Move the red time control line to the beginning of the current animation clip.
+Move to the last frame | Ctrl/Cmd + → | Move the time control line to the end of the current animation clip.
+Delete the currently selected keyframe | Delete / Cmd + Backspace | -
+Play/Pause Animation | P | -
+Stop animation | Alt + S | The current time will change to 0 and the time control line will move to the first frame.
+Add keyframe | K | When any animation property is selected, a keyframe will be added at the location of the time control line, ignored if no animation property is selected.
+Jump to previous keyframe | Ctrl/Cmd + Shift + ← | Move the time control line to the nearest keyframe on the left (on the selected property track or on the selected node).
+Jump to the next keyframe | Ctrl/Cmd + Shift + → | Move the time control line to the nearest keyframe on the right (on the selected property track or on the selected node).
+Multi-select keyframes | Ctrl | Hold down Ctrl and click on a keyframe to multi-select a keyframe.
+Select all animation property keyframes | Ctrl/Cmd + A | Select all keyframes on the selected animation property.
+Copy selected animation data | Ctrl/Cmd + C | Supports copying selected keyframes, property tracks, and node data, while only one type of data can be copied, and the copying priority is determined in this order.
+Paste last copied animation data | Ctrl/Cmd + V | Support to paste last copied animation data (e.g.: animation keyframes, animation properties, animation node data, and check the currently available data in that order) across editors (v3.x only).
+Unchecked keyframes/event frames/property tracks | Esc | -
+
+> **Note**: currently, all shortcuts require mouse focus on the Animation Editor panel to take effect, except for the shortcuts **Enter/Exit Animation Editor** and **Save Animation** which are globally available.
diff --git a/versions/4.0/en/animation/animation-editor/2-node-list.png b/versions/4.0/en/animation/animation-editor/2-node-list.png
new file mode 100644
index 0000000000..e1f55f79a8
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/2-node-list.png differ
diff --git a/versions/4.0/en/animation/animation-editor/4-pro-list.png b/versions/4.0/en/animation/animation-editor/4-pro-list.png
new file mode 100644
index 0000000000..ed3b197dd7
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/4-pro-list.png differ
diff --git a/versions/4.0/en/animation/animation-editor/above-timeline.png b/versions/4.0/en/animation/animation-editor/above-timeline.png
new file mode 100644
index 0000000000..3debddb753
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/above-timeline.png differ
diff --git a/versions/4.0/en/animation/animation-editor/animation-panel.png b/versions/4.0/en/animation/animation-editor/animation-panel.png
new file mode 100644
index 0000000000..e702b7d5e2
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/animation-panel.png differ
diff --git a/versions/4.0/en/animation/animation-editor/animation-property-track.png b/versions/4.0/en/animation/animation-editor/animation-property-track.png
new file mode 100644
index 0000000000..0c33b10e25
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/animation-property-track.png differ
diff --git a/versions/4.0/en/animation/animation-editor/animation-timeline.png b/versions/4.0/en/animation/animation-editor/animation-timeline.png
new file mode 100644
index 0000000000..e1e325bbed
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/animation-timeline.png differ
diff --git a/versions/4.0/en/animation/animation-editor/frame.png b/versions/4.0/en/animation/animation-editor/frame.png
new file mode 100644
index 0000000000..4093b2aea4
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/frame.png differ
diff --git a/versions/4.0/en/animation/animation-editor/hide-node.png b/versions/4.0/en/animation/animation-editor/hide-node.png
new file mode 100644
index 0000000000..d5258d84f2
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/hide-node.png differ
diff --git a/versions/4.0/en/animation/animation-editor/key-info.png b/versions/4.0/en/animation/animation-editor/key-info.png
new file mode 100644
index 0000000000..75d00cf5ee
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/key-info.png differ
diff --git a/versions/4.0/en/animation/animation-editor/layout.gif b/versions/4.0/en/animation/animation-editor/layout.gif
new file mode 100644
index 0000000000..a882fe8ce8
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/layout.gif differ
diff --git a/versions/4.0/en/animation/animation-editor/menu-spacing.png b/versions/4.0/en/animation/animation-editor/menu-spacing.png
new file mode 100644
index 0000000000..e20bce5e81
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/menu-spacing.png differ
diff --git a/versions/4.0/en/animation/animation-editor/menu_clips.png b/versions/4.0/en/animation/animation-editor/menu_clips.png
new file mode 100644
index 0000000000..48699315e8
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/menu_clips.png differ
diff --git a/versions/4.0/en/animation/animation-editor/menu_doc.png b/versions/4.0/en/animation/animation-editor/menu_doc.png
new file mode 100644
index 0000000000..ca00e9c0ba
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/menu_doc.png differ
diff --git a/versions/4.0/en/animation/animation-editor/menu_event.png b/versions/4.0/en/animation/animation-editor/menu_event.png
new file mode 100644
index 0000000000..e8eb1457a5
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/menu_event.png differ
diff --git a/versions/4.0/en/animation/animation-editor/menu_exit.png b/versions/4.0/en/animation/animation-editor/menu_exit.png
new file mode 100644
index 0000000000..2e6ae62e00
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/menu_exit.png differ
diff --git a/versions/4.0/en/animation/animation-editor/menu_first.png b/versions/4.0/en/animation/animation-editor/menu_first.png
new file mode 100644
index 0000000000..9d6a0f26fe
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/menu_first.png differ
diff --git a/versions/4.0/en/animation/animation-editor/menu_last.png b/versions/4.0/en/animation/animation-editor/menu_last.png
new file mode 100644
index 0000000000..258dbac7bf
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/menu_last.png differ
diff --git a/versions/4.0/en/animation/animation-editor/menu_next.png b/versions/4.0/en/animation/animation-editor/menu_next.png
new file mode 100644
index 0000000000..d4f1f50abc
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/menu_next.png differ
diff --git a/versions/4.0/en/animation/animation-editor/menu_play.png b/versions/4.0/en/animation/animation-editor/menu_play.png
new file mode 100644
index 0000000000..920a812f01
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/menu_play.png differ
diff --git a/versions/4.0/en/animation/animation-editor/menu_prev.png b/versions/4.0/en/animation/animation-editor/menu_prev.png
new file mode 100644
index 0000000000..3bd9d542f0
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/menu_prev.png differ
diff --git a/versions/4.0/en/animation/animation-editor/menu_save.png b/versions/4.0/en/animation/animation-editor/menu_save.png
new file mode 100644
index 0000000000..c1eec3cbcd
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/menu_save.png differ
diff --git a/versions/4.0/en/animation/animation-editor/menu_spacing_btn.png b/versions/4.0/en/animation/animation-editor/menu_spacing_btn.png
new file mode 100644
index 0000000000..9a732235a7
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/menu_spacing_btn.png differ
diff --git a/versions/4.0/en/animation/animation-editor/menu_stop.png b/versions/4.0/en/animation/animation-editor/menu_stop.png
new file mode 100644
index 0000000000..63b7867cc1
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/menu_stop.png differ
diff --git a/versions/4.0/en/animation/animation-editor/menu_time.png b/versions/4.0/en/animation/animation-editor/menu_time.png
new file mode 100644
index 0000000000..0193f7b9ff
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/menu_time.png differ
diff --git a/versions/4.0/en/animation/animation-editor/menu_time_frame.png b/versions/4.0/en/animation/animation-editor/menu_time_frame.png
new file mode 100644
index 0000000000..0154ab7379
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/menu_time_frame.png differ
diff --git a/versions/4.0/en/animation/animation-editor/menu_time_times.png b/versions/4.0/en/animation/animation-editor/menu_time_times.png
new file mode 100644
index 0000000000..b3e16b326f
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/menu_time_times.png differ
diff --git a/versions/4.0/en/animation/animation-editor/move-line.gif b/versions/4.0/en/animation/animation-editor/move-line.gif
new file mode 100644
index 0000000000..d5ee2c1393
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/move-line.gif differ
diff --git a/versions/4.0/en/animation/animation-editor/mult-select.png b/versions/4.0/en/animation/animation-editor/mult-select.png
new file mode 100644
index 0000000000..f40f5ade3a
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/mult-select.png differ
diff --git a/versions/4.0/en/animation/animation-editor/node-operation.png b/versions/4.0/en/animation/animation-editor/node-operation.png
new file mode 100644
index 0000000000..13c7917ebe
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/node-operation.png differ
diff --git a/versions/4.0/en/animation/animation-editor/pro-operation.png b/versions/4.0/en/animation/animation-editor/pro-operation.png
new file mode 100644
index 0000000000..1d0d00172e
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/pro-operation.png differ
diff --git a/versions/4.0/en/animation/animation-editor/scale-canvas.gif b/versions/4.0/en/animation/animation-editor/scale-canvas.gif
new file mode 100644
index 0000000000..5961c9f5d3
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/scale-canvas.gif differ
diff --git a/versions/4.0/en/animation/animation-editor/scale.gif b/versions/4.0/en/animation/animation-editor/scale.gif
new file mode 100644
index 0000000000..cd091b90fb
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/scale.gif differ
diff --git a/versions/4.0/en/animation/animation-editor/set-pro.png b/versions/4.0/en/animation/animation-editor/set-pro.png
new file mode 100644
index 0000000000..8ab665f3be
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/set-pro.png differ
diff --git a/versions/4.0/en/animation/animation-editor/shortcuts-change.png b/versions/4.0/en/animation/animation-editor/shortcuts-change.png
new file mode 100644
index 0000000000..a45048436a
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/shortcuts-change.png differ
diff --git a/versions/4.0/en/animation/animation-editor/shortcuts-manager.png b/versions/4.0/en/animation/animation-editor/shortcuts-manager.png
new file mode 100644
index 0000000000..f18d8fca14
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/shortcuts-manager.png differ
diff --git a/versions/4.0/en/animation/animation-editor/shortcuts.png b/versions/4.0/en/animation/animation-editor/shortcuts.png
new file mode 100644
index 0000000000..74d05bfd13
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/shortcuts.png differ
diff --git a/versions/4.0/en/animation/animation-editor/time.png b/versions/4.0/en/animation/animation-editor/time.png
new file mode 100644
index 0000000000..4e4f4ae13c
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/time.png differ
diff --git a/versions/4.0/en/animation/animation-editor/times.png b/versions/4.0/en/animation/animation-editor/times.png
new file mode 100644
index 0000000000..cd00284823
Binary files /dev/null and b/versions/4.0/en/animation/animation-editor/times.png differ
diff --git a/versions/4.0/en/animation/animation-event.md b/versions/4.0/en/animation/animation-event.md
new file mode 100644
index 0000000000..9b6ca37481
--- /dev/null
+++ b/versions/4.0/en/animation/animation-event.md
@@ -0,0 +1,50 @@
+# Adding Animation Events
+
+Animation clips can be better enriched by calling **Animation Event** functions on the specified frame of the animation timeline. After adding **event frames** to a frame of the animation timeline, the animation system will match the corresponding function method in the root node of the animation with the name of the trigger function set in the event frame and execute it when the animation reaches that frame.
+
+To add Animation Events via scripts, please refer to the [Frame Event](animation-component.md#frame-event) documentation for more details.
+
+## Adding event frames
+
+Adding event frames in the **Animation** panel consists of two ways:
+
+1. Drag the time control line to the position where you want to add the event frame, and then click  button in the **Animation Timeline** to add an event frame above the **Animation Timeline**.
+
+2. Right click on the area above the animation timeline and select **New Event Frame**.
+
+After the event frame is added, move the mouse over the event frame and the color will change from white to yellow. Right-click the event frame to perform **Edit**, **Delete**, **Copy-Paste** operations. Event frames can be batched while holding down Ctrl.
+
+
+
+- **Edit**: open the event editor and add event functions
+- **Delete**: delete event frames
+- **Copy/Paste**: copy and paste event frame data, supports cross-editor (v3.x) use.
+
+### Editing event frames
+
+Right-click on the added event frame and select **Edit** or double-click directly to open the event editor. In the event editor, it is possible to manually enter the name of the event function that needs to be triggered, and the trigger will match the corresponding function method in each component of the animation root node according to this function name, and call it with parameters.
+
+
+
+- 1 - add a new trigger function.
+- 2 - save the event function.
+- 3 - fill in the name of the function to be triggered.
+- 4 - delete the current event function.
+- 5 - add incoming parameters, currently supports **String**, **Number**, **Boolean** types.
+
+ 
+
+- 1 - add incoming parameters by choosing the parameter type as needed.
+- 2 - delete all the added incoming parameters below.
+- 3 - when the mouse moves over a parameter, this button will appear, click on it to delete the currently selected parameter.
+
+### Delete event frames
+
+Right-click on an event frame that has been added to the animation timeline (multiple selections are possible) and select **Delete** or use the shortcut Delete to delete the event frame and all event functions.
+
+### Copy and paste event frames
+
+Copy and paste of event frames and their event functions is supported across editors (v3.x). Copy and paste includes the following two ways of use:
+
+- After selecting an event frame (multiple selection is allowed), use the shortcut keys Ctrl + C and Ctrl + V to copy and paste. Note that the shortcut paste will start at the position of the current time control line.
+- Once selecting an event frame (multiple selection is allowed), right-click on (any) event frame and select **Copy** in the pop-up menu, then right-click on top of the animation timeline and select **Paste Event Frame**.
diff --git a/versions/4.0/en/animation/animation-event/add-animation-event.png b/versions/4.0/en/animation/animation-event/add-animation-event.png
new file mode 100644
index 0000000000..4ae7ede0ff
Binary files /dev/null and b/versions/4.0/en/animation/animation-event/add-animation-event.png differ
diff --git a/versions/4.0/en/animation/animation-event/animation-event-menu.png b/versions/4.0/en/animation/animation-event/animation-event-menu.png
new file mode 100644
index 0000000000..2b8e934ad2
Binary files /dev/null and b/versions/4.0/en/animation/animation-event/animation-event-menu.png differ
diff --git a/versions/4.0/en/animation/animation-event/event-editor.png b/versions/4.0/en/animation/animation-event/event-editor.png
new file mode 100644
index 0000000000..0b16cfcb69
Binary files /dev/null and b/versions/4.0/en/animation/animation-event/event-editor.png differ
diff --git a/versions/4.0/en/animation/animation-keyFrames.md b/versions/4.0/en/animation/animation-keyFrames.md
new file mode 100644
index 0000000000..290b3df0a6
--- /dev/null
+++ b/versions/4.0/en/animation/animation-keyFrames.md
@@ -0,0 +1,85 @@
+# Keyframe Editing View
+
+The node track display area and the property track display area are both displayed in keyframe editing view by default. In this view, one can edit the overall keyframe layout, add and delete keyframes more easily. The following describes the various keyframe manipulation methods supported in the keyframe edit view, and how to understand these methods and techniques to edit animation clips faster and more easily.
+
+## Selecting keyframes
+
+The selected keyframe will change from blue to white, including the following:
+
+- Clicking on a keyframe in the animation property track will select it.
+- Double-clicking a keyframe will move the time control line to the current keyframe while it is selected.
+- Clicking on a node's keyframe in the animation timeline selects all keyframes of the node's animation properties at the same location.
+
+ 
+
+Multiple selection of keyframes is also supported, including the following:
+
+- Holding Ctrl while clicking multiple keyframes
+
+- Selecting multiple keyframes by box selection will show the number of frames in the animation timeline for the first and last keyframes on the left and right side of the box.
+
+ 
+
+- After **selecting any property track**, press Ctrl/Cmd + A to select all the keyframes on the current animation property track.
+
+## Adding keyframes
+
+In addition to adding keyframes by modifying properties as described in **Creating Animation Curves**, they can also be added in the following ways:
+
+1. Select the animation property and use the shortcut K, which will add a keyframe at the location of the time control line, or ignore it if the animation property is not checked.
+
+2. Move the time control line to the position where you want to add the keyframe, and click the  button on the right side of the animation property to add a keyframe to the current animation property track.
+
+3. In the animation property track, right-click the position where you want to add the keyframe, and then select **Add keyframe** in the popup menu, the menu will also show the number of frames in the current added keyframe position.
+
+ 
+
+4. When dragging a batch of assets corresponding to an animation property from the **Assets** panel to the property track, keyframes will be added in the order in which the assets are selected, according to the spacing size set in  in the toolbar.
+
+## Removing keyframes
+
+1. Select the keyframe to be deleted (multiple selections are allowed) and press Delete (Windows) or Cmd + Backspace (macOS).
+
+2. Select the keyframe you want to delete (you can select more than one), then right click and select **Remove Keyframe** in the popup menu.
+
+3. Drag the time control line to the position of the keyframe to be removed or **double-click** the keyframe, and then click  button to the right of the corresponding animation property.
+
+
+
+## Moving keyframes
+
+Dragging a keyframe while it is selected will move it to the desired position.
+
+- When dragging a single keyframe, a small white box will appear below the keyframe, showing the number of frames and the distance moved during the move.
+- When dragging multiple keyframes, the box will show the number of frames in the animation timeline for the first and last keyframes during the move, on the left and right side respectively.
+
+
+
+## Scaling keyframes
+
+When multiple keyframes are selected, the first and last keyframes will show two control levers, drag any of the levers to move them to scale the selected keyframes as a whole.
+
+
+
+## Spacing keyframes
+
+With multiple keyframes selected, click the  button in the upper menu bar, the selected keyframes will be arranged in order with the first keyframe as the base and the value set in the  input box as the number of spacing frames.
+
+## Copying/pasting keyframes
+
+Copy and paste keyframe data, support cross-node and cross-clip usage. The following two usage methods are included:
+
+- After selecting a keyframe (multiple selection is possible), use the shortcut keys Ctrl + C and Ctrl + V to copy and paste. Note that the shortcut paste will start at the position of the current time control line.
+- After selecting a keyframe (multiple selections are allowed), right-click on (any) keyframe and select **Copy Keyframe** in the popup menu, then right-click on the target animation property track and select **Paste Keyframe** to paste the keyframe on the current animation property track.
+
+The above two pasting methods differ when copying and pasting data from multiple property tracks, the difference mainly lies in:
+
+- When using shortcut keys to paste keyframes, the keyframes will be pasted on the animation property track where they were copied, in the order of the copied keyframes.
+
+ 
+
+- When right-clicking on the target property track and select Paste, only the copied data will be pasted on the target property track.
+
+ 
+
+Component property tracks (e.g.: `x`, `y`, `z` properties under the animation property track `position`) as separate property tracks will also follow this rule. If right-clicking on the target component track after copying the keyframe data on the main track (e.g.: animation property track `position`) to paste it, only the target component track will be pasted with the keyframe data. Be sure to copy the data according to the actual position you want to paste, to avoid unintended results.
diff --git a/versions/4.0/en/animation/animation-state.md b/versions/4.0/en/animation/animation-state.md
new file mode 100644
index 0000000000..e7f2a2704d
--- /dev/null
+++ b/versions/4.0/en/animation/animation-state.md
@@ -0,0 +1,95 @@
+# Animation State
+
+Animation clips only describe the animation data of a certain type of object, such as a character running, walking, jumping, etc., but are not bound to the specific object to be animated. Animation states are Animation Clips that are used to control the animation on a certain object, similar to a player. In addition to providing simple control functions that are also available for Animation components, they also provide more animation information and an animation control interface that allows control of animation playback such as speed control, setting loop mode, etc. An Animation Clip can be used by multiple animation states at the same time.
+
+Animation states are managed by [Class `AnimationState`](%__APIDOC__%/en/class/AnimationState).
+
+## Setting the playback speed
+
+First get the animation state by [getState()](%__APIDOC__%/en/class/Animation?id=getState):
+
+```ts
+// Get the Animation component
+const animationComponent = node.getComponent(Animation);
+
+// Get the animation clips on the Animation component
+const [ idleClip, runClip ] = animationComponent.clips;
+
+// Get the animation state of 'idleClip'
+const idleState = animationComponent.getState(idleClip.name);
+```
+
+Then set the speed of the animation to play at:
+
+```ts
+// Play the 'idleClip' animation at two times the speed
+animationComponent.getState('idle').speed = 2.0; // the larger the speed value the faster it is, the smaller the value the slower it is
+```
+
+The animation state also provides `play()`, `pause()`, `resume()`, `stop()` methods for playback control, please refer to the **play state** section below for more details.
+
+## Play Time
+
+The animation state records the **cumulative play time** of the animation. Initially, the accumulated play time is 0. As the animation plays naturally, the time will be accumulated. For example, when the animation loops, the cumulative play time will be **animation period * 2** just after the second loop.
+
+The playback position of the animation at any given moment is called **progress time**, so the progress time is always in the range `[0, animation period]`.
+
+- The **cumulative play time** is obtained from the [time](%__APIDOC__%/en/class/AnimationState?id=time) field of `AnimationState`, and can be set explicitly.
+- The **progress time** is obtained from the [current](%__APIDOC__%/en/class/AnimationState?id=current) field of `AnimationState`, and is **read-only**.
+
+The wrap mode and repeat count of the animation determines the progress time of the animation when it reaches a certain time, whether the **cumulative play time** is increased by time or changed by direct setting, the **progress time** will be changed accordingly.
+
+## Wrap Mode and Repeat Count
+
+Animation can be played to the end and stop, or it can be looped all the time, or it can be played to the end and then looped from the end to the beginning, these are collectively called wrap modes and are represented by the enumeration [`AnimationClip.WrapMode`](%__APIDOC__%/en/class/AnimationState?id=current), the following are included:
+
+| Wrap Mode | Description |
+| :--- | :--- |
+| `AnimationClip.WrapMode.Normal` | Play from the beginning to the end and then stop. |
+| `AnimationClip.WrapMode.Loop` | Play from the beginning to the end continuously. |
+| `AnimationClip.WrapMode.PingPong` | Play from the beginning to the end, then reverse from the end to the beginning, and so on. |PingPong
+
+In addition, there are **reverse** looping modes for each of the looping modes in the table above:
+
+| Wrap Mode | Description |
+| :--- | :--- |
+| `AnimationClip.WrapMode.Reverse` | Play from the end to the beginning and then stop. |
+| `AnimationClip.WrapMode.LoopReverse` | Play from the end to the beginning continuously. |
+| `AnimationClip.WrapMode.PingPongReverse` | Play from the end to the beginning, then reverse from the beginning to the end, and so on. |
+
+The initial wrap mode of the animation state will be read from the animation clip. When you need to change the wrap mode of the animation state, simply set the `wrapMode` field of the animation state.
+
+> **Note**: setting the wrap mode will reset the **cumulative play time** of the animation state.
+
+Except `AnimationClip.WrapMode.Normal` and its counterpart `AnimationClip.WrapMode.Reverse` (which can be interpreted as a single loop), all other wrap modes perform an infinite loop. The infinite loop needs to be used in conjunction with `repeatCount` of `AnimationState` to achieve the effect, and the number of loops can be set and retrieved via the `repeatCount` field.
+
+When the animation wrap mode is:
+- Single loop mode: `repeatCount` will be set to **1**.
+- Infinite loop mode: `repeatCount` will be set to `Number.Infinity`, i.e. infinite loop.
+
+> **Note**: setting the repeat count should be done after setting the wrap mode, because resetting the wrap mode will reset the repeat count.
+
+## Playback Control
+
+The animation state provides the following methods to control the play, pause, resume and stop of the animation:
+
+| Method | Description |
+| :--- | :--- |
+| `play()` | Reset the playback time to 0 and start the animation. |
+| `pause()` | Pause the animation. |
+| `resume()` | Resume the animation from the current time. |
+| `stop()` | Stop the animation. |
+
+The playing status of the animation can be queried by the following fields:
+
+| Field (read-only) | Description |
+| :--- | :--- |
+| `isPlaying` | If or not the animation is in playing state. |
+| `isPaused` | If or not the animation is paused. |
+| `isMotionless` | If or not the animation is paused or has been stopped. |
+
+The relationship between the playback control and the playback state is shown in the following figure:
+
+
+
+The animation state allows getting information about all the animations in order to use this information to determine what needs to be done. For more interfaces, please refer to [Class `AnimationState`](%__APIDOC__%/en/class/AnimationState).
diff --git a/versions/4.0/en/animation/animation-state/playback-control.dot b/versions/4.0/en/animation/animation-state/playback-control.dot
new file mode 100644
index 0000000000..267f5b44e3
--- /dev/null
+++ b/versions/4.0/en/animation/animation-state/playback-control.dot
@@ -0,0 +1,22 @@
+strict digraph {
+ graph [fontname = "Courier New"];
+ node [fontname = "Courier New"];
+ edge [fontname = "Courier New"];
+
+ entry [labe="",shape="diamond"]
+ {
+ rank=same;
+ playing [label="isPlaying"]
+ playingPaused [label="isPlaying &&\nisPaused"]
+ }
+ stopped [label=""]
+
+ entry -> stopped
+
+ stopped -> playing [label="play()"]
+ playing -> playingPaused [label="play()/resume()"]
+ playingPaused -> playing [label="pause()"]
+
+ playing -> stopped [label="stop()"]
+ playingPaused -> stopped [label="stop()"]
+}
\ No newline at end of file
diff --git a/versions/4.0/en/animation/animation-state/playback-control.svg b/versions/4.0/en/animation/animation-state/playback-control.svg
new file mode 100644
index 0000000000..5b7cbee67e
--- /dev/null
+++ b/versions/4.0/en/animation/animation-state/playback-control.svg
@@ -0,0 +1,78 @@
+
+
+
+
+
diff --git a/versions/4.0/en/animation/animation.md b/versions/4.0/en/animation/animation.md
new file mode 100644
index 0000000000..4b7d2906c8
--- /dev/null
+++ b/versions/4.0/en/animation/animation.md
@@ -0,0 +1,32 @@
+# Animation Panel
+
+Creator supports creating, editing and previewing animation clips directly in the **Animation** panel. In addition to animating the basic properties of nodes, it also supports animating the properties of materials and some components, and it can enrich animation clips by calling the event functions of the [animation event](animation-event.md).
+
+To edit an **Animation Clip** using the **Animation** panel, add an **Animation Component** to a node and attach the clip to the Animation Component. For details, please refer to the [Creating Animation Components and Animation Clips](animation-create.md) documentation.
+
+
+
+## Animation editing mode
+
+The animation data in an Animation Clip can only be edited in **Animation Editing Mode**. In Animation Editing Mode, nodes cannot be added/deleted/renamed and property changes that are not recorded within animation keyframes will also be restored after exiting animation editing mode.
+
+When in the Animation Editing Mode, nodes that are not involved in animation data editing are grayed out in the **Hierarchy** panel. When a node is selected in the **Animation** panel, the **Hierarchy** panel will highlight the corresponding node and vice versa.
+
+
+
+**Opening the edit mode includes the following two ways**:
+
+- Select a node with an Animation component in the **Hierarchy** panel that contains more than one clip file, then click the **Enter Animation Edit Mode** button in **Animation** panel.
+- Shortcut Ctrl/Cmd + E.
+
+**Saving the edited animation data includes the following three ways**.
+
+Click the  (Save) button in the top right corner of the **Animation** panel.
+- Click the **Save** button in the top left corner of the **Scene** panel.
+- Shortcut Ctrl/Cmd + S.
+
+**Exit edit mode includes the following three ways**:
+
+- Click the  (Exit) button in the top right corner of the **Animation** panel.
+- Click the **Close** button in the top left corner of the **Scene** panel.
+- Shortcut Ctrl/Cmd + E.
diff --git a/versions/4.0/en/animation/animation/animation-play.gif b/versions/4.0/en/animation/animation/animation-play.gif
new file mode 100644
index 0000000000..a0ae8b7ae1
Binary files /dev/null and b/versions/4.0/en/animation/animation/animation-play.gif differ
diff --git a/versions/4.0/en/animation/animation/batched-skinning-model-component.png b/versions/4.0/en/animation/animation/batched-skinning-model-component.png
new file mode 100644
index 0000000000..0e908185f1
Binary files /dev/null and b/versions/4.0/en/animation/animation/batched-skinning-model-component.png differ
diff --git a/versions/4.0/en/animation/animation/exit.png b/versions/4.0/en/animation/animation/exit.png
new file mode 100644
index 0000000000..3b0d07833c
Binary files /dev/null and b/versions/4.0/en/animation/animation/exit.png differ
diff --git a/versions/4.0/en/animation/animation/keyframe.png b/versions/4.0/en/animation/animation/keyframe.png
new file mode 100644
index 0000000000..392398ed28
Binary files /dev/null and b/versions/4.0/en/animation/animation/keyframe.png differ
diff --git a/versions/4.0/en/animation/animation/save.png b/versions/4.0/en/animation/animation/save.png
new file mode 100644
index 0000000000..8324f2a20a
Binary files /dev/null and b/versions/4.0/en/animation/animation/save.png differ
diff --git a/versions/4.0/en/animation/animation/select_node.gif b/versions/4.0/en/animation/animation/select_node.gif
new file mode 100644
index 0000000000..0ea70b2d35
Binary files /dev/null and b/versions/4.0/en/animation/animation/select_node.gif differ
diff --git a/versions/4.0/en/animation/animation/sockets-attach0.png b/versions/4.0/en/animation/animation/sockets-attach0.png
new file mode 100644
index 0000000000..4850285819
Binary files /dev/null and b/versions/4.0/en/animation/animation/sockets-attach0.png differ
diff --git a/versions/4.0/en/animation/animation/sockets-attach1.gif b/versions/4.0/en/animation/animation/sockets-attach1.gif
new file mode 100644
index 0000000000..58e6468c53
Binary files /dev/null and b/versions/4.0/en/animation/animation/sockets-attach1.gif differ
diff --git a/versions/4.0/en/animation/curve-editor.md b/versions/4.0/en/animation/curve-editor.md
new file mode 100644
index 0000000000..a5ab433163
--- /dev/null
+++ b/versions/4.0/en/animation/curve-editor.md
@@ -0,0 +1,124 @@
+# Curve Editor
+
+The Curve Editor is mainly used to edit the curve trajectory that changes between keyframes. The keyframe curves of animations and particles in the editor are edited using the Curve Editor. For the key point on each curve, **the horizontal coordinate is the keyframe time/frame rate, and the vertical coordinate is the value of the current curve property at the corresponding time**. The Curve Editor supports editing multiple curves at the same time, but only single curve editing is currently available in the particle usage scene.
+
+## Scaling and moving the curve display area
+
+- **Scroll the mouse wheel** directly within the curve display area **to zoom in and out of the horizontal and vertical timeline at the same time**.
+- Hold down the right mouse button and drag to pan the current display area.
+
+In addition, shortcut keys can be used to control the pan and zoom of the horizontal and vertical timeline individually.
+
+- Hold down Shift and roll the mouse wheel to **pan** the curve view area to the left or right;
+- Hold Ctrl/Cmd + Shift and roll the mouse wheel to **zoom** the curve view area to the left or right;
+- Hold down Alt/Option and roll the mouse wheel to **pan** the curve view area up or down;
+- Hold down Ctrl+Alt / Cmd+Option and roll the mouse wheel to **zoom** the curve view area up or down.
+
+## Editing Curve Trajectory
+
+### Adding keyframes
+
+1. When there is only one curve, right-clicking on the curve or any blanket, and choose **Create key frame** on the popup menu to create a new key frame.
+
+ Take the particle system as an example:
+
+ 
+
+2. For animation editor, key frames could be added by clicking the following button:
+
+ 
+
+### Selecting keyframes
+
+A keyframe can be selected by clicking on it directly, or by framing it, and the selected keyframe will be shown in yellow. The selected keyframe will be shown in yellow. When the keyframe is selected individually, the value of the current keyframe will be shown on the left and right axes.
+
+
+
+### Moving keyframes
+
+Drag the keyframe directly after it is selected.
+
+
+
+### Scaling keyframes
+
+After selecting multiple keyframes, drag the border of the selected area to scale the keyframes as a whole.
+
+
+
+### Spacing keyframes
+
+After framing multiple keyframes, click on the selected area and select **Spacing selected keyframes** in the pop-up menu.
+
+### Removing keyframes
+
+After selecting a keyframe, press Delete (Windows) or Cmd + Backspace (macOS) or right-click the selected area and select `Delete` in the pop-up menu.
+
+### Copying and pasting keyframes
+
+- Copying keyframe
+After selecting a keyframe, right-click on the selected area and select **Copy**, or press Ctrl/Cmd + C.
+
+- Pasting keyframe
+In any blank space, right-click on the selected area and select **Paste**, or just use the shortcut Ctrl/Cmd + V.
+
+### Editing keyframe data
+
+In the Curve Editor, the keyframe values are already displayed visually, dragging the keyframes up, down, left, and right is actually modifying the underlying keyframe data. In some cases where controlling the keyframe value precisely is necessary, right-click on the keyframe and select **Edit Keyframe Data** in the pop-up menu.
+
+
+
+### Interpolation Mode
+
+Right-click on the keyframe and select the corresponding value for `Interpolation Mode` in the pop-up menu. The linear interpolation mode will affect the way the value changes between the current keyframe and the next frame, and different option values will have different display effects. See below for more details on the options.
+
+
+
+
+
+The interpolation mode includes the following option values:
+
+- **Linear**: linear mode, linearly varying the value between the current frame and the next keyframe, with the tangent direction pointing to the next keyframe.
+
+ 
+
+- **Constant**: constant mode, where changes between the current keyframe and the next keyframe keep the current keyframe value unchanged.
+
+ 
+
+- **Cubic**: free curve mode, where the value between the current frame and the next keyframe changes in a curve. Only in the current mode the left and right tangent levers appear when the keyframe is selected.
+
+ 
+
+### Editing keyframe tangents
+
+A keyframe has two tangents on the left and right, the length and direction of the tangents will control the shape of the curve between keyframes. In `Cubic` interpolation mode, just drag the tangent control point to edit it directly. In different tangent weight modes, the tangent lever can be operated in different ranges, please refer to the next paragraph.
+
+#### Tangent Weight Mode
+
+Right-click on the keyframe to see the modification options menu for the interpolation mode, and click on Modify. The tangent weight mode value will only work if the `Interpolation Mode` is `Cubic`.
+
+The tangent option range is actually two main types:
+
+- **No-Weighting Mode**: the variation between keyframes uses the Hermite algorithm, where the direction of the curve depends on the direction of the left and right tangents of the keyframes. In this case, the left and right tangent levers of the keyframe can only change the tangent direction. The tangent control points at this point are only drawn to facilitate the direction change, so the tangent lever length does not change when scaling the curve view area at this point.
+
+- **Weighting Mode**: the change between keyframes uses the Bessel algorithm, and the curve orientation is also influenced by the left and right tangent control points of the keyframes. The left tangent control point can be moved at will to adjust the control bar length, the left tangent control point is the real coordinate point at this time, and the control bar will be scaled simultaneously when scaling the curve view area.
+
+ 
+
+The keyframe has left and right tangents, and the tangent weight mode has the following option values:
+
+
+
+- `None`: the left and right tangents are in no-weighting mode.
+- `Left`: left tangent is in weighting mode, right tangent is in no-weighting mode.
+- `Right`: right tangent is in in weighting mode, left tangent is in no-weighting mode.
+- `Both`: both left and right tangents are in weighting mode.
+
+#### Broken
+
+By default, the left and right tangent slopes of the keyframe are kept the same. Adjusting the tangent lever on either side will follow the adjustment on the other side, which makes it easier for us to adjust the transition more naturally. In some cases, the curve does not always transition smoothly. At this time, right-click the keyframe and click the Broken option in the right-click menu to disconnect the key left and right joysticks. After disconnecting, the keyframes can be adjusted separately using the left and right joysticks.
+
+### Moving curves up and down
+
+The whole curve can be dragged up and down directly after double tapping the curve.
diff --git a/versions/4.0/en/animation/curve-example-test.html b/versions/4.0/en/animation/curve-example-test.html
new file mode 100644
index 0000000000..2105cefba7
--- /dev/null
+++ b/versions/4.0/en/animation/curve-example-test.html
@@ -0,0 +1,9 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/versions/4.0/en/animation/curve-example.js b/versions/4.0/en/animation/curve-example.js
new file mode 100644
index 0000000000..8e6a2c5363
--- /dev/null
+++ b/versions/4.0/en/animation/curve-example.js
@@ -0,0 +1,98 @@
+
+(() => {
+ /**
+ * @param {HTMLCanvasElement} canvas
+ * @param {{xAxisText?: string; yAxisText?: string;}} config
+ */
+ window.drawCurve = (canvas, countGenPoint, config) => {
+ config = config || {};
+
+ const xrange = { min: 0.1, max: 0.9 };
+ const yrange = { min: 0.1, max: 0.8 };
+ const xAxisLine = { start: 0.0 * canvas.width, end: 0.7 * canvas.width }; // In pixel.
+ const yAxisLine = { start: 0.7 * canvas.height, end: 0.1 * canvas.height }; // In pixel.
+ const xAxisLength = xAxisLine.end - xAxisLine.start;
+ const yAxisLength = yAxisLine.start - yAxisLine.end;
+
+ const generateIncresingNumbers = (count, min, max) => {
+ const intervals = new Array(count);
+ let sum = 0;
+ for (let i = 0; i < count; ++i) {
+ const interval = Math.random();
+ intervals[i] = interval;
+ sum += interval;
+ }
+ const extent = max - min;
+ let sumNi = 0;
+ return intervals.map((interval) => {
+ const ni = interval / sum;
+ const result = min + sumNi * extent;
+ sumNi += ni;
+ return result;
+ });
+ };
+
+ const context = canvas.getContext('2d');
+ context.fillStyle = 'white';
+ context.fillRect(0, 0, canvas.width, canvas.height);
+ context.fill();
+
+ context.strokeStyle = 'black';
+
+ const xs = generateIncresingNumbers(countGenPoint, xrange.min, xrange.max);
+ const points = xs.map((x) => {
+ return {
+ x,
+ y: yrange.min + (yrange.max - yrange.min) * Math.random(),
+ };
+ });
+ const pointPixels = points.map((point) => {
+ return {
+ x: xAxisLine.start + point.x * xAxisLength,
+ y: yAxisLine.start - point.y * yAxisLength,
+ };
+ });
+
+ // Draw axises.
+ context.moveTo(xAxisLine.start, yAxisLine.start);
+ context.lineTo(xAxisLine.end, yAxisLine.start);
+ context.moveTo(xAxisLine.start, yAxisLine.start);
+ context.lineTo(xAxisLine.start, yAxisLine.end);
+
+ // Draw curve.
+ if (pointPixels.length > 1) {
+ context.moveTo(pointPixels[0].x, pointPixels[0].y);
+ for (let iPoint = 1; iPoint < points.length; ++iPoint) {
+ context.lineTo(pointPixels[iPoint].x, pointPixels[iPoint].y);
+ }
+ }
+
+ context.stroke();
+
+ // Draw frames.
+ context.setLineDash([1, 3]);
+ pointPixels.forEach((pointPixel) => {
+ context.moveTo(pointPixel.x, pointPixel.y);
+ context.lineTo(pointPixel.x, yAxisLine.start);
+ });
+ context.stroke();
+
+ // Draw points.
+ context.fillStyle = 'red';
+ pointPixels.forEach((pointPixel) => {
+ const rectSize = 4;
+ context.fillRect(pointPixel.x - rectSize / 2, pointPixel.y - rectSize / 2, rectSize, rectSize);
+ });
+
+ if (config.xAxisText) {
+ context.fillText(config.xAxisText, xAxisLine.end + 1, yAxisLine.start);
+ }
+
+ if (config.yAxisText) {
+ context.fillText(config.yAxisText, xAxisLine.start, yAxisLine.end - 1);
+ }
+ };
+})();
+
+var myFoo = ()=>{}
+export default myFoo;
\ No newline at end of file
diff --git a/versions/4.0/en/animation/easing-method-example.js b/versions/4.0/en/animation/easing-method-example.js
new file mode 100644
index 0000000000..872f35d462
--- /dev/null
+++ b/versions/4.0/en/animation/easing-method-example.js
@@ -0,0 +1,83 @@
+
+(() => {
+ const makeOutIn = (infx, outfx) => {
+ return (k) => {
+ if (k < 0.5) {
+ return outfx(k * 2) / 2;
+ }
+ return infx(2 * k - 1) / 2 + 0.5;
+ };
+ };
+
+ const quadInFx = (k) => k * k;
+
+ const quadOutFx = (k) => k * (2 - k);
+
+ const methods = [
+ {name: 'linear', fx: ((k) => k),},
+ {name: 'constant', fx: ((k) => 0)},
+ {name: 'quadIn', fx: quadInFx},
+ {name: 'quadOut', fx: quadOutFx},
+ {name: 'quadInOut', fx: makeOutIn(quadInFx, quadOutFx)},
+ {name: 'quadOutIn', fx: ((k) => k)},
+ ];
+
+ window.initializeEasingMethodsExample = (parent) => {
+ const table = parent.appendChild(document.createElement('table'));
+ const showcases = [];
+ for (const method of methods) {
+ const { name, fx } = method;
+ const tr = table.appendChild(
+ document.createElement('tr'));
+
+ const label = tr.appendChild(document.createElement('td')).
+ appendChild(document.createElement('label'));
+ label.textContent = name;
+
+ const image = tr.appendChild(document.createElement('td')).
+ appendChild(document.createElement('img'));
+ image.src = "https://forum.cocos.org/images/logo.png";
+
+ const slider = tr.appendChild(document.createElement('td')).
+ appendChild(document.createElement('input'));
+ slider.type = 'range';
+ slider.min = 0;
+ slider.max = 100;
+ slider.value = 0;
+
+ showcases.push({
+ label,
+ image,
+ fx,
+ slider,
+ });
+ }
+
+ const firstTime = Date.now();
+ let duration = 3000;
+ setInterval(() => {
+ const timePast = Date.now() - firstTime;
+ const ratio = (timePast % duration) / duration;
+ for (const showcase of showcases) {
+ const mappedRatio = showcase.fx(ratio);
+ showcase.image.style.opacity = (1.0- mappedRatio);
+ showcase.slider.value = 100 * mappedRatio;
+ }
+ }, 16);
+ };
+})();
+
+(() => {
+ let easingMethodsExampleInitialized = false;
+ window.onEasingMethodExampleButtonClicked = () => {
+ const panel = document.getElementById('easing-method-example-panel');
+ if (!easingMethodsExampleInitialized) {
+ easingMethodsExampleInitialized = true;
+ initializeEasingMethodsExample(panel);
+ } else {
+ panel.hidden = !panel.hidden;
+ }
+ };
+})();
+
+export default ()=>{};
diff --git a/versions/4.0/en/animation/edit-animation-clip.md b/versions/4.0/en/animation/edit-animation-clip.md
new file mode 100644
index 0000000000..b639a2028e
--- /dev/null
+++ b/versions/4.0/en/animation/edit-animation-clip.md
@@ -0,0 +1,138 @@
+# Editing Animation Clips
+
+Once an Animation Clip is attached on to an Animation Component of a node, click **Enter animation editing mode** or use the shortcut Ctrl/Cmd + E to enter Animation Editing Mode and add keyframe data to the Animation Clip to animate the node. Please refer to the [Animation panel](animation-editor.md) documentation before editing animation clips.
+
+An Animation Clip may contain multiple nodes (nodes and their children), and multiple animation properties can be attached to each node. By moving, rotating, or scaling the nodes, keyframes are added to the animation property corresponding to the currently selected node. All the keyframes added to the animation property are displayed in the corresponding animation property as a list pattern of linear trajectories, which are called animation curves.
+
+## Creating an Animation Curve
+
+Before adding keyframes, it is necessary to know about animation properties. The animation properties include the node's own `position`, `rotation`, `scale`, and other properties, and also include the custom properties in the component `Component`. The properties included in the component are preceded by the name of the component, e.g.: `cc.Sprite.spriteFrame`.
+
+Click the **+** button in the upper-right corner of the **Property List** area to add animation properties as needed, depending on the node type. Added animation properties are grayed out and cannot be added repeatedly.
+
+
+
+Once the animation properties are added, keyframes can be added to the properties track on the right. When the node and its animation properties are shown in blue in the list, it is determined that the node's properties are the target object for the current keyframe creation. Then, when the corresponding property is modified in the **Animation** / **Inspector** / **Scene** panel, a solid blue diamond will be created on the right side of the animation property where the time control line is located, which is the keyframe (The selected keyframe data can also be modified by this method).
+
+
+
+For more information on the design of Animation Curves and how to control them via scripts, please refer to the [Using Animation Curve](use-animation-curve.md) documentation.
+
+### Editing Sprite animations
+
+Next, let's take a look at the process of creating a Sprite animation as an example.
+
+1. Create a Sprite node.
+
+ Create a Sprite node in the **Hierarchy** panel. Or add a Sprite component to the node by selecting the node and clicking the **Add Component** button in the **Inspector** panel and selecting **2D -> Sprite**.
+
+2. Add the Animation Component to the node, attach the Clip file, and enter the Animation Editing Mode. For details, please refer to the [Creating Animation Component and Animation Clip](animation-create.md) documentation.
+
+3. Add the animation property `cc.Sprite.spriteFrame` to the property list.
+
+ Click the **+** button in the upper right corner of the property list, then select **cc.Sprite -> spriteFrame**.
+
+ 
+
+4. Add a keyframe.
+
+ Drag the spriteFrame asset from **Assets** panel to the property track on the right side of the `cc.Sprite.spriteFrame` animation property, and then drag the spriteFrame to be displayed in the next keyframe to the specified position, or select the needed spriteFrame in the property box above the property track. Play to preview the animation that is just created.
+
+ 
+
+## Keyframe data editing
+
+### Common operations with node data
+
+The animation clip defines the position of the animation data by the name of the node, itself ignoring the root node, and the rest of the child nodes find the corresponding data by the relative path index to the root node.
+
+Right-clicking on a node in the **Node List** area of the **Animation** panel is currently supported to choose between clearing node data, migrating node data, and copying and pasting node data.
+
+
+
+#### Clearing node data
+
+Right-click the node that needs to clear all animation data (keyframes), then select **Clear data**, and click **Clear** in the popup window.
+
+#### Migrating node data
+
+Right-click the node that needs to migrate all animation data, then select **Move Data**, the node will show a dynamic dashed box, when the mouse moves to other nodes, it will show the prompt of "Move data to this node", click it and select **Move** in the pop-up window. If there is no need to migrate, just select **Cancel**.
+
+
+
+> **Note**: node data migration will overwrite the data on the original node by default.
+
+Because the animation clip will record all the node path information that participated in the animation data editing, so when the node information changes (e.g.: node renaming/deletion/move position), which is not consistent with the original saved in the animation clip, the **Animation** panel will show it in the node list as a yellow uneditable lost state, and the keyframes are also grayed out as uneditable. In this case, the **Migrate Data** function of the node can be used to migrate the animation data of the missing node to another node.
+
+
+
+#### Copy and paste node data
+
+Copy and paste of node animation data, supports cross-editor (v3.x) usage.
+
+- **Copy**: Select the node you want to copy data from in the node list, right click and select **Copy Data**, or use the shortcut Ctrl/Cmd + C to do so.
+- **Paste**: Select the target node in the node list, right click and select **Paste Data**, or use the shortcut Ctrl/Cmd + V to paste the animation data.
+
+> **Note**: the paste function does not support automatic creation of animation properties, so the copied and pasted nodes must have at least one of the same animation property, if not, please create it in advance. When pasting animation data of multiple nodes on the same node, the animation data of the overlapping part will be overwritten by the latter, and the different parts will be fused with each other.
+
+#### Edit child node data with the same name
+
+When editing animation data in the animation clip of the parent node, it is possible to also edit the animation data of the child nodes. The animation data will all be saved in the animation clip of the parent node, which is used to achieve effects like moving the hands of the character model with different speeds along with the body, etc. However, if the parent node contains more than one child node with the same name at the same time, only the first child node with the same name will be edited, and the other nodes with the same name will be grayed out to uneditable state.
+
+
+
+However, it is supported to add Animation components and animation clips for the same name child node separately and edit them separately.
+
+### Common operations for animation property data
+
+Right-click on the animation property or click  button to the right of the track to select **Remove property track**, **Clear keyframe data**, or **Copy property track**.
+
+
+
+- Remove property track: remove the currently selected animation property, including all keyframes on that property track. Or use the shortcut Delete key (Windows) or Cmd + Backspace (macOS).
+
+- Clear keyframe data: delete all keyframes on the currently selected animation property track.
+
+- Copy animation property track: copy all animation data on the currently selected animation property track and paste it to the target animation property track, supporting the shortcut keys Ctrl/Cmd + C and Ctrl/Cmd + V. When pasting, the overlapping keyframes are overwritten by the latter, and the different parts are blended with each other.
+
+ Copy/paste of animation property data between different editors (v3.x) is currently supported. Copy/paste of animation data is only supported for `ccType` data of the same type.
+
+As with nodes, there is a possibility of missing animation properties. For example, if an property corresponding to an animation property is removed from the **Inspector** panel, it will be displayed in the animation property list as a yellow uneditable missing state, and the keyframe will be grayed out as uneditable. In this case, either exit edit mode and add the relevant property to the corresponding node or simply remove the missing property track.
+
+ 
+
+### Node / Property track keyframe data editing
+
+The **Animation** panel has two types of view for keyframes: **Keyframe Editing View** and **Curve Editing View**. When you enter the **Animation** panel, the default is keyframe mode, by clicking the switch view button on the side of the property list  to switch the keyframes in the property track area to the curve editing view, and click it again to return to the keyframe editing view.
+
+#### Keyframe Editing Mode
+
+For some common keyframe operations in keyframe editing mode, see [keyframe editing mode](./animation-keyFrames.md) for a description of the documentation.
+
+#### Curve Editing Mode
+
+For some details of the keyframe operations in curve editing mode, see the [curve editing mode](./animation-curve.md) documentation.
+
+## Animation clip property settings
+
+The properties of the current animation clip that can be set directly on the **Animation** panel include: **WrapMode**, **Sample**, **Speed** and **Duration**.
+
+
+
+- **WrapMode**: use to set the loop mode of the current animation clip, currently include
+ - Default: the effect is the same as Normal
+ - Normal: forward single play
+ - Loop: loop forward
+ - PingPong: loop in forward and then reverse mode
+ - Reverse: reverse single play
+ - LoopReverse: loop reverse
+
+ For more information about how to set the loop mode by script code, please refer to [Loop Mode](use-animation-curve.md#wrap-mode).
+
+- **Sample**: define the frame rate per second of the current animation data, i.e. how many frames a second to divide into, default is 60. please refer to the **Timeline's scale unit display** section above for more details.
+
+- **Speed**: set the speed of current animation, default is 1, the smaller the value the slower the speed.
+
+- **Duration**: the number in front indicates the duration of the animation when the speed is 1, it is determined by the position of the last keyframe. The number in brackets after it indicates the actual running duration, which will change when Speed is adjusted.
+
+Animation clips are reusable and their states are stored in objects called animation states. Through the animation state interface the animation can be controlled by playing, pausing, stopping, shifting, etc. For details, please refer to [Animation State](animation-state.md).
diff --git a/versions/4.0/en/animation/edit-animation-clip/add-keyframe-button.png b/versions/4.0/en/animation/edit-animation-clip/add-keyframe-button.png
new file mode 100644
index 0000000000..2d2fba2a79
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/add-keyframe-button.png differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/add-keyframe.gif b/versions/4.0/en/animation/edit-animation-clip/add-keyframe.gif
new file mode 100644
index 0000000000..ed98e7a201
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/add-keyframe.gif differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/add-keyframe.png b/versions/4.0/en/animation/edit-animation-clip/add-keyframe.png
new file mode 100644
index 0000000000..a385de7a60
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/add-keyframe.png differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/add-property.png b/versions/4.0/en/animation/edit-animation-clip/add-property.png
new file mode 100644
index 0000000000..2d0dae9cb8
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/add-property.png differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/add-spriteframe.gif b/versions/4.0/en/animation/edit-animation-clip/add-spriteframe.gif
new file mode 100644
index 0000000000..bb3d5e53ec
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/add-spriteframe.gif differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/animation-sprite.gif b/versions/4.0/en/animation/edit-animation-clip/animation-sprite.gif
new file mode 100644
index 0000000000..efb2e33175
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/animation-sprite.gif differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/change-node.png b/versions/4.0/en/animation/edit-animation-clip/change-node.png
new file mode 100644
index 0000000000..444cf0e582
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/change-node.png differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/change-pro.png b/versions/4.0/en/animation/edit-animation-clip/change-pro.png
new file mode 100644
index 0000000000..f8a5d1b1eb
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/change-pro.png differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/choose-by-box.png b/versions/4.0/en/animation/edit-animation-clip/choose-by-box.png
new file mode 100644
index 0000000000..9469d70017
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/choose-by-box.png differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/choose-keyframe.png b/versions/4.0/en/animation/edit-animation-clip/choose-keyframe.png
new file mode 100644
index 0000000000..158648516a
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/choose-keyframe.png differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/copy-keyframes1.gif b/versions/4.0/en/animation/edit-animation-clip/copy-keyframes1.gif
new file mode 100644
index 0000000000..4b1462fad9
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/copy-keyframes1.gif differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/copy-keyframes2.gif b/versions/4.0/en/animation/edit-animation-clip/copy-keyframes2.gif
new file mode 100644
index 0000000000..f875d59cdb
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/copy-keyframes2.gif differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/menu-spacing.png b/versions/4.0/en/animation/edit-animation-clip/menu-spacing.png
new file mode 100644
index 0000000000..e20bce5e81
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/menu-spacing.png differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/menu_spacing_btn.png b/versions/4.0/en/animation/edit-animation-clip/menu_spacing_btn.png
new file mode 100644
index 0000000000..9a732235a7
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/menu_spacing_btn.png differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/move-data.png b/versions/4.0/en/animation/edit-animation-clip/move-data.png
new file mode 100644
index 0000000000..bb636f90a5
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/move-data.png differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/move-keyframes.gif b/versions/4.0/en/animation/edit-animation-clip/move-keyframes.gif
new file mode 100644
index 0000000000..866ed1996e
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/move-keyframes.gif differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/node-operation.png b/versions/4.0/en/animation/edit-animation-clip/node-operation.png
new file mode 100644
index 0000000000..13c7917ebe
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/node-operation.png differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/pro-operation.png b/versions/4.0/en/animation/edit-animation-clip/pro-operation.png
new file mode 100644
index 0000000000..1d0d00172e
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/pro-operation.png differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/remove-key-btn.png b/versions/4.0/en/animation/edit-animation-clip/remove-key-btn.png
new file mode 100644
index 0000000000..3c5b52cf70
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/remove-key-btn.png differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/remove-keyframes.gif b/versions/4.0/en/animation/edit-animation-clip/remove-keyframes.gif
new file mode 100644
index 0000000000..8baa243885
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/remove-keyframes.gif differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/same-name-node.png b/versions/4.0/en/animation/edit-animation-clip/same-name-node.png
new file mode 100644
index 0000000000..064d6d8d26
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/same-name-node.png differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/scale-keyframes.gif b/versions/4.0/en/animation/edit-animation-clip/scale-keyframes.gif
new file mode 100644
index 0000000000..eff95666ce
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/scale-keyframes.gif differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/set-animation-clip.png b/versions/4.0/en/animation/edit-animation-clip/set-animation-clip.png
new file mode 100644
index 0000000000..56927bef3b
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/set-animation-clip.png differ
diff --git a/versions/4.0/en/animation/edit-animation-clip/set-pro.png b/versions/4.0/en/animation/edit-animation-clip/set-pro.png
new file mode 100644
index 0000000000..8ab665f3be
Binary files /dev/null and b/versions/4.0/en/animation/edit-animation-clip/set-pro.png differ
diff --git a/versions/4.0/en/animation/embedded-player.md b/versions/4.0/en/animation/embedded-player.md
new file mode 100644
index 0000000000..97a14c0c5e
--- /dev/null
+++ b/versions/4.0/en/animation/embedded-player.md
@@ -0,0 +1,78 @@
+# Embedded Player (experimental feature)
+
+The role of the embedded player is to allow the production of animation clips that can be bound at the same time particle effects or other animation, etc., used to meet the function of playing animation at the same time play dynamic effects. It can be used to achieve the function of waving a weapon will appear knife light, or feet on the ground will appear smoke and so on.
+
+The entire nesting system can be viewed by expanding the **Player Track List** in the Animation window.
+
+
+
+> **Note**: In v3.6, this feature is experimental and developers need to enable it in **Preferences** -> **Laboratory**.
+> Any experience problems or suggestions, please feel free to feedback to us in [forum](https://forum.cocos.org/t/topic/137740).
+>
+> 
+
+## Track manipulation
+
+The embedded player supports **animation player** as well as **particle player**.
+
+Different tracks can be added by clicking the **+** buttons on the right side of the **animation track list**:
+
+
+
+Right click on the added track to **Remove Animation EmbeddedPlayer Track** and **Clear Data**.
+
+
+
+> **Note**: The clear data operation clears the entire track.
+
+You can select **Copy** and **Delete** operations by clicking the right mouse button on the track data.
+
+The delete operation only deletes the currently selected data.
+
+
+
+When no data is selected, you can select **Create Animation EmbeddedPlayer**, **Paste** and **Clear Data**.
+
+
+
+After adding a track, the position of the track data and the duration can be adjusted:
+
+
+
+### Particle player track
+
+Select the added Particle Player track on the left in the **Animation Track List**, and adjust the track's properties in the **Inspector** panel.
+
+! [inspector](embedded/particle-inspector.png)
+
+- **Reconciled speed**: keep the embedded particle system playing at the same rate as the current animation clip
+- **Child Path**: the drop-down box allows to select the particle system on different sub-nodes.
+
+ 
+
+### Animation player tracks
+
+Select the added animation player track on the left in the **Animation Track List**, and adjust the track's properties in the **Inspector** panel.
+
+
+
+- **Reconciled speed**: keeps the embedded animation at the same playback rate as the current animation clip
+- **Child Path**: the drop-down box allows to select the animation components on different sub-nodes.
+
+ 
+
+- **Animation clips**: The drop-down menu allows you to select different animation clips:
+
+ 
+
+## Preview
+
+The above operation can be used to nest different particle players and animation players when the animation is played, and the effect is displayed as follows.
+
+
+
+## Adding frame events
+
+You can also add frame events by right-clicking on the nested bar, in the same way as [Adding Animation Events](animation-event.md).
+
+
diff --git a/versions/4.0/en/animation/embedded/add-keyframe-event.png b/versions/4.0/en/animation/embedded/add-keyframe-event.png
new file mode 100644
index 0000000000..7556452996
Binary files /dev/null and b/versions/4.0/en/animation/embedded/add-keyframe-event.png differ
diff --git a/versions/4.0/en/animation/embedded/add-patricle.png b/versions/4.0/en/animation/embedded/add-patricle.png
new file mode 100644
index 0000000000..104e7ea268
Binary files /dev/null and b/versions/4.0/en/animation/embedded/add-patricle.png differ
diff --git a/versions/4.0/en/animation/embedded/add-track.png b/versions/4.0/en/animation/embedded/add-track.png
new file mode 100644
index 0000000000..c8677ffe96
Binary files /dev/null and b/versions/4.0/en/animation/embedded/add-track.png differ
diff --git a/versions/4.0/en/animation/embedded/clear-data.png b/versions/4.0/en/animation/embedded/clear-data.png
new file mode 100644
index 0000000000..528ac6d871
Binary files /dev/null and b/versions/4.0/en/animation/embedded/clear-data.png differ
diff --git a/versions/4.0/en/animation/embedded/embedded-overview.png b/versions/4.0/en/animation/embedded/embedded-overview.png
new file mode 100644
index 0000000000..690807d04c
Binary files /dev/null and b/versions/4.0/en/animation/embedded/embedded-overview.png differ
diff --git a/versions/4.0/en/animation/embedded/enable.png b/versions/4.0/en/animation/embedded/enable.png
new file mode 100644
index 0000000000..ffd17af49f
Binary files /dev/null and b/versions/4.0/en/animation/embedded/enable.png differ
diff --git a/versions/4.0/en/animation/embedded/inspector-select-anim.png b/versions/4.0/en/animation/embedded/inspector-select-anim.png
new file mode 100644
index 0000000000..4d63c0ab7f
Binary files /dev/null and b/versions/4.0/en/animation/embedded/inspector-select-anim.png differ
diff --git a/versions/4.0/en/animation/embedded/inspector-select-child-anim.png b/versions/4.0/en/animation/embedded/inspector-select-child-anim.png
new file mode 100644
index 0000000000..3e948ace44
Binary files /dev/null and b/versions/4.0/en/animation/embedded/inspector-select-child-anim.png differ
diff --git a/versions/4.0/en/animation/embedded/inspector-select-child.png b/versions/4.0/en/animation/embedded/inspector-select-child.png
new file mode 100644
index 0000000000..41eb922cf5
Binary files /dev/null and b/versions/4.0/en/animation/embedded/inspector-select-child.png differ
diff --git a/versions/4.0/en/animation/embedded/inspector-select-clip.png b/versions/4.0/en/animation/embedded/inspector-select-clip.png
new file mode 100644
index 0000000000..cf8c4fbf49
Binary files /dev/null and b/versions/4.0/en/animation/embedded/inspector-select-clip.png differ
diff --git a/versions/4.0/en/animation/embedded/particle-inspector.png b/versions/4.0/en/animation/embedded/particle-inspector.png
new file mode 100644
index 0000000000..c500231223
Binary files /dev/null and b/versions/4.0/en/animation/embedded/particle-inspector.png differ
diff --git a/versions/4.0/en/animation/embedded/preview.gif b/versions/4.0/en/animation/embedded/preview.gif
new file mode 100644
index 0000000000..e4ab7cd308
Binary files /dev/null and b/versions/4.0/en/animation/embedded/preview.gif differ
diff --git a/versions/4.0/en/animation/embedded/track-adjust.gif b/versions/4.0/en/animation/embedded/track-adjust.gif
new file mode 100644
index 0000000000..c494906b21
Binary files /dev/null and b/versions/4.0/en/animation/embedded/track-adjust.gif differ
diff --git a/versions/4.0/en/animation/embedded/track-data-menu.png b/versions/4.0/en/animation/embedded/track-data-menu.png
new file mode 100644
index 0000000000..2d1a4ab716
Binary files /dev/null and b/versions/4.0/en/animation/embedded/track-data-menu.png differ
diff --git a/versions/4.0/en/animation/embedded/unselect.png b/versions/4.0/en/animation/embedded/unselect.png
new file mode 100644
index 0000000000..803c2fd7e2
Binary files /dev/null and b/versions/4.0/en/animation/embedded/unselect.png differ
diff --git a/versions/4.0/en/animation/index.md b/versions/4.0/en/animation/index.md
new file mode 100644
index 0000000000..57cf391f56
--- /dev/null
+++ b/versions/4.0/en/animation/index.md
@@ -0,0 +1,31 @@
+# Animation System
+
+Cocos Creator has a built-in universal animation system for implementing keyframe-based animations. In addition to standard moving, rotation, scaling and frame animations, it also supports arbitrary component properties and user-defined property drivers, plus arbitrary time curves and innovative trajectory editing, allowing content producers to create detailed dynamic effects without writing a single line of code.
+
+
+
+> **Note**: the **Animation** panel that comes with Cocos Creator is suitable for creating less complex animations that need to be linked with logic, such as UI animations. If you want to create complex effects, character animations, nested animations, etc., consider using Spine, DragonBones or skeletal animation editor for 3D models instead.
+
+## Content
+
+- [Animation Clip](animation-clip.md): asset containing animation data, reusable. Animation clips can be produced by the **Animation** panel, or imported by some external asset that already contains skeletal animation.
+
+- [Animation Component Reference](animation-comp.md): the Animation component can drive node and component properties on their nodes and children in an animated manner, including properties in user-defined scripts.
+
+- [Animation Editor](animation.md): learn how to use the Animation Editor and create/modify/generate animation clip assets through the Animation Editor.
+
+- [Skeletal Animation](skeletal-animation.md): a common but special type of animation, this article mainly introduces it and explains its usage.
+
+- [Controlling Animation with Scripts](animation-component.md): the Animation component manages a set of animation states, which are used to control the play, pause, continue, stop, switch, etc. of each animation.
+
+ - [Animation State](animation-state.md): the state of animation clips is stored in an object called animation state, animation state can control the animation clips that need to be used on the object. Animation state provides more animation control interfaces, through which animation can be played, stopped, shifted, set to loop mode and other more detailed control.
+
+- [Embedded Player](embedded-player.md): embeded-player is used to embed other particle players or animation players in the animation clips.
+
+- [Marionette Animation System](./marionette/index.md): added in v3.4 and implements an automated and reusable skeletal animation process controlled by a state machine.
+
+- [Procedural Animation](./marionette/procedural-animation/index.md): New in v3.8, you can programmatically control the sampling process of the animation through different animation nodes.
+
+- [Auxiliary Curve](./animation-auxiliary-curve.md): New in v3.8, used to add a curve editor that can be used to get information in animation clips.
+
+According to different animation requirements, the operation steps and code implementation for specific animations are different, please refer to the official example [animation](https://github.com/cocos/cocos-test-projects/tree/v3.8/assets/cases/animation), which mainly introduces some common editing operations and code examples for reference.
diff --git a/versions/4.0/en/animation/index/main.gif b/versions/4.0/en/animation/index/main.gif
new file mode 100644
index 0000000000..6b202df4ea
Binary files /dev/null and b/versions/4.0/en/animation/index/main.gif differ
diff --git a/versions/4.0/en/animation/joint-texture-layout.md b/versions/4.0/en/animation/joint-texture-layout.md
new file mode 100644
index 0000000000..2a44bbe62e
--- /dev/null
+++ b/versions/4.0/en/animation/joint-texture-layout.md
@@ -0,0 +1,88 @@
+# Joint Texture Layout Settings
+
+To ensure that [Skeletal Animation](./skeletal-animation.md) can also participate fully and correctly in [Dynamic Instancing](../engine/renderable/model-component.md#instancing-%E5%90%88%E6%89%B9), the developer needs to manually specify how the data for each skeletal texture is assigned.
+
+For example, a scene where a large number of identical characters are to be drawn, each of which may be walking/jumping/attacking. If one Drawcall should be able to draw all characters correctly, an important prerequisite is that **the data for all three animations (walk, jump, attack) are stored inside the same joint texture**.
+
+Currently, in the default [pre-baked skeletal animation mode](./skeletal-animation.md#pre-baked-Skeletal-Animation-System), the joint textures are already globally auto-reused, but the size of each texture and which animations they store are not available. and which animations are stored in each of them are unpredictable. If instancing of the skinned model is enabled without any processing, The final runtime effect may have some animations that are correct and some that are completely wrong, which are completely unpredictable.
+
+A **Joint Texture Layout Settings** page was added to the editor **Project Setting** panel to manually specify which animation information is stored for which skeletons in each joint texture.
+
+
+
+> **Note**: the joint texture layout settings panel provides, essentially, runtime **memory allocation guidance rules**. For specified skeleton and animation assets, they are guaranteed to be allocated according to the specified rules. However, if an asset is used at runtime that is not specified by the rules, it will go back to the automatic allocation mode of global reuse.
+
+## Joint texture layout settings
+
+Use the **instanced-skinning** scenario from the example project [show-cases](https://github.com/cocos/cocos-example-projects/tree/v3.8/show-cases/assets/scenes) as an example to see how the joint texture layout is set up and how it works. The following figure shows a sample scene.
+
+The following figure shows a sample scenario with multiple instances from the same model, playing completely different animations at the same time. Notice the current scene, plus the UI, has a total Drawcall of 60 and an instance count of 0. This state will be used as the basis for later changes to compare.
+
+
+
+To create a model with instancing version turned on, the following steps are required:
+
+1. In the **Inspector** panel, check the `UseBakedAnimation` property in the SkeletalAnimation component (using pre-baked animation mode).
+
+ 
+
+2. check `USE INSTANCING` for all materials used by SkinningModel.
+
+ 
+
+In the example scene, two sets of Prefabs were made and set the material diffuse color to blue in the instancing version in order to see and distinguish the performance of both systems. Notice that the effect has been exactly correct and that only 5 drawcalls (each model is divided into 5 parts) were used, with 45 instances.
+
+
+
+> **Note**: the reason for rendering all models correctly here is that the amount of animation data is still relatively small, and the generic joint texture global reuse logic already writes all animation data to the same texture, so the effect is correct. However, if the size of the default joint texture (360 * 360) is exceeded by new animations that may be added at any time, the animation will definitely go wrong, which is why the joint texture layout panel must exist.
+
+## Joint Texture Layout Effects
+
+For demonstration purposes, we can intentionally put each animation on a separate texture in the **Joint Texture Layout Settings** panel to see the final rendering effect.
+
+First, open the **Joint Texture Layout Settings** panel:
+
+
+
+The three **+** in the panel are used as follows:
+
+- ① - Used to add Texture units, a Texture unit consists of multiple Skeleton units.
+- ② - Used to add Skeleton units, a Skeleton unit consists of a Skeleton asset and one to more AnimationClip assets.
+- ③ - Used to add AnimationClip asset slots.
+
+Here there are 9 different animations separated into 9 Texture cells.
+
+
+
+Rerun the scene and the effect becomes:
+
+
+
+Notice there is a problem with the animation, all the animations become attack actions, and the model disappears from time to time. The reason behind this can be precisely analyzed.
+
+- Each drawcall draws 9 instances, which are broadcasting 9 different animations.
+- However, each drawcall can only use one skeletal animation texture, and here it is obvious that the Texture unit 0 is used and there is only one attack animation.
+- The length of different animation segments is different, and some of them are longer than the attack segment, so at the last time they will be read outside the valid area of Texture unit 0, where the data is not defined (usually the default is all 0), not valid skeleton transformation data, so naturally they cannot be rendered correctly.
+
+> **Note**: the 9 textures here all have the same skeletal animation information, so only the action is wrong in the final result, even if the texture is already wrong, but if there are multiple skeletons with animation information in one texture, and the textures don't match at the same time, the rendering effect will be completely wrong.
+
+For the example scene above, since the model does need to play the 9 animation clips on the same screen at the same time, the correct joint texture layout setting should be:
+
+
+
+This will **guarantee** that it renders correctly. Observe the change in the relevant data on the panel:
+
+- Texture cell 0 has a total size of 276 x 276 (automatically generated by the algorithm, the minimum size sufficient to hold all the specified animation data).
+- The specified 9 groups of animation data take up 94.41% of this texture, with 5.59% excess space (this space is not involved in global reuse at runtime).
+
+In addition, the color of the icon next to the texture size indicates the device adaptation of the current texture:
+
+- Green (up to 1024 sides): all devices are guaranteed to work.
+- Yellow (1024 ~ 2048 sides): Some mobile devices or mini-game platforms that do not support floating point texture may not support it.
+- Red (side length 2048 or more): Not supported on many mobile devices.
+
+> **Note**: this is just a set of 9 animations for one skeleton, on one texture, but **any number of animations for any number of skeletons** can be put on each texture, as long as the total size does not exceed the device limit. It is often more common to have multiple sets of skeletons on a single texture, for example for [flat shadows for skinned models](./skeletal-animation.md#about-dynamic-instancing).
+
+As more instances continue being adding to the scene, notice the number of drawcalls does not change, only the number of instances increases:
+
+
diff --git a/versions/4.0/en/animation/joint-texture-layout/enabling_instancing.png b/versions/4.0/en/animation/joint-texture-layout/enabling_instancing.png
new file mode 100644
index 0000000000..572a50a021
Binary files /dev/null and b/versions/4.0/en/animation/joint-texture-layout/enabling_instancing.png differ
diff --git a/versions/4.0/en/animation/joint-texture-layout/instancing_baseline.gif b/versions/4.0/en/animation/joint-texture-layout/instancing_baseline.gif
new file mode 100644
index 0000000000..8ccfa39a27
Binary files /dev/null and b/versions/4.0/en/animation/joint-texture-layout/instancing_baseline.gif differ
diff --git a/versions/4.0/en/animation/joint-texture-layout/instancing_bulk.gif b/versions/4.0/en/animation/joint-texture-layout/instancing_bulk.gif
new file mode 100644
index 0000000000..9913a49ff6
Binary files /dev/null and b/versions/4.0/en/animation/joint-texture-layout/instancing_bulk.gif differ
diff --git a/versions/4.0/en/animation/joint-texture-layout/instancing_normal.gif b/versions/4.0/en/animation/joint-texture-layout/instancing_normal.gif
new file mode 100644
index 0000000000..be18cef6f3
Binary files /dev/null and b/versions/4.0/en/animation/joint-texture-layout/instancing_normal.gif differ
diff --git a/versions/4.0/en/animation/joint-texture-layout/instancing_wrong.gif b/versions/4.0/en/animation/joint-texture-layout/instancing_wrong.gif
new file mode 100644
index 0000000000..bee0f02ba6
Binary files /dev/null and b/versions/4.0/en/animation/joint-texture-layout/instancing_wrong.gif differ
diff --git a/versions/4.0/en/animation/joint-texture-layout/joint-texture-layout-panel.png b/versions/4.0/en/animation/joint-texture-layout/joint-texture-layout-panel.png
new file mode 100644
index 0000000000..9ef1a7bd3f
Binary files /dev/null and b/versions/4.0/en/animation/joint-texture-layout/joint-texture-layout-panel.png differ
diff --git a/versions/4.0/en/animation/joint-texture-layout/joint_texture_layout_correct.png b/versions/4.0/en/animation/joint-texture-layout/joint_texture_layout_correct.png
new file mode 100644
index 0000000000..12abeb7c26
Binary files /dev/null and b/versions/4.0/en/animation/joint-texture-layout/joint_texture_layout_correct.png differ
diff --git a/versions/4.0/en/animation/joint-texture-layout/joint_texture_layout_new.png b/versions/4.0/en/animation/joint-texture-layout/joint_texture_layout_new.png
new file mode 100644
index 0000000000..41af682980
Binary files /dev/null and b/versions/4.0/en/animation/joint-texture-layout/joint_texture_layout_new.png differ
diff --git a/versions/4.0/en/animation/joint-texture-layout/joint_texture_layout_wrong.png b/versions/4.0/en/animation/joint-texture-layout/joint_texture_layout_wrong.png
new file mode 100644
index 0000000000..50648f4818
Binary files /dev/null and b/versions/4.0/en/animation/joint-texture-layout/joint_texture_layout_wrong.png differ
diff --git a/versions/4.0/en/animation/joint-texture-layout/use-baked-animation.png b/versions/4.0/en/animation/joint-texture-layout/use-baked-animation.png
new file mode 100644
index 0000000000..430acb7490
Binary files /dev/null and b/versions/4.0/en/animation/joint-texture-layout/use-baked-animation.png differ
diff --git a/versions/4.0/en/animation/marionette/additive-animation/figures/cover.png b/versions/4.0/en/animation/marionette/additive-animation/figures/cover.png
new file mode 100644
index 0000000000..d7b539b8cd
Binary files /dev/null and b/versions/4.0/en/animation/marionette/additive-animation/figures/cover.png differ
diff --git a/versions/4.0/en/animation/marionette/additive-animation/figures/crouch+leaning-pose.png b/versions/4.0/en/animation/marionette/additive-animation/figures/crouch+leaning-pose.png
new file mode 100644
index 0000000000..1dc0cb55f6
Binary files /dev/null and b/versions/4.0/en/animation/marionette/additive-animation/figures/crouch+leaning-pose.png differ
diff --git a/versions/4.0/en/animation/marionette/additive-animation/figures/crouch-pose.png b/versions/4.0/en/animation/marionette/additive-animation/figures/crouch-pose.png
new file mode 100644
index 0000000000..79f6775083
Binary files /dev/null and b/versions/4.0/en/animation/marionette/additive-animation/figures/crouch-pose.png differ
diff --git a/versions/4.0/en/animation/marionette/additive-animation/figures/import-setting-import-as-additive.png b/versions/4.0/en/animation/marionette/additive-animation/figures/import-setting-import-as-additive.png
new file mode 100644
index 0000000000..cf6ee09495
Binary files /dev/null and b/versions/4.0/en/animation/marionette/additive-animation/figures/import-setting-import-as-additive.png differ
diff --git a/versions/4.0/en/animation/marionette/additive-animation/figures/layer-additive.png b/versions/4.0/en/animation/marionette/additive-animation/figures/layer-additive.png
new file mode 100644
index 0000000000..cd141e20b9
Binary files /dev/null and b/versions/4.0/en/animation/marionette/additive-animation/figures/layer-additive.png differ
diff --git a/versions/4.0/en/animation/marionette/additive-animation/figures/leaning-pose.png b/versions/4.0/en/animation/marionette/additive-animation/figures/leaning-pose.png
new file mode 100644
index 0000000000..de5ab96e7e
Binary files /dev/null and b/versions/4.0/en/animation/marionette/additive-animation/figures/leaning-pose.png differ
diff --git a/versions/4.0/en/animation/marionette/additive-animation/figures/standing-pose.png b/versions/4.0/en/animation/marionette/additive-animation/figures/standing-pose.png
new file mode 100644
index 0000000000..8f4dafe4b4
Binary files /dev/null and b/versions/4.0/en/animation/marionette/additive-animation/figures/standing-pose.png differ
diff --git a/versions/4.0/en/animation/marionette/additive-animation/index.md b/versions/4.0/en/animation/marionette/additive-animation/index.md
new file mode 100644
index 0000000000..b4f2c5f051
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/additive-animation/index.md
@@ -0,0 +1,62 @@
+# Additive Animation
+
+Additive animation is a way to reuse animation effects.
+
+Imagine your character has two basic poses: standing and crouching:
+
+
+
+
+
+In standing, you make a pose for the character where the upper body is tilted at an angle to the right:
+
+
+
+If you want the character to have a similar tilted stance in the crouching state, one way to do it would of course be to make another separate stance for the crouching state, but that would inevitably be a repetitive endeavor.
+
+Since the "change" from standing to standing tilt and from crouching to crouching tilt is similar, it is possible to "subtract" the standing stance from the tilted stance to get a difference stance. By superimposing such a differential stance on the crouching stance, one obtains a crouching tilted stance:
+
+
+
+The schematic is shown below:
+
+
+
+A tilted pose "minus" a standing pose is called an **Additive Pose**, and the animation effect created by applying it to a crouching pose is called an **Additive Animation**.
+
+Formally, an additive animation is the difference of an animation relative to a reference pose that can be superimposed on other animations. The underlying logic for using additive animation is that you can add the same type of changes to different animations, such as leaning forward, backward, left, or right when a character is moving differently. If you use additive animation, you can add the same effect to walking, running, jumping, standing, etc., instead of having to create a set of similar animations for each state, which reduces the amount of animation assets needed for each state.
+
+## Generating Additive Animations
+
+Currently, additive animations can only be generated from animation clips.
+
+By checking the "Import as Additive" box in the Animation Import Configuration panel, the selected animation clip will generate an additive animation when it is used in an animation drawing:
+
+
+
+> Note that an animation is either imported as an additive animation or as a non-additive animation.
+> If you want an animation to be used as both an additive and non-additive animation, you can copy this animation in the import panel and configure it separately.
+
+## Apply Additive animation
+
+The animation map applies additive animation in two ways, namely:
+
+- Configure the level as an additive level.
+
+- Use [Additive blend node](../procedural-animation/pose-graph/pose-nodes/blend-poses.md#Additive-blending) in the graph map.
+
+> Note that the animation used in the additive hierarchy must produce additive poses.
+> For example, if a additive layer ends up outputting non-additive poses, this will result in anomalous animations - often the model will be found to be "bigger".
+> Conversely, if a non-additive layer ends up with a additive animation, this will also result in an anomalous animation - the model will often be found to have "disappeared" or become smaller.
+
+## Additive Layers
+
+In the Animation Graph Inspector panel, you can set the selected layer to be **Additive**:
+
+
+
+When checked, when the animation effect (graph) generated by this layer will be blended to the preceeding layer as an additive.
+
+## Pose Graph: additive blending nodes
+
+See: [additive blend node](../procedural-animation/pose-graph/pose-nodes/blend-poses.md#additive-blending).
diff --git a/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration.blend b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration.blend
new file mode 100644
index 0000000000..485fd67c49
Binary files /dev/null and b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration.blend differ
diff --git a/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/.gitignore b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/.gitignore
new file mode 100644
index 0000000000..576a8e3741
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/.gitignore
@@ -0,0 +1,26 @@
+
+#///////////////////////////
+# Cocos Creator 3D Project
+#///////////////////////////
+
+/library/
+/temp/
+/local/
+/build/
+/profiles/
+/native/engine/android/**/*/assets
+
+#//////////////////////////
+# NPM
+#//////////////////////////
+node_modules/
+
+#//////////////////////////
+# VSCode
+#//////////////////////////
+.vscode/
+
+#//////////////////////////
+# WebStorm
+#//////////////////////////
+.idea/
diff --git a/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration.meta b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration.meta
new file mode 100644
index 0000000000..e0e66f3f8f
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration.meta
@@ -0,0 +1,9 @@
+{
+ "ver": "1.2.0",
+ "importer": "directory",
+ "imported": true,
+ "uuid": "29781f57-d558-4cd4-b7ae-6d6a37d4ae71",
+ "files": [],
+ "subMetas": {},
+ "userData": {}
+}
diff --git a/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.animgraph b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.animgraph
new file mode 100644
index 0000000000..5897720292
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.animgraph
@@ -0,0 +1,557 @@
+[
+ {
+ "__type__": "cc.animation.AnimationGraph",
+ "_name": "",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "_native": "",
+ "_layers": [
+ {
+ "__id__": 1
+ },
+ {
+ "__id__": 34
+ }
+ ],
+ "_variables": {
+ "BaseLayerPose": {
+ "__id__": 44
+ }
+ }
+ },
+ {
+ "__type__": "cc.animation.Layer",
+ "_stateMachine": {
+ "__id__": 2
+ },
+ "name": "Base",
+ "weight": 1,
+ "mask": null,
+ "additive": false,
+ "_stashes": {}
+ },
+ {
+ "__type__": "cc.animation.StateMachine",
+ "__editorExtras__": {
+ "name": "",
+ "id": "16866441677320.5891144306941865",
+ "clone": null,
+ "viewport": {
+ "scale": 1,
+ "top": 0,
+ "left": -1
+ }
+ },
+ "_states": [
+ {
+ "__id__": 3
+ },
+ {
+ "__id__": 4
+ },
+ {
+ "__id__": 5
+ },
+ {
+ "__id__": 6
+ },
+ {
+ "__id__": 10
+ },
+ {
+ "__id__": 14
+ }
+ ],
+ "_transitions": [
+ {
+ "__id__": 18
+ },
+ {
+ "__id__": 19
+ },
+ {
+ "__id__": 24
+ },
+ {
+ "__id__": 29
+ }
+ ],
+ "_entryState": {
+ "__id__": 3
+ },
+ "_exitState": {
+ "__id__": 4
+ },
+ "_anyState": {
+ "__id__": 5
+ }
+ },
+ {
+ "__type__": "cc.animation.State",
+ "__editorExtras__": {
+ "name": "",
+ "id": "16866441677320.3764511364334071",
+ "clone": null,
+ "centerX": -265,
+ "centerY": 3
+ },
+ "name": "Entry"
+ },
+ {
+ "__type__": "cc.animation.State",
+ "__editorExtras__": {
+ "name": "",
+ "id": "16866441677320.3923465698017483",
+ "clone": null,
+ "centerX": 125,
+ "centerY": 0
+ },
+ "name": "Exit"
+ },
+ {
+ "__type__": "cc.animation.State",
+ "__editorExtras__": {
+ "name": "",
+ "id": "16866441677320.3550700390662027",
+ "clone": null,
+ "centerX": 125,
+ "centerY": 0
+ },
+ "name": "Any"
+ },
+ {
+ "__type__": "cc.animation.Motion",
+ "__editorExtras__": {
+ "name": "",
+ "id": "16866441797990.8001792367096607",
+ "clone": null,
+ "centerX": -122,
+ "centerY": 23
+ },
+ "name": "Crouch",
+ "_components": [],
+ "motion": {
+ "__id__": 7
+ },
+ "speed": 1,
+ "speedMultiplier": "",
+ "speedMultiplierEnabled": false,
+ "transitionInEventBinding": {
+ "__id__": 8
+ },
+ "transitionOutEventBinding": {
+ "__id__": 9
+ }
+ },
+ {
+ "__type__": "cc.animation.ClipMotion",
+ "__editorExtras__": {
+ "name": "",
+ "id": "16866441798030.8594645607386218",
+ "clone": null
+ },
+ "clip": {
+ "__uuid__": "3705c9df-8a1c-4d36-92d3-512664e51cfe@2ff01",
+ "__expectedType__": "cc.AnimationClip"
+ }
+ },
+ {
+ "__type__": "cc.animation.AnimationGraphEventBinding",
+ "methodName": ""
+ },
+ {
+ "__type__": "cc.animation.AnimationGraphEventBinding",
+ "methodName": ""
+ },
+ {
+ "__type__": "cc.animation.Motion",
+ "__editorExtras__": {
+ "name": "",
+ "id": "16866458424730.7772643494706266",
+ "clone": null,
+ "centerX": -128,
+ "centerY": -29
+ },
+ "name": "Standing",
+ "_components": [],
+ "motion": {
+ "__id__": 11
+ },
+ "speed": 1,
+ "speedMultiplier": "",
+ "speedMultiplierEnabled": false,
+ "transitionInEventBinding": {
+ "__id__": 12
+ },
+ "transitionOutEventBinding": {
+ "__id__": 13
+ }
+ },
+ {
+ "__type__": "cc.animation.ClipMotion",
+ "__editorExtras__": {
+ "name": "",
+ "id": "16866458424760.04644098735663049",
+ "clone": null
+ },
+ "clip": {
+ "__uuid__": "3705c9df-8a1c-4d36-92d3-512664e51cfe@e7f91",
+ "__expectedType__": "cc.AnimationClip"
+ }
+ },
+ {
+ "__type__": "cc.animation.AnimationGraphEventBinding",
+ "methodName": ""
+ },
+ {
+ "__type__": "cc.animation.AnimationGraphEventBinding",
+ "methodName": ""
+ },
+ {
+ "__type__": "cc.animation.Motion",
+ "__editorExtras__": {
+ "name": "",
+ "id": "16866487662470.8543040974437142",
+ "clone": null,
+ "centerX": -117,
+ "centerY": 87
+ },
+ "name": "Leaning_Original",
+ "_components": [],
+ "motion": {
+ "__id__": 15
+ },
+ "speed": 1,
+ "speedMultiplier": "",
+ "speedMultiplierEnabled": false,
+ "transitionInEventBinding": {
+ "__id__": 16
+ },
+ "transitionOutEventBinding": {
+ "__id__": 17
+ }
+ },
+ {
+ "__type__": "cc.animation.ClipMotion",
+ "__editorExtras__": {
+ "name": "",
+ "id": "16866487662500.9587811069492036",
+ "clone": null
+ },
+ "clip": {
+ "__uuid__": "3705c9df-8a1c-4d36-92d3-512664e51cfe@d03ee",
+ "__expectedType__": "cc.AnimationClip"
+ }
+ },
+ {
+ "__type__": "cc.animation.AnimationGraphEventBinding",
+ "methodName": ""
+ },
+ {
+ "__type__": "cc.animation.AnimationGraphEventBinding",
+ "methodName": ""
+ },
+ {
+ "__type__": "cc.animation.Transition",
+ "__editorExtras__": null,
+ "from": {
+ "__id__": 3
+ },
+ "to": {
+ "__id__": 10
+ },
+ "conditions": []
+ },
+ {
+ "__type__": "cc.animation.AnimationTransition",
+ "__editorExtras__": null,
+ "from": {
+ "__id__": 5
+ },
+ "to": {
+ "__id__": 10
+ },
+ "conditions": [
+ {
+ "__id__": 20
+ }
+ ],
+ "destinationStart": 0,
+ "relativeDestinationStart": false,
+ "startEventBinding": {
+ "__id__": 22
+ },
+ "endEventBinding": {
+ "__id__": 23
+ },
+ "duration": 0.3,
+ "relativeDuration": false,
+ "exitConditionEnabled": false,
+ "_exitCondition": 1
+ },
+ {
+ "__type__": "cc.animation.BinaryCondition",
+ "operator": 0,
+ "lhs": 0,
+ "lhsBinding": {
+ "__id__": 21
+ },
+ "rhs": 0
+ },
+ {
+ "__type__": "cc.animation.TCVariableBinding",
+ "type": 3,
+ "variableName": "BaseLayerPose"
+ },
+ {
+ "__type__": "cc.animation.AnimationGraphEventBinding",
+ "methodName": ""
+ },
+ {
+ "__type__": "cc.animation.AnimationGraphEventBinding",
+ "methodName": ""
+ },
+ {
+ "__type__": "cc.animation.AnimationTransition",
+ "__editorExtras__": null,
+ "from": {
+ "__id__": 5
+ },
+ "to": {
+ "__id__": 6
+ },
+ "conditions": [
+ {
+ "__id__": 25
+ }
+ ],
+ "destinationStart": 0,
+ "relativeDestinationStart": false,
+ "startEventBinding": {
+ "__id__": 27
+ },
+ "endEventBinding": {
+ "__id__": 28
+ },
+ "duration": 0.3,
+ "relativeDuration": false,
+ "exitConditionEnabled": false,
+ "_exitCondition": 1
+ },
+ {
+ "__type__": "cc.animation.BinaryCondition",
+ "operator": 0,
+ "lhs": 0,
+ "lhsBinding": {
+ "__id__": 26
+ },
+ "rhs": 1
+ },
+ {
+ "__type__": "cc.animation.TCVariableBinding",
+ "type": 3,
+ "variableName": "BaseLayerPose"
+ },
+ {
+ "__type__": "cc.animation.AnimationGraphEventBinding",
+ "methodName": ""
+ },
+ {
+ "__type__": "cc.animation.AnimationGraphEventBinding",
+ "methodName": ""
+ },
+ {
+ "__type__": "cc.animation.AnimationTransition",
+ "__editorExtras__": null,
+ "from": {
+ "__id__": 5
+ },
+ "to": {
+ "__id__": 14
+ },
+ "conditions": [
+ {
+ "__id__": 30
+ }
+ ],
+ "destinationStart": 0,
+ "relativeDestinationStart": false,
+ "startEventBinding": {
+ "__id__": 32
+ },
+ "endEventBinding": {
+ "__id__": 33
+ },
+ "duration": 0.3,
+ "relativeDuration": false,
+ "exitConditionEnabled": false,
+ "_exitCondition": 1
+ },
+ {
+ "__type__": "cc.animation.BinaryCondition",
+ "operator": 0,
+ "lhs": 0,
+ "lhsBinding": {
+ "__id__": 31
+ },
+ "rhs": 2
+ },
+ {
+ "__type__": "cc.animation.TCVariableBinding",
+ "type": 3,
+ "variableName": "BaseLayerPose"
+ },
+ {
+ "__type__": "cc.animation.AnimationGraphEventBinding",
+ "methodName": ""
+ },
+ {
+ "__type__": "cc.animation.AnimationGraphEventBinding",
+ "methodName": ""
+ },
+ {
+ "__type__": "cc.animation.Layer",
+ "_stateMachine": {
+ "__id__": 35
+ },
+ "name": "Leaning",
+ "weight": 1,
+ "mask": null,
+ "additive": true,
+ "_stashes": {}
+ },
+ {
+ "__type__": "cc.animation.StateMachine",
+ "__editorExtras__": {
+ "name": "",
+ "id": "16866441867500.6467469582792678",
+ "clone": null,
+ "viewport": {
+ "scale": 1,
+ "top": 0,
+ "left": 0
+ }
+ },
+ "_states": [
+ {
+ "__id__": 36
+ },
+ {
+ "__id__": 37
+ },
+ {
+ "__id__": 38
+ },
+ {
+ "__id__": 39
+ }
+ ],
+ "_transitions": [
+ {
+ "__id__": 43
+ }
+ ],
+ "_entryState": {
+ "__id__": 36
+ },
+ "_exitState": {
+ "__id__": 37
+ },
+ "_anyState": {
+ "__id__": 38
+ }
+ },
+ {
+ "__type__": "cc.animation.State",
+ "__editorExtras__": {
+ "name": "",
+ "id": "16866441867500.2990931519407911",
+ "clone": null,
+ "centerX": -125,
+ "centerY": 0
+ },
+ "name": "Entry"
+ },
+ {
+ "__type__": "cc.animation.State",
+ "__editorExtras__": {
+ "name": "",
+ "id": "16866441867500.16966542714941157",
+ "clone": null,
+ "centerX": 125,
+ "centerY": 0
+ },
+ "name": "Exit"
+ },
+ {
+ "__type__": "cc.animation.State",
+ "__editorExtras__": {
+ "name": "",
+ "id": "16866441867500.650266379833792",
+ "clone": null,
+ "centerX": 125,
+ "centerY": 0
+ },
+ "name": "Any"
+ },
+ {
+ "__type__": "cc.animation.Motion",
+ "__editorExtras__": {
+ "name": "",
+ "id": "16866449866630.2924323274845875",
+ "clone": null,
+ "centerX": -1,
+ "centerY": -4
+ },
+ "name": "Leaning",
+ "_components": [],
+ "motion": {
+ "__id__": 40
+ },
+ "speed": 1,
+ "speedMultiplier": "",
+ "speedMultiplierEnabled": false,
+ "transitionInEventBinding": {
+ "__id__": 41
+ },
+ "transitionOutEventBinding": {
+ "__id__": 42
+ }
+ },
+ {
+ "__type__": "cc.animation.ClipMotion",
+ "__editorExtras__": {
+ "name": "",
+ "id": "16866449866670.9509605487815147",
+ "clone": null
+ },
+ "clip": {
+ "__uuid__": "3705c9df-8a1c-4d36-92d3-512664e51cfe@94e83",
+ "__expectedType__": "cc.AnimationClip"
+ }
+ },
+ {
+ "__type__": "cc.animation.AnimationGraphEventBinding",
+ "methodName": ""
+ },
+ {
+ "__type__": "cc.animation.AnimationGraphEventBinding",
+ "methodName": ""
+ },
+ {
+ "__type__": "cc.animation.Transition",
+ "__editorExtras__": null,
+ "from": {
+ "__id__": 36
+ },
+ "to": {
+ "__id__": 39
+ },
+ "conditions": []
+ },
+ {
+ "__type__": "cc.animation.PlainVariable",
+ "_type": 3,
+ "_value": 0
+ }
+]
\ No newline at end of file
diff --git a/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.animgraph.meta b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.animgraph.meta
new file mode 100644
index 0000000000..d25c93115e
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.animgraph.meta
@@ -0,0 +1,11 @@
+{
+ "ver": "1.2.0",
+ "importer": "animation-graph",
+ "imported": true,
+ "uuid": "815e2fd3-f7fc-4013-b18c-b42e9128d911",
+ "files": [
+ ".json"
+ ],
+ "subMetas": {},
+ "userData": {}
+}
diff --git a/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.glb b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.glb
new file mode 100644
index 0000000000..39805bcb0d
Binary files /dev/null and b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.glb differ
diff --git a/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.glb.meta b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.glb.meta
new file mode 100644
index 0000000000..0b68f5da70
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.glb.meta
@@ -0,0 +1,400 @@
+{
+ "ver": "2.3.8",
+ "importer": "gltf",
+ "imported": true,
+ "uuid": "3705c9df-8a1c-4d36-92d3-512664e51cfe",
+ "files": [
+ "__original-animation-0.cconb",
+ "__original-animation-1.cconb",
+ "__original-animation-2.cconb",
+ "__original-animation-3.cconb"
+ ],
+ "subMetas": {
+ "60865": {
+ "importer": "gltf-skeleton",
+ "uuid": "3705c9df-8a1c-4d36-92d3-512664e51cfe@60865",
+ "displayName": "",
+ "id": "60865",
+ "name": "Rig.skeleton",
+ "userData": {
+ "gltfIndex": 0,
+ "jointsLength": 27
+ },
+ "ver": "1.0.1",
+ "imported": true,
+ "files": [
+ ".json"
+ ],
+ "subMetas": {}
+ },
+ "e2349": {
+ "importer": "gltf-mesh",
+ "uuid": "3705c9df-8a1c-4d36-92d3-512664e51cfe@e2349",
+ "displayName": "",
+ "id": "e2349",
+ "name": "Mesh.mesh",
+ "userData": {
+ "gltfIndex": 0,
+ "triangleCount": 324
+ },
+ "ver": "1.1.1",
+ "imported": true,
+ "files": [
+ ".bin",
+ ".json"
+ ],
+ "subMetas": {}
+ },
+ "2ff01": {
+ "importer": "gltf-animation",
+ "uuid": "3705c9df-8a1c-4d36-92d3-512664e51cfe@2ff01",
+ "displayName": "",
+ "id": "2ff01",
+ "name": "Crouch.animation",
+ "userData": {
+ "gltfIndex": 0,
+ "wrapMode": 2,
+ "sample": 30,
+ "span": {
+ "from": 0,
+ "to": 0.0416666679084301
+ },
+ "events": []
+ },
+ "ver": "1.0.16",
+ "imported": true,
+ "files": [
+ ".cconb"
+ ],
+ "subMetas": {}
+ },
+ "94e83": {
+ "importer": "gltf-animation",
+ "uuid": "3705c9df-8a1c-4d36-92d3-512664e51cfe@94e83",
+ "displayName": "",
+ "id": "94e83",
+ "name": "Leaning_Additive.animation",
+ "userData": {
+ "gltfIndex": 1,
+ "wrapMode": 2,
+ "sample": 30,
+ "span": {
+ "from": 0,
+ "to": 0.0416666679084301
+ },
+ "events": [],
+ "additive": {
+ "enabled": true,
+ "refClip": "3705c9df-8a1c-4d36-92d3-512664e51cfe@e7f91"
+ }
+ },
+ "ver": "1.0.16",
+ "imported": true,
+ "files": [
+ ".cconb"
+ ],
+ "subMetas": {}
+ },
+ "d03ee": {
+ "importer": "gltf-animation",
+ "uuid": "3705c9df-8a1c-4d36-92d3-512664e51cfe@d03ee",
+ "displayName": "",
+ "id": "d03ee",
+ "name": "Leaning_Original.animation",
+ "userData": {
+ "gltfIndex": 1,
+ "wrapMode": 2,
+ "speed": 1,
+ "sample": 30,
+ "span": {
+ "from": 0,
+ "to": 0.0416666679084301
+ },
+ "events": []
+ },
+ "ver": "1.0.16",
+ "imported": true,
+ "files": [
+ ".cconb"
+ ],
+ "subMetas": {}
+ },
+ "aff49": {
+ "importer": "gltf-animation",
+ "uuid": "3705c9df-8a1c-4d36-92d3-512664e51cfe@aff49",
+ "displayName": "",
+ "id": "aff49",
+ "name": "ReferencePose.animation",
+ "userData": {
+ "gltfIndex": 2,
+ "wrapMode": 2,
+ "sample": 30,
+ "span": {
+ "from": 0,
+ "to": 0.0416666679084301
+ },
+ "events": []
+ },
+ "ver": "1.0.16",
+ "imported": true,
+ "files": [
+ ".cconb"
+ ],
+ "subMetas": {}
+ },
+ "e7f91": {
+ "importer": "gltf-animation",
+ "uuid": "3705c9df-8a1c-4d36-92d3-512664e51cfe@e7f91",
+ "displayName": "",
+ "id": "e7f91",
+ "name": "Standing.animation",
+ "userData": {
+ "gltfIndex": 3,
+ "wrapMode": 2,
+ "sample": 30,
+ "span": {
+ "from": 0,
+ "to": 0.0416666679084301
+ },
+ "events": [],
+ "additive": {
+ "enabled": false
+ }
+ },
+ "ver": "1.0.16",
+ "imported": true,
+ "files": [
+ ".cconb"
+ ],
+ "subMetas": {}
+ },
+ "b4e6b": {
+ "importer": "gltf-material",
+ "uuid": "3705c9df-8a1c-4d36-92d3-512664e51cfe@b4e6b",
+ "displayName": "",
+ "id": "b4e6b",
+ "name": "Material.material",
+ "userData": {
+ "gltfIndex": 0
+ },
+ "ver": "1.0.14",
+ "imported": true,
+ "files": [
+ ".json"
+ ],
+ "subMetas": {}
+ },
+ "bbd5d": {
+ "importer": "gltf-scene",
+ "uuid": "3705c9df-8a1c-4d36-92d3-512664e51cfe@bbd5d",
+ "displayName": "",
+ "id": "bbd5d",
+ "name": "AdditivePoseDemonstration.prefab",
+ "userData": {
+ "gltfIndex": 0
+ },
+ "ver": "1.0.13",
+ "imported": true,
+ "files": [
+ ".json"
+ ],
+ "subMetas": {}
+ }
+ },
+ "userData": {
+ "imageMetas": [],
+ "animationImportSettings": [
+ {
+ "name": "Crouch",
+ "duration": 0.0416666679084301,
+ "fps": 30,
+ "splits": [
+ {
+ "name": "Crouch",
+ "from": 0,
+ "to": 0.0416666679084301,
+ "wrapMode": 2,
+ "previousId": "2ff01"
+ }
+ ]
+ },
+ {
+ "name": "Leaning",
+ "duration": 0.0416666679084301,
+ "fps": 30,
+ "splits": [
+ {
+ "name": "Leaning_Additive",
+ "from": 0,
+ "to": 0.0416666679084301,
+ "wrapMode": 2,
+ "previousId": "94e83",
+ "additive": {
+ "enabled": true,
+ "refClip": "3705c9df-8a1c-4d36-92d3-512664e51cfe@e7f91"
+ }
+ },
+ {
+ "name": "Leaning_Original",
+ "from": 0,
+ "to": 0.0416666679084301,
+ "wrapMode": 2,
+ "speed": 1,
+ "previousId": "d03ee"
+ }
+ ]
+ },
+ {
+ "name": "ReferencePose",
+ "duration": 0.0416666679084301,
+ "fps": 30,
+ "splits": [
+ {
+ "name": "ReferencePose",
+ "from": 0,
+ "to": 0.0416666679084301,
+ "wrapMode": 2,
+ "previousId": "aff49"
+ }
+ ]
+ },
+ {
+ "name": "Standing",
+ "duration": 0.0416666679084301,
+ "fps": 30,
+ "splits": [
+ {
+ "name": "Standing",
+ "from": 0,
+ "to": 0.0416666679084301,
+ "wrapMode": 2,
+ "previousId": "e7f91",
+ "additive": {
+ "enabled": false
+ }
+ }
+ ]
+ }
+ ],
+ "redirect": "3705c9df-8a1c-4d36-92d3-512664e51cfe@bbd5d",
+ "lods": {
+ "enable": false,
+ "hasBuiltinLOD": false,
+ "options": [
+ {
+ "screenRatio": 0.25,
+ "faceCount": 1
+ },
+ {
+ "screenRatio": 0.125,
+ "faceCount": 0.25
+ },
+ {
+ "screenRatio": 0.01,
+ "faceCount": 0.1
+ }
+ ]
+ },
+ "assetFinder": {
+ "meshes": [
+ "3705c9df-8a1c-4d36-92d3-512664e51cfe@e2349"
+ ],
+ "skeletons": [
+ "3705c9df-8a1c-4d36-92d3-512664e51cfe@60865"
+ ],
+ "textures": [],
+ "materials": [
+ "3705c9df-8a1c-4d36-92d3-512664e51cfe@b4e6b"
+ ],
+ "scenes": [
+ "3705c9df-8a1c-4d36-92d3-512664e51cfe@bbd5d"
+ ]
+ },
+ "materials": {
+ "3705c9df-8a1c-4d36-92d3-512664e51cfe@b4e6b": {
+ "__type__": "cc.Material",
+ "_name": "",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "_native": "",
+ "_effectAsset": {
+ "__uuid__": "c8f66d17-351a-48da-a12c-0212d28575c4",
+ "__expectedType__": "cc.EffectAsset"
+ },
+ "_techIdx": 0,
+ "_defines": [
+ {},
+ {},
+ {},
+ {},
+ {}
+ ],
+ "_states": [
+ {
+ "rasterizerState": {
+ "cullMode": 0
+ },
+ "depthStencilState": {},
+ "blendState": {
+ "targets": [
+ {}
+ ]
+ }
+ },
+ {
+ "rasterizerState": {},
+ "depthStencilState": {},
+ "blendState": {
+ "targets": [
+ {}
+ ]
+ }
+ },
+ {
+ "rasterizerState": {},
+ "depthStencilState": {},
+ "blendState": {
+ "targets": [
+ {}
+ ]
+ }
+ },
+ {
+ "rasterizerState": {},
+ "depthStencilState": {},
+ "blendState": {
+ "targets": [
+ {}
+ ]
+ }
+ },
+ {
+ "rasterizerState": {},
+ "depthStencilState": {},
+ "blendState": {
+ "targets": [
+ {}
+ ]
+ }
+ }
+ ],
+ "_props": [
+ {
+ "albedoScale": {
+ "__type__": "cc.Vec3",
+ "x": 0.2694019675254822,
+ "y": 0.2722896635532379,
+ "z": 0.8000000715255737
+ },
+ "roughness": 0,
+ "specularIntensity": 0.1
+ },
+ {},
+ {},
+ {},
+ {}
+ ]
+ }
+ }
+ }
+}
diff --git a/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.scene b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.scene
new file mode 100644
index 0000000000..58c63c17d4
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.scene
@@ -0,0 +1,1990 @@
+[
+ {
+ "__type__": "cc.SceneAsset",
+ "_name": "AdditivePoseDemonstration",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "_native": "",
+ "scene": {
+ "__id__": 1
+ }
+ },
+ {
+ "__type__": "cc.Scene",
+ "_name": "AdditivePoseDemonstration",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "_parent": null,
+ "_children": [
+ {
+ "__id__": 2
+ },
+ {
+ "__id__": 5
+ },
+ {
+ "__id__": 7
+ },
+ {
+ "__id__": 22
+ },
+ {
+ "__id__": 39
+ },
+ {
+ "__id__": 56
+ },
+ {
+ "__id__": 73
+ },
+ {
+ "__id__": 76
+ },
+ {
+ "__id__": 83
+ }
+ ],
+ "_active": true,
+ "_components": [],
+ "_prefab": {
+ "__id__": 90
+ },
+ "_lpos": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": 0,
+ "z": 0
+ },
+ "_lrot": {
+ "__type__": "cc.Quat",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "w": 1
+ },
+ "_lscale": {
+ "__type__": "cc.Vec3",
+ "x": 1,
+ "y": 1,
+ "z": 1
+ },
+ "_mobility": 0,
+ "_layer": 1073741824,
+ "_euler": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": 0,
+ "z": 0
+ },
+ "autoReleaseAssets": false,
+ "_globals": {
+ "__id__": 91
+ },
+ "_id": "71e36a35-a552-4298-90b5-3d1064fa30cb"
+ },
+ {
+ "__type__": "cc.Node",
+ "_name": "Main Light",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "_parent": {
+ "__id__": 1
+ },
+ "_children": [],
+ "_active": true,
+ "_components": [
+ {
+ "__id__": 3
+ }
+ ],
+ "_prefab": null,
+ "_lpos": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": 0,
+ "z": 0
+ },
+ "_lrot": {
+ "__type__": "cc.Quat",
+ "x": -0.06397656665577071,
+ "y": -0.44608233363525845,
+ "z": -0.8239028751062036,
+ "w": -0.3436591377065261
+ },
+ "_lscale": {
+ "__type__": "cc.Vec3",
+ "x": 1,
+ "y": 1,
+ "z": 1
+ },
+ "_mobility": 0,
+ "_layer": 1073741824,
+ "_euler": {
+ "__type__": "cc.Vec3",
+ "x": -117.894,
+ "y": -194.909,
+ "z": 38.562
+ },
+ "_id": "c0y6F5f+pAvI805TdmxIjx"
+ },
+ {
+ "__type__": "cc.DirectionalLight",
+ "_name": "",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "node": {
+ "__id__": 2
+ },
+ "_enabled": true,
+ "__prefab": null,
+ "_color": {
+ "__type__": "cc.Color",
+ "r": 255,
+ "g": 250,
+ "b": 240,
+ "a": 255
+ },
+ "_useColorTemperature": false,
+ "_colorTemperature": 6550,
+ "_staticSettings": {
+ "__id__": 4
+ },
+ "_visibility": -325058561,
+ "_illuminanceHDR": 65000,
+ "_illuminance": 65000,
+ "_illuminanceLDR": 1.6927083333333335,
+ "_shadowEnabled": false,
+ "_shadowPcf": 0,
+ "_shadowBias": 0.00001,
+ "_shadowNormalBias": 0,
+ "_shadowSaturation": 1,
+ "_shadowDistance": 50,
+ "_shadowInvisibleOcclusionRange": 200,
+ "_csmLevel": 4,
+ "_csmLayerLambda": 0.75,
+ "_csmOptimizationMode": 2,
+ "_csmAdvancedOptions": false,
+ "_csmLayersTransition": false,
+ "_csmTransitionRange": 0.05,
+ "_shadowFixedArea": false,
+ "_shadowNear": 0.1,
+ "_shadowFar": 10,
+ "_shadowOrthoSize": 5,
+ "_id": "597uMYCbhEtJQc0ffJlcgA"
+ },
+ {
+ "__type__": "cc.StaticLightSettings",
+ "_baked": false,
+ "_editorOnly": false,
+ "_castShadow": false
+ },
+ {
+ "__type__": "cc.Node",
+ "_name": "Main Camera",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "_parent": {
+ "__id__": 1
+ },
+ "_children": [],
+ "_active": true,
+ "_components": [
+ {
+ "__id__": 6
+ }
+ ],
+ "_prefab": null,
+ "_lpos": {
+ "__type__": "cc.Vec3",
+ "x": -0.6228552625332178,
+ "y": 1.2214186893935963,
+ "z": 4.468293757497586
+ },
+ "_lrot": {
+ "__type__": "cc.Quat",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "w": 1
+ },
+ "_lscale": {
+ "__type__": "cc.Vec3",
+ "x": 1,
+ "y": 1,
+ "z": 1
+ },
+ "_mobility": 0,
+ "_layer": 1073741824,
+ "_euler": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": 0,
+ "z": 0
+ },
+ "_id": "c9DMICJLFO5IeO07EPon7U"
+ },
+ {
+ "__type__": "cc.Camera",
+ "_name": "",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "node": {
+ "__id__": 5
+ },
+ "_enabled": true,
+ "__prefab": null,
+ "_projection": 0,
+ "_priority": 0,
+ "_fov": 45,
+ "_fovAxis": 0,
+ "_orthoHeight": 1.5,
+ "_near": 0.1,
+ "_far": 100,
+ "_color": {
+ "__type__": "cc.Color",
+ "r": 51,
+ "g": 51,
+ "b": 51,
+ "a": 255
+ },
+ "_depth": 1,
+ "_stencil": 0,
+ "_clearFlags": 14,
+ "_rect": {
+ "__type__": "cc.Rect",
+ "x": 0,
+ "y": 0,
+ "width": 1,
+ "height": 1
+ },
+ "_aperture": 19,
+ "_shutter": 7,
+ "_iso": 0,
+ "_screenScale": 1,
+ "_visibility": 1822425087,
+ "_targetTexture": null,
+ "_postProcess": null,
+ "_usePostProcess": false,
+ "_cameraType": -1,
+ "_trackingType": 0,
+ "_id": "7dWQTpwS5LrIHnc1zAPUtf"
+ },
+ {
+ "__type__": "cc.Node",
+ "_objFlags": 0,
+ "_parent": {
+ "__id__": 1
+ },
+ "_prefab": {
+ "__id__": 8
+ },
+ "__editorExtras__": {}
+ },
+ {
+ "__type__": "cc.PrefabInfo",
+ "root": {
+ "__id__": 7
+ },
+ "asset": {
+ "__uuid__": "3705c9df-8a1c-4d36-92d3-512664e51cfe@bbd5d",
+ "__expectedType__": "cc.Prefab"
+ },
+ "fileId": "6eteDuTGJdMpDat7uq2H51",
+ "instance": {
+ "__id__": 9
+ },
+ "targetOverrides": null,
+ "nestedPrefabInstanceRoots": null
+ },
+ {
+ "__type__": "cc.PrefabInstance",
+ "fileId": "a74QLAgbVA66mIBu/fvUTR",
+ "prefabRootNode": null,
+ "mountedChildren": [],
+ "mountedComponents": [
+ {
+ "__id__": 10
+ },
+ {
+ "__id__": 13
+ }
+ ],
+ "propertyOverrides": [
+ {
+ "__id__": 17
+ },
+ {
+ "__id__": 19
+ }
+ ],
+ "removedComponents": [
+ {
+ "__id__": 20
+ },
+ {
+ "__id__": 21
+ }
+ ]
+ },
+ {
+ "__type__": "cc.MountedComponentsInfo",
+ "targetInfo": {
+ "__id__": 11
+ },
+ "components": [
+ {
+ "__id__": 12
+ }
+ ]
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "71nT0fGWxfJ7Ln9zk1h3p9"
+ ]
+ },
+ {
+ "__type__": "cc.animation.AnimationController",
+ "_name": "",
+ "_objFlags": 0,
+ "__editorExtras__": {
+ "mountedRoot": {
+ "__id__": 7
+ }
+ },
+ "node": {
+ "__id__": 7
+ },
+ "_enabled": true,
+ "__prefab": null,
+ "_graph": {
+ "__uuid__": "815e2fd3-f7fc-4013-b18c-b42e9128d911",
+ "__expectedType__": "cc.animation.AnimationGraph"
+ },
+ "graph": {
+ "__uuid__": "815e2fd3-f7fc-4013-b18c-b42e9128d911",
+ "__expectedType__": "cc.animation.AnimationGraph"
+ },
+ "_id": "b6E+SRjatAP6rP7rSbIwm4"
+ },
+ {
+ "__type__": "cc.MountedComponentsInfo",
+ "targetInfo": {
+ "__id__": 14
+ },
+ "components": [
+ {
+ "__id__": 15
+ },
+ {
+ "__id__": 16
+ }
+ ]
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "6eteDuTGJdMpDat7uq2H51"
+ ]
+ },
+ {
+ "__type__": "cc.animation.AnimationController",
+ "_name": "",
+ "_objFlags": 0,
+ "__editorExtras__": {
+ "mountedRoot": {
+ "__id__": 7
+ }
+ },
+ "node": {
+ "__id__": 7
+ },
+ "_enabled": true,
+ "__prefab": null,
+ "_graph": {
+ "__uuid__": "815e2fd3-f7fc-4013-b18c-b42e9128d911",
+ "__expectedType__": "cc.animation.AnimationGraph"
+ },
+ "graph": {
+ "__uuid__": "815e2fd3-f7fc-4013-b18c-b42e9128d911",
+ "__expectedType__": "cc.animation.AnimationGraph"
+ },
+ "_id": "04yDjhtuFECLr+R5dbRpvX"
+ },
+ {
+ "__type__": "9177brmDQ1BxYgGRYI7jZZd",
+ "_name": "",
+ "_objFlags": 0,
+ "__editorExtras__": {
+ "mountedRoot": {
+ "__id__": 7
+ }
+ },
+ "node": {
+ "__id__": 7
+ },
+ "_enabled": true,
+ "__prefab": null,
+ "baseLayerPose": 2,
+ "additiveLayerWeight": 0,
+ "_id": "0dW2UVM+ZHDoaXsOVlxnmL"
+ },
+ {
+ "__type__": "CCPropertyOverrideInfo",
+ "targetInfo": {
+ "__id__": 18
+ },
+ "propertyPath": [
+ "_name"
+ ],
+ "value": "Leaning_Original"
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "6eteDuTGJdMpDat7uq2H51"
+ ]
+ },
+ {
+ "__type__": "CCPropertyOverrideInfo",
+ "targetInfo": {
+ "__id__": 18
+ },
+ "propertyPath": [
+ "_lpos"
+ ],
+ "value": {
+ "__type__": "cc.Vec3",
+ "x": -2.863,
+ "y": 0,
+ "z": 0
+ }
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "46p/wNB7td07WS89tf2KfI"
+ ]
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "b1BxQNz2Fd1qVeG4pkCjo+"
+ ]
+ },
+ {
+ "__type__": "cc.Node",
+ "_objFlags": 0,
+ "_parent": {
+ "__id__": 1
+ },
+ "_prefab": {
+ "__id__": 23
+ },
+ "__editorExtras__": {}
+ },
+ {
+ "__type__": "cc.PrefabInfo",
+ "root": {
+ "__id__": 22
+ },
+ "asset": {
+ "__uuid__": "3705c9df-8a1c-4d36-92d3-512664e51cfe@bbd5d",
+ "__expectedType__": "cc.Prefab"
+ },
+ "fileId": "6eteDuTGJdMpDat7uq2H51",
+ "instance": {
+ "__id__": 24
+ },
+ "targetOverrides": null,
+ "nestedPrefabInstanceRoots": null
+ },
+ {
+ "__type__": "cc.PrefabInstance",
+ "fileId": "1bq5EPIq5NvrvsCKGygUQs",
+ "prefabRootNode": null,
+ "mountedChildren": [],
+ "mountedComponents": [
+ {
+ "__id__": 25
+ },
+ {
+ "__id__": 28
+ }
+ ],
+ "propertyOverrides": [
+ {
+ "__id__": 32
+ },
+ {
+ "__id__": 34
+ },
+ {
+ "__id__": 35
+ },
+ {
+ "__id__": 36
+ }
+ ],
+ "removedComponents": [
+ {
+ "__id__": 37
+ },
+ {
+ "__id__": 38
+ }
+ ]
+ },
+ {
+ "__type__": "cc.MountedComponentsInfo",
+ "targetInfo": {
+ "__id__": 26
+ },
+ "components": [
+ {
+ "__id__": 27
+ }
+ ]
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "71nT0fGWxfJ7Ln9zk1h3p9"
+ ]
+ },
+ {
+ "__type__": "cc.animation.AnimationController",
+ "_name": "",
+ "_objFlags": 0,
+ "__editorExtras__": {
+ "mountedRoot": {
+ "__id__": 22
+ }
+ },
+ "node": {
+ "__id__": 22
+ },
+ "_enabled": true,
+ "__prefab": null,
+ "_graph": {
+ "__uuid__": "815e2fd3-f7fc-4013-b18c-b42e9128d911",
+ "__expectedType__": "cc.animation.AnimationGraph"
+ },
+ "graph": {
+ "__uuid__": "815e2fd3-f7fc-4013-b18c-b42e9128d911",
+ "__expectedType__": "cc.animation.AnimationGraph"
+ },
+ "_id": "2ewNSgCdBMfJdOFfHmji7x"
+ },
+ {
+ "__type__": "cc.MountedComponentsInfo",
+ "targetInfo": {
+ "__id__": 29
+ },
+ "components": [
+ {
+ "__id__": 30
+ },
+ {
+ "__id__": 31
+ }
+ ]
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "6eteDuTGJdMpDat7uq2H51"
+ ]
+ },
+ {
+ "__type__": "cc.animation.AnimationController",
+ "_name": "",
+ "_objFlags": 0,
+ "__editorExtras__": {
+ "mountedRoot": {
+ "__id__": 22
+ }
+ },
+ "node": {
+ "__id__": 22
+ },
+ "_enabled": true,
+ "__prefab": null,
+ "_graph": {
+ "__uuid__": "815e2fd3-f7fc-4013-b18c-b42e9128d911",
+ "__expectedType__": "cc.animation.AnimationGraph"
+ },
+ "graph": {
+ "__uuid__": "815e2fd3-f7fc-4013-b18c-b42e9128d911",
+ "__expectedType__": "cc.animation.AnimationGraph"
+ },
+ "_id": "69m0LjdqRFdLaM/zqAkw5I"
+ },
+ {
+ "__type__": "9177brmDQ1BxYgGRYI7jZZd",
+ "_name": "",
+ "_objFlags": 0,
+ "__editorExtras__": {
+ "mountedRoot": {
+ "__id__": 22
+ }
+ },
+ "node": {
+ "__id__": 22
+ },
+ "_enabled": true,
+ "__prefab": null,
+ "baseLayerPose": 0,
+ "additiveLayerWeight": 0,
+ "_id": "1bPjyjBAhGFI0thugs+fo9"
+ },
+ {
+ "__type__": "CCPropertyOverrideInfo",
+ "targetInfo": {
+ "__id__": 33
+ },
+ "propertyPath": [
+ "_name"
+ ],
+ "value": "Standing"
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "6eteDuTGJdMpDat7uq2H51"
+ ]
+ },
+ {
+ "__type__": "CCPropertyOverrideInfo",
+ "targetInfo": {
+ "__id__": 33
+ },
+ "propertyPath": [
+ "_lpos"
+ ],
+ "value": {
+ "__type__": "cc.Vec3",
+ "x": -1.411,
+ "y": 0,
+ "z": 0
+ }
+ },
+ {
+ "__type__": "CCPropertyOverrideInfo",
+ "targetInfo": {
+ "__id__": 33
+ },
+ "propertyPath": [
+ "_lrot"
+ ],
+ "value": {
+ "__type__": "cc.Quat",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "w": 1
+ }
+ },
+ {
+ "__type__": "CCPropertyOverrideInfo",
+ "targetInfo": {
+ "__id__": 33
+ },
+ "propertyPath": [
+ "_euler"
+ ],
+ "value": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": 0,
+ "z": 0
+ }
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "46p/wNB7td07WS89tf2KfI"
+ ]
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "b1BxQNz2Fd1qVeG4pkCjo+"
+ ]
+ },
+ {
+ "__type__": "cc.Node",
+ "_objFlags": 0,
+ "_parent": {
+ "__id__": 1
+ },
+ "_prefab": {
+ "__id__": 40
+ },
+ "__editorExtras__": {}
+ },
+ {
+ "__type__": "cc.PrefabInfo",
+ "root": {
+ "__id__": 39
+ },
+ "asset": {
+ "__uuid__": "3705c9df-8a1c-4d36-92d3-512664e51cfe@bbd5d",
+ "__expectedType__": "cc.Prefab"
+ },
+ "fileId": "6eteDuTGJdMpDat7uq2H51",
+ "instance": {
+ "__id__": 41
+ },
+ "targetOverrides": null,
+ "nestedPrefabInstanceRoots": null
+ },
+ {
+ "__type__": "cc.PrefabInstance",
+ "fileId": "d54z2Ijy5P9auHqubsgUaK",
+ "prefabRootNode": null,
+ "mountedChildren": [],
+ "mountedComponents": [
+ {
+ "__id__": 42
+ },
+ {
+ "__id__": 45
+ }
+ ],
+ "propertyOverrides": [
+ {
+ "__id__": 49
+ },
+ {
+ "__id__": 51
+ },
+ {
+ "__id__": 52
+ },
+ {
+ "__id__": 53
+ }
+ ],
+ "removedComponents": [
+ {
+ "__id__": 54
+ },
+ {
+ "__id__": 55
+ }
+ ]
+ },
+ {
+ "__type__": "cc.MountedComponentsInfo",
+ "targetInfo": {
+ "__id__": 43
+ },
+ "components": [
+ {
+ "__id__": 44
+ }
+ ]
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "71nT0fGWxfJ7Ln9zk1h3p9"
+ ]
+ },
+ {
+ "__type__": "cc.animation.AnimationController",
+ "_name": "",
+ "_objFlags": 0,
+ "__editorExtras__": {
+ "mountedRoot": {
+ "__id__": 39
+ }
+ },
+ "node": {
+ "__id__": 39
+ },
+ "_enabled": true,
+ "__prefab": null,
+ "_graph": {
+ "__uuid__": "815e2fd3-f7fc-4013-b18c-b42e9128d911",
+ "__expectedType__": "cc.animation.AnimationGraph"
+ },
+ "graph": {
+ "__uuid__": "815e2fd3-f7fc-4013-b18c-b42e9128d911",
+ "__expectedType__": "cc.animation.AnimationGraph"
+ },
+ "_id": "d5zFrWqnhAxakZStdvmRZA"
+ },
+ {
+ "__type__": "cc.MountedComponentsInfo",
+ "targetInfo": {
+ "__id__": 46
+ },
+ "components": [
+ {
+ "__id__": 47
+ },
+ {
+ "__id__": 48
+ }
+ ]
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "6eteDuTGJdMpDat7uq2H51"
+ ]
+ },
+ {
+ "__type__": "cc.animation.AnimationController",
+ "_name": "",
+ "_objFlags": 0,
+ "__editorExtras__": {
+ "mountedRoot": {
+ "__id__": 39
+ }
+ },
+ "node": {
+ "__id__": 39
+ },
+ "_enabled": true,
+ "__prefab": null,
+ "_graph": {
+ "__uuid__": "815e2fd3-f7fc-4013-b18c-b42e9128d911",
+ "__expectedType__": "cc.animation.AnimationGraph"
+ },
+ "graph": {
+ "__uuid__": "815e2fd3-f7fc-4013-b18c-b42e9128d911",
+ "__expectedType__": "cc.animation.AnimationGraph"
+ },
+ "_id": "81d14rOElFe7/iPZEHkQT4"
+ },
+ {
+ "__type__": "9177brmDQ1BxYgGRYI7jZZd",
+ "_name": "",
+ "_objFlags": 0,
+ "__editorExtras__": {
+ "mountedRoot": {
+ "__id__": 39
+ }
+ },
+ "node": {
+ "__id__": 39
+ },
+ "_enabled": true,
+ "__prefab": null,
+ "baseLayerPose": 1,
+ "additiveLayerWeight": 0,
+ "_id": "e2ulA7F8xLfZBW2GTmZecQ"
+ },
+ {
+ "__type__": "CCPropertyOverrideInfo",
+ "targetInfo": {
+ "__id__": 50
+ },
+ "propertyPath": [
+ "_name"
+ ],
+ "value": "Crouch"
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "6eteDuTGJdMpDat7uq2H51"
+ ]
+ },
+ {
+ "__type__": "CCPropertyOverrideInfo",
+ "targetInfo": {
+ "__id__": 50
+ },
+ "propertyPath": [
+ "_lpos"
+ ],
+ "value": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": 0,
+ "z": 0
+ }
+ },
+ {
+ "__type__": "CCPropertyOverrideInfo",
+ "targetInfo": {
+ "__id__": 50
+ },
+ "propertyPath": [
+ "_lrot"
+ ],
+ "value": {
+ "__type__": "cc.Quat",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "w": 1
+ }
+ },
+ {
+ "__type__": "CCPropertyOverrideInfo",
+ "targetInfo": {
+ "__id__": 50
+ },
+ "propertyPath": [
+ "_euler"
+ ],
+ "value": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": 0,
+ "z": 0
+ }
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "46p/wNB7td07WS89tf2KfI"
+ ]
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "b1BxQNz2Fd1qVeG4pkCjo+"
+ ]
+ },
+ {
+ "__type__": "cc.Node",
+ "_objFlags": 0,
+ "_parent": {
+ "__id__": 1
+ },
+ "_prefab": {
+ "__id__": 57
+ },
+ "__editorExtras__": {}
+ },
+ {
+ "__type__": "cc.PrefabInfo",
+ "root": {
+ "__id__": 56
+ },
+ "asset": {
+ "__uuid__": "3705c9df-8a1c-4d36-92d3-512664e51cfe@bbd5d",
+ "__expectedType__": "cc.Prefab"
+ },
+ "fileId": "6eteDuTGJdMpDat7uq2H51",
+ "instance": {
+ "__id__": 58
+ },
+ "targetOverrides": null,
+ "nestedPrefabInstanceRoots": null
+ },
+ {
+ "__type__": "cc.PrefabInstance",
+ "fileId": "7daGB70FlJ24/isQrmW3WQ",
+ "prefabRootNode": null,
+ "mountedChildren": [],
+ "mountedComponents": [
+ {
+ "__id__": 59
+ },
+ {
+ "__id__": 62
+ }
+ ],
+ "propertyOverrides": [
+ {
+ "__id__": 66
+ },
+ {
+ "__id__": 68
+ },
+ {
+ "__id__": 69
+ },
+ {
+ "__id__": 70
+ }
+ ],
+ "removedComponents": [
+ {
+ "__id__": 71
+ },
+ {
+ "__id__": 72
+ }
+ ]
+ },
+ {
+ "__type__": "cc.MountedComponentsInfo",
+ "targetInfo": {
+ "__id__": 60
+ },
+ "components": [
+ {
+ "__id__": 61
+ }
+ ]
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "71nT0fGWxfJ7Ln9zk1h3p9"
+ ]
+ },
+ {
+ "__type__": "cc.animation.AnimationController",
+ "_name": "",
+ "_objFlags": 0,
+ "__editorExtras__": {
+ "mountedRoot": {
+ "__id__": 56
+ }
+ },
+ "node": {
+ "__id__": 56
+ },
+ "_enabled": true,
+ "__prefab": null,
+ "_graph": {
+ "__uuid__": "815e2fd3-f7fc-4013-b18c-b42e9128d911",
+ "__expectedType__": "cc.animation.AnimationGraph"
+ },
+ "graph": {
+ "__uuid__": "815e2fd3-f7fc-4013-b18c-b42e9128d911",
+ "__expectedType__": "cc.animation.AnimationGraph"
+ },
+ "_id": "d5R8c8TaVHlbC4CkeP6OZ0"
+ },
+ {
+ "__type__": "cc.MountedComponentsInfo",
+ "targetInfo": {
+ "__id__": 63
+ },
+ "components": [
+ {
+ "__id__": 64
+ },
+ {
+ "__id__": 65
+ }
+ ]
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "6eteDuTGJdMpDat7uq2H51"
+ ]
+ },
+ {
+ "__type__": "cc.animation.AnimationController",
+ "_name": "",
+ "_objFlags": 0,
+ "__editorExtras__": {
+ "mountedRoot": {
+ "__id__": 56
+ }
+ },
+ "node": {
+ "__id__": 56
+ },
+ "_enabled": true,
+ "__prefab": null,
+ "_graph": {
+ "__uuid__": "815e2fd3-f7fc-4013-b18c-b42e9128d911",
+ "__expectedType__": "cc.animation.AnimationGraph"
+ },
+ "graph": {
+ "__uuid__": "815e2fd3-f7fc-4013-b18c-b42e9128d911",
+ "__expectedType__": "cc.animation.AnimationGraph"
+ },
+ "_id": "4apPF/cRRBa6W/mcXucxjA"
+ },
+ {
+ "__type__": "9177brmDQ1BxYgGRYI7jZZd",
+ "_name": "",
+ "_objFlags": 0,
+ "__editorExtras__": {
+ "mountedRoot": {
+ "__id__": 56
+ }
+ },
+ "node": {
+ "__id__": 56
+ },
+ "_enabled": true,
+ "__prefab": null,
+ "baseLayerPose": 1,
+ "additiveLayerWeight": 1,
+ "_id": "46f+xniiRKIZ5Rq59QZthK"
+ },
+ {
+ "__type__": "CCPropertyOverrideInfo",
+ "targetInfo": {
+ "__id__": 67
+ },
+ "propertyPath": [
+ "_name"
+ ],
+ "value": "Result"
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "6eteDuTGJdMpDat7uq2H51"
+ ]
+ },
+ {
+ "__type__": "CCPropertyOverrideInfo",
+ "targetInfo": {
+ "__id__": 67
+ },
+ "propertyPath": [
+ "_lpos"
+ ],
+ "value": {
+ "__type__": "cc.Vec3",
+ "x": 1.553,
+ "y": 0,
+ "z": 0
+ }
+ },
+ {
+ "__type__": "CCPropertyOverrideInfo",
+ "targetInfo": {
+ "__id__": 67
+ },
+ "propertyPath": [
+ "_lrot"
+ ],
+ "value": {
+ "__type__": "cc.Quat",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "w": 1
+ }
+ },
+ {
+ "__type__": "CCPropertyOverrideInfo",
+ "targetInfo": {
+ "__id__": 67
+ },
+ "propertyPath": [
+ "_euler"
+ ],
+ "value": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": 0,
+ "z": 0
+ }
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "46p/wNB7td07WS89tf2KfI"
+ ]
+ },
+ {
+ "__type__": "cc.TargetInfo",
+ "localID": [
+ "b1BxQNz2Fd1qVeG4pkCjo+"
+ ]
+ },
+ {
+ "__type__": "cc.Node",
+ "_name": "Minus",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "_parent": {
+ "__id__": 1
+ },
+ "_children": [],
+ "_active": true,
+ "_components": [
+ {
+ "__id__": 74
+ }
+ ],
+ "_prefab": null,
+ "_lpos": {
+ "__type__": "cc.Vec3",
+ "x": -2.11,
+ "y": 0.883,
+ "z": 0
+ },
+ "_lrot": {
+ "__type__": "cc.Quat",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "w": 1
+ },
+ "_lscale": {
+ "__type__": "cc.Vec3",
+ "x": 0.476,
+ "y": 0.137,
+ "z": 0.249
+ },
+ "_mobility": 0,
+ "_layer": 1073741824,
+ "_euler": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": 0,
+ "z": 0
+ },
+ "_id": "017nKpSLdEP6NxjvHU06X4"
+ },
+ {
+ "__type__": "cc.MeshRenderer",
+ "_name": "Cube",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "node": {
+ "__id__": 73
+ },
+ "_enabled": true,
+ "__prefab": null,
+ "_materials": [
+ {
+ "__uuid__": "620b6bf3-0369-4560-837f-2a2c00b73c26",
+ "__expectedType__": "cc.Material"
+ }
+ ],
+ "_visFlags": 0,
+ "bakeSettings": {
+ "__id__": 75
+ },
+ "_mesh": {
+ "__uuid__": "1263d74c-8167-4928-91a6-4e2672411f47@a804a",
+ "__expectedType__": "cc.Mesh"
+ },
+ "_shadowCastingMode": 0,
+ "_shadowReceivingMode": 1,
+ "_shadowBias": 0,
+ "_shadowNormalBias": 0,
+ "_reflectionProbeId": -1,
+ "_reflectionProbeBlendId": -1,
+ "_reflectionProbeBlendWeight": 0,
+ "_enabledGlobalStandardSkinObject": false,
+ "_enableMorph": true,
+ "_id": "71XyR0nzdCRKtTw8wMmWIP"
+ },
+ {
+ "__type__": "cc.ModelBakeSettings",
+ "texture": null,
+ "uvParam": {
+ "__type__": "cc.Vec4",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "w": 0
+ },
+ "_bakeable": false,
+ "_castShadow": false,
+ "_receiveShadow": false,
+ "_recieveShadow": false,
+ "_lightmapSize": 64,
+ "_useLightProbe": false,
+ "_bakeToLightProbe": true,
+ "_reflectionProbeType": 0,
+ "_bakeToReflectionProbe": true
+ },
+ {
+ "__type__": "cc.Node",
+ "_name": "Add",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "_parent": {
+ "__id__": 1
+ },
+ "_children": [
+ {
+ "__id__": 77
+ },
+ {
+ "__id__": 80
+ }
+ ],
+ "_active": true,
+ "_components": [],
+ "_prefab": null,
+ "_lpos": {
+ "__type__": "cc.Vec3",
+ "x": -0.791,
+ "y": 0.906,
+ "z": 0
+ },
+ "_lrot": {
+ "__type__": "cc.Quat",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "w": 1
+ },
+ "_lscale": {
+ "__type__": "cc.Vec3",
+ "x": 1,
+ "y": 1,
+ "z": 1
+ },
+ "_mobility": 0,
+ "_layer": 1073741824,
+ "_euler": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": 0,
+ "z": 0
+ },
+ "_id": "a5V6Eg9ZZA3Zf/TOqw9lmm"
+ },
+ {
+ "__type__": "cc.Node",
+ "_name": "Minus-001",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "_parent": {
+ "__id__": 76
+ },
+ "_children": [],
+ "_active": true,
+ "_components": [
+ {
+ "__id__": 78
+ }
+ ],
+ "_prefab": null,
+ "_lpos": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": 0,
+ "z": 0
+ },
+ "_lrot": {
+ "__type__": "cc.Quat",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "w": 1
+ },
+ "_lscale": {
+ "__type__": "cc.Vec3",
+ "x": 0.476,
+ "y": 0.137,
+ "z": 0.249
+ },
+ "_mobility": 0,
+ "_layer": 1073741824,
+ "_euler": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": 0,
+ "z": 0
+ },
+ "_id": "853FDaObxMdYj1iraJPtSL"
+ },
+ {
+ "__type__": "cc.MeshRenderer",
+ "_name": "Cube",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "node": {
+ "__id__": 77
+ },
+ "_enabled": true,
+ "__prefab": null,
+ "_materials": [
+ {
+ "__uuid__": "620b6bf3-0369-4560-837f-2a2c00b73c26",
+ "__expectedType__": "cc.Material"
+ }
+ ],
+ "_visFlags": 0,
+ "bakeSettings": {
+ "__id__": 79
+ },
+ "_mesh": {
+ "__uuid__": "1263d74c-8167-4928-91a6-4e2672411f47@a804a",
+ "__expectedType__": "cc.Mesh"
+ },
+ "_shadowCastingMode": 0,
+ "_shadowReceivingMode": 1,
+ "_shadowBias": 0,
+ "_shadowNormalBias": 0,
+ "_reflectionProbeId": -1,
+ "_reflectionProbeBlendId": -1,
+ "_reflectionProbeBlendWeight": 0,
+ "_enabledGlobalStandardSkinObject": false,
+ "_enableMorph": true,
+ "_id": "efmgEXaWFKi6lYVacN/BQ+"
+ },
+ {
+ "__type__": "cc.ModelBakeSettings",
+ "texture": null,
+ "uvParam": {
+ "__type__": "cc.Vec4",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "w": 0
+ },
+ "_bakeable": false,
+ "_castShadow": false,
+ "_receiveShadow": false,
+ "_recieveShadow": false,
+ "_lightmapSize": 64,
+ "_useLightProbe": false,
+ "_bakeToLightProbe": true,
+ "_reflectionProbeType": 0,
+ "_bakeToReflectionProbe": true
+ },
+ {
+ "__type__": "cc.Node",
+ "_name": "Minus-002",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "_parent": {
+ "__id__": 76
+ },
+ "_children": [],
+ "_active": true,
+ "_components": [
+ {
+ "__id__": 81
+ }
+ ],
+ "_prefab": null,
+ "_lpos": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": 0,
+ "z": 0
+ },
+ "_lrot": {
+ "__type__": "cc.Quat",
+ "x": 0,
+ "y": 0,
+ "z": 0.7071067811865475,
+ "w": 0.7071067811865476
+ },
+ "_lscale": {
+ "__type__": "cc.Vec3",
+ "x": 0.476,
+ "y": 0.137,
+ "z": 0.249
+ },
+ "_mobility": 0,
+ "_layer": 1073741824,
+ "_euler": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": 0,
+ "z": 90
+ },
+ "_id": "0d4Kvp7KxKIbgRbYuiSVD9"
+ },
+ {
+ "__type__": "cc.MeshRenderer",
+ "_name": "Cube",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "node": {
+ "__id__": 80
+ },
+ "_enabled": true,
+ "__prefab": null,
+ "_materials": [
+ {
+ "__uuid__": "620b6bf3-0369-4560-837f-2a2c00b73c26",
+ "__expectedType__": "cc.Material"
+ }
+ ],
+ "_visFlags": 0,
+ "bakeSettings": {
+ "__id__": 82
+ },
+ "_mesh": {
+ "__uuid__": "1263d74c-8167-4928-91a6-4e2672411f47@a804a",
+ "__expectedType__": "cc.Mesh"
+ },
+ "_shadowCastingMode": 0,
+ "_shadowReceivingMode": 1,
+ "_shadowBias": 0,
+ "_shadowNormalBias": 0,
+ "_reflectionProbeId": -1,
+ "_reflectionProbeBlendId": -1,
+ "_reflectionProbeBlendWeight": 0,
+ "_enabledGlobalStandardSkinObject": false,
+ "_enableMorph": true,
+ "_id": "14JoQDoc5Af5mrbw3mrlaC"
+ },
+ {
+ "__type__": "cc.ModelBakeSettings",
+ "texture": null,
+ "uvParam": {
+ "__type__": "cc.Vec4",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "w": 0
+ },
+ "_bakeable": false,
+ "_castShadow": false,
+ "_receiveShadow": false,
+ "_recieveShadow": false,
+ "_lightmapSize": 64,
+ "_useLightProbe": false,
+ "_bakeToLightProbe": true,
+ "_reflectionProbeType": 0,
+ "_bakeToReflectionProbe": true
+ },
+ {
+ "__type__": "cc.Node",
+ "_name": "Equal",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "_parent": {
+ "__id__": 1
+ },
+ "_children": [
+ {
+ "__id__": 84
+ },
+ {
+ "__id__": 87
+ }
+ ],
+ "_active": true,
+ "_components": [],
+ "_prefab": null,
+ "_lpos": {
+ "__type__": "cc.Vec3",
+ "x": 0.768,
+ "y": 1.014,
+ "z": 0
+ },
+ "_lrot": {
+ "__type__": "cc.Quat",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "w": 1
+ },
+ "_lscale": {
+ "__type__": "cc.Vec3",
+ "x": 1,
+ "y": 1,
+ "z": 1
+ },
+ "_mobility": 0,
+ "_layer": 1073741824,
+ "_euler": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": 0,
+ "z": 0
+ },
+ "_id": "55tRriDhFAhobge/nkmlEq"
+ },
+ {
+ "__type__": "cc.Node",
+ "_name": "Minus-001",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "_parent": {
+ "__id__": 83
+ },
+ "_children": [],
+ "_active": true,
+ "_components": [
+ {
+ "__id__": 85
+ }
+ ],
+ "_prefab": null,
+ "_lpos": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": 0,
+ "z": 0
+ },
+ "_lrot": {
+ "__type__": "cc.Quat",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "w": 1
+ },
+ "_lscale": {
+ "__type__": "cc.Vec3",
+ "x": 0.476,
+ "y": 0.137,
+ "z": 0.249
+ },
+ "_mobility": 0,
+ "_layer": 1073741824,
+ "_euler": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": 0,
+ "z": 0
+ },
+ "_id": "cevtUbQ6xI8axpqv2Z40Mc"
+ },
+ {
+ "__type__": "cc.MeshRenderer",
+ "_name": "Cube",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "node": {
+ "__id__": 84
+ },
+ "_enabled": true,
+ "__prefab": null,
+ "_materials": [
+ {
+ "__uuid__": "620b6bf3-0369-4560-837f-2a2c00b73c26",
+ "__expectedType__": "cc.Material"
+ }
+ ],
+ "_visFlags": 0,
+ "bakeSettings": {
+ "__id__": 86
+ },
+ "_mesh": {
+ "__uuid__": "1263d74c-8167-4928-91a6-4e2672411f47@a804a",
+ "__expectedType__": "cc.Mesh"
+ },
+ "_shadowCastingMode": 0,
+ "_shadowReceivingMode": 1,
+ "_shadowBias": 0,
+ "_shadowNormalBias": 0,
+ "_reflectionProbeId": -1,
+ "_reflectionProbeBlendId": -1,
+ "_reflectionProbeBlendWeight": 0,
+ "_enabledGlobalStandardSkinObject": false,
+ "_enableMorph": true,
+ "_id": "9a+ZDOoUNCKrpS9Rc4Mkj8"
+ },
+ {
+ "__type__": "cc.ModelBakeSettings",
+ "texture": null,
+ "uvParam": {
+ "__type__": "cc.Vec4",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "w": 0
+ },
+ "_bakeable": false,
+ "_castShadow": false,
+ "_receiveShadow": false,
+ "_recieveShadow": false,
+ "_lightmapSize": 64,
+ "_useLightProbe": false,
+ "_bakeToLightProbe": true,
+ "_reflectionProbeType": 0,
+ "_bakeToReflectionProbe": true
+ },
+ {
+ "__type__": "cc.Node",
+ "_name": "Minus-002",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "_parent": {
+ "__id__": 83
+ },
+ "_children": [],
+ "_active": true,
+ "_components": [
+ {
+ "__id__": 88
+ }
+ ],
+ "_prefab": null,
+ "_lpos": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": -0.207,
+ "z": 0
+ },
+ "_lrot": {
+ "__type__": "cc.Quat",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "w": 1
+ },
+ "_lscale": {
+ "__type__": "cc.Vec3",
+ "x": 0.476,
+ "y": 0.137,
+ "z": 0.249
+ },
+ "_mobility": 0,
+ "_layer": 1073741824,
+ "_euler": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": 0,
+ "z": 0
+ },
+ "_id": "6dd9ucUANKFIyA8Fk6cljr"
+ },
+ {
+ "__type__": "cc.MeshRenderer",
+ "_name": "Cube",
+ "_objFlags": 0,
+ "__editorExtras__": {},
+ "node": {
+ "__id__": 87
+ },
+ "_enabled": true,
+ "__prefab": null,
+ "_materials": [
+ {
+ "__uuid__": "620b6bf3-0369-4560-837f-2a2c00b73c26",
+ "__expectedType__": "cc.Material"
+ }
+ ],
+ "_visFlags": 0,
+ "bakeSettings": {
+ "__id__": 89
+ },
+ "_mesh": {
+ "__uuid__": "1263d74c-8167-4928-91a6-4e2672411f47@a804a",
+ "__expectedType__": "cc.Mesh"
+ },
+ "_shadowCastingMode": 0,
+ "_shadowReceivingMode": 1,
+ "_shadowBias": 0,
+ "_shadowNormalBias": 0,
+ "_reflectionProbeId": -1,
+ "_reflectionProbeBlendId": -1,
+ "_reflectionProbeBlendWeight": 0,
+ "_enabledGlobalStandardSkinObject": false,
+ "_enableMorph": true,
+ "_id": "adhfUXA8VFBI93rDl6+Nrs"
+ },
+ {
+ "__type__": "cc.ModelBakeSettings",
+ "texture": null,
+ "uvParam": {
+ "__type__": "cc.Vec4",
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "w": 0
+ },
+ "_bakeable": false,
+ "_castShadow": false,
+ "_receiveShadow": false,
+ "_recieveShadow": false,
+ "_lightmapSize": 64,
+ "_useLightProbe": false,
+ "_bakeToLightProbe": true,
+ "_reflectionProbeType": 0,
+ "_bakeToReflectionProbe": true
+ },
+ {
+ "__type__": "cc.PrefabInfo",
+ "root": null,
+ "asset": null,
+ "fileId": "71e36a35-a552-4298-90b5-3d1064fa30cb",
+ "instance": null,
+ "targetOverrides": null,
+ "nestedPrefabInstanceRoots": [
+ {
+ "__id__": 7
+ },
+ {
+ "__id__": 22
+ },
+ {
+ "__id__": 39
+ },
+ {
+ "__id__": 56
+ }
+ ]
+ },
+ {
+ "__type__": "cc.SceneGlobals",
+ "ambient": {
+ "__id__": 92
+ },
+ "shadows": {
+ "__id__": 93
+ },
+ "_skybox": {
+ "__id__": 94
+ },
+ "fog": {
+ "__id__": 95
+ },
+ "octree": {
+ "__id__": 96
+ },
+ "skin": {
+ "__id__": 97
+ },
+ "lightProbeInfo": {
+ "__id__": 98
+ },
+ "bakedWithStationaryMainLight": false,
+ "bakedWithHighpLightmap": false
+ },
+ {
+ "__type__": "cc.AmbientInfo",
+ "_skyColorHDR": {
+ "__type__": "cc.Vec4",
+ "x": 0.2,
+ "y": 0.5,
+ "z": 0.8,
+ "w": 0.520833125
+ },
+ "_skyColor": {
+ "__type__": "cc.Vec4",
+ "x": 0.2,
+ "y": 0.5,
+ "z": 0.8,
+ "w": 0.520833125
+ },
+ "_skyIllumHDR": 20000,
+ "_skyIllum": 20000,
+ "_groundAlbedoHDR": {
+ "__type__": "cc.Vec4",
+ "x": 0.2,
+ "y": 0.2,
+ "z": 0.2,
+ "w": 1
+ },
+ "_groundAlbedo": {
+ "__type__": "cc.Vec4",
+ "x": 0.2,
+ "y": 0.2,
+ "z": 0.2,
+ "w": 1
+ },
+ "_skyColorLDR": {
+ "__type__": "cc.Vec4",
+ "x": 0.452588,
+ "y": 0.607642,
+ "z": 0.755699,
+ "w": 0
+ },
+ "_skyIllumLDR": 0.8,
+ "_groundAlbedoLDR": {
+ "__type__": "cc.Vec4",
+ "x": 0.618555,
+ "y": 0.577848,
+ "z": 0.544564,
+ "w": 0
+ }
+ },
+ {
+ "__type__": "cc.ShadowsInfo",
+ "_enabled": false,
+ "_type": 0,
+ "_normal": {
+ "__type__": "cc.Vec3",
+ "x": 0,
+ "y": 1,
+ "z": 0
+ },
+ "_distance": 0,
+ "_shadowColor": {
+ "__type__": "cc.Color",
+ "r": 76,
+ "g": 76,
+ "b": 76,
+ "a": 255
+ },
+ "_maxReceived": 4,
+ "_size": {
+ "__type__": "cc.Vec2",
+ "x": 1024,
+ "y": 1024
+ }
+ },
+ {
+ "__type__": "cc.SkyboxInfo",
+ "_envLightingType": 0,
+ "_envmapHDR": {
+ "__uuid__": "d032ac98-05e1-4090-88bb-eb640dcb5fc1@b47c0",
+ "__expectedType__": "cc.TextureCube"
+ },
+ "_envmap": {
+ "__uuid__": "d032ac98-05e1-4090-88bb-eb640dcb5fc1@b47c0",
+ "__expectedType__": "cc.TextureCube"
+ },
+ "_envmapLDR": {
+ "__uuid__": "6f01cf7f-81bf-4a7e-bd5d-0afc19696480@b47c0",
+ "__expectedType__": "cc.TextureCube"
+ },
+ "_diffuseMapHDR": null,
+ "_diffuseMapLDR": null,
+ "_enabled": true,
+ "_useHDR": true,
+ "_editableMaterial": null,
+ "_reflectionHDR": null,
+ "_reflectionLDR": null,
+ "_rotationAngle": 0
+ },
+ {
+ "__type__": "cc.FogInfo",
+ "_type": 0,
+ "_fogColor": {
+ "__type__": "cc.Color",
+ "r": 200,
+ "g": 200,
+ "b": 200,
+ "a": 255
+ },
+ "_enabled": false,
+ "_fogDensity": 0.3,
+ "_fogStart": 0.5,
+ "_fogEnd": 300,
+ "_fogAtten": 5,
+ "_fogTop": 1.5,
+ "_fogRange": 1.2,
+ "_accurate": false
+ },
+ {
+ "__type__": "cc.OctreeInfo",
+ "_enabled": false,
+ "_minPos": {
+ "__type__": "cc.Vec3",
+ "x": -1024,
+ "y": -1024,
+ "z": -1024
+ },
+ "_maxPos": {
+ "__type__": "cc.Vec3",
+ "x": 1024,
+ "y": 1024,
+ "z": 1024
+ },
+ "_depth": 8
+ },
+ {
+ "__type__": "cc.SkinInfo",
+ "_enabled": true,
+ "_blurRadius": 0.01,
+ "_sssIntensity": 3
+ },
+ {
+ "__type__": "cc.LightProbeInfo",
+ "_giScale": 1,
+ "_giSamples": 1024,
+ "_bounces": 2,
+ "_reduceRinging": 0,
+ "_showProbe": true,
+ "_showWireframe": true,
+ "_showConvex": false,
+ "_data": null,
+ "_lightProbeSphereVolume": 1
+ }
+]
\ No newline at end of file
diff --git a/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.scene.meta b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.scene.meta
new file mode 100644
index 0000000000..d6504e354d
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.scene.meta
@@ -0,0 +1,11 @@
+{
+ "ver": "1.1.45",
+ "importer": "scene",
+ "imported": true,
+ "uuid": "71e36a35-a552-4298-90b5-3d1064fa30cb",
+ "files": [
+ ".json"
+ ],
+ "subMetas": {},
+ "userData": {}
+}
diff --git a/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.ts b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.ts
new file mode 100644
index 0000000000..a24a50dcbc
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.ts
@@ -0,0 +1,27 @@
+import { _decorator, animation, ccenum, Component, Node } from 'cc';
+const { ccclass, property, requireComponent } = _decorator;
+
+enum BaseLayerPose {
+ Standing,
+ Crouch,
+ Leaning_Original,
+}
+ccenum(BaseLayerPose);
+
+@ccclass('AdditivePoseDemonstration')
+@requireComponent(animation.AnimationController)
+export class AdditivePoseDemonstration extends Component {
+ @property({ type: BaseLayerPose })
+ baseLayerPose = BaseLayerPose.Standing;
+
+ @property({ range: [0.0, 1.0, 0.01], slide: true })
+ additiveLayerWeight = 0.0;
+
+ update(deltaTime: number) {
+ const controller = this.node.getComponent(animation.AnimationController);
+ controller.setValue('BaseLayerPose', this.baseLayerPose);
+ controller.setLayerWeight(1, this.additiveLayerWeight);
+ }
+}
+
+
diff --git a/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.ts.meta b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.ts.meta
new file mode 100644
index 0000000000..6df311a021
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/assets/AdditivePoseDemonstration/AdditivePoseDemonstration.ts.meta
@@ -0,0 +1,9 @@
+{
+ "ver": "4.0.23",
+ "importer": "typescript",
+ "imported": true,
+ "uuid": "9177bae6-0d0d-41c5-8806-45823b8d965d",
+ "files": [],
+ "subMetas": {},
+ "userData": {}
+}
diff --git a/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/package.json b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/package.json
new file mode 100644
index 0000000000..c6a30e5e2c
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "additive-pose-demonstration",
+ "uuid": "578bc671-b84c-4255-b3d5-49e0ac13ad5e",
+ "creator": {
+ "version": "3.8.0"
+ }
+}
diff --git a/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/settings/v2/packages/builder.json b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/settings/v2/packages/builder.json
new file mode 100644
index 0000000000..b2b2e5b558
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/settings/v2/packages/builder.json
@@ -0,0 +1,3 @@
+{
+ "__version__": "1.3.5"
+}
diff --git a/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/settings/v2/packages/cocos-service.json b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/settings/v2/packages/cocos-service.json
new file mode 100644
index 0000000000..5ba4c7387f
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/settings/v2/packages/cocos-service.json
@@ -0,0 +1,23 @@
+{
+ "__version__": "3.0.7",
+ "game": {
+ "name": "未知游戏",
+ "app_id": "UNKNOW",
+ "c_id": "0"
+ },
+ "appConfigMaps": [
+ {
+ "app_id": "UNKNOW",
+ "config_id": "b34724"
+ }
+ ],
+ "configs": [
+ {
+ "app_id": "UNKNOW",
+ "config_id": "b34724",
+ "config_name": "Default",
+ "config_remarks": "",
+ "services": []
+ }
+ ]
+}
diff --git a/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/settings/v2/packages/device.json b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/settings/v2/packages/device.json
new file mode 100644
index 0000000000..70e599e6c9
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/settings/v2/packages/device.json
@@ -0,0 +1,3 @@
+{
+ "__version__": "1.0.1"
+}
diff --git a/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/settings/v2/packages/engine.json b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/settings/v2/packages/engine.json
new file mode 100644
index 0000000000..9f2f363f4b
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/settings/v2/packages/engine.json
@@ -0,0 +1,3 @@
+{
+ "__version__": "1.0.7"
+}
diff --git a/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/settings/v2/packages/information.json b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/settings/v2/packages/information.json
new file mode 100644
index 0000000000..9a4b0a4f55
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/settings/v2/packages/information.json
@@ -0,0 +1,23 @@
+{
+ "__version__": "1.0.0",
+ "information": {
+ "customSplash": {
+ "id": "customSplash",
+ "label": "customSplash",
+ "enable": true,
+ "customSplash": {
+ "complete": false,
+ "form": "https://creator-api.cocos.com/api/form/show?sid=e6da5f66f96264c0a291dafa04093ac7"
+ }
+ },
+ "removeSplash": {
+ "id": "removeSplash",
+ "label": "removeSplash",
+ "enable": true,
+ "removeSplash": {
+ "complete": false,
+ "form": "https://creator-api.cocos.com/api/form/show?sid=e6da5f66f96264c0a291dafa04093ac7"
+ }
+ }
+ }
+}
diff --git a/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/settings/v2/packages/program.json b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/settings/v2/packages/program.json
new file mode 100644
index 0000000000..356db6b721
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/settings/v2/packages/program.json
@@ -0,0 +1,3 @@
+{
+ "__version__": "1.0.3"
+}
diff --git a/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/tsconfig.json b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/tsconfig.json
new file mode 100644
index 0000000000..7dc649a956
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/additive-animation/source/additive-pose-demonstration/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ /* Base configuration. Do not edit this field. */
+ "extends": "./temp/tsconfig.cocos.json",
+
+ /* Add your custom configuration here. */
+ "compilerOptions": {
+ "strict": false
+ }
+}
diff --git a/versions/4.0/en/animation/marionette/animation-controller.md b/versions/4.0/en/animation/marionette/animation-controller.md
new file mode 100644
index 0000000000..284044d309
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/animation-controller.md
@@ -0,0 +1,71 @@
+# Animation Controller
+
+The animation controller component is used to apply the [Animation Graph Assets](animation-graph.md) to the object.
+
+Select the node in **Hierarchy** panel where you need to apply the animation graph, and then click **Add Component -> Animation -> Animation Controller** below in **Inspector** panel to add an animation controller component to the node.
+
+
+
+> **Note**: Because the Marionette animation system and the old animation system cannot be used together, **animation controller components also cannot be mounted on the same node as animation components or skeletal animation components**.
+
+## Properties
+
+
+
+| Properties | Description |
+| :---- | :----------- |
+| Graph | Added [animation-graph resource](animation-graph.md), default is empty |
+
+## Programmatically Controlling Animation Graphs
+
+The animation controller component provides a number of methods for controlling the [Animation State Machine](animation-graph-basics.md) of the animation graph at runtime.
+
+| Method | Description |
+| :----------------------- | :----------------------- |
+| `getVariables` | Get all variables and their names/types/values, etc. ||
+| `setValue` | Set the value of the variable. | `getValue
+| `getValue` | Get the value of the variable. | `getValue
+| `getCurrentStateStatus` | Get the current state information. | `getCurrentStateStatus`
+| `getCurrentClipStatuses` | Get the current state of the clip. | `getCurrentClipStatuses`
+| `getCurrentTransition` | Get the current state transition. | `getCurrentClipStatuses`
+| `getNextStateStatus` | Get information about the next state. | `getNextStateStatus
+| `getNextClipStatuses` | Get the status of the next animation clip. | `setLayerWeight
+| `setLayerWeight` | Set the weight of a certain [animation-graph layer](animation-graph-layer.md). | |
+
+- **Variable** Control
+
+ For example, we have a variable in the [Animation Graph Panel](./animation-graph-panel.md#Variables) added several variables, the code can get and modify the value of the variables, the code example is as follows.
+
+ ```ts
+ // Get the animation controller component
+ let animationController:animation.AnimationController = this.node.getComponent(animation.AnimationController)
+
+ // Get all variables
+ let variables= animationController.getVariables();
+
+ // Get the value of the variable named 'vertical'
+ let vertical: Number = animationController.getValue("vertical");
+
+ // Change the value of the variable named 'vertical' to 1.0, which will calculate the conditional transition on the next update frame
+ animationController.setValue("vertical", 1.0)
+ ```
+
+ > **Note**: Variables for the animation state machine can currently only be added and removed in the [Animation Graph Panel](animation-graph-panel.md#Variables).
+
+- Get the current **state**
+
+ Get the normalized progress of the current **state** of the state machine at layer 0, with the following code example.
+
+ ```ts
+ let states: animation.MotionStateStatus = animationController.getCurrentStateStatus(0)
+ console.log(states.progress);
+ ```
+
+- Get the current **transition**
+
+ Gets information about the upcoming **transition** of the state machine at layer 0.
+
+ ```ts
+ let transition: animation.TransitionStatus = animationController.getCurrentTransition(0)
+ console.log(transition.duration, transition.time)
+ ```
diff --git a/versions/4.0/en/animation/marionette/animation-controller/add-animation-controller.png b/versions/4.0/en/animation/marionette/animation-controller/add-animation-controller.png
new file mode 100644
index 0000000000..289921eb51
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-controller/add-animation-controller.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics.md b/versions/4.0/en/animation/marionette/animation-graph-basics.md
new file mode 100644
index 0000000000..11cb02399a
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/animation-graph-basics.md
@@ -0,0 +1,223 @@
+# Animation State Machine
+
+A state refers to an action performed by an animated actor in the form of animations being triggered and played, such as being idle, moving, running, attacking, etc.
+
+An actor may have multiple states and switches between them as different actions are performed. The act of switching from one state to another is called a [transition](state-transition.md). The condition that predetermines the transition is called a **transition condition**.
+
+A state machines manages all the states and transitions of an actor. Typically, the logical connections of states and transitions are depicted as a flow chart, which is editable in the [Animation Graph panel](animation-graph-panel.md). Currently, one animation graph corresponds to one state machine. When the state machine is at a certain state, animation corresponding that state will be played. Depending on the intricacy of the animation graph, the actor can perform a myriad of complex actions by switching between simple skeletal animations.
+
+## State Basics
+
+Besides states that contains animations, users can also create 4 special states in the animation graph including **Entry**, **Exit**, **Any** and **Sub State Machine**. As these states do not contain any animation, they will be referred as **pseudo states** from this point on.
+
+A [sub state machine](#sub-state-machine) serves as a container for a state machine nested within another state machine, primarily used to break down complex state machine designs into controllable chunks. By convention, the state machine with the highest hierarchy is referred as the **Top Level State Machine**. It is comparable to the root node in the scene.
+
+**Entry**, **Exit** and **Any** are mandatory pseudo states that cannot be deleted from the graph. They are accessible in the Animation Graph panel by default. Please take note that the **Exit** state is only available in a **sub state machine**.
+
+
+
+- **Entry**: Represents the entry point of the current state machine. It can only be used as the beginning state of a transition and never the end state.
+
+- **Exit**: Represents the end point of the current state machine. When the state machine reaches the end point, it is considered completed and will shut down. **Exit** can only be used as the end state of a transition and never the beginning state.
+
+ As the current sub state machine is completed, it will be shut down and transitioned to the next nearest state in its parent state machine. The actor will cease all animation if the top level state machine is shut down, which defeats the purpose of having the animation system in the first place. For this reason, **Exit** is only available in sub state machines.
+
+ To manually cease all animation for the actor, users may disable the **Animation Controller** component of the actor.
+
+- **Any**: Represents any state in the graph that is not a pseudo state. It can only be used as the beginning state of a transition and never the end state.
+
+ A transition beginning from **Any** is equivalent to a transition from all available states currently in the graph. In other words, no matter which state it is currently at, it will be transitioned to the end state as long as the transition conditions are met. For instance, a character can switch to the wounding animation from any other animation, be it walking, running, jumping, etc.
+
+ > **Note**: **Any** also includes any state from the sub state machines of the current state machine. Transitions from the sub state machines will be triggered if the transition conditions are met.
+
+## Creating states
+
+A state machine is the collection of all states, pseudo states and the transitions that connect them together under specific conditions.
+
+Right click on the grid in the [Animation Graph panel](animation-graph-panel.md) and select one of the following to add to the graph:
+- **Add State – Animation Clip**: Add an animation clip asset as a state, named `Clip Motion` by default.
+- **Add State – Blend 1D / 2D**: Add a new animation by blending multiple animations as a new state with a default name of `Blend 1D` / `Blend 2D`. Please see below in section **Animation Blending** for more details.
+- **Add Sub State Machine**: Add a new sub state machine named `State Machine` by default, Please see below in section **Sub State Machine** for more details.
+
+All states except sub state machines are represented as blue rectangles in the graph.
+
+
+
+### Setting state properties
+
+Select a state in the graph and the blue rectangle will be highlighted with yellow edges. Properties of the selected state will also be available in the **Inspector** panel to the left of the Animation Graph panel.
+
+
+
+- Name of the selected state is displayed on the top of the **Inspector** panel. Clicking the gear icon will yield options for the selected state to be renamed, deleted, or replaced by a state of a different type.
+
+- **Speed**: Playback speed for the animation attached to the selected state with a default value of 1. Lower value will result in slower animation.
+- **Speed Multiplier**: When enabled, a multiplication factor can be specified for the speed. The speed multiplier factor will base speed multiplication to control the speed of the animation state.
+
+ 
+
+- **Animation Clip Motion**: Specify the animation clip attached to the selected state. Users can drag and drop the animation clip asset from the Assets panel to the **Clip** property or select from its drop-down menu. Once specified, the animation clip will be attached to the selected state, and the selected state will be automatically renamed according to the attached animation clip.
+
+ > **Note**: If the animation clip is left unspecified, it could cause errors to the state machine.
+
+ 
+
+- **State Component**: Attach an animation graph script to the selected state. Users may call from the StateMachineComponent to insert events at certain junctions of the flow chart. For more information, please see below in section **Animation State Component** for more details.
+
+- Clicking the gear icon will yield options for the selected state to be renamed, deleted, or replaced by a state of a different type. Right click on the state note in the graph will also yield the same options.
+
+ 
+
+## Animation Blending
+
+Blend Motion creates new animations by blending existing ones with pre-determined parameters, commonly used to create mixed animations such as jumping while running. To achieve optimal results, it is not advisable to blend animations that are excessively different from one another. Based on the parameters used, Blend Motion can be categorized as follows:
+
+- **Blend 1D**: Use **one parameter** to **linearly interpolate** between multiple animations.
+
+- **Blend 2D**: Use **two parameters** to **barycentrically interpolate** between multiple animations.
+
+Blend Motion should be distinguished from [State Transitions](state-transition.md) as:
+
+- Transitions create a brief intersection period for one animation to morph into a second animation.
+
+- Blend Motion combines multiple animations with varying parameters, yielding one combined animation.
+
+### Adding animation blending
+
+Right click on the grid in the Animation Graph panel and select **Add State – Blend 1D** or **Add State – Blend 2D** to create new states. Their respective properties can be accessed in the **Inspector** panel on the left.
+
+
+
+Users can access the parameters for blending in either of the following ways:
+
+- Select the Blend Motion state and click the **Edit** button in the Inspector panel
+- Double click on the Blend Motion state node as seen in the animation graph
+- Right click on the Blend Motion state node and select **Edit**
+
+To exit the Blend Motion state, users may:
+
+- Right click on the grid and select **Return to Parent**
+- Select a higher hierarchy in the **Position** bar on top of the grid window
+
+
+
+### 1D Animation Blending
+
+Blend 1D **linearly interpolates** multiple animation with **one parameter**, with each target animation assigned with a threshold value.
+
+- When the parameter’s value equates to the threshold value of a target animation, said animation will be the output of the Blend 1D state.
+- When the parameter’s value is between the threshold value of 2 target animations, Blend 1D will output the linear interpolation between the two. The formula is `A * (1 - t) + B * t` where A and B are the threshold value of target animations, and t the percentage value of the parameter value in proportion to the range between the two thresholds.
+
+Double click on the Blend Motion state node to enter its sub graph. In it, users may import animation clips by creating a new Clip Motion state, or create additional Blend Motion states.
+
+
+
+- **Parameter**: Select the parameter to be used to blend between states. A parameter needs to be created under the **Variables** tab first. Blend Motion states require a float type parameter as the input variable. Users may also select from pre-existing variables to be used as the parameter at the Blend Motion state nodes in the graph. For more information, please see [Animation Graph Panel - Variables](animation-graph-panel.md) for details.
+
+- **Threshold**: With every animation clip imported, a new corresponding threshold variable will be added. Users may manually define the value, or enable **Automata Threshold** to allow Cocos Creator to assign threshold values automatically. Threshold variables will be listed in an ascending order.
+
+- Animation clips can be assigned from the drop-down menu from the state nodes in the graph, or from the **Inspector** panel while a Clip Motion state node is selected.
+
+ 
+
+ To remove an animation, select the Clip Motion state, go to the Inspector panel and click the gear icon, then select **Remove this Motion**.
+
+As an example, a state machine that plays different animations when the character is at different movement speeds should look like the screenshot below:
+
+
+
+### 2D Animation Blending
+
+Blend 2D **barycentrically interpolates** multiple animation with **two parameters**, with each target animation assigned with a threshold value.
+
+Users may set up a Blend 2D state in the same way as setting up a Blend 1D state, with a few exceptions:
+
+- Blend 2D requires 2 parameters (X, Y) to blend animations.
+- Clip Motion states have threshold value in 2 dimensions (`[x, y]`). Threshold variables are listed by the order of their creation. There is no option for **Automata Threshold**.
+- Parameter X corresponds to the x dimension of threshold variables while parameter Y the y dimension.
+
+Blend 2D is commonly used to create state machine for character motions, such as:
+
+
+
+In the example above, the range for parameter X is `[-1, 1]`, and the range for parameter Y is `[-1. 1]`.
+
+## Sub State Machine
+
+Users can create sub state machines to be used recursively anywhere in the animation graph. By convention, the state machine with the highest hierarchy is referred as the **Top Level State Machine**. It is comparable to the root node in the scene.
+
+Right click on the grid and select **Add Sub State Machine** to create a new sub state machine with the default name of `State Machine`.
+
+
+
+- Button ① is for entering the sub graph of the sub state machine to edit its content. It can also be done by double clicking the sub state machine node in the graph or right click on the node and select **Edit**.
+
+- Button 2 is for adding state components. Please see below in section **Animation State Components** for more details.
+
+- Click the gear icon to rename, remove, or add state components for the selected sub state machine.
+
+### Editing Sub State Machine
+
+The sub graph of a sub state machine is identical to a typical graph except for the **Exit** pseudo state. As the current sub state machine is completed, it will be shut down and transitioned to the next nearest state in its parent state machine.
+
+
+
+To exit the Blend Motion state, users may right click on the grid and select **Return to Parent** or select a higher hierarchy in the **Position** bar on top of the grid window.
+
+
+
+## Animation State Component
+
+States and sub state machines can be attached with state components, which can be created in the **Assets** panel by clicking the + button on the top and select **Animation Graph Script**.
+
+
+
+A new Animation Graph Script component will be named `AnimationGraphComponent` by default which is a .ts script.
+
+
+
+The Animation Graph Script can be attached to a state node in the animation graph by clicking the Add State Component button in the Inspector panel, or click the gear icon on the top and select Add State Component. A state node can be attached with multiple State Components.
+
+Click the gear icon on the right of the added state component and select Remove State Component to remove it.
+
+Animation Graph Script assets can call from the `animation.StateMachineComponent` class which includes methods that registers events of the state machine, which includes:
+
+| Method Name | Description |
+| :--- | :--- |
+| `onMotionStateEnter` | Triggered when entering a state |
+| `onMotionStateExit` | Triggered when exiting a state |
+| `onMotionStateUpdate` | Triggered when a state is updated |
+| `onStateMachineEnter` | Triggered when entering a sub state machine |
+| `onStateMachineExit` | Triggered when exiting a sub state machine |
+
+Methods listed above can also use the following parameters:
+
+- `controller: animation.AnimationController`: The Animation Controller component which the state machine is attached to. This parameter is appliable to all the methods above.
+
+- `motionStateStatus: animation.MotionStateStatus`: Status of the current state. This parameter is only applicable to methods intended for states (`onMotionStateEnter`, `onMotionStateExit`.)
+
+
+
+### Example: Enable particles when entering a state
+
+```ts
+import { _decorator, animation, PhysicsSystem, ParticleSystem } from "cc";
+const { ccclass, property } = _decorator;
+
+@ccclass("AnimationGraphComponent")
+export class AnimationGraphComponent extends animation.StateMachineComponent {
+ /**
+ * Called when a motion state right after it entered.
+ * @param controller The animation controller it within.
+ * @param stateStatus The status of the motion.
+ */
+ public onMotionStateEnter (controller: animation.AnimationController, stateStatus: Readonly): void {
+ // Enable all particles attached to the node where the animation controller is also located
+ for (const particleSystem of controller.node.getComponents(ParticleSystem)) {
+ particleSystem.play();
+ }
+ }
+}
+```
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/add-graph-script.png b/versions/4.0/en/animation/marionette/animation-graph-basics/add-graph-script.png
new file mode 100644
index 0000000000..64e57ef77e
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/add-graph-script.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/add-motion-of-blend1D.png b/versions/4.0/en/animation/marionette/animation-graph-basics/add-motion-of-blend1D.png
new file mode 100644
index 0000000000..d95b22c1c2
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/add-motion-of-blend1D.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/add-motion.png b/versions/4.0/en/animation/marionette/animation-graph-basics/add-motion.png
new file mode 100644
index 0000000000..aea7919dd5
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/add-motion.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/animation-graph-component.png b/versions/4.0/en/animation/marionette/animation-graph-basics/animation-graph-component.png
new file mode 100644
index 0000000000..1b5cd4cfcf
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/animation-graph-component.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/blend-edit-panel.png b/versions/4.0/en/animation/marionette/animation-graph-basics/blend-edit-panel.png
new file mode 100644
index 0000000000..b3a0cf1c10
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/blend-edit-panel.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/blend-edit.png b/versions/4.0/en/animation/marionette/animation-graph-basics/blend-edit.png
new file mode 100644
index 0000000000..98a5cb3dab
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/blend-edit.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/blend-property.png b/versions/4.0/en/animation/marionette/animation-graph-basics/blend-property.png
new file mode 100644
index 0000000000..dd43f4bf9b
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/blend-property.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/blend1-speed.png b/versions/4.0/en/animation/marionette/animation-graph-basics/blend1-speed.png
new file mode 100644
index 0000000000..ed9f0060ec
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/blend1-speed.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/blend2.png b/versions/4.0/en/animation/marionette/animation-graph-basics/blend2.png
new file mode 100644
index 0000000000..103bf1a557
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/blend2.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/change-state.png b/versions/4.0/en/animation/marionette/animation-graph-basics/change-state.png
new file mode 100644
index 0000000000..c63203fc07
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/change-state.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/choose-clip.png b/versions/4.0/en/animation/marionette/animation-graph-basics/choose-clip.png
new file mode 100644
index 0000000000..e51a0f12f6
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/choose-clip.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/clip-menu.png b/versions/4.0/en/animation/marionette/animation-graph-basics/clip-menu.png
new file mode 100644
index 0000000000..037b6d0e46
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/clip-menu.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/create-blend.gif b/versions/4.0/en/animation/marionette/animation-graph-basics/create-blend.gif
new file mode 100644
index 0000000000..596cd7ca0b
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/create-blend.gif differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/create-graph-script.png b/versions/4.0/en/animation/marionette/animation-graph-basics/create-graph-script.png
new file mode 100644
index 0000000000..ee42c28c16
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/create-graph-script.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/edit-sub-state.png b/versions/4.0/en/animation/marionette/animation-graph-basics/edit-sub-state.png
new file mode 100644
index 0000000000..07141a1e47
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/edit-sub-state.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/edit.png b/versions/4.0/en/animation/marionette/animation-graph-basics/edit.png
new file mode 100644
index 0000000000..6caa4d878a
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/edit.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/example.png b/versions/4.0/en/animation/marionette/animation-graph-basics/example.png
new file mode 100644
index 0000000000..584eee47ea
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/example.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/preview-blend1.png b/versions/4.0/en/animation/marionette/animation-graph-basics/preview-blend1.png
new file mode 100644
index 0000000000..a7efb4d208
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/preview-blend1.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/preview-blend2.png b/versions/4.0/en/animation/marionette/animation-graph-basics/preview-blend2.png
new file mode 100644
index 0000000000..66037279fa
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/preview-blend2.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/preview-clip.png b/versions/4.0/en/animation/marionette/animation-graph-basics/preview-clip.png
new file mode 100644
index 0000000000..05fd2e8adc
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/preview-clip.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/remove-graph-script.png b/versions/4.0/en/animation/marionette/animation-graph-basics/remove-graph-script.png
new file mode 100644
index 0000000000..894c222930
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/remove-graph-script.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/set-sub-state.png b/versions/4.0/en/animation/marionette/animation-graph-basics/set-sub-state.png
new file mode 100644
index 0000000000..4f767b4723
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/set-sub-state.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/speed-multiplier.png b/versions/4.0/en/animation/marionette/animation-graph-basics/speed-multiplier.png
new file mode 100644
index 0000000000..af77ddcfee
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/speed-multiplier.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/state-property.png b/versions/4.0/en/animation/marionette/animation-graph-basics/state-property.png
new file mode 100644
index 0000000000..359f57d8bb
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/state-property.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-basics/sub-state.png b/versions/4.0/en/animation/marionette/animation-graph-basics/sub-state.png
new file mode 100644
index 0000000000..51f4862185
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-basics/sub-state.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-layer.md b/versions/4.0/en/animation/marionette/animation-graph-layer.md
new file mode 100644
index 0000000000..5f5abf1a8e
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/animation-graph-layer.md
@@ -0,0 +1,93 @@
+# Animation Graph Layer
+
+The animation graph can have multiple layers, with layers running simultaneously between them, and the animation effects played on them can be mixed according to the configuration of the layers.
+
+## Create layers
+
+
+
+Click the **Layers** button in the animation graph, click the  button, and enter the name of the layer in the popup input box to create the layer.
+
+## Delete Layers
+
+After hovering over the layers, you can click **×** on the right side of the layers to delete them, this operation only takes effect when there are multiple layers.
+
+
+
+## Rename the layers
+
+Rename a layer by double-clicking the left mouse button at the layer name.
+
+
+
+## Layer Properties
+
+After selecting any layer in the animation graph, you can view the layer properties in the **Inspector** panel.
+
+
+
+| Properties | Description |
+| :-- | :-- |
+| **Mask** | The animation mask to specify the corresponding [Animation Mask](animation-mask.md) |
+| **Weight** | The weight of the layer to be used when mixing with **previous layers**, in the range [0, 1] |
+
+### Animation Masks
+
+A mask can be assigned to a layer by dragging an animation mask from the **Assets** panel to the **Mask** property of the Animation Graph window or by checking the **Mask** property in the layer.
+
+Refer to the following figure and follow steps 1, 2 and 3.
+
+- Select any layer
+- Click on the drop-down menu in the **Inspector** panel.
+- Select a pre-created **Mask** resource or drag it from the **Assets** panel.
+
+
+
+When specified, all animation effects on that layer are affected by that mask.
+
+For example, you can specify an animation mask to a layer that keeps only the upper body skeleton, with all lower body skeletons disabled, and the animation effect on that layer will only work on the upper body.
+
+### Layer weights
+
+The animation effect of each layer will be blended with the animation effect of the previous layer in a certain proportion, the proportion of the blending is specified by the weight property of the layer.
+
+0 means that the animation of the previous level is used completely, 1 means that the level completely overwrites the animation of the previous layer, when it is at [0,1] then the blending is done properly.
+
+Blending of layers will only blend those bones that are not disabled by the animation mask. For example, if Layer 1 has a skeleton enabled, but a subsequent Layer 2 has disabled it with an animation mask, then
+The skeleton will only play the animation of Layer 1 in full, regardless of the weight specified for Layer 2.
+
+You can also dynamically modify the layer weights in code via `AnimationController.prototype.setLayerWeight`.
+
+## Grid layout area manipulation
+
+Right-clicking on a blank space within the grid opens the layer menu.
+
+
+
+You can add **states, sub-state machines, blends and empty states** to the menu.
+
+- See [Animation State Machine](animation-graph-basics.md) for how to use **sub-states, sub-state machines** and **blends**.
+
+- **Add Empty State**: This menu creates a default empty state named Empty on the hierarchy, please refer to the **Empty State** section below for more information.
+
+ 
+
+- **Return to center view**: This menu returns the view of the layer to the center of the layer.
+
+- Hold down the right or middle mouse button to move the layer grid; use the scroll wheel to zoom in and out of the layer.
+
+## Empty state
+
+In many cases, a requirement is to enable a layer only in certain situations; in all other cases make this layer inactive.
+
+For this requirement, **Empty State** can be used. The **Empty State** can be considered as an animation whose animation effect is the animation effect of the previous level.
+
+The transition from the **Empty State** state is equivalent to the gradual transition from the animation effect of the previous level to the target animation. Transition conditions and transition period can be specified on this transition. However, the transition period can only be specified as an absolute duration (in seconds).
+
+
+
+The transition leading to the **Empty** state is equivalent to the source animation's animation decaying until the transition is complete, which is equivalent to the current level being disabled.
+
+As in the example below, when **Empty** transitions to the **RunShoot** state only after the trigger **Trigger** is triggered, and in the **Empty** state, the layer does not affect the animation effects of the preceding layers.
+
+
diff --git a/versions/4.0/en/animation/marionette/animation-graph-panel.md b/versions/4.0/en/animation/marionette/animation-graph-panel.md
new file mode 100644
index 0000000000..63c72d5fb4
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/animation-graph-panel.md
@@ -0,0 +1,80 @@
+# Animation Graph Panel
+
+The Animation Graph panel is used to view and edit animation graph assets. Once you have prepared the skeletal animations required for an object, you can assemble and combine them into a complete animation flow in the **Animation Graph Panel**.
+
+## Opening the Panel
+
+Select the animation graph asset in the **Assets** panel, then click **Edit** in the **Inspector** panel:
+
+
+
+This opens the Animation Graph panel, which consists of **Layers**, **Variables**, **Inspector** tab on the left, and the grid layout area on the right:
+
+
+
+When there are multiple animation graph assets, click the **Switch Animation Graphs** button in the upper right corner of the panel to switch other animation graphs that need to be edited.
+
+## Layers
+
+This tab is mainly used to create, view and edit layers of animation graphs, each layer is controlled by a state machine respectively, but currently only one animation graph layer is supported. The animation layer can be renamed by clicking on the gear icon button to the right of the layer.
+
+
+
+For more informations, please refer to [Animation Graph Layer](animation-graph-layer.md)。
+
+## Grid Layout Area
+
+This area mainly shows the state machine corresponding to the layer selected in the **Layers** tab, where the user can visually create, edit and arrange the states in the state machine, as well as set the transition between states. Right-click in the area to create as many states as needed:
+
+
+
+When finished with editing, click **Save** or **Reset** (reset to the last save) in the upper right corner as needed. Please refer to the [Animation State Machine](animation-graph-basics.md) documentation for more operations.
+
+## Variables
+
+This tab is mainly used to create, view and edit the variables of the state machine in the current animation graph layer. The user can manipulate the flow of the animation graph expression in the animation graph by means of custom **variables**, which serve the following purposes:
+
+- as **transition conditions** for transitions between states
+
+- as an **input parameter** for mixing animation states to mix different animation clips
+
+
+
+### Creating variables
+
+In the following figure, for example, the steps are:
+- Fill in the variable name in the **Name** input box
+- Select the variable type in the **Type** drop-down box. The supported variable types include **Float**, **Boolean**, **Trigger** and **Integer**, please refer to **Variable Types** section below for details.
+- Finally, click the **Add** button to create the variables, and the created variables will be displayed in order at the bottom of the tab.
+
+
+
+Each created variable will have a gear icon button on the right side, click it to delete the corresponding variable. Please don't forget to click the **Save** button in the top right corner of the Animation Graph panel to save the settings when done.
+
+### Variable Types
+
+The currently supported variable types to create include:
+
+- **Float**: the value of the variable can be any real number
+
+- **Boolean**: the value of the variable can be true/false
+
+- **Integer**: the value of the variable can be any integer
+
+- **Trigger**: the variable is a trigger, if checked, the value is a trigger. Trigger is used for one-time condition judgment, when the trigger condition is satisfied, the state transition occurs. After the transition is completed, all the triggers referenced will be reset to **untriggered state**.
+
+ > **Note**: the trigger will be reset only when it transitions to a certain state. If it transitions to a "pseudo-state", the trigger will not be reset.
+
+ For example, in the following figure, if the trigger is set to T1 or T2 in ① once, state A will reach state B or C in the sub-state machine without setting the triggers in ② and ③ again:
+
+ 
+
+
+
+## Inspector
+
+This tab is mainly used to set the properties and transition conditions of the various states in the state machine, please refer to the [Animation State Machine](animation-graph-basics.md) documentation for details.
+
+
diff --git a/versions/4.0/en/animation/marionette/animation-graph-panel/add-layer.png b/versions/4.0/en/animation/marionette/animation-graph-panel/add-layer.png
new file mode 100644
index 0000000000..23d9cc20b8
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-panel/add-layer.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-panel/add-variables.png b/versions/4.0/en/animation/marionette/animation-graph-panel/add-variables.png
new file mode 100644
index 0000000000..0c6a966031
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-panel/add-variables.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-panel/animation-graph-panel.png b/versions/4.0/en/animation/marionette/animation-graph-panel/animation-graph-panel.png
new file mode 100644
index 0000000000..961b5e4542
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-panel/animation-graph-panel.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-panel/btn-add-layer.png b/versions/4.0/en/animation/marionette/animation-graph-panel/btn-add-layer.png
new file mode 100644
index 0000000000..01e6b73f53
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-panel/btn-add-layer.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-panel/delete-variable.png b/versions/4.0/en/animation/marionette/animation-graph-panel/delete-variable.png
new file mode 100644
index 0000000000..90d2f03485
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-panel/delete-variable.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-panel/edit.png b/versions/4.0/en/animation/marionette/animation-graph-panel/edit.png
new file mode 100644
index 0000000000..99fa0d4387
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-panel/edit.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-panel/inspector.png b/versions/4.0/en/animation/marionette/animation-graph-panel/inspector.png
new file mode 100644
index 0000000000..56f49212b1
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-panel/inspector.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-panel/layer-inspector.png b/versions/4.0/en/animation/marionette/animation-graph-panel/layer-inspector.png
new file mode 100644
index 0000000000..bb2a152b09
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-panel/layer-inspector.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-panel/layers.png b/versions/4.0/en/animation/marionette/animation-graph-panel/layers.png
new file mode 100644
index 0000000000..1f8c16d5c8
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-panel/layers.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-panel/open-animation-graph-panel.png b/versions/4.0/en/animation/marionette/animation-graph-panel/open-animation-graph-panel.png
new file mode 100644
index 0000000000..3abcc30d4a
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-panel/open-animation-graph-panel.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-panel/remove-layer.png b/versions/4.0/en/animation/marionette/animation-graph-panel/remove-layer.png
new file mode 100644
index 0000000000..7eabda741a
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-panel/remove-layer.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-panel/rename-layer.png b/versions/4.0/en/animation/marionette/animation-graph-panel/rename-layer.png
new file mode 100644
index 0000000000..8204adc8f8
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-panel/rename-layer.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-panel/reset-on-nextframe.png b/versions/4.0/en/animation/marionette/animation-graph-panel/reset-on-nextframe.png
new file mode 100644
index 0000000000..76925ac4c8
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-panel/reset-on-nextframe.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-panel/variable-eg.png b/versions/4.0/en/animation/marionette/animation-graph-panel/variable-eg.png
new file mode 100644
index 0000000000..25f39f35f3
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-panel/variable-eg.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph-panel/variables.png b/versions/4.0/en/animation/marionette/animation-graph-panel/variables.png
new file mode 100644
index 0000000000..0e3c14b715
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph-panel/variables.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph.md b/versions/4.0/en/animation/marionette/animation-graph.md
new file mode 100644
index 0000000000..1ac2b13566
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/animation-graph.md
@@ -0,0 +1,35 @@
+# Animation Graph Assets
+
+The animation graph asset is used to store the entire animation flow data of the object. The flow of the animation is described by a state machine, currently an animation graph only supports one state machine.
+
+## Creating
+
+In the **Assets** panel click the **+** button on the top left, then select **Animation Graph**.
+
+
+
+This creates an animation graph asset named `Animation Graph` by default.
+
+
+
+## Editing
+
+Once the animation graph is created, it can be edited it in the Animation Graph panel, please refer to the [Animation Graph Panel](animation-graph-panel.md) documentation for details.
+
+## Applying
+
+Animation graph assets need to depend on the Animation Controller component to be applied to the object.
+
+Click **Add Component -> Animation -> Animation Controller** at the bottom of the **Inspector** panel to add the Animation Controller component to the node.
+
+
+
+> **Note**: since the Marionette animation system and the old animation system cannot be used together, the animation controller component cannot be attached on the same node as the animation component or the skeletal animation component either.
+
+Then click the arrow icon button behind the **Graph** property box of the animation controller component to select the animation graph asset.
+
+
+
+Or just drag and drop the animation graph asset from the **Assets** panel into the **Graph** property box of the Animation Controller component:
+
+
diff --git a/versions/4.0/en/animation/marionette/animation-graph/add-animation-controller.png b/versions/4.0/en/animation/marionette/animation-graph/add-animation-controller.png
new file mode 100644
index 0000000000..7dc532411d
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph/add-animation-controller.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph/animation-controller.png b/versions/4.0/en/animation/marionette/animation-graph/animation-controller.png
new file mode 100644
index 0000000000..50a05c5abb
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph/animation-controller.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph/animation-graph-asset.png b/versions/4.0/en/animation/marionette/animation-graph/animation-graph-asset.png
new file mode 100644
index 0000000000..9c902f373f
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph/animation-graph-asset.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph/animation-graph-select.png b/versions/4.0/en/animation/marionette/animation-graph/animation-graph-select.png
new file mode 100644
index 0000000000..2a15927c1c
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph/animation-graph-select.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph/create-animation-graph.png b/versions/4.0/en/animation/marionette/animation-graph/create-animation-graph.png
new file mode 100644
index 0000000000..e20b078933
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph/create-animation-graph.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-graph/create-empty-state.png b/versions/4.0/en/animation/marionette/animation-graph/create-empty-state.png
new file mode 100644
index 0000000000..a9b29aaaa2
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-graph/create-empty-state.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-layer/create-empty.png b/versions/4.0/en/animation/marionette/animation-layer/create-empty.png
new file mode 100644
index 0000000000..48d6c42ede
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-layer/create-empty.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-layer/empty-state.png b/versions/4.0/en/animation/marionette/animation-layer/empty-state.png
new file mode 100644
index 0000000000..42a8561bc3
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-layer/empty-state.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-layer/transit-empty-state.png b/versions/4.0/en/animation/marionette/animation-layer/transit-empty-state.png
new file mode 100644
index 0000000000..ba999f76fc
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-layer/transit-empty-state.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-mask.md b/versions/4.0/en/animation/marionette/animation-mask.md
new file mode 100644
index 0000000000..d5d0393548
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/animation-mask.md
@@ -0,0 +1,57 @@
+# Animation Mask
+
+An animation mask is an asset used in the animation layer to mask the animation effects on a given bone.
+
+For example, if you want to create a walking animation while shooting, you can use the animation mask to mix the upper half of the shooting animation with the lower half of the walking animation.
+
+## Creation
+
+In the **Assets Manager** click on the **+** button at the top left and select **Animation Mask**.
+
+
+
+An animation mask named **Animation Mask** can be created by default.
+
+
+
+## Edit Mask
+
+After selecting an animation mask in the **Assets** panel, you can edit the animation mask resource in the **Inspector** panel.
+
+
+
+### Bone import
+
+Before everything starts, you need to make sure that all the bones affected by the skeleton mask are selected.
+
+On the **Inspector** panel, click the  button, and in the pop-up prefab selection dialog, we select the prefab where the bone hierarchy is located. In general, we select the imported Prefab from the model file (FBX, glTF) where the target model is located, and usually there is only one.
+
+
+
+When selected, all bones contained in the Prefab will be included in the Bone Mask resource at
+
+。
+
+You can also clear all imported bones by clicking  to clear all imported bones.
+
+### Bone Enable and Disable
+
+When you want the animation effect on a bone to be disabled, make sure the checkbox in front of it remains unchecked.
+
+This is done by clicking on the check box next to the name of the imported skeleton .
+
+If you want to operate only a single bone, you can select it by pressing Alt and using the left mouse button at the same time.
+
+Clicking  check box will check/uncheck both the current skeleton and its children.
+
+By clicking  to expand/hide the sub-bones.
+
+> **Note**: The direct enable/disable relationship between child and parent skeletons is mutually exclusive. That is, even if the parent skeleton is disabled, the child skeleton can still take effect.
+
+If the animation of the layer where the mask is located is not selected, all animations related to that bone will not be played. In the image below, **Bip001 Pelvis** is unchecked, so all animations at that level will not affect that bone.
+
+
+
+## Example
+
+For the full example, please refer to ([GitHub](https://github.com/cocos-creator/example-marionette))
diff --git a/versions/4.0/en/animation/marionette/animation-mask/check-skeleton.png b/versions/4.0/en/animation/marionette/animation-mask/check-skeleton.png
new file mode 100644
index 0000000000..b5f33fc50d
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-mask/check-skeleton.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-mask/checkbox.png b/versions/4.0/en/animation/marionette/animation-mask/checkbox.png
new file mode 100644
index 0000000000..b6dc2e1f2d
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-mask/checkbox.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-mask/clear.png b/versions/4.0/en/animation/marionette/animation-mask/clear.png
new file mode 100644
index 0000000000..a4d18352bb
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-mask/clear.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-mask/create.png b/versions/4.0/en/animation/marionette/animation-mask/create.png
new file mode 100644
index 0000000000..749ff88b60
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-mask/create.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-mask/default-mask.png b/versions/4.0/en/animation/marionette/animation-mask/default-mask.png
new file mode 100644
index 0000000000..0ee6b8b021
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-mask/default-mask.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-mask/expand.png b/versions/4.0/en/animation/marionette/animation-mask/expand.png
new file mode 100644
index 0000000000..213dfb498e
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-mask/expand.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-mask/import-finish.png b/versions/4.0/en/animation/marionette/animation-mask/import-finish.png
new file mode 100644
index 0000000000..77c2a811c2
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-mask/import-finish.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-mask/import-skeleton.png b/versions/4.0/en/animation/marionette/animation-mask/import-skeleton.png
new file mode 100644
index 0000000000..31eadfcb22
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-mask/import-skeleton.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-mask/import.png b/versions/4.0/en/animation/marionette/animation-mask/import.png
new file mode 100644
index 0000000000..7e18574bf7
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-mask/import.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-mask/inspector.png b/versions/4.0/en/animation/marionette/animation-mask/inspector.png
new file mode 100644
index 0000000000..f16b64e557
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-mask/inspector.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-mask/mask-example-skeleton.png b/versions/4.0/en/animation/marionette/animation-mask/mask-example-skeleton.png
new file mode 100644
index 0000000000..a479a526ee
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-mask/mask-example-skeleton.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-mask/revert.png b/versions/4.0/en/animation/marionette/animation-mask/revert.png
new file mode 100644
index 0000000000..1ade8e1f56
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-mask/revert.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-mask/save.png b/versions/4.0/en/animation/marionette/animation-mask/save.png
new file mode 100644
index 0000000000..4efd79783d
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-mask/save.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-mask/select.png b/versions/4.0/en/animation/marionette/animation-mask/select.png
new file mode 100644
index 0000000000..3c0060fa99
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-mask/select.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-mask/weight.png b/versions/4.0/en/animation/marionette/animation-mask/weight.png
new file mode 100644
index 0000000000..77d8f58cf0
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-mask/weight.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-variant.md b/versions/4.0/en/animation/marionette/animation-variant.md
new file mode 100644
index 0000000000..a92d1268fc
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/animation-variant.md
@@ -0,0 +1,26 @@
+# Animation Graph Variants
+
+If two animation graphs have the same animation logic but different corresponding animation clips, re-creating an animation graph will create an additional maintenance burden. By using animation variants, this problem can be better solved.
+
+An animated graph variant is an asset that is created by clicking **Animation Graph Variant** within **Assets Manager**.
+
+
+
+The created variant is shown in the following figure.
+
+
+
+## Properties
+
+
+
+| Properties | Description |
+| :-- | :-- |
+| **Animation Graph** | Animated graph that require variants, selected by drop-down or from within **Assets Manager** |
+| **Clip Overrides** | Animation clips that need to be covered  With the Overrides column on the right, select the animation clips to be replaced from the **Assets Manager** |
+
+## Use of variants
+
+The different variants can be selected by pulling down the **Animation Graph** property of the Animation Controller component.
+
+
diff --git a/versions/4.0/en/animation/marionette/animation-variant/controller.png b/versions/4.0/en/animation/marionette/animation-variant/controller.png
new file mode 100644
index 0000000000..65f186361a
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-variant/controller.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-variant/create-asset.png b/versions/4.0/en/animation/marionette/animation-variant/create-asset.png
new file mode 100644
index 0000000000..f62a61ade1
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-variant/create-asset.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-variant/empty-varint.png b/versions/4.0/en/animation/marionette/animation-variant/empty-varint.png
new file mode 100644
index 0000000000..317cd26341
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-variant/empty-varint.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-variant/overrides.png b/versions/4.0/en/animation/marionette/animation-variant/overrides.png
new file mode 100644
index 0000000000..5bef6ed4ec
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-variant/overrides.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-variant/select.png b/versions/4.0/en/animation/marionette/animation-variant/select.png
new file mode 100644
index 0000000000..08ad16e3b2
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-variant/select.png differ
diff --git a/versions/4.0/en/animation/marionette/animation-variant/variant-asset.png b/versions/4.0/en/animation/marionette/animation-variant/variant-asset.png
new file mode 100644
index 0000000000..d8efd39e94
Binary files /dev/null and b/versions/4.0/en/animation/marionette/animation-variant/variant-asset.png differ
diff --git a/versions/4.0/en/animation/marionette/flow-chart.pos b/versions/4.0/en/animation/marionette/flow-chart.pos
new file mode 100644
index 0000000000..5826a7b2f1
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/flow-chart.pos
@@ -0,0 +1 @@
+{"diagram":{"image":{"x":-129,"width":1455,"y":-35,"pngdata":"iVBORw0KGgoAAAANSUhEUgAABa8AAARGCAYAAAA/wUxuAAAACXBIWXMAAAsTAAALEwEAmpwYAAAgAElEQVR4nOzdeXiV9Z03/s8JkLBFFjUIIyhIqaKABNwISuqGdd+q0kXaccZOO9XaOtpnHn2q1um0I62/tvRpr1HaUfsolJICaqvWhWANCK6AqEHZqmUnggZMCMn9+8NymgiSBELOCbxe1+Vl7vvc3+/3nZMTljd3vicCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgJaUyHQAA9lPtCwsLv5QkyT9FxLBUKtUl04EOMFuTJFkcEb9+5ZVXfhURNZkOBAAAQPMorwGg5bUvLCycGhGXZDoIEUmSPP3KK698NhTYAAAAbYryGgBaWGFh4Vci4tf9+/ePW265JQYOHBj5+fmZjnVAqaysjOXLl8ddd90Vr7/+eiRJ8u+vvPLKDzOdCwAAgKbLyXQAANjf/G2rkLjlllti+PDhiusM6Nq1awwZMiRuvfXWiIhIpVLjMhwJAACAZlJeA0DLGxYRMXDgwEznOOAdfvjhOz78VCZzAAAA0HzKawBoYTvenNEd15nXpUv6fTI7ZTIHAAAAzae8BgAAAAAg6yivAQAAAADIOsprAAAAAACyjvIaAAAAAICso7wGAAAAACDrKK8BAAAAAMg6ymsAAAAAALKO8hoAAAAAgKyjvAYAAAAAIOsorwEAAAAAyDrKawAAAAAAso7yGgAAAACArKO8BgAAAAAg6yivAQAAAADIOu0zHQAAaLotW7bEL37xi+jRo0esXr06/vCHP8T3vve9OPvsszMdrdlmzJgRqVQqLrrookxHAQAAIAsprwGgDZkwYUKcc845cfLJJ0dExPHHHx9r1qzZ6boFCxbEsGHD9mqtlphjd5566qno1KmT8hoAAIBdsm0IALQhTz31VAwfPjx9fP7550f//v13uu6Pf/zjXq/VEnN8kq1bt8bQoUNj8eLF+2wNAAAA2jblNQC0IalUKt59990Gx6eeemr6uK6uLl5++eV4/PHH93iNlpijMQsWLIgTTzwx8vPzY/Xq1ftsHQAAANou24YAQBty9tlnx7e+9a244447GtyBvcMTTzwRW7ZsicrKypg2bVpERAwePDgGDx4cEREffvhhTJ48OQ466KCIiFi+fHmMGjUqioqKmjxHRMTvf//72LBhQ0REvP/++3HddddFXl5ekz+PxYsXx9VXXx1DhgyJRYsWRe/evZv5TAAAAAAA0CyFhYVJYWFhsi/U1NQkEydOTE466aTk5ptvTlavXr3L6z5p/bvvvjuZPHly+riioiI588wzmzXHk08+mTz00EPp44cffjiZMGFCUz+FJEmS5Gc/+1mSJEkyffr0Zo9trh1fj0y/LgAAAGge24YAQBvSvn37+MY3vhG/+93vYuvWrfH5z38+li5d2uTxZ511VoO7rPPy8qKioqJZGR588MH47Gc/mz4eM2ZMPPPMM00ev3379mjf/qMf/hoyZEgsXLiwWesDAABwYLBtCAC0QX379o2f/exn8f3vfz9+/OMfxy9+8YsmjTvuuOPihRdeiJkzZ0b37t2je/fuzV67vLw8nnrqqQbnjjnmmCaPf/PNN2PTpk0xbdq0SJIkli9fHtu2bYvc3NxmZwEAAGD/pbwGgDaitrY2Pvjgg3ThnEql4vrrr4+xY8c2eY6HHnooli1bFv/+7/8e7dq1i4iI2267rVk5kiSJ888/Pzp27Jg+d/nllzd5/Kuvvhpf//rXo1u3bhER8dhjj8Ubb7wRw4YNa1YOAAAA9m+2DQGANqK2tjbuv//+Bufat28fnTp12unanJy//xa/fv36qKuri4iIX//613HDDTeki+vd+aQ5jjzyyFi5cmWDaz9+vDsbN25MF9cREccee2wsWrSoyeMBAAA4MCivAaCNyM3NjYULF8aqVavS555//vk466yzdrq2d+/esWHDhvQ1O4ronJyceO+999LX7Zjr7bffbvIcl112WUydOjV93XvvvReLFy9u8ufx4YcfNjg+9thjY8GCBU0eDwAAwIGh8duuAIBm6d279+0REV/96ldbfO6XX345fvrTn0ZFRUUsWrQo3nrrrfjmN78ZHTp0aHBdjx494ic/+Um8+eabMWzYsOjTp09ERAwaNCjuv//+ePfdd+PFF1+MysrKWL9+feTl5cXQoUObNMfgwYNj+fLlUVJSEq+//nq89dZb8bnPfS5SqVSj+X/961/Hk08+GSNGjIiDDz44IiJ++9vfxtNPPx0DBgyI/v37t8TT1MA999wTERGrV6++o8UnBwAAYJ9p/G+ZAECzFBYWJhERL730UqajEBEjRoyIiIiXX37Zn3sAAADaENuGAAAAAACQdZTXAAAAAABkHeU1AAAAAABZR3kNAAAAAEDWUV4DAAAAAJB1lNcAAAAAAGQd5TUAAAAAAFlHeQ0AAAAAQNZRXgMAAAAAkHWU1wAAAAAAZB3lNQAAAAAAWUd5DQAAAABA1lFeAwAAAACQdZTXAAAAAABkHeU1AAAAAABZR3kNAC1va0REZWVlpnMc8LZu3brjw6pM5gAAAKD5lNcA0MKSJFkcEbF8+fJMRzngrV69OiIikiRZluEoAAAANJPyGgBa3q8jIu66664oLy+PLVu2ZDrPAWfr1q2xdOnS+NGPfrTj1LRM5gEAAKD5UpkOAAD7oQ7Dhw9/LJVKnZHpIERExLzq6urTFi9evC3TQQAAAGi6dpkOAAD7obo1a9ZMPuyww7amUqmCiDgoIjpkOtQBpipJkiUR8ctt27b9o+IaAAAAAGA/UVhYmBQWFiaZzgEAAMCByZ7XAAAAAABkHeU1AAAAAABZR3kNAAAAAEDWUV4DAAAAAJB1lNcAAAAAAGQd5TUAAAAAAFlHeQ0AAAAAQNZRXgMAAAAAkHWU1wAAAAAAZB3lNQAAAAAAWUd5DQAAAABA1lFeAwAAAACQdZTXAAAAAABkHeU1AAAAAABZR3kNAAAAAEDWUV4DAAAAAJB1lNcAAAAAAGQd5TUAAAAAAFlHeQ0AAAAAQNZRXgMAAAAAkHWU1wAAAAAAZB3lNQAAAAAAWUd5DQAAAABA1lFeAwAAAACQdZTXAAAAAABkHeU1AAAAAABZR3kNAAAAAEDWSWU6AAAHjiRJkkxnAD6SSqX8ORAAAMhq7rwGAAAAACDrtM90AAAObNu3b4+1a9dGRERubm707Nkz2rVrl+FUAAAAQKb5cVEAWk39bUOSJImKioro0qVLdOzYMX1NTU1NVFVVRZcuXSInxw8Iwa5UVFTEihUrorCwcI/nsG0IAACQ7bQCALS62traePrpp6NHjx4NiuuIiA4dOkR+fn689dZbUVtbm6GEtKTy8vJMR9jvPPHEE3H00UdnOgYAAMA+pbwGoNU9+OCDccopp6TvrE6SJCZOnNjgmkGDBsWsWbManau8vDyuvfbamDJlSpx66qkxderUuP7662PhwoX7JHtzXH/99a06bk8sXrw4fvWrX8VDDz0UV199dUyYMKFF5y8tLY2vf/3rO51vC89NS6/Z2Gt1+fLlUVJSEldeeeVu59m2bVts3749Onfu3Oicq1atinvvvTemTJkSt912m39IAAAAAIBdSZIkWbJkSfKb3/wm2WHTpk3Jj370o2TMmDHJxz377LPJW2+9tdP5+mbOnJls3LgxSZIkOe+885IkSZL3338/efjhh3c7rjU8//zzuzx///3379G4lrZhw4bklltuSR9XV1cn3/ve91p8nR1fl/qy/bnZF2s29bV67rnn7naeRx99NFm9enWT5vzXf/3XpLq6OkmSJPnrX/+afPnLX07Pk+lfDwAAABrjzmsAWtXMmTPj1FNPTR9369YtbrzxxujSpctO1xYWFsb06dN3O9/o0aOjZ8+eDc7l5+c3WCMTamtr49BDD93p/MqVK+MPf/hDs8ftC1OmTIlzzz03fZybmxvnn3/+Pl+3LTw3+2LNpr5WG9uKes2aNXHYYYc1ac7y8vJYtmxZRET06dMn1q1bt1efAwAAQGtqn+kAABxYFi1aFDfeeONO53dV2HXp0qXRbQ4+Xtzt0L1791i0aFHMnTs3Jk+eHDNnzoyZM2fG888/HxdeeGGMHTs2Vq1aFY899lj07t07Vq9eHQUFBXHBBRdERMTs2bPjzjvvjFtvvTWWLVsWK1asiBNPPDFd7j733HPx2muvRUFBQcyYMSNGjx4d1157bURErF+/PubPnx933313PP300+lMb775ZqxcuTI2bNgQTzzxREREnHbaadGpU6fdjtvhwQcfjLy8vMjJyYmtW7fGF7/4xSZl/STz5s2Lr3zlKw3ODR8+fK/Xq66ujp/+9Kdx8MEHR15eXtTV1aXnbCvPTWNr7u7r/0l291ptqhdffDFOOOGEJs/54x//OA4//PCIiFi7dm36YwAAAACgniRJkgsvvHCXWyHsamuJJEmSz372s7vdQqEpc5x33nnJb3/726S2tjZ59dVXk1dffTVJkiS54447knnz5iVJkiS1tbXJBRdc0GDcGWeckd4yorq6Orn00kvTj11yySVJXV1dkiRJUllZmUyYMKFZeZr7eTzyyCPJ9OnT08ePPvpoMnPmzCZl/SQf/3xbar2f//znSWlpafqxsWPHNulz3N353T2+L56bxtZsyte/uXM25bFJkybt0bgkSZKJEycmL7zwQvo4078eAAAANMa2IQC0qurq6qiqqmrStWvWrGlw1+6e+vDDD2PMmDGRk5MTw4YNi2HDhkVExL/927/FyJEjo7y8PJ544onYtm1bg3EdO3aMk046KSI+2lKj/uM9evSIe++9NzZv3hxdunSJb3/723udc3emTp0aY8eOTR+fccYZMW3atCZlbe31SktL45RTTkk/1r79vv1Br9Z+biJa/+sfEfHOO+9Ev3799mjsa6+9FocffniMHDmyhVMBAADsO8prAFpVnz59YtGiRU269qWXXorevXvv9ZqdOnWKXr167XT+r3/9a9x+++1RWVkZZ599dqMla/2bVX/yk59EbW1tjBs3Lm699daoqKjY65y7s2nTpvQWGhEfFbKbNm1qUtZPkpeXF9XV1S2+XnV1deTm5ja6fkvZF89NY1r76x8R8cwzz8Tpp5/e7HEbNmyIJUuWxMUXX7wPUgEAAOw7ymsAWtWYMWN2+SaM27dv3+lcSUlJnHjiifssyw9+8IO44YYbYsSIEdGuXbsmj6uuro4kSeJrX/tazJgxIwYNGhQ333xzk8fX39+7qXeWH3TQQQ3uGN62bVvk5+c3ec1dOfroo3faU3zWrFl7vV5ubu4e3zGfLc/N7uzt139PVFZWRufOnZv1Oo346A0nn3rqqbj00ksjImL58uUt8tMMAAAArUF5DUCr+tznPhcvv/xy/PnPf46IiM2bN8e0adNi5MiRMXXq1Ni8eXNERMyYMSPefPPNuOyyy/ZZlvXr10fXrl0j4qPyvK6uLtasWRM1NTW7Hbd58+Z0AZ+bmxtf+tKX0rmbomPHjlFbWxtJkqTL4sZceOGF6ecs4qM3DLzooouavOauXHbZZVFSUpI+3rhxY1RWVu71eiNHjozXXnstIiKWLFmSnrMpsuW52Z29/fo3Zlfl8uOPP95ga5Smeuqppxo8F4888kjk5PjjHwAA0DY07/YdANgLt99+++0dOnSI4cOHxy233BL9+/ePQYMGxeDBg+P000+PY489Njp27Bh/+tOf4s4774wbb7wxTjjhhCbN/fjjj8ef/vSn6NOnTwwcODAiIsrLy6OsrCyefvrpOOSQQ2Lbtm0Ntg/p1q1blJSUxKpVq6K8vDzWrVsXVVVVMXLkyHj++edj5syZcfTRR0e/fv1izpw58fDDD8cxxxwT/fv3j2984xvx/vvvx7p162LWrFlx0UUXpfcjXrduXTzzzDPx9NNPx6GHHhq9e/eOvLy89Lrt27eP++67L5YuXRrnnHNO+rHdjRs8eHCUlZXFihUr4u23346Kioq48sorI5VK7TZr3759P/E5O+yww6KqqiqmTZsWr7zySrz11ltx1VVXRSqV2qv1hg4dGv/zP/8Tb7/9dnzwwQfxzjvvxGGHHRb9+vVrM8/N7tZs3779br/+e/JajYhYunRplJSUxOzZs6Ndu3bRtWvXOPjgg6Ouri5eeOGF9L7dzZnz29/+dkyePDkefPDBuO+++2Lz5s3pu7DvuOOOO5oUGAAAIENSjV8CAC0jqbfZ8PLly+OOO+6IQw89NE4//fTo0aNHrF69Op588slYsGBBXH/99XHllVdmMi5khdLS0ujfv38cccQRLTpvqv4eLQAAAFnIX1oAaDXJLt4pb8GCBTFv3rxYu3ZtdOjQIQYMGBCnn356HHLIIZmICFmntra22XtdN4XyGgAAyHb+0gJAq9lVeQ1khvIaAADIdt6xBwAAAACArKO8BgAAAAAAAKBtKCwsTAoLC231AgAAQEa48xoAAAAAgKyjvAYAAAAAIOsorwEAAAAAyDrKawAAAAAAso7yGgAAAACArKO8BgAAAAAg6yivAQAAAADIOsprAAAAAACyjvIaAAAAAICso7wGAAAAACDrKK8BAAAAAMg6ymsAAAAAALKO8hoAAAAAgKyjvAYAAAAAIOu0z3QA4MBSVFSUNOW6srKylHFtd1xVVVX3l156aXO9ce9FRPfGxiVJcuScOXNW7jgeNWrU8lQqdWRj41Kp1PHPPffcgnrjXkmlUsc3Nq6urq547ty5s+vlnBURxU3IefGcOXNm1ltveiqVurixcRHx5bKysvvrjfufVCr15SbkvGHu3Lk/rZfz/4uIG5o7btSoUbelUqnbGxuXJMntc+bMuWPH8SmnnPLNnJycnzQ2LiJ+UlZW9q16OcdHxH1NWO++OXPmfGUPxs2YM2fOJTuOR40adVEqlZrRhJylZWVln9lxcMopp4zJyckpbcJ6r86ZM2f4juPRo0cPS5Lk1SaMWzFnzpz+9XIekUqlVjQh56aysrIeOw5GjBjRrWPHjpuaMK7N/Fph3L4dBwAAbZ07r4FWU1RUdFNTr314/ftJ/f+Ma1vjvlPyyKb64/K6dGm0uI6I+Nq996+oP65br15HNmXc+Lsnvlp/XK8BRzVaXEdEfOE/J5TWH9f3uCHFTRl36f/+7oz64wadPKopxXWce/2376s/bsgZZ325KePO/Od/+Un9cSMvuLjR4npX40aP++LtTRk3etwXb6//9T7zn/+lKcV1jLzg4hvqr3fu9d++rynjhpxx1pf3ZNygk0ddXH/cpf/7u00prqPvcUOK64/7wn9OKG3KuF4Djjq+/rjxd09stLiOiOjWq9eR9cd97d77VzRlXF6XLt3rj/tOySNNKq4j2s6vFca1/Lip69Z1ber1AACQ7dydAbSq5vwlHMis28cWf/T/J0ozmgNouqqkKv+KgoLKTOcAAICW4M5rAADYD9RUV8X8kpLOmc4BAAAtxZ7XAACwH5g4flzUVFWtLS4uzi8tLXX3NQAAbZ47r4FWU1RUdNes+yZlOgYAAAAAbYDyGmhNN82fUZLpDAAAAAC0AcprAAAAAACyjvIaAAAAAICso7wGAAAAACDrKK8BAAAAAMg6ymsAAAAAALKO8hoAAAAAgKyjvAYAgP1Ah9y8iIitFRUVSaazAABAS2if6QAAAMDeu+6BKVGVVPW6oqBgS6azAABAS3DnNdCabi4ef02mMwAAAADQBiivgVZTVlY24aRLLs90DAAAAADaANuGAAAREbHslZfirRfm7XT+iXt+kf647+BjY/DoMa0ZC2iimuqqmP9ISeeIqMx0FgAAaAnKawAgIiJy2rWLuSVTdzpf/1zfwd9rzUhAM0wcPy5qqqrWFhcX55eWliqwAQBo82wbArSaoqKiu2bdNynTMYBP0HfwcdEpP/8TH8/r3Dk+fdIprZgIAACAA5nyGmhNN82fUZLpDMAnaNe+fRw75vRPfHxA4cho16FDKyYCAADgQKa8BgDSBhed+omPHXuqva4BAABoPcprACCt35Chkde5807nO+TlxadHjc5AIgAAAA5UymsAIK19h9w4ZvTOd1gPGD4iOuTmZSARAAAAByrlNQDQwOBdbA9yTNFpGUgCAADAgUx5DQA0cOTQ4yO3Y8f0cfvcvF0W2gAAALAvKa8BgAZyO3aMo+vtb33k0GGR26lTBhMBAABwIFJeAwA7qb/v9dHeqBHahL/tS7+1oqIiyXQWAABoCe0zHQAAyD4Dho+I9h1yoy6pi2NP+0ym4wBNcN0DU6Iqqep1RUHBlkxnAQCAluDOa6A13Vw8/ppMZwCaIK9z5xh00ilxxHFDo1N+fqbjAAAAcABKZToAcGB5eP37fpQZ2ojFz86Kyvfei5MuujTTUYAmqkqq8q8oKKjMdA4AAGgJtg0BgH3kjcXvRNmf34g1q96L2tq6TMdpvtrqiCSJx+dPznSSZmvXLicKenWLU0YfE0OGHZHpONAqaqqrYv4jJZ0jQnkNAMB+wZ3XQKty5zUHijcWvxNTH3ou0zGIiPMvPiFGnDAw0zFgn7v7qkuipqoqOnTokF9aWqrABgCgzbPnNdBqioqK7pp136RMx4BWUfbnNzIdgb+ZN2dJpiMAAACwB5TXQGu6af6MkkxngFaxZtV7mY7A32zc+EGmIwAAALAHlNcAsA+0yT2u91N1vhYAAABtkvIaAAAAAICso7wGAAAAACDrKK8BAAAAAMg6ymsA2E+kUhGFg3pnOgYAAAC0iPaZDgAANNSlY258/eKRUfF+VfQ+uGucd/KguO1/ZsWfXly623FXnX5c3HjFqBj51XtafW0AAABoacprAMgy/3blqHjihbfj+dffjYiIBUvXxGE9uzY6bvLTr8WNV4xqlbWHHtUrFi5du1drtcQcwN91yM2LmqqqrRUVFUmmswAAQEuwbQgAZJkzRwyIV95akz5+dO6SWL7mvaxa+9yTPrXXa7XEHMDfXffAlPjm9Om9Fi5cuCXTWQAAoCUor4HWdHPx+GsynQGyXpIkcfihB9U7jvjzwr9kxdo5qVQUfqp3nHPiwD1eoyXmAAAAYP9n2xCg1ZSVlU34zozH7sp0Dsh2f3pxadz9r2fH7feVNrgLOiLiC2cOjW997uT0vtYXFn06vnv1mAb7XB95WPcYe8LAyO+cGwcf1Dn+4zfPxpaqbXu9dkTE2BOPis55udG1U25cdtrgiIh4Y+X6eH3l+oiI6JTXPsadPiTe31odSRLRv3f3mLv43Sh77S9NniMi4tJTj4lDunWOiIj8znnx8+nzo7pme5M+BwAAAPYPymsAyDI/fOi5+OoFI+MXN5wfsxesiJ9Mez7WVFRGRMSDTy2Mb33u5PS1D5eVx3evHtNg/GnDjoj/fuTFiIi4ovjY+OqFI+LuqXPjtGFHxJhhR+xyzSdeWBrz3/jrbteOiHhs3tsREfHvXxgdJc++vtM8/3LhyFi9sTKmzf7osR75HeO33/1cnH3Tb5o8xxmFAyIvt13c8+hLERFxwahB8Y1LTowfT53TyDMHB7aa6qqY/0hJ54iobPRiAABoA5TXAJBlttfWxf+dMT8envNm3HRVUTx466Xxzz96JJatatq+14/Pfzv98Z8XrYxffuv8uHvq3Hh2wcp4dsHKfbr2ky8ui81bqtLH1TW10fOgTk0au8MXzhoS3/6/T6SPZ7+6Mr524QnKa2jExPHjoqaqam1xcXF+aWmpAhsAgDbPntdAqykqKrpr1n2TMh0D2ox31r0f35z4WDzz8or4tytGNXncuve21Pt4a/Tq0bXV1n5t+bo4rGfX+NeLT4wvnjU0Th/ev9lrf7rvwXHmiAFx2WmD47LTBsdZI4+KN/6yvvGBAAAA7FfceQ20ppvmzyiJz3z5nzKdA7JWu5ycyO+cG5sqP7p7Oa2q1LEAACAASURBVEkiJv5+Xjx+1xf3aL5UKiKJpNXW/vwZQ6J/7x7xw4eei9q6uoiIuP3Lxc3MnIpH5y6Jqm1/3+N6V9uLAAAAsH9z5zUAZJF2Oam4euywBue219bFh9tq0sd1SVLv+p1/K8/JSaU/LujeJd5Zt7nF1t5VhkO7d46c1EdrfuWzw+OnJc+ni+vd+aQ5VqzZFP16dWtw7cePAQAA2P8prwEgi2zbXhtDB/SKPgfnp8+dPPjwePLFZenjNRWV0bfgoIiIKD7+yIj46A7rHY7rX5D+uPj4I2Pmc+UttnY6w8bKOKRb5/Q1O4rouqQueuR3TF+3Y66B/9CzyXOUzH4jrvzMsenreuR3jOOOLNhpPAAAAPu3dpkOABw4+vXrd3tExOir9mz7A2hLZj/z2h6PLRzUO755+clxcLdOMXRAr/hU357xs5J5UVP70d3MH2zdFt8ZNzqO6XdI/GXt5hh21GGRSqVi4bK10a9Xt2iXkxPHDzwsTjm2b7RrlxMP/GlBi629Q8UHVXHD5SfF0f0OiQVL18bqjR+9N9ySdzfG+LHHR9+Cg+KEo/tE10550atHl6iuqY2Fy9Y2aY43Vq6PAb17xKWnHRODjyiIQX0Pjt/Nfj2Spu1+skvFZwzZ88HQRsyd9tuo27492rVr94MVK1Zsy3QeAADYW6nGLwFoGUVFRUlExHdmPJbpKLDP3XHL5ExHoJ7bvj8u0xFgn7v7qkuipqoqOnTokF9aWlqZ6TwAALC3bBsCAAAAAEDWUV4DAAAAAJB1lNcAALAf6JCbFxGxtaKiYi92iAcAgOzRPtMBAACAvXfdA1OiKqnqdUVBwZZMZwEAgJbgzmugNd1cPP6aTGcAAAAAoA1QXgOtpqysbMJJl1ye6RgAAAAAtAHKawAA2A/UVFfF/JKSzpnOAQAALUV5DQBtyIVFn44X//va+O7VY9LnCgf1jhf/+9q4ePTRLbLGuDOOixf/+9pGr5v8fy6PH/zzmS2yJrD3Jo4fF3P/3/9bW1xc3DXTWQAAoCUor4FWU1RUdNes+yZlOga0aQ+XlUdERP/ePdLnjujVLSIiZjz3ZousMfnp15p03TOvLIvnX3+3RdYEAACAj1NeA63ppvkzSjKdAfYLNbW16Y+ra2p3c+W+c++jL8fMspYpzAEAAODjlNcA0Aat37QlCrp3+eggaf31czu0i1OOPbz1FwYAAOCA0T7TAQCA5lu66r3o37tHrN+8JeqShu11p7z2Me70IfH+1upIkoj+vbvH3MXvRtlrf2lw3cWjj46C7l2ismpbHNGrW/z4t3Nj2/a/38Vd+KnecebIATH4iEPj939+I71lydCjesXxAw+L6y89KUZ+9Z4Gc44fe3xcd+mJ8Y//NTPGHH9EHN3vkPjD3Lfij/PeSl9z6anHxCHdPnpPufzOefHz6fOjumZ7iz4/AAAAtH3uvAaANmj56vdiQJ/u0btnfqzeWNngsX+5cGRsra6JabNfj5JnX49f/fHluG38mAbXfGb4kTH0qF5xz6MvxUNPLYqIj94Msr4jDusWd00ui/91z1PxLxeOTJ9fuHRtPPDEgl3muv+JVyMiYuDhPWPi7+fHHffPjq9ddEL68TMKB0Rebru459GX4p5HX4ol726Ib1xy4p4/EQAAAOy3lNcA0AbtuPP6qH/oEW//taLBY0++uKzBXdbVNbXR86BODa750tnD4neli9PHL7y5Kt56t+E8O94Acu17lXFoty7Nyjfjzx+NXb9pS/Tq+fexXzhrSDw27+308exXV8YZhf2bNTcAAAAHBtuGAEAb9O769+PwQw6KLh1zY0vVtgaPvbZ8XZxwdJ+4cNTRsXlLVWyqrNpp/Kf7HhxLV72XPn7qpWU7XbNjN5IkiUilmpdvx1YmSRKRU2/wp/seHGeOGBD1dzp54y/rmzc5AAAABwTlNQC0QXV1SeTk7LpR/vwZQ6J/7x7xw4eei9q6uoiIuP3LxQ2uSaVSUVfX+u/0mEql4tG5S6Jq29/3uC559vVWzwEAAED2s20IALRRFe9/GAcf1Hmn81/57PD4acnz6eJ6V/6ydnP0LTiowbnBRxza4hk/bsWaTdGvV7cG5z5+DOyZDrl5ERFbKyoqWv9fpgAAYB9QXgNAG7V01XuxftOWnc7XJXXRI79j+rjPwfkRETHwH3qmz8147s249NTB6eODOufF4CP3fXldMvuNuPIzx6aPe+R3jOOOLNjn68KB4LoHpsQ3p0/vtXDhwp1/YQAAgDaoXaYDAAeOfv36bS0ef81Zhx8zuPGLoY2b/cxr+2Tec0/6VHxmeP9Y8u7G2FT5YSxfvSlOGnx4nF7YP9Zt2hJv/mVDLHl3Y4wfe3z0LTgoTji6T3TtlBe9enSJ6praWLhsbURELF6xLo4bUBDnnTIojuvfK4YMKIgpz7wWtXVJXD5mcIwe0i/eWb853v5rRZxz4sA4vbB/bKqsisUr1sfQo3rF2SccFScPPjxq65IY0LtHVLz/YWyp2tbo2DdWro8BvXvEpacdE4OPKIhBfQ+O381+vcEe2PtC8RlD9u0CkCW2x/Yf/G7ChG2NXwkAANmvmW+/BLB3Hl7/vh9l5oBwxy2TMx2Bem77/rhMR4BWUZVU5V9RUFCZ6RwAANASbBsCAAD7gZrqqphfUrLzRvgAANBGtc90AAAAYO9NHD8uaqqq1hYXF+eXlpa6+xoAgDbPnddAqykqKrpr1n2TMh0DAAAAgDZAeQ20ppvmzyjJdAYAAAAA2gDlNQAAAAAAWUd5DQD7QLt2fovNFjk5qUxHAAAAYA/4mzUA7AMFvbplOgJ/06Nn10xHAAAAYA8orwFgHzhl9DGZjsDfjDhxYKYjAAAAsAfaZzoAAOyPhgw7IrZtq4l5c5bExo0fRF1tXaYjHVByclLRo2fXGHHiwDil6OhMxwEAAGAPKK8BYB8ZccLAGHFC273r9/axxRER8Znx/xhjPn91ZsMAAABwwLFtCAAA7Ac65OZFRGytqKhIMp0FAABagjuvAQBgP3DdA1OiKqnqdUVBwZZMZwEAgJbgzmugNd1cPP6aTGcAAAAAoA1QXgOtpqysbMJJl1ye6RgAAAAAtAHKawAA2A/UVFfF/JKSzpnOAQAALcWe1wAAsB+YOH5c1FRVrS0uLs4vLS2tzHQeAADYW+68BlpNUVHRXbPum5TpGAAAAAC0AcproDXdNH9GSaYzAAAAANAGKK8BAAAAAMg6ymsAAAAAALKO8hoAAAAAgKyjvAYAAAAAIOsorwEAAAAAyDrKawAAAAAAso7yGgAA9gMdcvMiIrZWVFQkmc4CAAAtoX2mAwAAAHvvugemRFVS1euKgoItmc4CAAAtwZ3XQGu6uXj8NZnOAAAAAEAboLwGWk1ZWdmEky65PNMxAAAAAGgDlNcAALAfqKmuivklJZ0znQMAAFqKPa8BAGA/MHH8uKipqlpbXFycX1paWpnpPAAAsLfceQ20mqKiortm3Tcp0zEAAAAAaAOU10Brumn+jJJMZwAAAACgDVBeAwAAAACQdZTXAAAAAABkHeU1AAAAAABZR3kNAAAAAEDWUV4DAAAAAJB1lNcAAAAAAGQd5TUAAOwHOuTmRURsraioSDKdBQAAWkL7TAcAAAD23nUPTImqpKrXFQUFWzKdBQAAWoI7r4HWdHPx+GsynQEAAACANkB5DbSasrKyCSddcnmmYwAAAADQBiivAQBgP1BTXRXzS0o6ZzoHAAC0FHteAwDAfmDi+HFRU1W1tri4OL+0tLQy03kAAGBvufMaaDVFRUV3zbpvUqZjAAAAANAGKK+B1nTT/Bklmc4AAAAAQBugvAYAAAAAIOvY8xpoMy44JD/TEaBNemTDBxlZ1/cs7JlMfc8CAEC2cec1AAAAAABZx53XAECrSZIk1q1bF9u3b4+OHTtGz549I5VKZToWAAAAWUh5DbRZS5YsiRdffDEOOuigiIiorq6ODz74IEaOHBnHHXdchtMBH7dp06Zo3759HHLIIdGuXbuoq6uLbdu2RU1NTXTt2jXT8QAAAMgyymugTZo8eXLk5OTEuHHjdrpr8/HHH4/FixfHlVdemaF0tKTy8vL49Kc/nekY7IUkSWL27NkxatSoyM3NTZ/PycmJvLy8yM3NjfLy8hg0aJC7sPcDvmcBAICWYs9roM2ZOXNmbN++Pa688srYuHFj/PKXv4z/+I//iEmTJsXWrVvjnHPOib59+8bMmTMbnau8vDyuvfbamDJlSpx66qkxderUuP7662PhwoWt8Jns3vXXX9+q4/bE4sWL41e/+lU89NBDcfXVV8eECRNadP7S0tL4+te/vtP5tvDctPSajb1Wly9fHiUlJVn5jza/+93vYujQoZGbmxtbt26NadOmxS9/+ct49tlnI0mSSKVSMXDgwHj22Wcbncv37N7xPdt6azb2Wl21alXce++9MWXKlLjtttuivLx8r9fskJsXEbG1oqIi2evJAAAgCyivgTZlw4YN8cc//jG++MUvRl1dXdx7773xla98JW699dY45JBD4rrrrouIiFGjRsWSJUtiw4YNu52vvLw8fvjDH8ZVV10V3bp1iyuuuCK+//3vx8qVK1vj09mtL3zhC7s8/8ADD+zRuJa2cePGmDx5clxzzTXx+c9/PiZNmhRVVVUtukZxcXF06tRpp/PZ/tzsizUbe632798/LrvssqisrGyR9VrKO++8E5WVldGzZ8/48MMPY9KkSXHmmWfGtddeG8uWLYs777wzIiK9jcg777yz2/l8z+4537NN01rfs//5n/8Z48ePj6uuuiq++tWvxg9/+MO9XvO6B6bEN6dP77Vw4cItez0ZAABkAeU10JpuLh5/zV5NMGPGjLjooosilUrFkiVL4u23346OHTtGRMTFF18cy5Yti4qKioiIGDt2bMyYMWO3840ePTp69uzZ4Fx+fn6ceuqpe5Vzb9XW1sahhx660/mVK1fGH/7wh2aP2xemTJkS5557bvo4Nzc3zj///H2+blt4bvbFmk19rWbbthvTp0+PMWPGRETE66+/HqWlpdG9e/do165dXHLJJfHoo4+mrx0xYkRMnz59t/P5nt1zvmcb15rfs+Xl5bFs2bKIiOjTp0+sW7euRdYFAID9iT2vgVZTVlY24TszHrtrb+aYN29e/Nd//VdERAwYMCDOO++89GPvvfde5Obmpt/AcfDgwfHzn/88/umf/ukT5/t4sbBD9+7dY9GiRTF37tyYPHlyzJw5M2bOnBnPP/98XHjhhTF27NhYtWpVPPbYY9G7d+9YvXp1FBQUxAUXXBAREbNnz44777wzbr311li2bFn8/+zdeXiU5bk/8HsSEhBZRCQRlEXcUJRVjRCsKLjVDZci1l1re7S1P4+12tpa7VG7uB0ttta6VC24VRTFulCVaIkQBAUEcRfBhV02MWSZ+f3hYQpFSAJJJomfz3VxyfPOe7/PdybMi9fNM8/MnTs3DjjggHSjaOLEiTFr1qzIy8uLsWPHxqBBg+L73/9+REQsXrw4pkyZEjfffHO88MIL6UxvvfVWfPTRR7FkyZJ47rnnIiLiW9/6VnqV46bq1hk9enQ0b948srKyYs2aNXH66adXK+vmfhbnnHPOBsf69u271fOtXbs2br311mjfvn00b948kslk+pqN5bWpas7N/fw3ZXN/Vhuy6dOnx49+9KOI+Ko5PXr06PRjM2fOjKFDh6bHbdq0iVmzZm32et6z3rN18dpUNWddvGdvuumm2HnnnSMiYuHChenfAwAAABny5OKVqS39lUqlUscdd1xqU6688srUP//5zw2OnXjiiZs8/z8dffTRmzz+8MMPpyorK1PTp09PTZ8+PZVKpVK//vWvUyUlJalUKpWqrKxMHXvssRvUDRkyJDV58uRUKpVKrV27doMsJ5xwQiqZTKZSqVRq9erVqRtuuKFGeWr6PMaNG5d6/PHH0+Onnnoq9cQTT1Qr66b85/Otrfluu+22VFFRUfqxI444olrPcXPHN/d4Xbw2Vc1ZnZ9/Ta+52fnOPHuLfvXr1y/Vr1+/1KFHHbVF9alUKjVs2LCN8kyePDl16623pn71q1+lli9fvsFjxxxzzFa/Dt6zX897tnrq+z2bSqVSI0eOTL366qvp8Zb+PTnm40WpS2+/PS/Tf9cDAEBtsfIaaFTKy8u/9vgdd9wR++233warOJPJZKxatWqr5/zyyy/j4IMPjqysrOjdu3f6+KWXXhotWrRIf/S7rKxsg7oWLVpEQUFBRHz18fz1H2/Xrl3ceeedccopp0Tbtm3jkksu2eqcm/PII4/EHXfckR4PGTIkvv/978dxxx1XZdb6nq+oqCjOP//89GPNmtXtX1X1/dpE1P/P/6NZW/dlhssXLozlCxduUe0XX3wRZWVlkZubGxUVFZFIJKKgoCAKCgri/fffj3POOSfuu+++aN26dSxZsiTWrl27VVkjvGfrez7v2a0za9as2HnnnWO//fbb6muNPOvUKC8tXTh48ODWRUVFDWsDfAAA2AKa10C9KSwsvH7CvXfFIWdvehuPqrRt2zY+//zzaNeuXfrYXXfdFX369Ek3K95///3YddddY+7cuZv82HZNbLPNNpGfn7/R8U8++ST+9re/xfHHHx+HH354/PGPf9zsdVKpVPr3t9xyS4waNSpOPfXU6NevX1x88cWxww47bHXWTVm+fPkGX6LWokWLWL58ebWybkrz5s1j7dq10bx581qdb+3atZGbm1vl/LWlLl6bqtT3z/+cm/6wRXVfrloZq5d9Hjt06bLFe2nvuOOOMWfOnOjdu3fccccdkUgk4sILL4yIiF133TU6deoU77zzTvTv3z+mT5/+te+1mvKe/Xres1uurn7+S5YsiXfeeSdOPPHErb4WAAA0RZrXQH366ZSxY7aqeX3AAQfElClT4ogjjohkMhl33nlnDBkyJHbbbbeI+GoF28qVK2PXXXeN4uLiDVZd1rbf/va3ceONN9a4Qb527dpIpVJxwQUXxHnnnRcPPfRQXHbZZXHPPfdUq379JmIymYysrKq/e7dNmzbp1a8REWVlZdG6desa5f5PPXr0iLfffjt69eqVPjZhwoQ45JBDtmq+3Nzcaj+v/9RQXpvN2dqf/5bouk+vqk+qI4WFhfHkk09G7969Y9CgQfHuu++mH/vss89i7dq16T9Djz32WPTv37/OsnjPes9uibp6z1ZWVsbzzz8fI0aMiIiIDz/8MLp27bpFryMAADRV/u8YaFRGjBgRjz76aCSTyXjrrbeiqKgofvOb38S5554b5557bvzmN7+JDh06RFlZWTz00EN1uppt8eLF0apVq4iIqKioiGQyGQsWLNjk1ibrrFixIh5//PGI+Krpc8YZZ8SKFSuqPW+LFi2isrIyUqlUTJgwoVo1xx13XPzrX/9KjydOnBjHH398tef8OieddFKMGTMmPV66dGmsXr16q+fbb7/90l/a984776SvWR0N5bXZnK39+Vdl/S/LawhGjBgRRUVFMX369Ojdu3d07tw57r777rjnnnviqaeeihtvvDFycnJiwoQJMXXq1Dj55JPrLIv3rPfslqir9+zzzz+/Qe5x48ZpXAMAwH/IznQA4JujS5cuV0dEDBpx+hbV79myebRu3ToSiURMmDAhvv3tb8fJJ58cxx9/fPrXSSedFO3bt4/f/e530bVr1xg2bFi1rv3ss8/G+PHjo1OnTulV3G+//XYUFxfHCy+8EDvssEOUlZVtsBVB27ZtY8yYMfHpp5/G22+/HYsWLYrS0tLYb7/9YvLkyfHEE09Ejx49okuXLvHKK6/Ek08+GXvttVfssssu8aMf/ShWrlwZixYtigkTJsTxxx8fXbp0iYiIRYsWxYsvvhgvvPBCdOjQITp27LjBx/ybNWsW9957b7z//vtx5JFHph/bXN3ee+8dxcXFMXfu3Hjvvfdi2bJlccopp0Qikdhs1s6dO2/yNdtxxx2jtLQ0Hn300Xj99dfj3XffjREjRkQikdiq+Xr16hV//etf47333otVq1bF/PnzY8cdd4wuXbo0mtdmc3M2a9Zssz//LfmzGvHVdjljxoyJl156KbKzs6NVq1bRvn37iIh4Z83W7/m7JfZs2TxatGgRPXr0iCuuuCL69OkT/fr1i379+kXfvn2jf//+0aJFi3j11VfjZz/7WXzve9+LwYMHV+va3rPes439PXvJJZfEgw8+GKNHj4577703VqxYkf4H1y19z0569OFIVlREdnb2b+fOnZuZNz4AANSiLdvAEmALFBYWpiIiLh/7zBbVH7vDvz8W/txzz8WHH34Y55xzzgaNkC+++CJuvvnmWLNmTVxzzTV1/sVh0BiMW7L1X1y6JdZ/z86YMSN+/etfx/777x9DhgyJdu3axaeffhr//Oc/4/nnn48zzzwzvRc2fNNt6Xv25hEnRHlpaeTk5PjCRgAAmgRdHaBROuKII2LFihXx3HPPRbNmzaK8vDwWL14cixYtikMOOSQGDRqU6YjAenr37h1///vfY8KECfH888/HwoULIzc3N7p37x4PPPBAdO/ePdMRAQAAaGA0r4FGq23btnHcccdlOgZQTdnZ2TF06NAYOnRopqMAAADQCPhWGAAAAAAAGhzNawAAaAJycptHRKxZtmxZKtNZAACgNvjCRqDebO0XNn4TXX3E4K/++1xRRnMA1If/+faQSFZWxq+efiGysrMzHadRKk2Vth6el+fLGgEAaBKsvAbq02WDzzov0xkAAAAAaAQ0r4F6U1xcfEPBCSdnOgYAAAAAjYDmNQAANAHla0tjypgxLTOdAwAAakuzTAcAAAC23sizTo3y0tKFgwcPbl1UVGTfawAAGj0rr4F6U1hYeP2Ee+/KdAwAAAAAGgHNa6A+/XTK2DGZzgAAAABAI6B5DQAAAABAg6N5DQAAAABAg6N5DQAAAABAg6N5DQAAAABAg6N5DQAAAABAg6N5DQAAAABAg6N5DQAATUBObvOIiDXLli1LZToLAADUhmaZDgAAAGy9i+5/KEpTpfnD8/K+yHQWAACoDVZeA/XpssFnnZfpDAAAAAA0AprXQL0pLi6+oeCEkzMdAwAAAIBGQPMaAACagPK1pTFlzJiWmc4BAAC1xZ7XAADQBIw869QoLy1dOHjw4NZFRUWrM50HAAC2lpXXQL0pLCy8fsK9d2U6BgAAAACNgOY1UJ9+OmXsmExnAAAAAKAR0LwGAAAAAKDB0bwGAAAAAKDB0bwGAAAAAKDBaZbpAAD82+vPPR1Fo+7d6Pj/njE8/ft9Dz0shp5zfj2mAqgb08c/GxP+dk96nEomIyLi1rNPTR/rd+TRcfBpZ9V7NgAAIPM0rwEakJ177B0rFi3a6Pj6x3bfv6A+IwHUmZ337lnlPW/XfvvXZyQAAKABsW0IQAPSoWu3aL9z500+3mr79tF1n171mAig7uywc+fo0LXbJh9v0yEvdt5r7/oLBAAANCia1wANTK8hh23yse59+tZjEoC61+vQTd/zfNKkZnJym0dErFm2bFkq01kAAKA2aF4DNDB7Hjhwk4/1OfyoekwCUPf2KBiwycf2GXxoPSZp/C66/6H4f48/nj9z5swvMp0FAABqg+Y1UJ8uG3zWeZnO0ODt2H232C5/x42Ot2y7XezSp18GEgHUnfxdusf2nXba6Pi227WLbr36ZCARAADQUGheA/WmuLj4hoITTs50jEbh6z5Gv0vvvpFIJDKQBqBu7Xvo0I2O7b5/gXseAAB8w2leAzRAew4o3OhY76GHZyAJQN3b88CN73m2DKm58rWlMWXMmJaZzgEAALVF8xqgAeq0x57Ruv0O6fE2rVv74jKgyeq42+7RNi8vPd6mTZvo3rd/BhM1TiPPOjUmjRq1cPDgwa0ynQUAAGqD5jVQbwoLC6+fcO9dmY7RKCQSiei13sfou+7bOxJZbtlA05RIJGLf9bZL2rXffpGVnZ3BRAAAQEOgEwLUp59OGTsm0xkajfW3Dvm6/WABmpIe620d0vOgwZkLAgAANBjNMh0AgK+3c4+9Y9u220VlZUXsNfCgTMcBqFM77dkjtt2uXVSUrY09CgZkOg4AANAAaF4DNFBZ2dmxz+BDY/Xnn/v4PNDkJbKyoteQw2L5ggWRnZOT6TgAAEADoHkNNGlzZs+P4n/NiQWffh6VlclMx6mx1MrySFTmxK9/8WCmo9RYdnZW5OW3jQGD9op9e3fNdBz4Rmjs97xYXRqpte55AADAVzSvgSZrzuz58cgDEzMdY+u0yo9IZDrElqmsTMZnn34ejz3ySpSVlUf//XfLdCRo0prCPS+1bX5Ey0bYdA/3PAAAqAu+sBFosor/NSfTEbZaIis7ItH4twwpeeWdTEeAJq9J3PMSWZHIavxrK9zzAACgdmheA03Wgk8/z3QE/s/SpasyHQGaPPe8hsM9DwAAaofmNdBkNcr9XpuopJ8F1Dn3vIYjU/e8nNzmERFrli1blspIAAAAqGWN/3OZAABAXHT/Q1GaKs0fnpf3RaazAABAbbDyGqhPlw0+67xMZwAAAACgEdC8BupNcXHxDQUnnJzpGAAAAAA0AprXAADQBJSvLY0pY8a0zHQOAACoLfa8BgCAJmDkWadGeWnpwsGDB7cuKipanek8AACwtay8BupNYWHh9RPuvSvTMQAAAABoBDSvgfr00yljx2Q6AwAAAACNgOY1AAAAAAANjuY1AAAAAAANjuY1AAAAAAANjuY1AAAAAAANjuY1AAAAAAANjuY1AAAAAAANjuY1AAA0ATm5zSMi1ixbtiyV6SwAAFAbmmU6AAAAsPUuuv+hKE2V5g/Py/si01kAAKA2aF4D9emywWedd32mQ2ytbVvkxoXD9otlK0ujY/tWcfSBe8RVf50Q46e+n+lo1XLqkH3iJ8MHxh/HTonVX5ZFh+22je4d28UfHiuJglcSZgAAIABJREFUeQtXZDoe0MA09nveOq1b5sYZh/WO1aVl0S1/uzh6wO5x8W3PxqTZH2c6GgAAsAma10C9KS4uvuHysc80+ub1pacMjOdefS8mv/lVw2PG+wtix+1bbXRer13zY+b7C7dqrtq4xn968IVZ8ZPhA+Ovz0xPHxu4T+e4+uzBce7vn6jVuYDGr7Hf8yIiEomI/znn0PjdAxNj4eerIyJi+vsLYo+dd9C8BgCABsye1wA1NLR/93j93QXp8VOT3okPF3y+0XnfLth9q+eqjWtUx6tvfRJ7delQL3MBjUtTuOcd0meXmLdoebpxHREx7pW3o3ludp3Mlynla0tjypgxLTOdAwAAaovmNUANpVKp2LlDm/XGEf+aOS89zkokot/uHePIA3bb4jlq4xo10XbbFvH56i/rZS6gcWkK97wjD9gtJr4xb4NjqVTEvc9O30RF4zTyrFNj0qhRCwcPHrzx0ngAAGiEbBsC1JvCwsLrJ9x7Vxxy9vcyHWWrjJ/6ftz8w8Pj6nuLNliNuM4RB+waLZvnRqttcuOkb+0dERFzPlocb360OCIitmneLE49dN9YuWZtpFIRu3TcLibN/jiKZ82r9jUiIk48aK/Yoe1XC+xat2wetz0+JdaWV9T4+SQSEd87ul/c9+yMGtcCTV9TuOft3a1DvP/gxqvFy8orq/kqAAAAmaB5DdSnn04ZO6bRN69/98DE+MGx+8WfLj4mXpoxN255dHIsWPbvj6I/U/JeRET8/LRBMeblNzeq/6/j9ovPlq6OR1/66rF2rVvEw7/6Thz+079V+xpD+nWP5rnZ8ZenpkVExLED94gfnXBA3PTIK9V+Hid9a+/IzkrE4L7dYsZ7C+PhCbOqXQt8czSFe177Ni1jxeq11XzGAABAQ2HbEIAaqqhMxh/HTonhv34kWrbIidG/PDG6d2pX7fp/Tv1ggxWHa8srY/s229Qow2mH7Ztu9kREvDT9oxjSb5caXWPMy2/GI0Wz40e3Ph2d89rU2/7aQOPSFO55Wf6PFwAAGiUrrwG20PxFK+P/jXwmrjjtW3Hp8IFx4S3/qFbdrA8Xxf49OsVxA3vEii9KY/nq0hrPvWfn9jG0f/dIpf59bM68xZsu2IxkMhV3/eO1+J9zD4mnS97domsATV9jvuet/rIsWm2TGyu+qPncAABA5mheA9RAdlZWtG6Zm26+pFIRIx8riWevP73a1/jukH1jl47t4ncPTIzKZDIiIq4+e3CNciQSiXhq0jtRWvbv/V6/7qP21TV/0crYtQYrKYFvhqZyz/to4YrYuUObjZrX3Tu2iw8+23gvbAAAoGHwIUqAGsjOSsSZR/Te4FhFZTK+LCvf6NzkeksEO2zXMrISiYiIOOeovnHrmMnpJs7mbOoacxcsjy75bTc49z/HNbHtNjmx1heXAf+hqdzzSt78JPbv0WmDY7nNsmP/HjtV+xoAAED907wGqIGyisro1T0/OrVvnT524N47xz+nfrDRuQuWro4d2rZMn7OuKZNMJaNd6xbp89Zda7edtq/2Nca8NCdOOaRn+rx2rVvEPt3ytvh5HbH/rvH8tI2fA/DN1lTueY8UzYrD99t1gxxnHN47XnjNfQ8AABqy7EwHAL45unTpcnVExKAR1f+4+dZ46cVZdXLdfnt0jP938oHRvu020at7fuzeefv4w5iSKK/ccFXhslWlcfHJBdGjyw4x4/2F8dnS1RER8c7HS+OsI/pE57w2sX+PTtFqm+aR327bWFteGTM/WFita8z5aHF079guTvzWXrF317zYo3P7+PtLb26wH+zXyWmWFacf1isK9to5yioqY9dO28fAnp0jv12r+MOYkqiorHpl5JYaPGTfOrs24J63OaVlFTHj/YXx4xMLYmDPznFI313ihdc+iA8/W771L9AmZOKeN+nRhyNZURHZ2dm/nTt3blm9BwAAgFqWyHQA4JujsLAwFRFx+dhn6mW+X//iwXqZh+q56rpTMx0BmjT3vIYlE/e8kWeOiDUrV6xZtWpV3syZM7+o9wAAAFDLfGEjAAA0ARfd/1CUpkrzh+flaVwDANAk2PMaqE+XDT7rvExnAAAAAKAR0LwG6k1xcfENBSecnOkYAAAAADQCmtcAANAElK8tjSljxrTMdA4AAKgt9rwGAIAmYORZp0Z5aenCwYMHty4qKlqd6TwAALC1rLwG6k1hYeH1E+69K9MxAAAAAGgENK+B+vTTKWPHZDoDAAAAAI2A5jUAAAAAAA2O5jUAAAAAAA2O5jUAAAAAAA2O5jUAAAAAAA2O5jUAAAAAAA2O5jUAAAAAAA2O5jUAADQBObnNIyLWLFu2LJXpLAAAUBuaZToAQF3Jzs6KyspkpmMQEVlZiUxHgCbPPa/hyNQ976L7H4rSVGn+8Ly8LzISAAAAapmV10B9umzwWefV22R5+W3rbS42r932rTIdAZo897yGwz0PAABqh+Y1UG+Ki4tvKDjh5Hqbb8CgveptLjav/wG7ZToCNHnueQ2Hex4AANQO24YATda+vbtGWVl5lLzyTixduiqSPk5fr7KyEtFu+1bR/4DdYkBhj0zHgSbPPS+zGsI9r3xtaUwZN6ZlRKzOSAAAAKhlNiEF6tWTi1f6EikAqAM3jzghyktLIycnp3VRUZEGNgAAjZ5tQ4B6U1hYeP2Ee+/KdAwAAAAAGgHNa6A+/XTK2DGZzgAAAABAI6B5DQAAAABAg6N5DQAAAABAg6N5DQAAAABAg6N5DQAAAABAg6N5DQAAAABAg6N5DQAAAABAg6N5DQAATUBObvOIiDXLli1LZToLAADUhmaZDgAAAGy9i+5/KEpTpfnD8/K+yHQWAACoDVZeA/XpssFnnZfpDAAAAAA0AolMBwC+WZ5cvNJHmQGgjpSmSlsPz8tbnekcAABQG6y8BgCAJqB8bWlMGTOmZaZzAABAbbHyGqhXVl4DQN24ecQJUV5aGjk5Oa2LioqsvgYAoNGz8hqoN4WFhddPuPeuTMcAAAAAoBHQvAbq00+njB2T6QwAAAAANAKa1wAAAAAANDia1wAAAAAANDia1wAAAAAANDia1wAAAAAANDia1wAAAAAANDia1wAAAAAANDia1wAA0ATk5DaPiFizbNmyVKazAABAbWiW6QAAAMDWu+j+h6I0VZo/PC/vi0xnAQCA2mDlNVCfLht81nmZzgAAAABAI5DIdADgm+XJxSt9lBkA6khpqrT18Ly81ZnOAQAAtcG2IUC9e+72kfHxnDerPG/o934QXXv1SY+fv+vP8dHMGVXWHXLWudG9//7p8YR774oPXptWZd23Tjszdi8YkB6/PPq+eLdkcpV1hcNPjR6DvpUeFz/8QLxV/K8q6w488eToOXhIejz5sUdidtGEGtdNffLxmPH8+Crr9j/2+Oh12JHp8evPPBWvPfOPKuv6HXV09D3qmPR45j+fjVfHPVFlXe+hh8d+x51Q47qegw+JA08cnh7PLnohJj/2aJV1PQoPisJTvpsevzXx5Sh+5MEq63YvODC+ddpZ6fG7JZPi5dH3V1nXvV//OOTs76XHH0x7NSbcd0+VdV179Y6h3/uv9PijmdPj+bvuqLJu5732jiMuuCg9/njO7Hju9tuqrOu4++7x7YsuSY8/e/edeHrk/9a4btHcD2LczTdUWZfXrVsce8nl6fHSj+fH2Ot/U2Vd+513jmGX/SI9Xr5wQYy57tdV1m2Xnx8n/eLqGte1br99DL/quvR41dKl8civf1llXcs2beLUa3+fHq9ZuSIe/OXPqqzL3WabOOP3N6fHa9esiVE/+0mVddk5zeLsm0amxxXl5XHfT35cZV1ExHl/uH2D8d0/vqBadWfd9IdolpOTHt/7k4uisryiyrrTf3dTNG/ZMj3+2+WXRNmXX1ZZd+q1v4uWbdqmxw/+8vJYs3Jljese+fUvYtXSZVXWDb/q2mjdvn16POa6q2P5woVV1p30i6tiu/wda1w37LIrov3OndPjsddfF0s//rjKumMv+WnkdeueHo+7+fexaO7cKuvyu+y8fURoXgMA0CRoXgP1KllZ0WvOxJduX/vFF4VVnTtl7Jj/17nnPulu7uyXJtxSumrloVXVlTz26GXd+vR9dt34jQnPX//lihVHbq4mIqLk8Uev3HW//dPd1Tf+Of6a1cuXHV9lzicevWaPAQP/vm48Y/zTV65auvQ7Vc439rHr9zro4FHrxtOf+cdlKxYvOr2mddOefvLi5QsWnFtlznGP37LPoUPT3dWp4564YNmnH1fZzZo67onbex9+ZLoLNmXc4+cunTfv4qrqpj395D39jj72lprWTX/mH6MOOP7E69eNS8Y+dvqSeXMvq6puxher/j7g5OHXpOd74tHvLJk398qq6kpXrnxi0IjT0ueVPP7o8Uvmzb1mczUREV+s+PzZg884O52r5LFHj1wyb+71m6uJiFj9+bIXDz3ne+nXYcrYMYcsmTf31qrqVi1dXHzY9y9I/7ymPP5o4ZJ5c2/fXE1ExKrFi1498sIfp/freXXc2P2WzJtbZZf9P+umjnui15J5c0dtriYiYuWiBTOTlRXpP8evjX9qzyXz5v59czURESsWfPZWsrIi/a8WM1/8Z7cl8+Y+WVXd55998mGysiL9Pq123aeffJKsrDhq3fjtlyd0WjJv7rObq4mIyMrOXpKsrEjfhz58bWr7JfPmVvmvTolE1spkZcWgdeNP35rdesm8ucVV1yXWJisr0v8at3LJotwl8+ZOraou4qv77frjJfPmzqxO3coli/bbLi+/bN140Qfvv5pKpZpXVffpW7MLu/buu2rd+LN33p6YSiXbVFX34WtTD9nroIOXrht/PGf2i8nKyh1qWjfvjTeeqawo36mqurdfnnBkv+OGfZq+zvTXnqgsL9+lqrqZL/7zuEHDT51b07rXxj/1nSFnnf/2uvEHU199pLxsbY+q6qaOe+L0Iy+8KP0ze2/K5FFlpaW9NlcTEbH4ow9fGzx48I5FRUVV/4sDAAA0cLYNAerdgQce2C2RSLSu6rxkMvlRSUlJevndoEGDulRWVrbdXE1ERFlZ2bxp06atWDfef//9Ozdr1my7quq+/PLL+dOnT1++blxQULBzVlZWu6rqIuKTSZMmpZf7FRYWdkomk+03VxARUVlZ+emUKVPSjZf+/ft3zM3NrbJh8591BQUF+VlZWXlV1ZWWli54/fXXF68bDxw4MC+VSuVXVZdIJBa+8sori9aN+/bt26FFixY7bq4mIiKZTC4qKSlJL0usbl1ZWdmSadOmfbZufMABB7TPzs7uVFVdVlbW0uLi4nRDasCAAdtHRJWNrGQy+XlJSUl6GWSfPn2222abbTpvriYioqKiYvmrr746f924f//+bXNzc7tUVZednb1i4sSJ89aNCwoK2mRlZXWtqi6VSq2aPHny3HXjnj17tmrTpk2VjbPKysrVU6ZM+XDduFevXttuu+223TdX83V1AwYM2CYidquqLpFIrHnllVfeXzfu1q1bi44dO+5eVV1EfDlp0qT31g1222235h06dNijqqJkMllaUlLybk3rsrKyyoqLi9MNxf79++fk5uZW2VCMiPJJkya9td642YABA/aqRs7KkpKS9T9ykjVgwICe1ciZLC4unr3eocSAAQP2qUbOmDRp0hvrjwcMGLBvNetmRUR6i6fCwsKeyWSyyu9JmTRp0uyISK4bFxQU7J2VlZVdjbo5EZFutA4YMKBHRORsuuLr6woLC/dMJpO5VdWVlZW9NW3atPL1cu6elZXVoqq6xYsXv/Pee++trWndZ5999u7cuXNL140HDBiwW0RsU1VdRLw3adKk9NL1gQMH7ppKpVpuruD/bPB3EgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANSXRKYDQBWy+vXrNyyVSl2YSCQOiIjWmQ4E1L1UKlWeSCTmplKpBysrK/84c+bMRZnOBBmU3bdv3+8mEonzU6lU30Qi0SrTgWhQyiLig1Qq9UhFRcUtb7zxxueZDgQAALVF85qGLKtfv353R8TZmQ4CZE4qlVpUXl4+cNasWe9nOgtkQLO+ffv+LZFIjMh0EBq+VCr1YXl5+cGzZs2an+ksAABQG5plOgBsSt++fY+JiLM7dOgQP//5z6NXr17Rrl27TMciIt566614+eWXo6ysLPr06RODBg3KdKQaW716dfz5z3+Ofv36xaGHHprpOPyHtWvXxvz58+Oee+6J5557Li8nJ+fuiBic6VxQ3/r163dGRIzo3LlzXHnllbH77rtHmzZtMh2LBmTt2rXxySefxJ133hnjx4/fJTc39/aIOCbTuQAAoDZYeU2D1a9fv+ci4vA//OEPUVhYmOk4/J+HHnoobrzxxkilUulj3/3ud+MnP/lJerxo0aK4//77o2/fvjFkyJAaz7G19dXxwgsvxGWXXRY9e/aM+++/v07mYOulUqkYNmxYfPzxx5FKpXq+/vrrb2Y6E9Snvn37FicSiYF/+tOfoqCgINNxaMAqKipi6NChsXLlylRWVlbetGnTlmQ6EwAAbK2sTAeAzTgwIqJnz56ZzsH/+eKLL+KWW26JXXfdNcaMGROPPPJIdO3aNR566KFYuHBh+rzPP/88HnzwwZg6deoWzbO19dUxefLkiIiYM2dOrFy5ss7mYeskEono3LlzREQkk8l9MhwHMqF3RMRee+2V6Rw0cM2aNYtOnTpFIpFIVFRU9Mh0HgAAqA22DaEhaxMRsd1222U6B/9n0aJFUV5eHl26dIlu3bpFRMQpp5wSL7zwQixZsiS23377uPXWW+Pzz7/6rqjp06fHjTfeGHl5eXHmmWducK0ZM2bExIkTIycnJ4YOHRrdu3eP8vLyatd/8MEH8cILL0RExDHHHBMdO3as0XMpKSmJiIhkMhklJSVx2GGH1fj1oH5su+22ERGRlZXlS+r4xkkkEttGhK1CqJZ198vs7Gz3SwAAmgTNa6DaunTpEjvttFO8+OKLceGFF8Ypp5wS3/nOd+KUU06JiIg1a9bEgw8+mD7/nXfeiXfeeSf22GOPDZrPTz/9dFx55ZXp8b333hujR4+O/Pz8atX/61//iksvvTQqKioiIuLBBx+MBx98MPLz86v1PObNmxeffPJJ7LXXXjFnzpyYPHmy5jUAAABAA2PbEKDasrOz4/bbb4/9998/SkpK4pJLLonhw4fHrFmzIiKiZcuWUVRUFHfddVdERJxwwglRVFQUd9999wbX+dvf/hYtW7aMRx55JO68885Yu3ZtjB8/vtr1v//97yORSMQdd9wR11xzTaxYsWKDpndV1m0ZcvLJJ0ebNm3SYwAAAAAaDiuvgRrZaaed4s9//nO89dZb8fDDD8dTTz0VP/jBD2L06NHRrVu3aN26dbRs2TIiInJycqJ169YbXePmm2+Of/zjH3HnnXfGzJkzIyJi9erVERFV1n/66afx2WefRX5+fkybNi1SqVRkZWWlG+jVsa5Z/frrr8c222wTCxYsiLlz56a3QgEAaGgKCwtTVZ8VUVxcnFDXeOtKS0u3mzZt2or16j6PiCr3UUylUt1eeeWVj9aNBw4c+GEikehWVV0ikegzceLEGevVvZ5IJPpUVZdMJgdPmjTppfVyToiIwdXIOeyVV155Yr35Hk8kEsOqqouIs4uLi+9br+6viUTi7JrWFRYW/m9EXFxVUTKZvHjSpEm3rjffVYlE4uqvObWkuLj4wGrkAGALWXkNVNv8+fPj3HPPjdGjR0ePHj3iqquuissvvzxKS0vjmWeeqdY1UqlU/OIXv4jbb7893njjjejatWv6eHWUlpZGRMTChQvjL3/5S9x5552RTCZj2bJl1aqvrKyMV199NSIinnrqqfQXTVp9DQA0BU8uXpla/5e6xlV3+Zhxy9eva77tttX6AqAL7rxv7vp1bfPzu1Wn7qybR05fvy6/+65VNq4jIk77zQ1F69d13mffwdWpO/GKX41dv26PAwdWp3Ed3/7xJfeuX7fvkMPO3pK6/Y4dVmXjOiJi6Pn/dcv6dYNOPf3qTZxa0LNnz9zqXBOALWPlNVBtubm5MWPGjMjOzo7TTjstIv79hZq5uf/+f7Zmzb66tSSTyfR/S0tLo2XLljF//vyYMWNGDB06NH7/+9/H008/HVOmTNlgns3Vd+zYMZo1axZ9+vSJq666KiIiRo4cmT63KjNnzow1a9bEwQcfHD/+8Y9j/vz5cfHFF8ekSZNixIgRW/rSAADUmcLCwj/3OeLbccQFF9W49vKx1VtgoK5h1l08+tEtqrvgL/dVfdLXOOd//7hFdd+99votqjvx57/aorqjf/yTOPrHP6lx3ZDzfhBDzvtBjesGjTg9Bo04fYNjN5x0TCQrK2t8LQBqRvMaqLb8/Pzo379/TJs2Lc4444zo2LFjvPLKK5GbmxtDhw5Nn7fTTjtFy5YtY/z48bF69ep4880345e//GX0798/WrVqFVlZWfHaa6/Ff//3f0dxcXFEfLUiujr122yzTRx77LHx+OOPx9VXXx05OTkxefLkOPbYY6v1HNatsD744IOjW7du0bVr12jXrl289tprUV5eHjk5ObX4igEA1IofTH/u6S1qXgMANGa2DQFq5Prrr4+jjjoq5s+fHy+//HLstttucdttt6W3/4iIaNGiRfz2t7+N1q1bx/jx4yOZTEa7du0iImL77bePn/3sZ5FKpWLq1KlxyCGHRG5ubrz00kuxZs2aKusjIi677LI4+eST4+23346ZM2fGt7/97bj00kurlX/SpEkREVFQUBAREYlEIgoKCmLNmjXp/bcBAAAAyLxE1adAZvTr1y8VETFt2rRMRwEy6PLLL4/nn38+UqnUea+//vo9mc4D9cnfhdTE+eefH6+99lpExFGvvfbas5nOQ+1Z92V/W7r1BFD7XvrbX6Pksb/fNHHixMsjwv4hAHXEymsAAACAGjj4jHPix3fccUVoXAPUKc1rAAAAAAAaHM1rAAAAAAAaHM1rAAAAgBqYMvbRGHnhhT8JfRWAOuUmCwAAAFADL/3t3khWVPymZ8+ezTKdBaAp07wGaKBWr14dM2fOjIULF2Y6CgAAAEC907yGOjRjxozo379/fPzxxzWqe/vtt6N///5RWVm/X1ydiXkz9VxrO0dtP48pU6bEscceG9dff32ccMIJ8cADD9TKdal9KZqcTP+ZAvga/3XEf/0o0xkAAOqd5jXUoUmTJkVExOTJk2tUt/vuu0dRUVFkZ2fXap6qGqx1NW9DUlfN8tp87SorK+N//ud/4sYbb4xRo0bFn//85xg5cmR8+eWXtZAUAGhsiouL7+hz5NGZjgEAUO80r6EOTZ48Obp27ZpuYldXVlZWtG7duo5SNbx5m4LafO1Wr14d3/ve96J///4REbHHHntEWVlZrF69ulauDwAAANAYaF5DHVm1alXMnj07zj///Jg6dWp6pe+6lb9Tp06N4447Lg466KB46qmnNqj9utXB647dcsstMWjQoPjlL38Z1157bQwcODCuvfba9Hnz58+Pc889NwoKCuK4446LkpKSWLNmTfTv3z+++93vRkTEAQccEP37949p06ZVOW9ExJdffhnXXHNNHHTQQXHYYYfFXXfdFes+WV+d57MlPv/887jkkktiwIABcfLJJ8ecOXOqNd/s2bPj1FNPjYKCgjjttNPi2muvjQEDBlT7NXj99de36Hls6rUbO3ZsHH300XHAAQfESSedFCUlJVVeq23btjFs2LCIiEilUnH//ffHXnvtFR06dKiydkvmAwAAAGiINK8s22dUAAAgAElEQVShjkyZMiXy8vJi6NChUVZWFrNmzdrg8b/85S8xcuTIGDZsWPzpT3+q9nW33Xbb+NWvfhXPPPNM7LjjjnH11VfHuHHj0o9fd9110aVLl3j66afjhz/8YVx33XXRsmXLKCoqirvuuisiIl588cUoKiqKPn36VGvOa665JubOnRujRo2KW265JZ588skYNWpUrTyfTbnyyitjzZo18eijj8bhhx8eP//5z2P9rWi/br6Kior47//+7zj66KNj3Lhxseeee8Ybb7wR//jHP6r9GtTm81i4cGFce+21cckll8Szzz4bAwYMiCuvvLLa9UuXLo2jjz46/vrXv27wDxR1NR8A0DAVFhb++bnbR2Y6BgBAvdO8hjoyefLk6Nu3b+Tk5MQ+++yz0dYh5513XnTt2jWOPPLIWLhwYbWve9ppp0XXrl0jIuL000+Prl27RkVFRfrx3/72t3HFFVfE6tWrY/HixfHpp59GRETr1q2jZcuWERHRqlWraN26dbX2Z165cmWMHz8+rrjiiujatWv07NkzfvjDH8YjjzxSK8/n6yxfvjwmTZoUF110Uey0005xzjnnxIIFC+LDDz/c7HyfffZZLF26NIYPHx55eXkxbNiw+PDDD2P77bev9mtQm8+jRYsWkZ2dHalUKlq1ahWXXHJJjVZzt2/fPm6//fb41re+FVdeeWUkk8k6nY8tl5z7Qaz5zlGx5qQj4ouhBV/9/jtHZS7PJx/HmtOOr/OaLZGcP/ffr9Fxh0bppRdGaumSrbvmVmZPzp8bXxx10FZlAKhjP5j+3NOZzgAAUO80r6GOlJSUxHPPPRcDBgyI6dOnb/Sljb169YqIiGbNmtXous2bN0//vkWLFhs9/uKLL8YxxxwTP/vZz2L27NkbrFbeEosXL45UKhWdO3dOH+vcuXMsWrRog/O29Pl8naVLl0ZExAUXXBAHH3xwDB06NCoqKmLBggWbna9Tp07RvXv3mDhxYkRETJw4MfbYY48azV2bz6Nt27Zx7bXXxgMPPBCHH354nH/++entT6qra9eucc0118T7778fs2fPrvP52DJZ3bpHy78/Ey1uuSMiJzda/v2ZaPn3ZzKXZ6edo+XoJzY6nlqxPMpH31Ojmjqx7jV64vnI6r5blN1241Zdrl6zAwAAUG+2vjsDbGTevHnxySefxJ/+9KfIz8+Pt956K6688spYtWpV+pzc3Nxan3fp0qXxu9/9LkaNGhV77rlnzJw5M8aPH59+PJFI1PiaHTp0iKysrPj444+je/fuERHx8ccfR35+/gbn1ebzad++fURE3H333bHttttGxFf7bufn58cnn3yyyfmys7PjpJNOiquuuiquuOKKyM/Pj5tuummDc6p6DWrzeXz55ZfRqVOnuOeee6KysjLuv//+uPzyy+PZZ5/dbN2bb74ZY8aMSW/50axZs8jJyYmsrM3/e+OWzsc3R2rl8igb9dfIOe3cTEf5SiIrmh1+dJT+9EeZTgJAPUslk/Hu1CkxZeyYmD9ndqxdsybTkagDiaysaLNDh9j30KGx/9HHRdu8/KqLGokDhp0UJY/9/abZs2dXVn02AFvKymuoA5MnT478/PwoKCiIbt26xZAhQyI3NzemTJlSp/OWlpZGMpmM1atXx9tvvx033HDDBo/n5eVFVlZWTJ48OZYsWbLRPtxfp02bNnH44YfHddddFx999FHMnj07brvtthg+fHhdPY3YbrvtYuDAgTF27NjIzs6Ozz77LM4888x043pTFi9eHA8//HDcd999MXr06Hj44Ydjt9122+CcLXkNtlRZWVlceOGF8eqrr8aKFSuisrIyysvLq6zr0qVLvPjii3H//ffHsmXL4u677462bdtGjx7/n737jquq/OMA/jkXLnupICopWColZopbrAxRNNMwzD0zZ2mmJi7QFDX3wNwDMXGRe+FAcJRaiqBo/NyKA0FBQMa93HN+fxA30cu+cBE/79fLV3DOM77PhVC+57nf5/0SmY9KVnZJCvH2TaT/OBQZP0/47971aKSN6I/Uru2R2vtLqM6E5eiTGXYMaf27IrWzKzIP7Fb3UwYFIrX3l0j1bI+0fp7IPHVC45wvSxsxAOmjhwJKhbqsiZT6Is8+WdfvIu27gUj1dEe6zzhIKckFirHgL5AE/PtQSbx3B2kjv0GqpzvSfhgMKT4u39ewKLEDgHjtSlbc3TtCGbSl8HETEVGRSaKIPQvnItB7Am5c+IuJ63JMEkU8fxKL01s3Y9m3/fDgn/LzrsBP+w7EqFWrJgFg8pqIqARx5zVRCTh79iyaNWum/lwul6NRo0Y4e/YsunbtWmLz2tnZYcCAARg9ejTMzc3h6emJq1ev4vr166hduzasrKwwbtw4eHt7Iy0tDV27dkW9evXyHXfKlCmYN28e+vTpA0NDQ/To0QO9e/cusXUAwPTp0zFjxgx4eHio43Z0dER0dHSufWxsbNTlMlJSUpCZmYmKFSuif//+6NOnDwAU+TUoCktLS0ycOBG+vr54+PAhqlWrBh8fn3z7mZmZYdGiRZg1axZ+/fVXfPTRR1i2bFm+NcqLOh+VAlEFxbL5MBg+GrIaDurLyl3bIPfsCf027aHcE4QMv3kwcfk062amEqqzp2G8bisyjx+GYu2v0O/oAelpPBSrlsIkcC8Em8rIPBkCVehR6H/8WZ4hGC/3h3j/DtKG9C1USZOM6ROh/8VXkHf2RMaCmVAsXwTD8T55xlhgSgWUB3ZBr2GTrLl+ngB5/yHQ/8QVyk3roPBfCcNx/x46mstrWKTYJQnpM6fAoPc30G/fCRnzZhQ8ZiIiKraoU6G4dPQwrK2t4eXlhYYNG6JChQq6DotKgFKpxIMHD7B161bs2LEDQbOn4/t1m6CnhRJ9RET0dih8DQGiUuLs7CwBwIULF3QdCr0h4uPj0alTJyxduhR16tRBZmYmtm/fjsDAQJw6dUrX4VEReXl54dixY5AkaVB4eLjmgs06JL1UWD47OWx66L/vN/H+HaQN7A7jlQGQ1XLM2fdFClQnQyDeiEbmuT8gPY2H6aFT6j4m2w5AqGSdtSN56L/jiiLSvv8GsspVIPuwAfQ+cIKs7oc5xtUUR17Xc7snxcchtWdnmB46CejLIf7vGtIn/giT3w/nHWMesvsJFSoCKhVkH9SD4bgpQGYmUnt2yroOAKIIwa46jJeuzfM1LErsUlwsUnt9CdODJwG5AcSrl5E2doS6v1CUGksl5E36u/Cff/7ByZMnoVAo0KBBA7Rq1UrXIRXYkydPEBAQACCrvJS1tTU6duwIa2trHUdWOIMHD8bFixcBoMPFixdZM6occXFxkQDAa7fuzlPQpo1eY3D70kUsX748x4YPKt9GjBiBc+fOoc/MuajVuKmuw9GK9Cf3Dbs5OSl0HQcRUXnGx51EVG5UqFABX375Jby9vfH06VMYGhri3Xff5e5j0j25wetJ10wl0kf0h17zVll/XN2RPu67/+7ryyFU+jdx9nIqVSaD8bL1UF29DOn2TShW+0GwrgzDKb4lvowsLx0Cm1uM+fn3wMYco8Y9AQQZTLbsA/T1AVGE9OJFjj6aEteF82/s4r//zc5R51NPXhucnZ37ZGZmXoqMjCy5WkU6tHXrVsyfPz/HIcG9evXC2LFj1Z9nJ4gbNmyINm3aFHqO4vbPS0JCArZsyVk+JjAwEFu2bEHFihW1OhcRAQ+is0pH5FcSjcoXR0dHnDt3Dg+vR5eL5PX53UEI+23jWABzAIi6joeIqLxizWsiKjf09PQwYcIEHD58GH/99RdOnz6NgIAAtG3bVtehEb1Gio+H+PAB5L0GQq9+Q2QGH8jZIJfNv9LzRKQN6gFZdXvod/oK8m59oLpYsHr6gpkFkJkJKTEBkCRISc/zbm9tA5lDTSgP7AEkCcoDu6HXzCXfGItCsKkMWfUaUB7Mqput3LcTGdMn5NMrj/HyiF2obAuhkjUyQ49l3Tu0VytryIeXvr7+5YYNG0Y3bNjQ56OPPmqIcvIOuBcvXmDx4sV477338Pvvv2P79u2wt7fH1q1bERsbq26XnSD++++/izRPcfsXRJcuXRAaGorRo0cjPj4e+/fvL7G5iN5mirQ0AFklz+jtkf31Li81zsM2+UPMzJzl5OTETYFERCWIP2SJiIh0QKhSFfJOnkj7pjtgYAj9Tz4DMpWQ4mLz7mdpBf2vuiPt+2+AtFQIpqYw+G5MweasUBEG/b9F2rc9AVGEweDvod+hc559DH1mI+OXaVBuXA2ZU30Yek0t8BoLy9BnNjLmzYBywyoI79SA4YSfiz+eptgFAYaTpkMxfyYUq5dBr0EjLURfMIIg1AHws56e3s/Ozs53RVHcLIri3sjIyL/xhh749OTJEyiVStSoUQMODg4AgO7du+P48eOIj49HxYoVsWTJEiQkJAAALl26hPnz56Ny5cro169fjrEiIiJw+vRpyOVyuLm54d1334VSqSxw/1u3buH48eMAgC+++AJVq1Yt1FrkcjnMzc3VZyE8f573Ax4iIiIiIipZ5WLHD5VPb1KdTyIqOW9SzWsqH0qi5rWzs/NlALmeDitJUqwgCIGSJO2RyWR/XLhwQflvvzL/d6FKpUKXLl3w4MEDNGvWDN27d8fHH38M2b/lWFJTU/Hxxx+/1q9OnTo5SnUcPHgQ3t7e6s8NDQ2xefNm2NraFqj/qVOnMG7cOGRmZgLI2uG3ZcsW2Nra5ruG6Oho9OrVC05OTmjZsiVOnjyJ6OhorFy5Ek2aNCn4i6FjrHldfrm4uAx1H/b9ygbtO+o6FK2Y5t4aQNn+2Uba5+/vDz8/P7h064m2g4bqOpxim+f5BUSVComJiYZRUVGse01EVEK485qIyoxjx47Bzs4OH3zwga5DKbaQkBDY2trCyclJ16GUG4IgrHV2dl7776cSgBz1dQVBeDWJrCmp/HKuWeN9DfMWZFwqR5ydna/n8n1SkO8Pje0kSaqZV05cEARbAD8KgvCjKIrPnJ2dt0qStKtwkeuGnp4eVqxYgRkzZuDcuXM4d+4catasiWnTpqFevXowMTFBaGgobty4gW+//RZdunTBDz/8AD09vRzjbNq0CSYmJvD398fz588xePBgHDlyBEOHDi1Q/zlz5kAQBKxatQpPnjyBt7c3tmzZgtGjRxd4LVFRUYiKigIAGBsbIzk5ufgvEJEWnDlzZpXX7kMrdR0HERERUWlj8pqIyoQLFy5g6dKlWLdunfpaSkoKbt26BVtb2wLtnNMVTXFWqVIF48aNw5o1a2BnZ5fvGOfOnUN8fDw6duyY65hvu3+TiTmSgq/skBVe+a9GJbCplsqfWtr+PinMeIIg6EuSZCsIQiVJkt6I71k7OzusXLkS//zzD7Zt24b9+/dj6NCh2Lx5MxwcHGBubg4TExMA/5XmeNXChQtx4MABrFmzBpGRkQCyfhYCyLf/w4cP8ejRI9ja2uLChQuQJAkymQxXrhTufMwvvvgCQ4cORUJCAlatWoXx48dj5cqVaNy4caFfEyIiIiIiKj4mr+mtkf2W4FeFhoZq/CU6t/7nz59/bbfX26KkXoOUlBRMnjwZM2fOhI2NDQDg/Pnz8PLygp2dHW7duoXvv/9e49dPW/7++2/MmDEDz549w8CBA/HNN98UqF9ucdatWxcDBgzAlClTsH79+nyTT9u2bcOsWbPyHLOkFGXtoihi/fr1+P3335GSkoK2bdti3Lhx6uRSCfm2iGVDNL34BbkmtG7dGgCQnJz8Wvv09PTsaxlFiInKMKVS+d6r1yRJEgDAwMDgte8FURQFTW1fJpPJ9guCUDu3OSVJegbgCICjqampO6Kjo5MBwNnZeWvhV1C67t+/j6lTp6JNmzbo3bs3pk6dCicnJ8yePRuHDh3C8OHD8x1DkiRMnjwZERERqFKlCuzt7REbG4uCVuVJT08HAMTGxmL16tXq68+ePSvUWkxMTFCtWjVUq1YNgwcPxpkzZ/DHH38weU1EREREpCNMXtNbJyQkRF2HEwDMzMwK1K927doIDQ19LWn7piW1ixNvbq9BcW3atAlOTk5o1Cjr0DSVSoXp06dj/vz5aNSoESIjIzF06FB06dIFxsbGWp0bABISEjBhwgT4+PigatWqGDFiBD788MN865zmF2fXrl2xZcsWHDt2DG3bts11nBMnTqB58+YwMjJ6Y9a+detW7NmzB4sXL4ahoSEmT56M2bNnY8aMGVqPUQsKVNZBk9DQUO1GQm+Ey5cv39L2mM7OzpoecjwCEKxSqbZEREQcxxt6YKOBgQEiIiKgp6eH3r17AwCsrKzU97Lp62f9s1MURfV/09PTYWJigvv37yMiIgJubm6YM2cODh48iPPnz+eYJ6/+VatWhb6+Pho0aICpU7MO5vTz81O3LYr79+8DACwsLIo8BpG2uLi4rAxe4Qf34SN1HQoRERFRqWLymt46ZmZmRUq+ymSyAu3QLs9K6jXYv38/xo0bp/48JSUF3377rTqZXadOHSgUCqSkpJRIAnffvn349NNP8cknnwAAvvrqK+zatSvfBG5+ccpkMnTs2BH79u3LNXktiiL27NmDefPmFWjM3IwfPx7nzp177Xq/fv0waNAgra99//79GDBgABwdHQEAQ4YMwZQpU/LsQ0QAgHsADkmStCU8PPwkykENdVtbWzRq1AgXLlxA3759UbVqVfzxxx8wMDCAm5ubup2dnR1MTExw5MgRpKSk4OrVq5gyZQoaNWoEMzMzyGQyXLx4ET/++CPOnDkDIOshYUH6Gxsbo1OnTti1axemTZsGuVyOs2fPolOnToVay/nz5zF16lQkJSXh7Nmz0NPTU/98JNKxoZeCDzJ5TURERG8dWf5NiMq/+Ph4fPLJJwgPDwcABAQEoFevXjl2bEVHR6NRo0bqX6RTU1PRqFEjdTmHpk2bqn95LwiFQoF58+bB1dUVLVu2xMiRI/Ho0SP1/bS0NMyYMQMff/wx2rZti7Vr16rfPv1qLNmfv/zx33//jc6dO+Pjjz/G/v37ix2vpnmz7d69Gx07dkTTpk3h6empMYmam6dPn+Lx48c5Dja0tLSEh4cHgKy3kgcEBOCDDz5QlxTRths3buRI1tarVw9Xr17Nt19B4nRyclIf/qXJ4cOH4ebmBrlcXuAxNZkwYQK2bNny2p9u3brl2a+oa09MTESVKlXUn78J7zog0iVJkvwBtLh48aL9xYsXh4WHh4ehHCSus82dOxcdOnTA/fv3cfLkSdSqVQvLli2Dvb29uo2RkRFmz54Nc3NzHDlyBKIookKFCgCAihUrYsKECZAkCX///Tc+++wzGBgYICwsDKmpqfn2B7Ie4nXt2hXR0dGIjIzE559/nuPBaEHcuXMH+/fvx7lz5+Dk5IRly5bh3Xff1cIrRERERERERcGd1/TWcXV1VX/cuHFjLFiwANbW1hg2bBiWLl2KJUuWYMOGDViyZEmO8iKvMjExQWhoKG7cuIFvv/1WXY6koDV/Z8yYgZiYGKxZswb6+vqYPn06vLy8EBAQoL4fGxuL3377DSkpKZg4cSIMDQ3Rt2/fAo2/evVq+Pn5ISgoCMuXL8cXX3xRrHhzExsbC19fX8yZMwcNGzbE+vXr4e3tjSNHjhSof2JiIoD/3mL+sqdPn6Jv375ISEjAli1b8h2rqLuPU1NTcxyKaGVlhbi4uIKEn2+cVlZWeP78OTQduqZSqXDkyBEsXLiwUGNqUrFixQLH+7Kirv29995DWFgYXFxcAAB79uxBixYtihTD20B8EIP08d/BZPMeXYeic5mnT0CxfDGgyIB+u44wGFKAXYQqFRS/rYMYEQ7B2hryvoMgq+5Q4rFqU3h4+AJdx1CSrKys4Ovrm2+7Vq1aoVWrVhrveXp6wtPTs8j9DQwMMHHiREycODH/gF/h6OhYqIe5RERETT08cW7njgVRUVFvZNkvIqI3BZPX9NbZvHmzOiltZGSkvt6jRw/s3bsX33//PVxdXVG/fv18xzI3N1cnfwtTjiQpKQmHDx/G1q1b8d57WeeCTZ06FdHR0er7R44cwbZt29S71r777jssW7aswMnrQYMGwd7eHu3bt0dgYGCx4s2LkZER9PT0IEkSzMzMMGbMGIwaNarA/bProSoUihy1UQGgUqVKWLFiBZYvXw5vb29s3LgxzwcKEyZMUB/a9bL8Sp3o6enlmFsulyMjo+Bn8OUVp0KhgFwu13hg4+7du/HFF19oXFNh115URV37jz/+iFGjRmH48OHqt++vW7dO6/GVFzK7d8pE4lp6nojM/Tsh712wA0mL2ic34r07yJjpAyPfBdD7qCHSx36HzJBg6Lu659lPuXkDpEcPYThhKjL/PI2MqV4wXr+t2PEQERG9TBRFbN68GQcOHMDdu3cBZG0Q6Nu3L3r06PFae02bEwqqOH1ftWLFCqxduxYAMH/+fHz22WdaGZfy9mnfgWjm7jbptJMTk9dERCWIZUPorVO1alVUq1YN1apVy7FbVSaToUuXLoiKikLXrl1LNIa4uDiIoojq1aurr9WoUUNdFzkuLg6SJOW4X716dTx58kTjeJmZma9dy06+Zx9wVVIsLS3h6+uLwMBAtGvXDoMHD8a1a9cK3L9q1aowMDBQ/4LwKnt7e8yYMQM3b97Ms/wGkPXLRfbX9uU/+SWvLSwskJCQoP48JSWl0L9M5BbnnTt34ODg8Fp7hUKBM2fOoE2bNoUeU5Px48fj008/fe1Pfgnloq793Xffxe7duzF69GiYmZmhZcuWaNCgQb79SLekpEQofttQ4n1yk3nsEPScPoReo6aAvhz6X3ZF5rHD+Xc0kMNg1E8QKleBfruOEGPuAVLRD+IjIiLSZM6cOVi8eDFSU1Ph4eGBr776CnZ2drh9+3aOdj4+PmjXrh2eP39e6DmK0zc3hw4dUm9QOXy4AH+vEhERvUG485roX6mpqdi4cSNatGiBFStWYOnSpQXqV5QdEzY2NhAEATExMepamv/88w9mzZqFgIAA2NjYQCaT5bgfExOjLu+QPacoitDT08PNmzdfm+PVXczFiTcvaWlpqFatGtavXw+VSoWAgAB4eXkV+B/O+vr6aNGiBU6dOqWue3316lX8/vvv8Pb2VreRy+UlsvMYyHq7+NWrV9VvRf/nn39QuXLlfPsVJM7Tp0/j448/fq3v9u3b0bVr19e+HkVde1F3nRd17dmxmZmZITw8HJs2bSpQn7eVeP8O0ob0hemhUzmuK4MCody1DUjPgGBqCvng76H/cf67pfLqJ967g4x50yE9fADhnRow8p4FwdoGaSMGQIp9BCgVSP26AwDAeGMQBBPTXOfJq494/y4yfpkG6fFDyJw+hOH4qRDM8v5+k57EQlbLUf257J0aEO/eyne98h79sz7ISIcyYA30XT4FhPx/HhT19SUiorfTgQMHAADLli1DjRo11NfT0tI0tivOHNoSERGBBw8eoG3btjhz5gxOnjyJFy9ewNQ097/fiYiI3iTceU1vnZSUFCQnJ6v/ZO9aXrFiBd5//30sXLgQt2/fLnDytXLlypDJZDh79izi4+Nx5cqVfPtYWFigXbt28PX1xa1bt3Dv3j0sX74c1apVy3F/5syZuHv3LqKiorBs2TL14XvW1tYQBAHXrl1DampqgWoiFyfevCgUCowYMQJ//fUXnj9/DpVKBaVSWagx+vfvj6CgICQnJwPI2oUeEhKCgIAAPHv2DOvWrYOlpSXef//9YsWam9atW2P37t2Ii4tDSkoKdu7ciebNmwPIekCQHder8ovz5s2bOH/+/GuHJqampiIiIgItW7Ys9Ji5Kequ86KuPdvq1avRsWNH1K5dO8929DrpaTwUq5bCePEamPx+GPJvv4Mq9Gix+2X8PAHyr/vA5Pdg6DduDoX/SgCA8XJ/GC1eBcgNYLLjEEx2HMozcZ1fn4zpE6HfriNMgg5DsLCCYvmi/BctisDLdfYNDYF8vsdelvbjUCh374C8W5982xb19SUioreXmZkZAGDBggU53hVobGys/jj7kHQAaNOmTY7P4+Pj8dNPP6FNmzZo1qwZ+vXrpy4LmF9fADh27Bh69OiB5s2bo23btliwYAEUCkWeMR88eBBA1pkATZs2hUKhQEhISGGWTUV0fncQ/EaMGAvmVYiIShR/yNJbx9XVFa1bt1b/CQ0NxbVr17Bz506MHTsWBgYGGDt2LBYsWICkpKR8x7OyssK4cePg7e2NTp06ITg4uEBxeHt7o1atWhg4cCB69+4NKysrTJkyRX1/ypQpsLe3R58+ffDDDz+gc+fO6N27N4CsRGXv3r0xevRojBw58rXkaEnEmxtLS0tMnDgRvr6+cHd3x759++Dj41OoMT766CN8/vnn6sO+zMzMsGjRIuzfvx8dOnTAX3/9hWXLlmmlRrcm1tbW6Nu3Lzw9PdGxY0ekp6djyJAhAIDr16+jdevWUKleL2WXV5wZGRnw9vbG2LFjYW1tnaNfYGAgevXqpTGWN2XtAHDjxg2cOHECw4cPL5HYyjuhQkXIar8Pxa8Lofx9K2TWNjD0nlWsflLcE4h3b0PhNw+pX3eAcvd2iPc0l+QpDik+DuKd25B3/BIQBMg7e0J17o/8Y7ewzJmsTksFIBV4XuPlG2E07RekTxkL5FObvaivLxERvb1Gjx4NmUyG06dPw9PTE6NGjXpto8eAAQPUH/fo0SPH5zExMbh37x7at2+PRo0aISoqSv1uuvz6BgcHw8vLC0qlEl9//TXeeecdBAYGYvHixbnGm5mZiaNHj0IQBLRs2VJ9ePahQ4eK9gJQoYRt8oeYmTnLycmJ72gnIipB2q0fQKRFzs7OEgBcuHBB16FQKRBFEV5eXvDw8ICLi4tOYrh79y5u376NJk2aFPutlv7+/khLS9OY2L1586b6oM6yQptr1zYvLy8cO3YMkiQNCg8PX5UjJ/MAACAASURBVK/reF4lSVK+2dfcyoZAFKG6ehnS7ZvIPH4YgnVlGE7xzX/SXPpJcU+Q2uvLrHn09QFRhPTiBYR/d+DnGkchY5fi45DaszNMD50E9OUQ/3cN6RNHw+T3vB+GZYYEQxm0BcbL/QEAyt07kHlgF4zXBObeSRKReSoU+p+4qi+ldnaF0YqNkNlVz70fUOTXV9B2faVi4N+FVBiDBw/GxYsXAaDDxYsXWfi2HHFxcZEAwGt3+UhKTnNvDaBs/my7du0a1q1bh5MnT0KlUkEmk8HHxwedOnVSt8neMX38+HFYWVmprysUCgiCgLt37+LGjRuYPHkyAODUqVPqmtS59f36669x69YtdO3aFWZmZkhJSUFQUBCsrKxw/PhxjbGGhYVhzJgxcHR0RGBgIB49eqQ+DPzw4cOoVKmSdl+cYvL394efnx9cuvVE20FDdR1Osc3z/AKiSoXExETDqKiovLfIExFRkXHnNRGVCTKZDHPmzNFZ4hrIOiCxdevWWkne9uvXL9cdyWUtcQ1od+1UMNLzRKQN6gFZdXvod/oK8m59oLp4vlj9BJvKkFWvAeXB3QAA5b6dyJg+Qd1XMLMAMjMhJSYAkgQpKf/DojT1EaxtIHOoCeWBPYAkQXlgN/Sa5f//rr5La0gJT6EM9Icq8iKU2zZB361DPgHIoNy8Acq9QQCQtcPbyAgy26p5divq60tEVEYNcx/2va5jeCt88MEHmD9/Pvbt2wdXV1eIogg/P78C9Q0JCYGbmxu++eYb7Ny5U309v9IfAHDv3j0AQFBQEPz9/REUlPX3XmJiYq59skuGAICfnx+CgoJgZGQEURRx5MiRAsVMRERU1vHtLURUZpTUgYy6UJ7WQiVDsLSC/lfdkfb9N0BaKgRTUxh8N6bY/Qx9ZiNj3gwoN6yC8E4NGE74+b++FSrCoP+3SPu2JyCKMBj8PfQ7dM57vlz6GPrMRsYv06DcuBoyp/ow9Jqa/6INDWE0fzkUq/2QefQQ9Nt2gPzrrHJI4oMYpI//Diab97zebfIMZMybnrWmqtVgNGN+1s7yYrxORERvkjNnzqzy2n1opa7jKO8iIyNRv359AICtrS2+++47hISEIDU1VWP7V5PSc+fOzbFj2s3NLde5Xu1bqVIlxMbGIjAwEI6Ojrn0+s+LFy9w8uRJAEB0dHSO2tpAVumQnj175jsOERFRWcfkNRERUQmTVXfQWKpD3skT8k6ehR4vr34yh3dh/OuG3Pv2GQR5n0GFm09DH1l1+zznyY3MrjqMfp6r4fo7GhPXACCr4QBjv8JXjCnq60tERG+ngQMHon79+qhbty5EUcTp06cBAO7u7jna2draIjY2Vn1GTXZ5EFEUAQDLli1DQkKCxjly6/vVV19hxYoVGDlyJFxdXWFgYICbN2+iS5cuGpPgx44dg0KhgK2tLfbv36/eOHHjxg10794dUVFRuH//PqpXz6fEFhERURnHrYFERERERET01nNzc8OjR4+wY8cO7Nq1C0ZGRhg+fDgmTJiQo92kSZNgZ2eH8PBwdYIbAMaOHQsLCwtcunQJnTtrfmdTbn2/+eYb/PDDDzAxMcHOnTuxa9cupKenw8HBQeM42SVDOnTokOMdf7Vq1VLv3D58mKXviYjozced10RERERERGWYi4vLyuAVfnAfPlLXoZRrc+bMKVC7Vq1aoVWrVq9d79SpU46DHT08PArcVyaToV+/fujXr1+BYli1alWu9wID8zgImYjKC1mDBg3ay2SyUQBaALDQdUBUIlSSJN0HsEWpVK64cuXKfV0HpAvceU1ERERERFS2Db0UfDD/VkRE9DaQOTs7r5PJZAcAuIOJ6/JMTxAEB0EQJsrl8muNGjVqpuuAdIE7r4lIJ6Kjo9GrVy+cP38eenp6ug6HqMgEQRB0HQMREREREb0dPvroo64ABlhbW8PLywsNGzZEhQoVdB0WlQClUokHDx5g69at2LFjh6kkSYEAHAFk6jq20sSd10RUIqKjo9GoUSOoVCqN92vXro3Q0FAmromIiIiI6I3T1MMTgiAsiIqK0vwLD1EJ0dPTGwoA06dPh6urKxPX5ZhcLoeDgwMmTJiAZs2aAcC7zs7Or5/iW84xeU1EOiGTyWBubq7rMIiIiIiIiArt074DMWrVqkkAmLym0tYEAN5//31dx0GlKPswXgCNdBmHLjB5TURalZqaikaNGqFXr14AgKZNm6JRo0a4cOFCjnaadmZnX1u8eDFatWqFKVOmwNfXFy1btoSvr6+6XUJCAsaMGYMWLVqga9euuHbtmvre7t270bFjRzRt2hSenp44d+5cCa+YiIiIiIiIqNSYA4ClpaWu46BS9NLX+62rcc7kNRFplYmJCUJDQ7F27VoAQEhICEJDQ9GgQYMCj2FqagofHx8cOnQIVapUwbRp07Bv3z71fW9vb6SmpiIoKAjt2rXDxIkTIUkSYmNj4evrizFjxuDw4cNo0aIFvL29tb5GIiIiIiIiIiIqeUxeE5HWmZubw8TEBABgZmYGc3PzQtW27t27N+zt7QEAffr0gb29PTIzs84jSExMxJ9//omRI0fCzs4OAwcOxOPHj3H79m0YGRlBT08PkiTBzMwMY8aMwf79+7W/QCIiIiIiequd3x0EvxEjxoJ5FSKiEsUfskRU5hgaGqo/NjIyynHv6dOnAIDhw4fj008/hZubGzIzM/H48WNYWlrC19cXgYGBaNeuHQYPHpyjpAgREREREZE2hG3yh5iZOcvJyUlf17EQEZVn/CFLRCVCEIQSGbdSpUoAgHXr1sHU1BQAkJaWBltbW6SlpaFatWpYv349VCoVAgIC4OXlhcOHD5dILEREREREREREVHK485rKsnQgKzFJb57KlStDJpPh7NmziI+Px5UrV7QyrpWVFVq2bIndu3dDT08Pjx49Qr9+/fDgwQMoFAqMGDECf/31F54/fw6VSgWlUqmVeUl3FAoFAEAQhAwdh0JERKQrw9yHfa/rGLRGX24AgP/Of9ukp6cD+O/rT0REVBBMXlOZJUlSNADcu3dP16FQEVhZWWHcuHHw9vZGp06dEBwcrLWxp0+fjkePHsHDwwNTpkzBuHHj4OjoCEtLS0ycOBG+vr5wd3fHvn374OPjo7V5STfi4uIAACqV6q6OQyEiItKJM2fOrGrQvqOuw9CainZ2AIAHDx7oOBIqTTExMQCAitXsdBwJERG9SVg2hMosSZI2CIKw2M/PD4sWLYJcLtd1SFRI3bt3R/fu3TXec3R0xIULF3K9ltvHAFChQgUsXLhQ47jt27dH+/bttRE+lQHHjh1DdHQ0ANzPzMw8r+t4iIiIqPg+/MwNxzeswZIlS7Bw4UL+O/8tEBERgePHj0NuaIj3W7joOpwyT5IkSdcxUNEJJVVDk+gtxeQ1lVkpKSkbzM3NR/z555912rRpg6pVq6prHBNR+ZaZmYmnT5/i8ePHAABRFEdFRUUpdBwWERERaUGTTh64dOQQ/vjjD7i6usLGxgbGxsa6DotKgCiKSEpKQmxsLCRJQrvBw2HI3+mIiKgQmLymMuvGjRtJDRs2bAVgUUpKSs8bN26wzA3R2ycawOhLly7x1E0iInprubi4rAxe4Qf34SN1HYpWGJma4ptFy3B0zUpcOhaMu3dZGay8s7C2QbvBw1CvdRtdh0JERG8YJq+pTAsPD48D0KdWrVojTE1N3xMEwUTXMRFRydPT08tUKpVPIiMjb+s6FiIdSwVgkpycDHNzc13HQmVcampq9ocvdBkHlYihl4IPlpvkNQCYWlrBY9wEdBgxCs+fxCKTh2yXS4IAGJmZw8q2ClhJofBu3bqFX375BZcvX4ZMJkO/fv0wdOjQUo+jUaNGGq+/WgZS2xISEjBs2DBs27atWG20NZc2OTs7f69UKg9evnz5VqlMWApEUcTmzZtx4MAB9UPJihUrom/fvujRo8dr7SVJKvLPheL0zfby97UgCLC0tETz5s0xZswYVKpUqVhjk3YxeU1vhBs3biQBCNd1HERERKVJkqQoQRCaXL9+Hc7OzroOh8owlUqFx48fQ5IkSalU/k/X8RAVlKGJCSo71NR1GERljiiKGDlyJHr06AE/Pz8kJSXh9u3/9nXExsZi+PDh2LlzZ5HnKOgY2UnqmzdvokePHvjrr7+KPGdhVKhQIUcyWVO8r7bR1lylwE8ul/s5OzuHS5K0OTMz88Dly5f/Kc0AtG3OnDkICgqCnZ0dPDw8IJPJcP369RzftwDg4+ODs2fPYvv27bCysirUHMXpm5sePXpAFEWEhYXh8OHDiIuLw+rVq7UyNmkHk9dEREREZdd6AE3mzp2LadOmoXr16jz/gXJQKBSIi4tDQEAAEhMTIQhCyJUrV2J1HRcRUXnX1MMT53buWBAVFaUqifFjYmLw+PFjdO3aFYaGhrCxsYGNjY36fkpKCu7fv1/k8SVJKvYYmsYsyR322o63jGgoCEJDuVw+v2HDhlclSfpNpVLtv3z58mVdB1ZYBw4cAAAsW7YMNWrUUF9PS0vT2K44c2jT4MGDYWVlhS5duqBnz56IjIzU+hxUPExeExEREZVR4eHh6xo2bNj5+vXrHXr37q3rcKjseyiK4nBdB0FE9Db4tO9ANHN3m3TayalEktfW1tYwMjJCQEAAhgwZ8lpSuFu3bgD+K32QvTv6/PnzWLRoEW7dugVbW1v4+PigcePGuHnzJrp16wZvb28sWLAAU6dOhZeXl8YxCkrTmBYWFnnOP3PmTCxYsACCIMDX1xdNmzYFAAQFBWHNmjVISkpCz549MWrUKHWf7Lg0rfnVNqmpqZgzZw5OnDiRdUhou3bw8vKCgYFBnjG8PE5+sSYnJ2PmzJk4deoULC0t0a1bN/z666/F3pEuCEJdQRBmyWSyWc7OzjcB/AZg38WLFy8CkIo1eCkwMzNDWloaFixYgDFjxsDe3h4AchzI+3KpjjZtsmrgZ3/t4uPjMWfOHFy8eBEpKSlwdHTE5MmT4ejomG9fADh27BjWrl2LO3fuwNzcHO3bt8fIkSNhYGBQoPizy699+OGHhV47lSwmr4mIiIjKLmV4eHjnBg0ajBYEobcgCHUA8PwHeplSkqSHgiAEKxQKH+66JiIqXc7OzuIrl3IkGSUpZ85REIS8kpDqeyYmJvjpp58wa9Ys/P3335g0aRJq1vyvxM727ds1lvBISUnBlClTULt2baxZswZz587F9u3b1fdv3LiBo0ePQpKkXMcorJfH/PPPP/Oc//r169i3bx+WLFmCJUuWYPPmzYiPj8cvv/wCf39/1KxZM9dDXAsS7/Tp05Geno69e/ciIyMDP/30E1asWIEffvghzxg0ya3dzJkzkZycjL179wIAJk2alKOfs7Nz3CtDFSXx/B6AqQCmOjs73/93R/beyMjI80UYq1SMHj0a3t7eOH36NM6cOYOWLVtiyJAhqFevnrrNgAED4O/vDyCrXIeRkZH6XkxMDO7du4f27dvj9u3bOHfuHLy9vdXfP3n1DQ4OxqRJk+Dg4ICvv/4aV65cQWBgIFQqFcaPH59n3GvWrIEoijh27BiaNGmCGTNmaOkVIW1h8pqIiIiobMu8dOnSfADzdR0IERER/efx3buC9Gp2+iVCltcuv/LfXHl4eKBOnTqYNWsW+vTpgyVLlqBx48Z59nF1dUVGRgZu374NU1NT3Lt3L8f9nj175kj6acPLY+Y3f+/evWFkZITPP/8ce/bsAQDI5XLIZDI8ePAA9erVQ926dYsUx4sXL3D8+HH8/vvv6nrIgwcPxi+//JIjea0pBk00tUtNTcXx48exfft29aF+I0aMwLfffvtyV+siLSAXkiQZAKimr69viQJ83+hK+/btYW9vj3Xr1uHkyZM4c+YM/vzzT/j4+KBTp04AgJEjR6oT0NnlOrLVrVsXv/32G+7evYsbN27g3LlzuHnzJlJTU2FiYpJn37Vr1wIAGjduDAMDA9SpUweRkZEIDg7ON3m9detW9ccVKlTAvXv3cpToId1j8pqIiIiIiIiIqBDO7w5C2G8bx4SHh8sBvLr7urjUCfG6desiICAAP//8MxYuXIjAwMA8O65duxY7duxAvXr1YGpqCpUqZ1WTqlWrajnUnGPmN3/FihUBZO0sVyqVAABLS0vMmjULixYtwsaNGzF58mQ4OTkVOo74+HiIooh33nlHfa1y5cp49uxZvjFooqldXFwcRFFUl8QAssplvCwjI6NS9scqlUpjstnExCQ+r7VIkhQjCMIhAPvCw8P34w0oGwIAH3zwAebPn4/Y2FjMnz8fISEh8PPzUyev8xISEoLZs2dDkiS8//776usKhQImJnm/8TD7IUlQUFCO64mJifnOe/z4cZiYmODIkSOYOnUqxo8fj6NHj0Imk+Xbl0oHk9dERERERERERIUQtskfoko1y8nJaUFUVJSiJOeSyWTo1q0bhg4dmme7p0+fYuXKldi/fz+qVKmC8PBwHDp06LWxSiK+gs6fGzc3N3z22WdYvXo1Jk6cqC7JURgVKlSAIAh49OgR7OzsAABPnjxB5cqVCz1WbszNzQEAsbGx6qR9bGzOil1RUVHPXuv4Cmdn59euSZJ0WxCEg6IoBl66dOkPbcRbmiIjI1G/fn0AgK2tLb777juEhISoa0m/SqHI+b/N3LlzkZKSgqCgIFhZWcHNzS3XuV7tW6lSJcTGxiIwMFBdI7swDAwM0KJFCwBZCe+MjIwctbpJt5i8JiIiIiIiIiIqQ+7fv4+wsDB07NgRBgYG2L9/f46D5MzMzCCKIi5fvgx7e3tYWFggMzMTkiTh/v37MDExQUBAQJ5zaBqjOAo7f7YnT57g/v37qF+/Pt555x1kZGQUKV4LCwu0atUKCxcuhI+PDxQKBdatW4cvv/yyWOt6WcWKFVG/fn0sXrwYU6ZMQVJSkrpkRRFFS5J0QBCEwPDw8MKdmFnGDBw4EPXr10fdunUhiiJOnz4NAHB3d8/RztbWFrGxsZgyZQrs7e0xefJkAIAoZr2BYdmyZUhISNA4R259v/rqK6xYsQIjR46Eq6ur+oDOLl265JkEB7JqXuvp6anjbdKkCRPXZQyT10RERERERGXbMPdh36/UdRBEVHpMTU0REhKC5cuXQyaToUmTJpg2bZr6vq2tLXr06IEhQ4bAzMwMR48eha2tLQYMGIDRo0ejYsWK6Nu3rzohp4mmMYqjsPNnE0URs2bNQkxMDOzs7PDzzz8XOd6ff/4ZM2fOxOeffw5DQ0N4eHhgwIABxVrXq3x9feHj44O2bdvi3XffRa9evfDPP/8UagxJkmaLorg5IiIiSqvB6ZCbmxsiIiIQFRUFmUyG6tWrY/jw4ejfv3+OdpMmTcLcuXMRHh6O+/fvq6+PHTsWCxcuxKVLlzBy5EhERES8Nkdufb/55hsYGBhg586d2LlzJwwNDVGnTh04ODjkG/fWrVshCAKsrKzw5ZdfYvTo0UV/EahElNlC70RERERERJRlb1zSG1HvlOhtMc/zC4gqFRITEw21XTYkr0Mgqew5duwYVq5cqa63rOmUTm1ydnaWAODChTd6ozYVkr+/P/z8/ABg7sWLF710HU9pYvVxIiIiIiIiIiKiAjhx4gRiYmKgUqlw7do1/Prrr1otTUJEObFsCBEREREREdEb4n/n/gQA1GnWQseRFN6bHDtRtnv37mHOnDlISEiAjY0NPDw80Lt3b12HRVRuMXlNRERERERUhrm4uKwMXuEH9+EjdR0KaVF48EHUatwU5pWsC9Uv0GciAGBacGgJRFWy3uTYibL179//tTrORFRymLwmIiIiIiIq24ZeCj7I5HU5s2fhXACAfb36qPtJa9Rp1gIVqlTVcVRUFpR0zWQiojcJk9dEREREREREOnL3SiTuXonEoeVLUa12HXzo2ha1mzaH9TvVdR0aERGRzjF5TURERERERFQGPLz+Pzy8/j8Er/oVlR1qol5rVzg2bwnbmu/pOjR6RVMPT5zbuWNBVFSUStexEBGVZ0xeExERERERUama5t5a1yGUeU/u3EaI/zqE+K9DharVUN+1LRxbuOg6LPrXp30Hopm726TTTk5MXhMRlSCZrgMgIiIiIiIiotxlKhRIfhqPjBcpug6FiIioVHHnNREREREREZWqacGhug5B5/LbfV6hajXUatwUH37WBtXr1sOrZ/hx9zoREb0NmLwmIiIiIiIiKgOsq9dA7abNUd/VDVVr1dHYxs7xfTyI/qeUI9Oeyg41dR2CVpzfHYSw3zaOBTAHgKjreOitkg7AKC0tDcbGxrqOhUpJeno6AECSpHQdh1LqmLwmIiIiIiIi0pEq79ZSJ6xt7B3ybT946cqSD4ryFbbJH6JKNcvJyWlBVFSUQtfx0FvlBoB6Dx48QK1atXQdC5WSmJiY7A9v6DIOXWDymoiIiIiIiKiUuQ4YhPqubWFlW0XXoRDRG0SSpM2CIMxesmQJFi5cCLlcruuQqIRFRETg+PHjkCTphUwm26vreEobk9dERERERERl2zD3Yd9zu20580nPvroOgYjeQMnJycvNzc0H/vHHH3VcXV1hY2PD8iHllCiKSEpKQmxsLCRJAoCpFy5ceK7ruEqbkH8TIiIiIiIi0qW9cUmSrmMoqCd3bmP50IEAAH25HA4fNUDnH72QnpKM5UMHltphjX8f2IsTARugSEvF5L3BxR7vuP9aXDy4H2kpyajyXi18MWosqtXWXJeayr95nl9AVKmQmJhoyLIhVNoaNmxoIwjCXEmS+gmCINN1PFTiHkiSNC48PHyrrgPRBe68JiIiIiIiIq2bFhyK1OfPsW/JfOxbMh9tBw0ttblfJCbggN9i9J+7CNXqOGplzGq1HdFibTfo6eshxH8dgmZOwyj/QK2MnZ9p7q01Xw8OVT8sKO5DAW2NU1DafrhA9DYJDw+PAzDQ0dFxlJGRUQ09PT0jXcdE2qdSqURJkhIjIyPvAHhjHmJrG5PXREREREREVCJMLC3RwrM7fpv8U6nO++L5cwgC4FD/oyL1lyQJgpDzjcofuHys/ri+WztcOnK4WDEWRnZC+cmd21g5fBB8DoWU2tyF8TzuCQImjMXIdZvybFcSDxeI3kbR0dHJAKJ0HQdRSeJbC4iIiIiIiMowFxeXlcEr/HQdRpGplArIDV/fFHgr/CJWDh+EGR3dsGRAL9yOCEdachJmdGyLRzf+p24XefwoVo/M2rX994G9WNDTE76d2uHoulW5zrl8yACIoohp7q3Vu5Yz0lKxa95szO7SEbM9PsfexfOQqciq9vDkzm1Mc2+Ni4cOYJZHB1w7fVLjuJIkISk+Hn/+vh2NOnbKdf6CxlneZLx4gYSHD/Jt9/LDBQOj1783/q3tSkRExJ3XREREREREZdzQS8EH4T58pK7jKLQXzxNxelsgnD5p/dq9jNQUdPrxJ9g6vIuwwAAcWr4UI1ZtgGPzFogKC0XVWln1pC+HHkeDtu2R/OwpDvgtwqDFy2FTowaexsTkOu+IVRte26G8d+E8KDPS8YN/IDKVCmyb7oMTAevR9tth6jZP7t7GT9t2QVPuNObaVawdPQIAUKtxU3iMnaBx7sLEqU2RIUcRvPJXCDIBX46dgNpNmgEAMpVKHFu3ChHHjkCVqcQHLT9Gx1FjNCaNX3Yr/CKOrP4VcffuwsKmMjr/+BNqftQQQFZyPuy3jUhLSUYzD091SZjsWufZDwxyK0GyfMiAHO1GrNqA5UMHovPon3B41TJ4jJ0AIzNzjfNnlzfxGDcBR9eshL6BATwneOPulUic2bEFckMjeIybgPecGxdr/UREVDZw5zURERERERFp3TT31ljavxesbKvkSBBn+8DlE1S2r4m4e3dhaGKiTvI2aNcBUadCAQBpyUm4ezkCH37WBnr6cggyGRIfP4KhiWmhyk1kpL7A1VNhcB/6HUwsLWFhbYNPe/fDlbATOdo1+/IryA2NNCY23/mgLqYeDsHIdZugTE/HgWWLNc5VnDiL49GN6xi9aSvqftwax9atVl8/9OsSPLwejWEr1uLHTduQmvQcx9evzmOkLNkPFybuOoh6rV1xaPlSAP8l57tP9cVP23bB6ePW6j4jVm2ATCbDtODQPGtn59Yu++FBrSbNcp0/29OY+/hh4xbUbtoc26Z7I/lpPMb8tgN1W32Co2tWFHv9RERUNjB5TURERERERFo3LTgUE3cfRKfR4yA3NHztftjmACwd0Athv/kj7s4dSKIKQNauZmV6Oh5e/x+ungpDrcZNYWxuARMLC3hO8MbRdauw6rvBeBB9rcCxJD97BkkSUaFqNfU1C2sbvEhMyNHOqkqVPMcRBBkqvVMdrgMG4eqpMI1tihNncbh83RNyQyPUb9MOTx/cB5BVKiX8yCF0/nE8LG0qw9jcAi7deuFqLmVRXpbbw4WSTM6//PAgt/mztfiqGwyMjdGgXQe8eJ6I1n0GwMDYGPXbtEV8TPHXn5+mHp4QBGFBVFSUqtiDERFRrlg2hIiIiIiIiEpVSsIzhG7agNEBW2FZ2RZ3r0Ti8oljAACZnh7qu7bF1ZOheBB9DS26dlf3c/qkNT5w+Rihv/kjaPYM/OAfWKD5TC0tIQgCnsc+Viewk+LjYFHJOkc7QSjg/i5BgL5cnuvtosZZHGYVKgAADIyMIGZmAgCSnz6FqFJh2aC+Odrq6eefCgjbHIC/9++BneP7MDQxVT9cyE7OH1mzAmd2bMEXo8bAzvEDrazh5YcHuc2fzcTSEkDWemUymfpzuaF21p+fT/sORDN3t0mnnZyYvCYiKkFMXhMREREREVGpElUqSJKEZw8fwMDEBH/s2JrjfoN27bHZewIkUYVajZsCAJLi4/Hs4QNUr1sXFavaITMjo8DzGZtboHbT5ghevRydfxwPlVKBk1s2oaH75wXqn/DoIe5ejkTdT1ojPSUFoQEb4PTpEUs9IgAAIABJREFUZxrbFidObTO1soIgCBi/Yw+MzS0K3C+vhwtAySXnsx8e5Dd/QRV1/UREVHYweU1ERERERESlysLaBq2690KgzySYWlmhZdfuuH7+rPp+ZYeaMDYzw7vOjSGTZSU0JVGF/UsXIOHRQ1SoUhUe4zQfmJgbj3ETsX/JfCzq0w1yQwM0bN8RLt17Faiv3MgIf+3bjX1L5sPAyBj1WrtqrOOtjTi1ydjMHLWbNMPBX5ei3eBhMLG0wpM7t5GekoyaDZxz7ZfXw4W8kvNGZmYQRREx166i0jvvFDlhnN/DjYIq6vqJiKjsYPKaiIiIiIiItKayQ02Nh/W9et3tmyFw+2aI+vOmnbuoP1ZmpCMx9jEatOugvmZZ2Rbfrw0ocAw+h0JyXDOxsEA37+mFijmbWYWKGOy3skBzFybO0uDx0yQc/HUxlg3qh0ylEpUdaqLdYM2J92x5PVzIKzlvYW2DZh6e8B8/GoYmpvhp264ixZzfw43CKMr6C+L87iCE/bZxLIA5AMRiD0hERBoJug6AiIiIiIiIcufi4iIBgNfuQ7oOpVSkJiXhj6CtePi/aPT7ZYGuwyHSaJ7nFxBVKiQmJhpGRUUpdB0PEVF5xZ3XREREREREVGYs6OmJyg410WPqDF2HQkRERDrG5DUREREREVHZNsx92PcFq1lRDngfOKrrEIiIiKiMkOk6ACIiIiIiIsrdmTNnVjVo31HXYRARERGVOiaviYiIiIiIiIiIiKjMYdkQIiIiIiIiIiqUvw/sxYmADVCkpWLy3uBijydJEmKuReHamVNoN3h4ru3iY+7j+PrVuB0RjkyFAg71P0LnH8fDwtqm2DEQEVHZw53XREREREREZZiLi8vK4BV+ug6DyqjncU/gN6hvqc75IjEBB/wW4+vJ0/DT9j1aGXNRn6+xfcZUnN25I892//xxCjUbOOMH/0D8uGkb9OUG2D3/F63EQEREZQ+T10RERERERGXb0EvBB3UdA5VRGS9eIOHhg1Kd88Xz5xAEwKH+RzAwMip0f0mSXrvWY9os9J09P9++Lbv2QNPOXWBsbgFTqwpw6d4L969GFToGIiJ6MzB5TURERERERFTG/X1gLxb09IRvp3Y4um6V+vryoQMhiiKmubfGNPfW6uu3wi9i5fBBmNHRDUsG9MLtiHCkJSdhRse2eHTjf+p2kcePYvXIoXnO8arlQwa8NmdGWip2zZuN2V06YrbH59i7eB4yFQoAwJM7tzHNvTUuHjqAWR4dcO30ydfGrFa7ToFeB5ksZxrjRWIiLGxyLxlS0DUREVHZxJrXRERERERERGVY8rOnOOC3CIMWL4dNjRp4GhOjvjdi1QasHD4IPodCcvTJSE1Bpx9/gq3DuwgLDMCh5UsxYtUGODZvgaiwUFStlZUsvhx6HA3ats9zjldpmnPvwnlQZqTjB/9AZCoV2DbdBycC1qPtt8PUbZ7cvY2ftu2Cho3XRSKKIv4I2oqG7TpovF+YNRVWUw9PnNu5Y0FUVJRKa4MSEdFruPOaiIiIiIiIqAzT05dDkMmQ+PgRDE1MUa2OY759PnD5BJXtayLu3l0YmpioE7cN2nVA1KlQAEBachLuXo7Ah5+1KdIc2TJSX+DqqTC4D/0OJpaWsLC2wae9++FK2Ikc7Zp9+RXkhkZFKjWiyeEVfpBECS08u2m8X5w15efTvgMxatWqSQCYvCYiKkFMXhMRERERERGVYSYWFvCc4I2j61Zh1XeD8SD6Wr59wjYHYOmAXgj7zR9xd+5AErNyrLUaN4UyPR0Pr/8PV0+FoVbjpjA2tyjSHNmSnz2DJImoULWa+pqFtQ1eJCbkaGdVpUqBx8zP8Q1rcCciHD1/ngU9fc1vKi/OmoiIqGxg8pqIiIiIiIiojHP6pDV+8A9E7abNETR7Rp5tUxKeIXTTBny7ZDl6TJsJ58+/UN+T6emhvmtbXD0ZiiuhIWjwUsmNwszxMlNLSwiCgOexj9XXkuLjYFHJOkc7QdBOCuJEwHr888dp9J+7CCYWFnm2LeqaiIiobGDymoiIiIiIiKgMS4qPx53ICEiSiIpV7ZCZkaG+Z2RmBlEUEXPtKtKSkwAAokoFSZLw7OEDpKUk448dW3OM16Bde1wOPY6nD+6jVuOm+c6RH2NzC9Ru2hzBq5cjNSkJyU/jcXLLJjR0/1wLq88p9Dd/RJ0MRf+5i2FqVSHPtsVZU37O7w6C34gRY8G8ChFRieKBjURERERERERlmCSqsH/pAiQ8eogKVarCY9wE9T0Laxs08/CE//jRMDQxxU/bdsHC2gatuvdCoM8kmFpZoWXX7rh+/qy6T2WHmjA2M8O7zo0hk8nynaMgPMZNxP4l87GoTzfIDQ3QsH1HuHTvVeD+09xbv/bxtOBQpD5/jo1eP2L4yvUAgNBN/gCA+T26qNvLZLLXDqzUxpryErbJH6JKNcvJyWlBVFSUQmsDExFRDoKuAyAiIiIiIqLcubi4SADgtfuQrkOhckKZkY4FPT3xzaJfUdneQdfhvJHmeX4BUaVCYmKiIZPXREQlh29vISIiIiIiKtuGuQ/7XtcxUDmRmpSEsM0BqFbnfSauiYiozGPymoiIiIiIqAw783/27jw+pnv/4/h7JhIEsUtJibZqqaWSWEooJZSi1Vqr+HW5blstbVXREnqJ3mpRyrU02qrat7p2Wm6q0ggShBStfV+isUSQZc7vj2lGQpKZRGKGvp6Px3k033PO53w/54yb3Mcn33xOePj0um3aOTsN3CfGvdhJB6O267kBg5ydCgAAdtHzGgAAAACAv4ngVT86OwUAABzGymsAAAAAAAAAgMuheA0AAAAALiwwMHDauqmTnJ0GAADAXUfxGgAAAABc2+s71612dg4AAAB3HcVrAAAAAAAAAIDLoXgNAAAAAACQAw06dpLJZBoXGxub6uxcAOB+ZnJ2AgAAAACArAUGBhqSNHjZGmenAiCd6+eOF+xas2aSs/MAgPsZK68BAAAAAAAAAC6H4jUAAAAAAAAAwOVQvAYAAAAAAMiBrcsWa1Lfvu+LugoA5Cu+yQIAAAAAAOTAz9/PlCUl5ZOaNWsWcHYuAHA/o3gNAAAAAAAAAHA5FK8BAAAAwLW98fQbbzs7BwAAgLuO4jUAAAAAuLDw8PDpddu0c3YaAAAAdx29mQAAAADgHrDyi8919vAhu+c90+9dlX+0mm28etJ4nf7jD7txT7/5th6sUdM2XjflS53Yt9duXKs+b6hS7cdt4x+/mqJje3bbjWvxah89VNffNt7wzVc6snNHjuPCvvtGB6O22Y1r3vsVPVKvgW28ac53+iNyi924pj16qeoTjW3j8AVztC98s924wK4vqnqTJ3Mc1/D5Tqr1VJBtHLl0kfaEbbQbF9D+WdVt3dY23r5imXb9uM5uXN3WbRTQ/jnbeOe61YpatcJuXK2nWqrh851t4z0bf1LksiV246o3aarArj1s472bf9avC+fbjXu0QUM92fNl2/iPyAhtmjMrx3GHd0Rp47cz7MY95OevFq/0sY2P7YnRj19NtY0tqal2rwEAuHMUrwEAAADAxVlSU+r8HhkxK/n6tbr2zt26fMlrHd4dZKvm/h4RPuNGYmKD7GIkaduyJW9UqFrt17Tx3vBNU29cvRpoLy5i6aL+Dz5WMyxt/NumsC+vJ1xpbi9uy9JF7/vWrvOjLS5sw9jEy5db5zRu98Yf/5146aLdpemRSxcNecjPf3XaOOandSOvxsd3tDvfDwuHV6nfYFnaeOe6NcEJf17oYj9u8aiqjRovymlc5H+XfP7Yk82/TxtHrVnxwZXz53vZi9u2fOmkOi1bhdriVi3vd/HM6T7ZxUjS9pXLv/Jr227yzev80OfPkyf62YuLXrNiVv1nO4615b18aa+4Y0c+sBe3c+2VhY06dQ2xxf2wpEvcsSPB9uISL19c3uTFnsPSxluWLXo27tiRkOxiMo1buqh13LEjY7OLkaSrF/9c17z3K7b7ifxh8ZNxx45MTn+OYRjnYmNjk+1dCwCQeyZnJwAAAAAAsK9JkyYPp6amFrF33tWrVw/FxMRcTRs3aNDgITc3t6L24goWLHg4LCwsIW38xBNPVDaZTMXsxZnN5iPh4eFX0saNGzf2NQzDy15cUlLSsaioqEtp4yZNmlRKTU0tntO4+vXrVyxQoEAJe3HXrl07vnPnzotp44YNGz5oNptL2otzc3M7sXnz5vi0caNGjXwklbIXJ+lkRETEnzmNS0pKOh0VFRWXNg4ICCjv4eFRxl5cgQIFzvzyyy/n08YNGzb0NpvN5ezFWSyWc5GRkWfTxk2bNi2bkpLygAPzxf3yyy+n0+VZxsPDo7y9OLPZfCE8PPxU2rhRo0alJPk4kGd8ZGTkibRx3bp1SxQuXLhiTuMCAgKKe3h4VLIX5+bmdmnz5s3H0saBgYHFLBZL5fTnJCQknNi9e3f8bcEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAZTM5OAMhGAX9//16GYfxD0uMmk6mIsxMCkKlEwzBizWbzTEmhUVFRyc5OCLjPuPn5+fUwmUx9DMPwM5lMRZ2dEFxKkqRDhmEsTElJmbB79+54ZycEAAAA5BWK13BVBfz9/RdKet7ZiQBwnGEYYWazuTUFbCDPFPDz8/veZDJ1d3YicH2GYRxOTk5utmfPnuPOzgUAAADICwWcnQCQGX9//16Snn/ooYc0dOhQValSRcWKFXN2WgAycfXqVR0+fFhjx47V7t27m1sslsGSQpydF3A/+OvnYfeKFSsqODhYjz76qLy8vJydFlzIjRs3dPLkSYWGhmr9+vUPeXh4TJXU3tl5AQAAAHmBlddwSX5+fuEmk6nxjBkz5Ofn5+x0ADjgwIED6tatmwzDiN2xY0ctZ+cD3A/Sfh5OmTJFDRs2dHY6cGEpKSkKCgrS5cuXDbPZXC4qKirO2TkBAAAAd8rs7ASALDwuSVWqVHF2HgAc5OPjk/Yl/8MF8s7jklSjRg1n5wEXV6BAAVWoUEEmk8mUkpJS3dn5AAAAAHmB4jVcUtrLGWkVAtw7ChcuLDc3N5lMpoLNmzenLRWQB9J+HtIqBI4oUsT6bms3Nzde6gkAAID7AsVrAAAAAAAAAIDLoXgNAAAAAAAAAHA5FK8BAAAAAAAAAC6H4jUAAAAAAAAAwOVQvAYAAAAAAAAAuByK1wAAAAAAAAAAl0PxGgAAAAAAAADgciheAwAAAAAAAABcTgFnJwDAdezbt0+bNm1SUlKS6tatqyZNmjg7pRxLSEjQtGnT5O/vrxYtWjg7HQAAAAAAAOQSxWsAkqT58+dr7NixMgzDtq9Hjx56//33beNz585p1qxZ8vPzU8uWLXM8x53GOyIyMlLz5s1TTEwMxWsAAAAAAIB7GG1DAOjq1auaMGGCHnnkES1ZskQLFy6Ur6+v5s+fr7Nnz9rOi4+P17x587R9+/ZczXOn8Y7YsmWLJGnv3r26fPlyvs0DAAAAAACA/MXKawA6d+6ckpOTValSJVWuXFmS1K1bN23YsEFxcXEqVaqUJk6cqPj4eEnSzp07NXbsWJUrV069e/fOcK1du3Zp8+bNcnd3V1BQkB5++GElJyc7HH/o0CFt2LBBktS+fXuVL18+R/cSGRkpSbJYLIqMjFSrVq1y/DwAAAAAAADgfBSvAahSpUry8fHRxo0b1bdvX3Xr1k1dunRRt27dJEmJiYmaN2+e7fzff/9dv//+u6pWrZqh+Lx69WoFBwfbxjNnztScOXPk7e3tUPwvv/yigQMHKiUlRZI0b948zZs3T97e3g7dx7Fjx3Ty5EnVqFFDe/fu1ZYtWyheAwAAAAAA3KNoGwJAbm5umjp1qurXr6/IyEgNGDBAXbt21Z49eyRJnp6eCgsL04wZMyRJzz//vMLCwvT1119nuM73338vT09PLVy4UKGhobpx44bWr1/vcPyYMWNkMpk0ffp0jRo1SpcuXcpQ9LYnrWVI586d5eXlZRsDAAAAAADg3sPKawCSJB8fH02bNk379u3TggULtHLlSr3++uuaM2eOKleurGLFisnT01OS5O7urmLFit12jfHjx2vVqlUKDQ1VTEyMJCkhIUGS7MafOnVKp0+flre3t6KiomQYhsxms62A7oi0YvWOHTtUuHBhnTlzRkeOHLG1QgFuZaR/Qyn+tkwmk8nZOQAAAAAAbsfKawA6fvy4Xn31Vc2ZM0fVq1fXiBEjNHjwYF2/fl1r1qxx6BqGYWjo0KGaOnWqdu/eLV9fX9t+R1y/fl2SdPbsWX311VcKDQ2VxWLRn3/+6VB8amqqtm3bJklauXKl7UWTrL4GAAAAAAC4N1G8BiAPDw/t2rVLYWFhtn0lSpSwHUtToID1jzUsFovtv4mJiZKsBfBdu3YpKChIq1atUocOHW6bJ7v48uXLq0CBAqpXr55WrFihFStWqHXr1nr00UcduoeYmBglJiaqWbNmWrJkiSZMmCBJioiIcPg5AAAAAAAAwHXQNgSAvL29FRAQoKioKPXq1Uvly5fXr7/+Kg8PDwUFBdnO8/Hxkaenp9avX6+EhAT99ttvGjZsmAICAlS0aFGZzWZFR0frvffeU3h4uCTrimhH4gsXLqwOHTrohx9+0Mcffyx3d3dt2bIl0yJ4ZtJWWDdr1kyVK1eWr6+vSpYsqejoaCUnJ8vd3T0PnxgAAAAAAADyGyuvAUiSPvvsM7Vt21bHjx/Xpk2bVKVKFU2ePNnW/kOSChUqpH//+98qVqyY1q9fL4vFopIlS0qSSpUqpSFDhsgwDG3fvl1PPfWUPDw89PPPP9tWV2cXL0mDBg1S586dtX//fsXExOiZZ57RwIEDHco/bYV1w4YNJUkmk0kNGzZUYmKirf82AAAAAAAA7h28oAguyd/f35CkqKgoZ6cCIAcaNGig1NRUeXl5uYeFhaU4Ox97sn1hY2ys1LKllJoqxcVJ3t7W/WfO3KXsbnHggBQUJB05kr8xubFvn1SjhvUZXbsmBQRIs2dLFSrk/pp3mvu+fVLdutJf/fSz48ovbOTnIXKiT58+io6OlqS20dHRa52dDwAAAHCnWHkNAEBmata0Fqp/+UUqWND6tbMK15JUpUrmhdy4OCkkJGcx+SHtGcXHS3XqSP3739n17mbuAAAAAACXRPEaAIB7WXbFa2cwm6X/+z/pf/9zdiYAAAAAgHscxWsAAHJq3z6pUCFp927pySelzp1vHouOlurVs7bQqFxZWrYsY8zChVLVqlLx4tJXX92MGz/een65ctZVx0uWZD5nevXrS02bSjduSA88YN0uX84+RpL275caNJDKlpWee066eNGxHB1lsUhpnTj27pWeeMI6V2CgdPJkxrkye4a5yV2Stmyx5u3jI33xRc7zBgAAAAC4FIrXAADkRmqqtTXG+PHSd9/d3P/ll9J770lnz0offCC9/fbNY0lJ0sqV1n7aEydKw4db9586JQ0cKG3eLJ07J336qbRggf0ctm27va2Jl5f9uC5drKujz52TypSR3n3Xfo6OunHDWvBu2dI67tzZem/nz0tPPy0FB988N6tnmJvcDUN68UVp8GDpxAlrHgAAAACAexrFawAAciMlxVp0rVdPKlLk5v6JE60vCXz7bWncOGtbjzSGYS1Mu7tLDRveXDXs7W19yeE770gTJlhXDi9cmD95nzxpLUz36WNdHf3mm9Lq1fZztCdt9bePj3WOL7+0FpF/+836LB54QJo0ybqiOk1WzzA3uZ84IR09KvXsaT32+uuOPxMAAAAAgEsq4OwEAODvJiEhQYcOHZK3t7e8vb2dnQ5yq2BByc8v476kJGshtn1769ajh9Sixc3jHh5ShQrWr9PaakiSm5u15cWWLdY2GoMGWYvA8+fn/31I1oK1vRztSVv9nd6JE9Ye2MePW4vhqakZ25pk9gxzKi13iyVjzm5ud3bdPFa3bt3/M5vNO6Kjo2OcnUt+2bdvnzZt2qSkpCTVrVtXTZo0cXZKDjt37pxmzZolSTKZTCpTpozatWunMmXKODkzAAAA4O+NlddALuzatUsBAQE6ceJEjuL279+vgIAApaam5lNmrjOvs+41r/PI6/vYunWrOnTooM8++0zPP/+85s6dmyfXhYs4dUo6eFAaOtTax3nmzIzHsyoGx8VJNWtK1apJb7xhbbPx00+OzVmypJScbG2jYRjShQvZn+/jY50rNNR6fmio1K6d/Rxz48EHrfcUGmodT5t2e2/rnMgu90qVrEX3hQutx77++s7zz0Nms/l9Sbv8/f0P+vn5/cvPz6+epDx82M41f/589ezZU9OnT9e3336rd955R+PGjctwzrlz5zR27Fht2LAhV3PcaXx24uPjNW/ePM2bN09z587Vl19+qZdeekl//vlnns8FAAAAwHEUr4FciIiIkCRt2bIlR3GPPvqowsLC5JbHKwLtFVjza15Xkl/F8rx8dqmpqRo5cqTGjh2r2bNna9q0aZo0aZKuXbuWB5nCJVSubG1lUaOGVL26tRVGUpJ15XF2ypSxtgxp2NDaQmTgQGv7EUd4e0sffyzVrm19iWHaCyKzs2iRtcd02bLS6dPWViX5ZdEiaxG/dGlp9mxp+vQ7v15muZtM0pw51mfh4yMlJNxp5vnlYZPJNNxkMm3z8/M75ufn92mdOnUa6h7+/2RXr17VhAkT9Mgjj2jJkiVauHChfH19NX/+fJ09e9Z2XlqBePv27bma507jHfH8888rLCxM7777ruLi4rRy5cp8mwsAAACAfbQNAXJhy5Yt8vX1VUREhDrnYBWh2WxWsWLF8jEz15r3fpCXzy4hIUH/+Mc/FBAQIEmqWrWqkpKSlJCQoMKFC+fJHC7q1tWl9sa37jNJsj2369evZzj/xo0bGcYpKSlZjitWrKikpKScrXatXt3aw9revjT/+Y91S/PFFze/Th9z6zXefNO65SSPNMHBGV+EaC+mWjVp61b752c3p6O51azp2FyOHs8qd0lq1kw6cODmeM6crK+fzuOPP14z/dgwDFNmX0uSh4fHbfuyG6d9bRhGYdMtq9pNJtODkgYXKFBgsL+//2nDMOZK2pKamromJibmqkPJu4Bz584pOTlZlSpVUuXKlSVJ3bp104YNGxQXF6dSpUpp4sSJio+PlyTt3LlTY8eOVbly5dS7d+8M19q1a5c2b94sd3d3BQUF6eGHH1ZycrLD8YcOHbKtzG7fvr3Kly+fo3txd3dXsWLFVKtWLUnSpUuXcvw8AAAAAOQditdADl25ckWxsbEaOXKkPv30U6WmpsrNzU379+9Xjx49NH36dI0cOVLx8fEaPHiw2rdvb4tNO2fr1q22lbxp+3r16qXFixerefPmKlSokFavXq1nnnlGw4YNkyQdP35cI0aMUGxsrLy9vTV06FDVrl1bTZs2tV2/QYMGkqSvvvrKVujLal5JunbtmsaOHav169erUKFC6tatm1577TWZTCaH7ic34uPjNWrUKEVERMjHx0ejRo1SjRo17M4XGxurkJAQHTp0SFWqVFGNGjW0atUqbdiwwaFnsGPHjlzdR1bPbtmyZQoNDdX58+dVsWJFDRo0SA0bNsz2WsWLF1fHjh0lSYZhaNasWapRo4bKli1rN4/czOdMV65cMfn7+xv2z3Sc8Vdv44IFC2bYf+s4Ozdu3MjLlHCfcHNz2+PouYZx+z/rTIrSuUmjvMlkel+SChQoEOfn5zffZDL9kJsL3W2VKlWSj4+PNm7cqL59+6pbt27q0qWLunXrJklKTEzUvHnzbOf//vvv+v3331W1atUMxefVq1crON0vYWbOnKk5c+bI29vbofhffvlFAwcOVEpKiiTZ2oDk5N0CsbGxmjZtmjZt2iRJeuKJJ3L4NAAAAADkpXv2T1QBZ9m6davKlSunoKAgJSUlac+ejDWPr776SpMmTVLHjh01ZcoUh69bpEgRDR8+XGvWrNEDDzygjz/+WCtWrLAdHz16tCpVqqTVq1frrbfe0ujRo+Xp6amwsDDNmDFDkrRx40aFhYWpbt26Ds05atQoHTlyRLNnz9aECRO0fPlyzZ49O0/uJyvBwcFKTEzU4sWL1bp1a3344YcZikGZzZeSkqL33ntP7dq104oVK1StWjXt3r1bq1atcvgZ5OV9nD17ViEhIRowYIDWrl2rRo0aZSi42HPhwgW1a9dO3377rUJCQvJ9PmcoVqyYISn1ry0lky35li1JUpJhGGnbjVs3Sddv2a6l2xLTb4ZhXM1kS0i/Sbpy1x4IXN0eSbtv2WLSNsMw0rZdt2w70zZJOzLZotNtDvcHMgyjgMlk8jYMo1Re3mR+cXNz09SpU1W/fn1FRkZqwIAB6tq1q+3n463fp9Nac3x9S1/y77//Xp6enlq4cKFCQ0N148YNrV+/3uH4MWPGyGQyafr06Ro1apQuXbqUoejtiNjYWIWGhmr//v0qXLiwrlzh2wQAAADgTKy8BnJoy5Yt8vPzk7u7u2qGa7oYAAAgAElEQVTVqqWIiAg9/vjjtuOvvfaafH191aZNmxy9jO+ll17S8b/64vbs2VNHjx61rR6TpH//+98qUqSITp8+rfPnz+vUqVOSpGLFisnT01OSVLRoUYd7M1++fFnr16/XggUL5OvrK0l66623NHnyZPXq1euO7yczFy9eVEREhGbNmiUfHx+98sor+uabb3T48OFs5zt9+rQuXLigrl27ysPDQx07dtTKlStVqlQph59BXt5HoUKF5ObmJsMwVLRoUQ0YMED9+/d3OL506dKaOnWqpkyZouDgYH333Xcym7P+XeKdzucs0dHR98LPmDxdHY57U3R0dO38nsPf3z9GUnbzxElaZxjGwh07dqyR9Zc68vf3z+/U8oSPj4+mTZumffv2acGCBVq5cqVef/11zZkzR5UrV87wfTqtNcetxo8fr1WrVik0NFQxMTGSrO2WJNmNP3XqlE6fPi1vb29FRUXJMAyZzebbfsFsT/v27fX6668rPj5e06dP16BBgzRt2jTVq1cvx88EAAAAwJ1j5TWQQ5GRkVq3bp0aNWqknTt33vbSxjp16kiSChTIWd0ufeuDQoUK3XZ848aNat++vYYMGaLY2NhM/3Q9J86fPy/DMFSxYkXbvooVK+rcuXMZzsvt/WTmwoULkqQ333xTzZo1U1BQkFJSUnTmzJls56tQoYIefvhhbd68WZK0efNmVa1aNUdz5+V9FC9eXCEhIZo7d65at26tPn36aO/evTm6hq+vr0aNGqWDBw8qNjY23+cD4HoMwzhnGMZ3qampT0dHR3tHR0f33LFjx3L9Vbi+Vxw/flyvvvqq5syZo+rVq2vEiBEaPHiwrl+/rjVr1jh0DcMwNHToUE2dOlW7d++2/VLV0Z911//qj3727Fl99dVXCg0NlcVi0Z9//pmje/H09FSFChVUs2ZN9enTR4Zh6Ndff83RNQAAAADknXthVRzgMo4dO6aTJ09qypQp8vb21r59+xQcHJzhz4o9PDzyfN4LFy7o008/1ezZs1WtWjXFxMRo/fr1tuO56a9atmxZmc1mnThxQg8//LAk6cSJE7f1Bs3L+yldurQk6euvv1aRIkUkWftue3t76+TJk1nO5+bmpk6dOmnEiBH66KOP5O3trXHjxmU4x94zyMv7uHbtmipUqKBvvvlGqampmjVrlgYPHqy1a9dmG/fbb79pyZIltpYfBQoUkLu7e7arru9kPgCuxzCMkyaTaXVKSsr8mJiY/+k+WP3v4eGhXbt2yc3NTS+99JIkqUSJErZjadJ+eWixWGz/vX79ujw9PXX8+HHt2rVLQUFBGjNmjFavXq2tt7yYM7v48uXLq0CBAqpbt65GjBghSZo0aZLt3NxI+2soLy+vXF8DAAAAwJ2heA3kwJYtW+Tt7W17UV7aCwe3bt2qBx98MN/mvX79uiwWixISErR//359/vnnGY6XK1dOZrNZW7ZsUbVq1XTmzBnVqlUr22t6eXmpdevWGj16tIYPH66EhARNnjxZXbt2zbf7KFGihBo3bqxly5apd+/eOnHihPr3769vvvkm27jz589rwYIF+u6772QYhnx8fG5bnZ6bZ5BbSUlJ6tu3r8aOHatHHnlEqampSk62v1CyUqVK2rhxo3x9fdW+fXstWbJExYsXV/Xq1fNlPgAu5XuLxRK+c+fO+24Zr7e3twICAhQVFaVevXqpfPny+vXXX+Xh4aGgoCDbeT4+PvL09NT69euVkJCg3377TcOGDVNAQICKFi0qs9ms6OhovffeewoPD5ckpaamOhRfuHBhdejQQT/88IM+/vhjubu7a8uWLerQoUOO7mXr1q0aMWKELl++rC1btsjNzU1PPvlk3jwoAAAAADlG2xAgB7Zs2WIrXEvWvpsBAQG3tQ7Jaz4+Pnr55Zf17rvv6r333lPz5s0lSX/88Ycka1F44MCBCg4OVocOHbRu3TqHrjts2DD5+vqqZ8+eeuedd/Tss8/aVs3ll5EjR+r06dPq2LGjhg0bpoEDB6patWrZxpQtW9bWLqNHjx4KDAxUq1atMrxcMrfPIDeKFy+uDz/8UCEhIXr66ae1YsUKDR8+3G5c0aJF9cUXX2jlypVq27attm3bpsmTJ9vtU57b+ZBDBw5IlSs7OwvXsHSp5OsreXtLgwY5FpOSIo0YITVvLvXoIe3bd+d53EefSXR09Of3Y+E6zWeffaa2bdvq+PHj2rRpk6pUqaLJkyfb2n9I1pZY//73v1WsWDGtX79eFotFJUuWlCSVKlVKQ4YMkWEY2r59u5566il5eHjo559/VmJiot14SRo0aJA6d+6s/fv3KyYmRs8884wGDhyYo/s4cuSIVq5cqcjISNWsWVOTJ0+2/XUSAAAAgLsv570GgLvA39/fkKSoqChnpwIXEBcXpw4dOujLL79U1apVlZKSooULF2ru3Ln65ZdfnJ0e0mnQoIFSU1Pl5eXlHhYWlmI/wrmMO20enx/i4qRp06Rhw/I3Jit790p+ftKKFVKzZlKLFlLfvtaCdHb+9S9rsXn0aGvsf/4j/fbb3c09l0y56b10l/DzEDnRp08fRUdHS1Lb6OhoeksBAADgnsfKawAur2TJknruuecUHBysoKAgPffcc4qIiGD1Me5PcXFSSEj+x2Rl9mypcWOpVSvJw0N66y3rPnsKFrQWrCtVkv7v/6Tff5cc6Tecl7kDAAAAAO4rFK8BuDw3NzcNGTJEa9eu1bZt27R582bNmjVLrVq1cnZquJ/s2yfd0ktdkjR+vLV1RblyUpUq0pIljl0vu7i9e6UnnpDKlpUCA6W/Xliq+vWlpk2lGzekBx6wbpcvZz9PdjH790sNGljnee456eJF+3kfO2ZdeZ2malXHVlAPGSJ5eUmJidLHH0sdO0p2XkZq934z+0z27bMWyp9+2royvHFjqU0b67GsnquU+88RAAAAAOA0FK8BAMjKqVPSwIHS5s3SuXPSp59KCxbceVznztbj589bi7DBwdb927ZJv/xiLc6eOWPdvLyynyu7mC5drKugz52TypSR3n3Xfu4Wi1Ss2M1x4cJSfLz9uDRPPilNnmy9P3tyc7+SlJQkvfOOtGmTtd3Ipk3W/Vk919x+jgAAAAAApyrg7AQAAHBZ3t5SQIC1UNq0qdSwobRw4Z3FnThhXcn89tvWLTVVevTRvM/95EkpNlbq00cymaQ335SeecZ+XOnSGYvVCQlSTlqDb98urVoldehgXcVduHDOc7fHw0N6+OGb/7VYsn+uuf0cAcCFBAYGOvTNODw8PEMff+Lurbjr16+XiIqKupQuLl5SCXtxhmFU/vXXX4+mjRs3bnzYZDJVthdnMpnqbt68eVe6uB0mk6muvTiLxdI8IiLi53R5/k9Scwfy7Pjrr7/+N918P5hMpo724iS9HB4e/l26uG9NJtPLOY0LDAz8QpLd3+ZbLJZ3IyIiJqabb4TJZPo4k1Mjw8PDn3AgDwBALrHyGgCArLi5SVu2SAMGWNtXDBokde9+53Fms3T8+M3VxqtW5d89pOdIEfqJJ6Rff7053rrV2m4jOxaLtHjxzXG7dtbV0SdO5CpNu9Ler3jrexazeq65/RwB4B60/PxlI/1G3L0VN3jJiovp4woWKWK3cC1Jb4Z+dyR9XHFv78qOxP3f+Ek708d5P/yI3cK1JL30yedh6eMq1qrd3JG4Fz4avix9XNUnGjtSuNYz/QfMTB9Xu2Wrl3MTV69DRwf+DE0K6vPGhPRxTV7s+XEWpzasWbOmhyPXBADkjsn+KcDd5+/vb0hSVFSUs1MBkAMNGjRQamqqvLy83MPCwlKcnY89hpGumrtvn1S3rnT9+s0T4uKkJk2s7SbKlJH++1/ptdes+7NjL+6xx6yrg/v2tb7kcOlSacMG67GzZ6UKFaTTp629m//807oaOjtZxdSpI73+unWeN96w9paeOTP7a127Zu1z/eab1r7RvXpZcx00KPs4Pz/rKu++faXVq633e+yY5O6eu9ylzD+TtH07d2b87/XrWT9XO5+HyXRrFdx18PMQOdGnTx9FR0dLUtvo6Oi1zs4HeScwMHBa3aefef3pN/s5OxUAf/m8U3tZUlN18eLFgrGxsUnOzgcA7lesvAYctH//fgUEBNy2XblyJUfxqamp+Zyp68rrZ7B9+3Y999xzatq0qb755huH4zL7HAMCAvIkJz7n+0yZMtZWEw0bWltPDBwoTZx453GLFlmLyKVLS7NnS9On3zzm7W194WHt2tZi7rJl9ufLKmbRIum776z7Tp+WJkywf63ChaWNG639qN94w1q8fv9967EDB7JehT13rjRrlvWehg+Xli+3X7jO7f1mJavnmtvPEQBcx+s71612dg4AAAB3ncuuNMLfmyuuNNu/f7969OihjRs3ymy++XufokWLypFFexaLRVevXlWx9C9CS3fdrVu3ys3NLc/zzmt3km9WzyA34uPj1aVLFw0fPlzly5dX37599cknn6h+/fp2Y2/9hcOyZcsUERGhKVOm2I21d/95eY/3ont65TX+tlh5jfsFK6/vX2n9kgcvW+PsVAD8hZXXAHB3sPIayKGiRYuqWLFits3RmofZbP7bFjTT5OUzWLFihZo1a6Ynn3xSjz76qF544QX98MMPDsWm//w8PDw0b9489e/fP0/y4nMGAAAA7n8NOnaSyWQaFxsby59cAkA+ongN5IG4uDg9+eST2rFjhyRp1qxZ6tGjhywWi+2cW9tJJCYmKiAgQD169JBkXbEaEBDg8Oq6pKQkff7552rRooUaN26sfv366fTp07bj165d06hRo9S0aVO1atVKM2bMUNoi01tzSRun/3r79u169tln1bRpU61cufKO881s3jTLli1Tu3bt1KBBA3Xq1EmRkZF2r3XgwIEMq6xr1aql3377zeFc0ixdulQ1atRQ9erVsz3P0fvP7B7T9k2YMEFNmjTRsGHDFBISosaNGyskJMR2Xnx8vAYMGKBGjRqpc+fO2rt3r+1Ybp4RAAAAgPzRrNcr6j99+keSKF4DQD6ieA3kUIsWLdSsWTM1a9ZM7//VB7ZMmTJ644039OWXX+ry5cv69ttvNWTIkAztRW7l6empsLAwzZgxQ5K0ceNGhYWFqW5dh17wrVGjRum3335TaGio5s2bp8TERA0ePDjD8SNHjmj27NmaMGGCli9frtmzZzt8n1999ZUmTZqkjh07asqUKXecb1bOnj2rkJAQDRgwQGvXrlWjRo0UHBxsNy4xMVHe3t62cYkSJXT+/PkczW2xWDRv3jxbQTo7eXH/RYoU0fDhw7VmzRo98MAD+vjjj7VixQrb8eDgYCUmJmrx4sVq3bq1PvzwQxmGketnBAAAAAAAcC8r4OwEgHvNnDlzbEXpQoUK2fZ3795dy5cv19tvv60WLVqoTp06dq9VrFgxeXp6SrK2I3G0h/Tly5e1du1azZ8/X4888ogkacSIEdq/f7/t+Pr167VgwQL5+vpKkt566y1NnjxZvXr1cmiO1157Tb6+vmrTpo3mzp17R/lmp1ChQnJzc5NhGCpatKgGDBjgUAsPNzc3eXh42Mbu7u66ceNGjubevHmzChcu7PDLGu/0/l966SUdP35cktSzZ08dPXpUKSnWttAXL15URESEZs2aJR8fH73yyiv65ptvdPjwYZUuXTpXzwj2uXKvYwAAAAAA/u5YeQ3kUPny5VWhQgVVqFBBpUqVsu03m816/vnnFRsbq86dO+drDufPn5fFYlHFihVt+ypVqqRWrVrZjhuGkeF4xYoVde7cuUyvl1ZATS+t+F6gQP7+jqt48eIKCQnR3Llz1bp1a/Xp0ydDu4yseHl5KT4+3jZOSEhwuP94mlWrVqlt27Y5zjm3ChYsaPs6/S8+JOnChQuSpDfffFPNmjVTUFCQUlJSdObMmVw/IwAAAAD5Y+uyxZrUt+/7oq4CAPmKb7JAHklMTNR3332nRo0aaerUqQ7H5WbhZ9myZWUymXTixAnbvn379ql3796242azOcPxEydO2NpspM2Z1pP74MGDt82RflXzneabnWvXrqlChQr65ptvtGHDBjVp0iRD+5OsVKtWLUOP63379qlcuXIOz5uYmKhNmzbZCv6Oyq+FuqVLl5Ykff3115o3b57mzZunBQsWqE6dOrl+RgAAAADyx8/fz5QlJeWTmjVr8hftAJCPKF4DOZSQkKArV67YtrRVy1OnTlX16tU1fvx4HT58WGvXrnXoeuXKlZPZbNaWLVsUFxenPXv22I3x8vJS69atFRISokOHDunYsWOaMmWKKlSokOH46NGjdfToUcXGxmry5Mnq2rWrJGuPbpPJpL179yoxMVHz5s1z+P5zk292kpKS1LdvX23btk2XLl1SamqqkpOT7cY1b95cy5Yt0/nz55WQkKClS5fqiSeekGQtyl+5ciXb+K1bt6ps2bLy8fHJUb55ff9pSpQoocaNG2vZsmVyc3PT6dOn1bt3b508eTLXzwgAAAAAAOBexm8IgRxq0aJFhvGYMWPk4+OjpUuXauHChfLw8ND777+v0aNHq3HjxvLy8sr2eiVKlNDAgQMVHBysa9euqXPnzqpVq5bdPIKDg/XFF1/olVdekcVi0VNPPaVBgwbZjg8bNkyff/65evbsqYIFC6p79+566aWXJEmlSpXSSy+9pHfffVcPPfSQunbtqpCQEIfuP7f5ZqV48eL68MMPFRISolOnTqlChQoaPny43bgyZcqoV69e6tSpk0wmk4oUKaJ//vOfkqQ//vhDPXr00NatW7PsS71t27ZcvWwyr+8/vZEjR2rUqFHq2LGjbZ5q1apJUq6eEQAAuG+88fQbb09zdhIAAAB3Gy+qgkvy9/c3JCkqKsrZqcDFHT16VIcPH1b9+vVVpEgRZ6fzt9egQQOlpqbKy8vLPSws7PZm6gByhJ+HyIk+ffooOjpaktpGR0c79idguGcsP3/ZcHYOAG76vFN7WVJTdfHixYKxsbFJzs4HAO5XrLwGcE/z9fWVr6+vs9MAAAAAAABAHqPnNQAAAAAAAADA5VC8BgAAAAAXFhgYOG3d1EnOTgMAAOCuo3gNAAAAAK7t9Z3rVjs7BwAAgLuO4jUAAAAAAAAAwOVQvAYAAAAAAMiBBh07yWQyjYuNjU11di4AcD+jeA0AAAAAAJADzXq9ov7Tp38kieI1AOQjitdwVYmSlJCQ4Ow8ADjoxo0bSk1NlWEYSWFhYSnOzge4TyRK0pUrV5ydB+4BiYmJaV9edWYeAAAAQF6heA2XZBhGrCQdPnzY2akAcNCpU6ckSSaT6ZCTUwHuG2k/D//44w9npwIXl5qaqjNnzsgwDCMpKel3Z+cDAAAA5AWK13BV30jSZ599pv379+vqVRYQAa7q2rVrOnjwoMaOHZu2a4kz8wHuM7afh/v27ePnIW6TlJSkkydP6rPPPtPFixdlMpk27tmz56yz8wKA+93WZYs1qW/f90VdBQDylcnZCQBZcPfz81tjMplaOjsRAI4zDGPblStXmh44cOCGs3MB7hPufn5+/zWZTG2dnQjuCacsFkvznTt3slT/PhMYGGhI0uBla5ydSp4xLBb9sX2rti5bouN7Y3XjZtsb3EdMZrO8ypRV7RZBqt/uWRUv5+3slPLM553ay5KaqosXLxaMjY1NcnY+AHC/4jeEcFXJO3bsaGsYxoeSYiRdc3ZCALJ0XdJewzBCKFwDeS55x44dz1oslg8Mw9ipv3pgA+kkG4ZxVNJXSUlJ/hSucS8wLBb9d/xnmhs8RAeitlG4vo8ZFosunTurzfPnaPI/euvkvr3OTgkAcI9h5TUAAAAAuLDAwMDXn37j7Wl127Rzdip5Ys/PG7X4k5EqU6aMBg8eLD8/P5UsWdLZaSEfJCcn6+TJk5o/f74WLVqkkg+U19tffy+3AgWcndodY+U1ANwdrLwGAAAAABcWHh4+/X4pXEtS1OqVkqSRI0eqRYsWFK7vY+7u7qpcubKGDBmihg0bKv7MaR3eGe3stAAA9xCK1wAAAACAu+bkfmvriOrVqzs5E9xN1apVkySd+mO/kzMBANxLKF4DAAAAAO6apGvW19kUL17cyZngbkr7vOlxDgDICYrXAAAAAODCAgMDp62bOsnZaQAAANx1FK8BAAAAwLW9vnPdamfnAAAAcNdRvAYAAAAAAAAAuByK1wAAAAAAADnQoGMnmUymcbGxsanOzgUA7mcUrwEAAAAAAHKgWa9X1H/69I8kUbwGgHxE8RoAAAAAAAAA4HIoXgMAAAAAAAAAXA7FawAAAAAAgBzYumyxJvXt+76oqwBAvuKbLAAAAAAAQA78/P1MWVJSPqlZs2YBZ+cCAPczitcAAAAAgL89i8Wi77//Xt27d1ejRo3UqFEjtWvXTvPnz8/0fMMwcj3XncTeaurUqQoICFBAQID+97//5dl1AQBwBRSvAQAAAMC1vfH0G287O4f73pgxYzRhwgQlJiaqY8eOeuGFF+Tj46PDhw9nOG/48OFq3bq1Ll26lOM57iQ2K2vWrJGnp6ckae3atXl2XQAAXAF/3gIAAAAALiw8PHz64GVrpjk7j/vdqlWrJEmTJ09WpUqVbPuvXbuW6Xl3Mkde2bVrl06ePKlWrVopPDxcmzZt0tWrV1WkSJE8nQcAAGdh5TUAAAAA4G+vaNGikqRx48bp6NGjtv2FCxe2fR0QEGD7umXLlhnGcXFx+uCDD9SyZUs1bNhQvXv31v79+x2KlaSffvpJ3bt31xNPPKFWrVpp3LhxSkpKyjbn1atXS5KaNGmiBg0aKCkpSRs3bszJbQMA4NIoXgMAAAAA/vbeffddmc1mbd68WZ06dVL//v21Z8+eDOe8/PLLtq+7d++eYXzixAkdO3ZMbdq0UUBAgGJjYxUcHOxQ7Lp16zR48GAlJyerS5cuevDBBzV37lxNmDAhy3xTUlL0448/ymQyqXHjxmrUqJEkaxsRAADuF7QNAQAAAAAXFhgYOG3d1El6+s1+zk7lvtamTRv5+vrq66+/1qZNmxQeHq6IiAgNHz5cHTp0kCT169dPM2fOlCT16dNHJUqUsMU/9thjmj17to4ePaoDBw4oMjJSBw8eVGJiojw9PbONnTFjhiSpXr168vDwUNWqVRUTE6N169Zp0KBBmeYbHh6uS5cuqVq1aipVqpQCAwMlSdu2bdOFCxdUunTpvH5EAFyHuW7dum3MZnN/SY0keTk7IeSLVMMwjkual5ycPHXPnj3HnZ2QM7DyGgAAAABc2+s71612dg5/CzVq1NDYsWO1YsUKtWjRQhaLRZMmTXIoduPGjQoKCtKrr76qpUuX2vbba/0hSceOHZMkLV68WDNnztTixYslSRcvXswyJq1liCRNmjRJixcvVqFChWSxWLR+/XqHcgZwTzL7+/t/bTabV0l6WhSu72duJpOpsslk+tDd3X1vQEBAQ2cn5AysvAYAAAAA/O3FxMSoTp06kiRvb2+99dZb2rhxoxITEzM9/9ai9GeffaaEhAQtXrxYJUqUUFBQUJZz3RpbunRpnT17VnPnzlW1atXs5nr16lVt2rRJkrR///4MvbUla+uQF1980e51ANx7Hn/88c6SXi5TpowGDx4sPz8/lSxZ0tlpIR8kJyfr5MmTmj9/vhYtWlTEMIy5kqpJSnF2bncTxWsAAAAAwN/eK6+8ojp16uixxx6TxWLR5s2bJUlPP/10hvO8vb119uxZDRs2TL6+vho6dKgkyWKxSJImT56s+Pj4TOfIKvaFF17Q1KlT1a9fP7Vo0UIeHh46ePCgnn/++UyL4D/99JOSkpLk7e2tlStXymy2/lH1gQMH1K1bN8XGxur48eOqWLFi3jwc3KZBx06KXLpoXGxsbKqzc8Hfi5ub2+uSNHLkSDVs+LdciPu34e7ursqVK2vIkCE6duyYIiMjH/b39w+Kjo5e6+zc7ibahgAAAAAA/vaCgoJ0+vRpLVq0SD/88IMKFSqkN998U0OGDMlw3kcffSQfHx/t2LHDVuCWpPfff19eXl7auXOnnn322UznyCr21Vdf1TvvvCNPT08tXbpUP/zwg65fv67KlStnep20liFt27a1Fa4lqUqVKraV22vX/q1qG3dds16vqP/06R9JoniNu62+JFWvXt3ZeeAuSvdXOQHOzMMZWHkNAAAAAPjbGzNmjEPnNWnSRE2aNLltf4cOHWwvdpSkjh07OhxrNpvVu3dv9e7d26Ecpk+fnuWxuXPnOnQNAPesYpJUvHhxZ+eBuyjd5/2363HOymsAAAAAAAAAgMuheA0AAAAAAJADW5ct1qS+fd8XdRUAyFd8kwUAAAAAAMiBn7+fKUtKyic1a9akHSsA5COK1wAAAAAAAAAAl0PxGgAAAABc2xtPv/G2s3MAAAC46yheAwAAAIALCw8Pn163TTtnpwEAAHDX0ZsJAAAAAADAxRiGYTg7B+SeyWQyOTsH4H7AymsAAAAAAAAAgMuheA0AAAAALiwwMHDauqmTnJ0GAADAXUfxGgAAAABc2+s71612dg55poC7hyTp2rVrTs4Ed9P169cl3fz84bhDhw7pn//8pxo1aqTAwEBNnz7dKXkEBARkuuW3+Ph4devW7Y7Pyau58pq/v//btWvXfviuTpoPLBaLvv/+e3Xv3l2NGjVSo0aN1K5dO82fPz/T8++kK05edNRJ/2+4Xr16atmypYYOHaoLFy7c8bWRtyheAwAAAADumlI+PpKkkydPOjkT3E0nTpyQJJWq4OPkTO4tFotF/fr1U9OmTRUWFqZly5bJz8/Pdvzs2bN64YUX7mgOR68RFRWlqKgoLVy4UGaz2TbObyVLltSCBQts48zyvfWcvJrrLpnk7u5+0N/fP9rPz+/92rVrV7/bCeSFMWPGaMKECUpMTFTHjh31wgsvyMfHR4cPH85w3vDhw9W6dWtdunQpx3PcSWxWunfvrtPP97oAAB/xSURBVC5duqhgwYJau3atPvzwwzy7NvIGL2wEAAAAANw1tZ8K0oZvQzVx4kSNHz9e7u7uzk4J+WzXrl3asGGD3AsWVPVGgc5OJ0806NhJkUsXjYuNjU3Nz3lOnDihM2fOqHPnzipYsKDKli2rsmXL2o4nJCTo+PHjub6+YRh3fI3Mrpmf7yrM63xdiJ/JZPJzd3cf6+fn95thGLNTU1NX7t69e7ezE3PEqlWrJEmTJ09WpUqVbPtv/SubtPPuZI681KdPH5UoUULPP/+8XnzxRcXExOT5HLgzFK8BAAAAAHdN/Q4dtXP9Gv36669q0aKFypYtq8KFCzs7LeQDi8Wiy5cv6+zZszIMQ637vKmCRYo4O6080azXK2r4dNBHm2vWzNfidZkyZVSoUCHNmjVL//znP28rCnft2lWSbO070lZCb926VV988YUOHTokb29vDR8+XPXq1dPBgwfVtWtXBQcHa9y4cRoxYoQGDx6c6TUcldk1vby8sp1/9OjRGjdunEwmk0JCQtSgQQNJ0uLFixUaGqrLly/rxRdfVP/+/W0xaXllds+3npOYmKgxY8bof//7n/XfXuvWGjx4sDw8PLLNIf117OV65coVjR49Wr/88ouKFy+url276j//+Y+2bduWo+eXGZPJ9JjJZPrEbDZ/4u/vf1DSbEkroqOjo+/44vmkaNGiunbtmsaNG6cBAwbI19dXkjJ8f0/fZqZly5aSbv57i4uL05gxYxQdHa2EhARVq1ZNQ4cOVbVq1ezGStJPP/2kGTNm6MiRIypWrJjatGmjfv36ycPDsVZFiYmJkqTatWvn+N6RvyheAwAAAADumkJFiujVLybrx9Bp2vnTOh09etTZKSGfeZUpq9Z93lCt5i2dnUqe8/f3t9yyK0Mz3lt785pMJnvNejMc9/T01AcffKBPPvlE27dv10cffaSHHnrIdnzhwoXq3r37bQXThIQEDRs2TI8++qhCQ0P12WefaeHChbbjBw4c0I8//ijDMLK8Rk6lv2ZERES28//xxx9asWKFJk6cqIkTJ2rOnDmKi4vTp59+qpkzZ+qhhx7K8nuDI/mOHDlS169f1/Lly3Xjxg198MEHmjp1qt55551sc8hMVueNHj1aV65c0fLlyyVJH330UYY4f3//81mkl9OGzY9IGiFphL+/v8suOX/33XcVHByszZs3Kzw8XI0bN9Y///lP1apVy3bOyy+/rJkzZ0qytusoVKiQ7diJEyd07NgxtWnTRocPH1ZkZKSCg4Nt/26yi123bp0++ugjVa5cWV26dNGePXs0d+5cpaamatCgQdnmHRoaKovFop9++kn169fXqFGj8uiJIK9QvAYAAAAA3FVFipdQx4FD1LZvf106d1YpycnOTgn5wGSSChUtphLeD+RrGwlnOXP0qMnI5s1xJqvbdmfxdZY6duyoqlWr6pNPPlHPnj01ceJE1atXL9uYFi1a6MaNGzp8+LCKFCmiY8eOZTj+4osvZij+5YX017Q3/0svvaRChQrpmWee0X//+19Jkru7u8xms06ePKlatWrpsccey1UeV69e1YYNG7RkyRKVKFFCkrU1xKeffpqheJ1ZDpnJ7LzExERt2LBBCxcuVOnSpSVJffv21T/+8Y/0oWVydQPZMAzDw1X/t9SmTRv5+vrq66+/1qZNmxQeHq6IiAgNHz5cHTp0kCT169fPVoBOa9eR5rHHHtPs2bN19OhRHThwQJGRkTp48KASExPl6emZbeyMGTMkSfXq1ZOHh4eqVq2qmJgYrVu3zm7xOv0LJUuWLKljx45laM0D56N4DQAAAABwioKenipX+SH7JwIuZuuyxfp59ncDduzY4S7p1tXXecGU/rqPPfaYZs2apX/9618aP3685s6dm23wjBkztGjRItWqVUtFihRRamrG7ibly5fP84TTX9Pe/KVKlZJkXVme/Ncvr4oXL65PPvlEX3zxhb777jsNHTpUNWvWzHEecXFxslgsevDBB237ypUrpz///NNuDpnJ7Lzz58/LYrHYWmNI1rYZ/9/enUdVWe1/HP+cg4Ki4pCz5lAOKcV1xAFzSsXUkrJrZpmatxzKsswsK6/dSn85G6ZoWaRlg2Zex4gkSKksjUFPVnbTBDUUBUEQkHOe3x9eTpri4SDyHLnv11qtxT7P/u79wZK1/Lrbz/lyc3Ovs9vthXaaHQ6H5b91hZ3QliQZhpFssVi2StoYFxe36RKn/T1Gq1atNHfuXKWkpGju3LmKiopSaGios3l9OVFRUZo1a5YMw9BNN/35zsq8vDz5+vpetrbgL0fWrl17wefp6eku9922bZt8fX31+eef65///KeeeeYZRUZGymq1uqxF6aB5DQAAAAAA4IaYVeFy2O0z/f3959lstryrsMVFJ7qtVquGDh2qsWPHXrbwxIkTCgsL06ZNm1S3bl3FxcVp69atF61V0grWLMr+henTp4969eql5cuX67nnnnNeyeGO6tWry2Kx6OjRo2rQoIEk6dixY6pdu7bbaxWmSpUqkqSUlBRn0z4lJeWCOTab7eRFhZfQrl27iz4zDOOAxWLZ4nA4VsfHx399pXlLQ2JiogICAiRJderU0aOPPqqoqCjnXdJ/lZd34W+b2bNn6/Tp01q7dq2qVaumPn36FLrXX2uvu+46paSkaPXq1c47st3h7e2tLl26SDrX8M7NzeVdDB6E5jUAAAAAAIAHSkpKUkxMjAYOHChvb29t2rTpghfKVa5cWQ6HQ3v27FHjxo3l5+en/Px8GYahpKQk+fr6auXKlZfd41JrXAl39y9w7NgxJSUlKSAgQA0bNlRubm6x8vr5+albt26aP3++pk+frry8PK1YsUKDBw++ou/rfDVq1FBAQIAWLlyoF154QRkZGc6rK67Az4ZhbLZYLKvj4uLce2umBxg9erQCAgLUunVrORwO7dixQ5IUHBx8wbw6deooJSVFL7zwgho3bqznn39e0rkXvErS4sWLlZaWdsk9Cqu9++67tXTpUk2cOFG9e/d2vpjzrrvuumwTXDp357WXl5czb8eOHWlcexia1wAAAADg2cYFj3sszOwQAEpfpUqVFBUVpSVLlshqtapjx46aMWOG83mdOnU0bNgwPfLII6pcubIiIyNVp04djRo1SpMmTVKNGjU0YsQIZ2PuUi61xpVwd/8CDodDM2fOVHJysho0aKCXXnqp2HlfeuklvfrqqxowYIB8fHwUEhKiUaNGXdH39VevvPKKpk+frr59++qGG27Q8OHD9dNPP7m9jmEYsxwOx/sJCQm2Eg1Yyvr06aOEhATZbDZZrVZdf/31Gj9+vEaOHHnBvGnTpmn27NmKi4tTUtKf75+cPHmy5s+fr/j4eE2cOFEJCQkX7VFY7UMPPSRvb2+tW7dO69atk4+Pj1q0aKEmTZq4zP3hhx/KYrGoWrVqGjx4sCZNmlT8XwRcFZ55yzsAAAAAwGnD8YxCXwoHoPTNGTJIDrtd6enpPlfp2hBd7mWQ8DxffPGFwsLCnPcuX+ptnSWhXbt2hiTt3n3NHc7GFQgPD1doaKgkzf7hhx+mmp2nNHH7OAAAAAAAAOCGL7/8UsnJybLb7dq3b5/eeOONEr2aBMA5XBsCAAAAAAAAuOHQoUN67bXXlJaWplq1aikkJET333+/2bGAMofmNQAAAAB4sKCgoLCIpaEKHj/R7CgAgP8aOXLkRfc5Ayh5NK8BAAAAwLONjY/YQvMa+B9zte5MBoBrCXdeAwAAAAAAAAA8Ds1rAAAAAAAANwSGDJHFYplns9nsZmcBgLKM5jUAAAAAAIAbeowYrceXLZsmieY1AFxFNK8BAAAAAAAAAB6H5jUAAAAAAKUoLmKLMk+kmh2jRCT9uFe//bBL+WfzzI4CACiDypkdAAAAAACA/yX/nj9bktT45gC17t5TLTp1UfW69UxOVTyH9u5R5Ipl8vH1VatuPdT61h5qEtBG3hUqmB3tqvpu/VrFvPfuZEmvSXKYnQf/U3IkVThz5owqVqxodhaUkpycHEmSYRg5JkcpdTSvAQAAAAAwwe97E/X73kRtXfK66jdvoVt691XzwM6q2fB6s6O5LTc7W/Gfb1X851vlXaGCburaTa269dANbdvLx9fX7HglLmZVuBx2+0x/f/95NpuNY+coTb9Kuvnw4cNq1qyZ2VlQSpKTkwu+/NXMHGageQ0AAAAAgMmO7P9FR/b/oohlb6h2k6a6uWdvtezcVXWa3njBvGMHD2jJ2NGaERFtTtAiyMvJUWLUF0qM+kKS1LpbD7Xu3kM3tuuoilWqFGtNwzCUvM+mfbHb1e/h8YXOS01O0ra3l+tAQpzy8/LUJOBvuvPJZ+RXs1ax9gU8jWEY71ssllmLFi3S/PnzVb58ebMj4SpLSEjQtm3bZBhGltVq3WB2ntJmMTsAAAAAAKBwQUFBY4PHPRbWpv9As6OUiBnBPc2OcE2pXq++0o4eMTtGibCWK6fmHQLl36O3mnXoKF+/qkWunX//PTIchrLS0zR9a1Sh83Z8vFreFSrqll63yWG3a+PCucrLydGD/zevJL4FpzlDBslhtys9Pd2Hk9coTc2aNfOrUqXK9xaLpYWvr69q1arF9SFllMPhUEZGhlJSUmQYhgzDeDouLq5kf5hdAzh5DQAAAAAeLDY2dtnU9VvDzM4Bc+TnlaG+qGHoTGamMk+kyn727GWmGbJYLjxrN2zGTJUrX15h48dcdouu9wyT1Wp1joPuHa6VUydfWW7Ag/z6668Zbdu27SZpdlZW1oPZ2dlWl0W41h3+b+P6Q7ODmIHmNQAAAACg1HjydRelxdXp8+r16qtZh0Dd0us2Xd/65gsauZe7NiT3TLa2LF6kn77eIRmG/Hv20oAJT6ict7fL5wXrPvDqbG15Y5EyUo/rxvYdddfTz6lC5cqSpF2bNyjmvXd15nSmOoUMUd8xYxX78QeKXLHsst9P0zbt1KxjoI788rN+/f47pfz2H504nHTR3ndOmqLPli1WyORn1frWHhesUb95Cx07eMDlr+35jWtJykpPl18trgxB2RIXF3dc0uiWLVs+XqFChUZeXl5l+w2p/6PsdrvDMIz0xMTEg5IMs/OYheY1AAAAAAAmq3l9IzUP7KyA3n1Ur1mLYq2xYf4cnc3N0RPhq5V/Nk8f/Wu6vlz5tvr+Y1yRnktSfORnGrNgsRx2uz5+ZYYi3wrTHZOeVubJE9ocukBjFi5RrUaNdOLPl4ddxKu8t+z5ZzVo4pPy795LFatU0ZpXX3K597HfD2jKR5/KKKEWjcPh0NdrP1TbfreXzIKAh/n5558zJdnMzgFcTfyvBQAAAADgwYKCgsIiloaaHQNXQd0bmunWYQ/o0eXheuytlQp+ZEKxG9e52Vn6cXuMgsc+Kt+qVeVXs5Z63P+g9sZ8WaTnBfo9PF6VqlVXletqqsf9I/Xzt19LkrzKlZfFalX6H0fl41tJ9Vu0vKCuvI+PWnbuqpDJz+qheYtktVjUYeCdqlilSpH37jT4bpX3qSDvCiVziPSzpaEyHIa6DBlaIusBAEofJ68BAAAAwLONjY/YouDxE83OgRLSe9QYBfTuq2p16pbYmpknT8owHKper77zM7+atZSVnlak5+d/VqBy9erKzc6SJPn6+WnIsy/q8zeXKnbNBxr0+FNq0LKVat9wo+6ZNl0tO3dVeZ9zTee/Xu9R1L2r1S25X49t77ypgwlxGjX3dXmVo/UBANcqTl4DAAAAAFCKut83okQb15JUqWpVWSwWnUr5w/lZRupx+V1Xs0jPC+ScPu38+vih31W1Vm3n2L97Tz0RvlrNAztr7ayXJUnNOwTq5h69nY3r4mQrYLGUTIviy5Vv66evd2jk7AXy9fMrkTUBAOageQ0AAAAAcMuxgwc0I7inZgT31CuD+uq956coIzXV+Xlp2bV5g+bce5devTO4RNbbFv6W5gwN0b8G3KblE8fqyP5fSmTdq+F02knnP7nZWapYxU/NAzsrYvkSZWdkKPNEqr76YJXaBg+QJJfPC0SuWKbcM9k6kZykmPfC1ea/90VnpKbqYGKCDMOhGvUaKD83t8hZi7p3SYh+L1y2r6I1cvZCVapWvcTXLxAYMkQWi2WezWazX7VNAABcGwIAAAAAKJ4ZEdHKPnVKGxfN1cZFc9V3zNhS2zsrPU2bQxdq5OwFF92/XFz1m7dUl7eGyqucl6LCV2jtqzP0ePjqElm7pM0ddrfz63b9B+rOJ6co5OnntGnRXC14YKjK+3irbf+BCrp3uHOeq+eSVL95Cy16cJgcDofa9rtdXf8+TJJkOOza9Po8pR09oup16ynk6WfdyluUvS/n/L8UKfi64L+/d6c+qfFhb0uSoleFS5LmDrvLOd9qtWr61ii38rrSY8RodQruM22Hvz/NawC4iixmBwAAAAAAFC4oKMiQpKnrt5odxenYwQNaMna0ZkRES5IO2fbqveen6B8Ll1zw+VXN8PtBhY17qNhNScMwZLEU/kfiw7/8pJXPPKXn1m8pbsRryl//ncK1nGNJPkP9/fPMzgEAZRnXhgAAAAAAroj9bN4l7zz+Le4HhY0fo5cH9tGiUcN1ICFOZzIz9PLAvjr6659XciRui9TyiedObe/avEHz7huiV+7op8gVywrdc8kjo+RwOJzXl0hS7plsfTpnlmbdNVCzQgZow8I5ys8711ssuNLkh62bNTPkdu3b8dUl1zUMQxmpqfrmk4/VfuAdhe5f1JwAAKD4uDYEAAAAAFBsWafSteOj1fLv3vOiZ7nZp3XHk1NUp8kNilm9UluXvK4Jy95Ry85dZIuJVr1mLSRJe6K3qU3f/so8eUKbQxdozMIlqtWokU4kJxe674Rl7yhs/JgLTl5vmD9HZ3Nz9ET4auWfzdNH/5quL1e+rb7/GOecc+z3A5ry0acyjIvXTN73o96aNEGS1KxDoEImX/pqDHdyomz6bv1axbz37mRJr0lymJ0HAMoqTl4DAAAAAIplRnBPvT5yuKrVqXtBg7hAq6Duqt24qY4f+l0+vr7OJm+bfrfLtj1aknQmM0O/70nQLb1uk1e58rJYrUr/46h8fCu5dZd1bnaWftweo+Cxj8q3alX51aylHvc/qL0xX14wr9Pgu1Xep4K8K1x8Urxhq9b652dRmrhilc7m5Gjz4oWX3OtKcnqq2k2acmWIG2JWhcuRnz/T39+fQ4EAcBXxQxYAAAAAUCyump0x76/Urk3/VoOWN8nHt5IMx7l32zXrEKizOTk6sv8XHd3/s5p1CFTFKn6SpCHPvqjP31yq2DUfaNDjT6lBy1ZFypJ58qQMw6Hq9eo7P/OrWUtZ6WkXzKtWt+5l17FYrLqu4fXqPWqMVk+fpsFPPXPRHF8/v2LnBAAARcfJawAAAADwbOOCxz1mdga3nU47qehV7+gfi5Zo2IxX1W7AIOczq5eXAnr31Y9fRWtvdJTa9Lvd+cy/e089Eb5azQM7a+2sl4u8X6WqVWWxWHQq5Q/nZxmpx+V3Xc0L5lksRfxjsMWicuXLF/q4uDkBAEDR0bwGAAAAAA8WGxu7rE3/gWbHcJvDbpdhGDp55LDOnM7U12s+vOB5m379tSd6m04cTlKzDoGSpIzUVB1MTJBhOFSjXgPl5+YWeb+KVfzUPLCzIpYvUXZGhjJPpOqrD1apbfCAItWnHT2i+M8/U15OjjJSUxW98h359+h1yblXkhMAABQd14YAAAAAAEqcX81a6nbvcK2ePk2VqlVT13vu1f7vvnU+r92kqSpWrqwb2nWQ1XruXJXhsGvT6/OUdvSIqtetp5CnL/3CxMKEPP2cNi2aqwUPDFV5H2+17T9QQfcOL1Jt+QoV9P3G9dq4aK68K1TUzT17X/Ie78vlzD51Su9OfVLjw952KzcAALg0i9kBAAAAAACXt+F4hmF2hpJ2NjdH8+4boocWvKHajZuYHQfFtGvzBsW8967OnM5Up5Ah6jtmrNmRSsWcIYPksNuVnp7uY7PZ8szOAwBlFSevAQAAAMCDBQUFhUUsDVXw+IlmRykx2RkZ+nrth6rf4iYa19ewzJMntDl0gcYsXKJajRrpRHKy2ZEAAGUMd14DAAAAgGcbGx+xxewMJWrefUP0n927NPipZ8yOgivgVa68LFar0v84Kh/fSqrfoqXZkQAAZQwnrwEAAAAAperFzZFmR0AJ8PXz05BnX9Tnby5V7JoPNOjxp9SgZSuzYwEAyhBOXgMAAAAAgGLx795TT4SvVvPAzlo762Wz45SawJAhslgs82w2m93sLABQltG8BgAAAAAAbstITdXBxAQZhkM16jVQfm6u2ZFKTY8Ro/X4smXTJNG8BoCriGtDAAAAAACA2wyHXZten6e0o0dUvW49hTz9rCQp+9QpvTv1SY0Pe9vkhACAa53F7AAAAAAAgMIFBQUZkjR1/VazowA4T86xJJ+h/v55ZucAgLKMa0MAAAAAAADc8N36tQqdMGGy6KsAwFXFD1kAAAAAAAA3xKwKlyM/f6a/vz/XsQLAVUTzGgAAAAAAAADgcWheAwAAAIBnGxc87jGzMwAAAJQ6mtcAAAAA4MFiY2OXtek/0OwYAAAApY7mNQAAAAAAAADA49C8BgAAAAAAAAB4HJrXAAAAAODBgoKCwiKWhpodAwAAoNTRvAYAAAAAzzY2PmKL2RkAAABKHc1rAAAAAAAAAIDHoXkNAAAAAADghsCQIbJYLPNsNpvd7CwAUJZZzA4AAAAAAChcUFCQIUlT1281OwqA8+QcS/IZ6u+fZ3YOACjLOHkNAAAAAAAAAPA4NK8BAAAAAAAAAB6H5jUAAAAAAIAbvlu/VqETJkwWfRUAuKr4IQsAAAAAAOCGmFXhcuTnz/T39y9ndhYAKMtoXgMAAAAAAAAAPA7NawAAAADwbOOCxz1mdgYAAIBSR/MaAAAAADxYbGzssjb9B5odAwAAoNRxNxMAAAAAXAM2LZijlAO/uZw3YOIk1Wve0jneEjpfR/fvd1kXPP4xNWzl7xxHLHldyT/tc1nX9+FxanTL35zjyOVLdGjvHpd1vR96WE3btHOOt729XAfj49yui373bf1n9/cu63o+OFo3dgh0jr96/13t3/mty7pbh49Qi85dnePYj97XT7E7XNYFDb1PN3Xr7nZdp7uG6OZefZzjnevWaG90lMu69oPuVJt+tzvHuzauV0JkhMu6Nv36q/2gwc5xfMQW7d680WXdzb1uU6e77nGO90Z9oZ3rP3FZd1O3WxU0dLhzvG9HjL7++EOXdc0DO6n7A6Oc4/07v9FX7690u+5A3G5FvfOWy7qmbdup9+iHneNDexMVuXypc+yw212uAQC4cjSvAQAAAMDDOez5Ab/s/Gbl2ZwzbVzN/W7DJ2PumPSMs5v7yzexb+VmZwderkaSvl//ybj6LVp+XTDeF/vV0tysrCBXdd+sW/N4w9b+0QXjH7+Kfj3ndGZPV3XfrlszufEtAZHOuuhtc7MzMvq5W7cnKnJW9ql0l0fTd65b82zTtu22FIwTv4j4V1ZaWojL/T79eHqzjoHrC8bxEVtfPH3yxN9d1619uUWXrmvcrdv570/mtO7ec1XBePfWjVMyjx8f4aru+w3rQgNu6/ums27zhonpfxx9+HI1krRr04blbW8fuPjPdT59+OTh5Imu6n7YunFlxztD5jpzb1g3IvXQwSmu6uI/y/y4y5ChrzjrPv3k76mHDr7oqi47I31Dt/seeKFg/O36NXemHjr4yuVqLlm3bk2/1EMH516uRpKy0k9G9HxwtPP72fnp2u6phw4uPn+OYRjHbDbbWVdrAQCKz2J2AAAAAACAa926dbvBbrdXcjUvKyvrt8TExKyCcWBgYFMvL6/Krup8fHwOREdHny4Yd+7cuYnFYqniqs5qtR6MjY3NLBh37dq1sWEYfq7q8vLyDu3evftUwbhbt26N7HZ7VXfrOnbseH25cuWquao7c+ZMUnx8fHrBuFOnTg2tVmt1V3VeXl7JO3bsSCsYd+nSpYGkGq7qJB3+5ptvTrpbl5eXd3T37t2pBeP27dvX8/b2rumqrly5cn9s3779eMG4U6dOdaxWa21XdQ6H49jOnTtTCsa33nprrfz8/LpF2C91+/btR8/LWdPb27ueqzqr1XoiNjb2SMG4S5cuNSQ1KELOtJ07dyYXjNu0aVOtYsWK17tb1759+6re3t6NXNV5eXmd2rFjx6GCcVBQUBWHw9Hk/DmnT59O3rNnT9pFxQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKXv/wGbJiJ8IxMSQgAAAABJRU5ErkJggg==","height":1094},"elements":{"elements":{"QuxAPESuAl939574":{"fontStyle":{"fontFamily":"黑体","size":14},"props":{"zindex":31},"dataAttributes":[],"points":[{"x":385,"y":205.2881851196289},{"x":385,"y":205.2881851196289}],"linkerType":"broken","lineStyle":{},"name":"linker","from":{"x":385,"y":157.7881851196289,"angle":4.71238898038469,"id":"syaefAixCt765305"},"textPos":{"t":16,"pos":"in","x":389,"y":195.78818511962893},"to":{"x":385,"y":252.7881851196289,"angle":1.570796326794897,"id":"LrfDSUkhXm666325"},"id":"QuxAPESuAl939574","text":"① Transition Condition is T1/T2","locked":false,"group":""},"agukVAlhCz403244":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w","x":0,"h":"h","y":0},"text":"The last frame stays for 1.2 s"}],"anchors":[],"title":"","fontStyle":{"size":12},"dataAttributes":[],"props":{"zindex":53,"w":92.72222222222172,"x":865.1388888888896,"h":29.370370370370438,"y":726.8055477142334,"angle":0},"path":[{"lineStyle":{"lineWidth":0},"fillStyle":{"type":"none"},"actions":[{"x":"0","action":"move","y":"0"},{"x":"w","action":"line","y":"0"},{"x":"w","action":"line","y":"h"},{"x":"0","action":"line","y":"h"},{"action":"close"}]}],"lineStyle":{},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"standardText","fillStyle":{},"theme":{},"id":"agukVAlhCz403244","attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":false,"markerOffset":5},"category":"standard","locked":false,"group":""},"SypMMbosuj035158":{"fontStyle":{"fontFamily":"黑体","size":14},"props":{"zindex":32},"dataAttributes":[],"points":[{"x":385,"y":351.64409255981445},{"x":225.01388549804688,"y":351.64409255981445}],"linkerType":"broken","lineStyle":{},"name":"linker","from":{"x":385,"y":303.7881851196289,"angle":4.71238898038469,"id":"LrfDSUkhXm666325"},"textPos":{"t":35,"pos":"in","x":265,"y":351},"to":{"x":225.01388549804688,"y":399.5,"angle":1.570796326794897,"id":"DSkMisjWOm425681"},"id":"SypMMbosuj035158","text":"② Transition Condition is T1","locked":false,"group":""},"LrfDSUkhXm666325":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w-20","x":10,"h":"h","y":0},"text":"Sub-State Machine"}],"anchors":[{"x":"w/2","y":"0"},{"x":"w/2","y":"h"},{"x":"0","y":"h/2"},{"x":"w","y":"h/2"}],"title":"圆角矩形","fontStyle":{"fontFamily":"黑体","size":16,"color":"255,255,255"},"dataAttributes":[{"name":"序号","id":"dTtcktIOLC729055","type":"number","category":"default","value":""},{"name":"名称","id":"sGiYRnWpmR375338","type":"string","category":"default","value":""},{"name":"所有者","id":"ekqNGGdDgI080445","type":"string","category":"default","value":""},{"name":"连接","id":"FSvorrBldx827818","type":"link","category":"default","value":""},{"name":"便笺","id":"TrWluBgnfu492975","type":"string","category":"default","value":""}],"props":{"zindex":28,"w":100,"x":335,"h":51,"y":252.7881851196289,"angle":0},"path":[{"actions":[{"x":"0","action":"move","y":"4"},{"y1":"0","x":"4","action":"quadraticCurve","x1":"0","y":"0"},{"x":"w-4","action":"line","y":"0"},{"y1":"0","x":"w","action":"quadraticCurve","x1":"w","y":"4"},{"x":"w","action":"line","y":"h-4"},{"y1":"h","x":"w-4","action":"quadraticCurve","x1":"w","y":"h"},{"x":"4","action":"line","y":"h"},{"y1":"h","x":"0","action":"quadraticCurve","x1":"0","y":"h-4"},{"action":"close"}]}],"lineStyle":{"lineColor":"125,200,227","lineWidth":0},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"roundRectangle","fillStyle":{"color":"51,102,153","type":"solid"},"theme":{},"id":"LrfDSUkhXm666325","attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":true,"markerOffset":5},"category":"basic","locked":false,"group":""},"MATMaFbgjN204862":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w-20","x":10,"h":"h","y":0},"text":"State A Animation length is 3 s Exit count is (3 - 0.3)/3 = 0.9 times"}],"anchors":[{"x":"w/2","y":"0"},{"x":"w/2","y":"h"},{"x":"0","y":"h/2"},{"x":"w","y":"h/2"}],"title":"圆角矩形","fontStyle":{"fontFamily":"黑体","size":14},"dataAttributes":[{"name":"序号","id":"pRACDmrZfe160856","type":"number","category":"default","value":""},{"name":"名称","id":"vZKjYqFBFO852812","type":"string","category":"default","value":""},{"name":"所有者","id":"diNTnKgWyI303854","type":"string","category":"default","value":""},{"name":"连接","id":"nREDFhSrMO478942","type":"link","category":"default","value":""},{"name":"便笺","id":"tsEPHrBSOp105062","type":"string","category":"default","value":""}],"props":{"zindex":34,"w":258.38571240283824,"x":31.243917226791382,"h":64.7673568725586,"y":636.8489646911621,"angle":0},"path":[{"actions":[{"x":"0","action":"move","y":"4"},{"y1":"0","x":"4","action":"quadraticCurve","x1":"0","y":"0"},{"x":"w-4","action":"line","y":"0"},{"y1":"0","x":"w","action":"quadraticCurve","x1":"w","y":"4"},{"x":"w","action":"line","y":"h-4"},{"y1":"h","x":"w-4","action":"quadraticCurve","x1":"w","y":"h"},{"x":"4","action":"line","y":"h"},{"y1":"h","x":"0","action":"quadraticCurve","x1":"0","y":"h-4"},{"action":"close"}]}],"lineStyle":{},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"roundRectangle","fillStyle":{},"theme":{},"id":"MATMaFbgjN204862","attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":true,"markerOffset":5},"category":"basic","locked":false,"group":""},"GzvfAXRGKz669720":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w-20","h":"h","x":10,"y":0},"text":" "}],"anchors":[{"x":"w/2","y":"0"},{"x":"w/2","y":"h"},{"x":"0","y":"h/2"},{"x":"w","y":"h/2"}],"fontStyle":{"fontFamily":"黑体","size":24,"vAlign":"top"},"title":"矩形","dataAttributes":[{"name":"序号","id":"hptjuCleeV248452","category":"default","type":"number","value":""},{"name":"名称","id":"axXhaRVApX210753","category":"default","type":"string","value":""},{"name":"所有者","id":"YasBcpEkcp107705","category":"default","type":"string","value":""},{"name":"连接","id":"SIvgjbwyhD242661","category":"default","type":"link","value":""},{"name":"便笺","id":"oLstSpiqzZ729966","category":"default","type":"string","value":""}],"props":{"zindex":26,"w":473.0451383590698,"h":255.1562614440918,"x":148.4774308204651,"angle":0,"y":222.79110697696083},"path":[{"actions":[{"x":"0","action":"move","y":"0"},{"x":"w","action":"line","y":"0"},{"x":"w","action":"line","y":"h"},{"x":"0","action":"line","y":"h"},{"action":"close"}]}],"lineStyle":{"lineStyle":"dashed","lineColor":"59,59,59","lineWidth":2},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"rectangle","theme":{},"fillStyle":{"color":"178,235,242","type":"solid"},"attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":true,"markerOffset":5},"id":"GzvfAXRGKz669720","category":"basic","locked":false,"group":""},"vGOfwwnBKx332586":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w-20","x":10,"h":"h","y":0},"text":"State C"}],"anchors":[{"x":"w/2","y":"0"},{"x":"w/2","y":"h"},{"x":"0","y":"h/2"},{"x":"w","y":"h/2"}],"title":"圆角矩形","fontStyle":{"fontFamily":"黑体","size":16,"color":"255,255,255"},"dataAttributes":[{"name":"序号","id":"srOHaCwHbp078562","type":"number","category":"default","value":""},{"name":"名称","id":"NoozbVQUGa425311","type":"string","category":"default","value":""},{"name":"所有者","id":"wSmxXkEpQc737187","type":"string","category":"default","value":""},{"name":"连接","id":"NsYavWwerg813225","type":"link","category":"default","value":""},{"name":"便笺","id":"OlNLtfaCzX103361","type":"string","category":"default","value":""}],"props":{"zindex":30,"w":100,"x":492.0138854980469,"h":51,"y":399.5,"angle":0},"path":[{"actions":[{"x":"0","action":"move","y":"4"},{"y1":"0","x":"4","action":"quadraticCurve","x1":"0","y":"0"},{"x":"w-4","action":"line","y":"0"},{"y1":"0","x":"w","action":"quadraticCurve","x1":"w","y":"4"},{"x":"w","action":"line","y":"h-4"},{"y1":"h","x":"w-4","action":"quadraticCurve","x1":"w","y":"h"},{"x":"4","action":"line","y":"h"},{"y1":"h","x":"0","action":"quadraticCurve","x1":"0","y":"h-4"},{"action":"close"}]}],"lineStyle":{"lineColor":"125,200,227","lineWidth":0},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"roundRectangle","fillStyle":{"color":"51,102,153","type":"solid"},"theme":{},"id":"vGOfwwnBKx332586","attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":true,"markerOffset":5},"category":"basic","locked":false,"group":""},"eluChmQMLQ844377":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w-20","x":10,"h":"h","y":0},"text":"State B"}],"anchors":[{"x":"w/2","y":"0"},{"x":"w/2","y":"h"},{"x":"0","y":"h/2"},{"x":"w","y":"h/2"}],"title":"圆角矩形","fontStyle":{"fontFamily":"黑体","size":14,"bold":true},"dataAttributes":[{"name":"序号","id":"wcvfIDBMKB939913","type":"number","category":"default","value":""},{"name":"名称","id":"gRnbANycCM219711","type":"string","category":"default","value":""},{"name":"所有者","id":"dWIDtjxoTO597808","type":"string","category":"default","value":""},{"name":"连接","id":"BRTDyVwwfR565453","type":"link","category":"default","value":""},{"name":"便笺","id":"KIWkNhCXeZ891688","type":"string","category":"default","value":""}],"props":{"zindex":38,"w":139.77777099609375,"x":481.74479818344116,"h":70,"y":817.2326431274414,"angle":0},"path":[{"actions":[{"x":"0","action":"move","y":"4"},{"y1":"0","x":"4","action":"quadraticCurve","x1":"0","y":"0"},{"x":"w-4","action":"line","y":"0"},{"y1":"0","x":"w","action":"quadraticCurve","x1":"w","y":"4"},{"x":"w","action":"line","y":"h-4"},{"y1":"h","x":"w-4","action":"quadraticCurve","x1":"w","y":"h"},{"x":"4","action":"line","y":"h"},{"y1":"h","x":"0","action":"quadraticCurve","x1":"0","y":"h-4"},{"action":"close"}]}],"lineStyle":{},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"roundRectangle","fillStyle":{},"theme":{},"id":"eluChmQMLQ844377","attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":true,"markerOffset":5},"category":"basic","locked":false,"group":""},"wHvLfYVkjp576282":{"fontStyle":{"fontFamily":"黑体","size":13,"color":"255,0,0"},"props":{"zindex":39},"dataAttributes":[],"points":[{"x":375.625,"y":852.2326431274414},{"x":375.625,"y":852.2326431274414}],"linkerType":"broken","lineStyle":{},"name":"linker","from":{"x":269.50520181655884,"y":852.2326431274414,"angle":3.141592653589793,"id":"eylwQzJALs204157"},"to":{"x":481.74479818344116,"y":852.2326431274414,"angle":0,"id":"eluChmQMLQ844377"},"id":"wHvLfYVkjp576282","text":"Transition Period\nis set to 0.3 times","locked":false,"group":""},"eJraDwpUGc777013":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w-20","h":"h","x":10,"y":0},"text":" "}],"anchors":[{"x":"w/2","y":"0"},{"x":"w/2","y":"h"},{"x":"0","y":"h/2"},{"x":"w","y":"h/2"}],"fontStyle":{"fontFamily":"黑体","size":24,"vAlign":"top"},"title":"矩形","dataAttributes":[{"name":"序号","id":"FGkIfyXTbq664794","category":"default","type":"number","value":""},{"name":"名称","id":"VFdjstByFV351886","category":"default","type":"string","value":""},{"name":"所有者","id":"qpqwyqZuMp850782","category":"default","type":"string","value":""},{"name":"连接","id":"YCJufzsDap172106","category":"default","type":"link","value":""},{"name":"便笺","id":"vBlcmZhZzw375489","category":"default","type":"string","value":""}],"props":{"zindex":56,"w":229.5225691795349,"h":126.1562614440918,"x":741.4774308204651,"angle":0,"y":862.8437385559082},"path":[{"actions":[{"x":"0","action":"move","y":"0"},{"x":"w","action":"line","y":"0"},{"x":"w","action":"line","y":"h"},{"x":"0","action":"line","y":"h"},{"action":"close"}]}],"lineStyle":{"lineStyle":"dashed","lineColor":"59,59,59","lineWidth":2},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"rectangle","theme":{},"fillStyle":{"color":"178,235,242","type":"solid"},"attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":true,"markerOffset":5},"id":"eJraDwpUGc777013","category":"basic","locked":false,"group":""},"yondKCrIIK620777":{"linkerType":"broken","lineStyle":{},"name":"linker","from":{"x":793,"y":721},"to":{"x":868.5,"y":721},"id":"yondKCrIIK620777","text":"","locked":false,"props":{"zindex":52},"dataAttributes":[],"group":"","points":[{"x":830.75,"y":721},{"x":830.75,"y":721}]},"UcVpfHyYlq805818":{"fontStyle":{"fontFamily":"黑体","size":13,"color":"244,67,54"},"props":{"zindex":36},"dataAttributes":[],"points":[{"x":386.09659119503397,"y":671.8489646911621},{"x":386.09659119503397,"y":671.8489646911621}],"linkerType":"broken","lineStyle":{},"name":"linker","from":{"x":290.4483842066268,"y":671.8489646911621,"angle":3.141592653589793,"id":"MATMaFbgjN204862"},"to":{"x":481.74479818344116,"y":671.8489646911621,"angle":0,"id":"NZAPcPzVpQ732100"},"id":"UcVpfHyYlq805818","text":"Transition Period\nis set to 0.3 s","locked":false,"group":""},"TjeXVcYEDA847150":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w-20","h":"h","x":10,"y":0},"text":" "}],"anchors":[{"x":"w/2","y":"0"},{"x":"w/2","y":"h"},{"x":"0","y":"h/2"},{"x":"w","y":"h/2"}],"fontStyle":{"fontFamily":"黑体","size":24,"vAlign":"top"},"title":"矩形","dataAttributes":[{"name":"序号","id":"ZEhNvlenyx576941","category":"default","type":"number","value":""},{"name":"名称","id":"aeGgSdyumS256807","category":"default","type":"string","value":""},{"name":"所有者","id":"yGsvNFuzdg690269","category":"default","type":"string","value":""},{"name":"连接","id":"nAykxhgNfH631668","category":"default","type":"link","value":""},{"name":"便笺","id":"inzdjBpjRE331276","category":"default","type":"string","value":""}],"props":{"zindex":47,"w":229.5225691795349,"h":126.1562614440918,"x":741.4774308204651,"angle":0,"y":644.8437385559082},"path":[{"actions":[{"x":"0","action":"move","y":"0"},{"x":"w","action":"line","y":"0"},{"x":"w","action":"line","y":"h"},{"x":"0","action":"line","y":"h"},{"action":"close"}]}],"lineStyle":{"lineStyle":"dashed","lineColor":"59,59,59","lineWidth":2},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"rectangle","theme":{},"fillStyle":{"color":"178,235,242","type":"solid"},"attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":true,"markerOffset":5},"id":"TjeXVcYEDA847150","category":"basic","locked":false,"group":""},"syaefAixCt765305":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w-20","x":10,"h":"h","y":0},"text":"State A"}],"anchors":[{"x":"w/2","y":"0"},{"x":"w/2","y":"h"},{"x":"0","y":"h/2"},{"x":"w","y":"h/2"}],"title":"圆角矩形","fontStyle":{"fontFamily":"黑体","size":16},"dataAttributes":[{"name":"序号","id":"COcKBsDOgf128282","type":"number","category":"default","value":""},{"name":"名称","id":"ZftffmbwyT593976","type":"string","category":"default","value":""},{"name":"所有者","id":"ZESvkXVynb543594","type":"string","category":"default","value":""},{"name":"连接","id":"wTTUNJrNDJ147164","type":"link","category":"default","value":""},{"name":"便笺","id":"iczxGnUMNn801395","type":"string","category":"default","value":""}],"props":{"zindex":64,"w":100,"x":335,"h":51,"y":106.7881851196289,"angle":0},"path":[{"actions":[{"x":"0","action":"move","y":"4"},{"y1":"0","x":"4","action":"quadraticCurve","x1":"0","y":"0"},{"x":"w-4","action":"line","y":"0"},{"y1":"0","x":"w","action":"quadraticCurve","x1":"w","y":"4"},{"x":"w","action":"line","y":"h-4"},{"y1":"h","x":"w-4","action":"quadraticCurve","x1":"w","y":"h"},{"x":"4","action":"line","y":"h"},{"y1":"h","x":"0","action":"quadraticCurve","x1":"0","y":"h-4"},{"action":"close"}]}],"lineStyle":{},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"roundRectangle","fillStyle":{},"theme":{},"id":"syaefAixCt765305","attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":true,"markerOffset":5},"category":"basic","locked":false,"group":""},"IUAYCHpwvR585542":{"linkerType":"broken","lineStyle":{},"name":"linker","from":{"x":792,"y":945},"to":{"x":867.5,"y":945},"id":"IUAYCHpwvR585542","text":"","locked":false,"props":{"zindex":58},"dataAttributes":[],"group":"","points":[{"x":829.75,"y":945},{"x":829.75,"y":945}]},"eylwQzJALs204157":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w-20","x":10,"h":"h","y":0},"text":"State A Animation length is 3 s Exit count is 0.7 times"}],"anchors":[{"x":"w/2","y":"0"},{"x":"w/2","y":"h"},{"x":"0","y":"h/2"},{"x":"w","y":"h/2"}],"title":"圆角矩形","fontStyle":{"fontFamily":"黑体","size":14},"dataAttributes":[{"name":"序号","id":"pYeCfEHYee569827","type":"number","category":"default","value":""},{"name":"名称","id":"kTsRKlpAAQ519464","type":"string","category":"default","value":""},{"name":"所有者","id":"zyFOmOanwF025376","type":"string","category":"default","value":""},{"name":"连接","id":"OJYzTJqrzL111338","type":"link","category":"default","value":""},{"name":"便笺","id":"jEaMAeEiFr520764","type":"string","category":"default","value":""}],"props":{"zindex":37,"w":239.01388549804688,"x":30.491316318511963,"h":70,"y":817.2326431274414,"angle":0},"path":[{"actions":[{"x":"0","action":"move","y":"4"},{"y1":"0","x":"4","action":"quadraticCurve","x1":"0","y":"0"},{"x":"w-4","action":"line","y":"0"},{"y1":"0","x":"w","action":"quadraticCurve","x1":"w","y":"4"},{"x":"w","action":"line","y":"h-4"},{"y1":"h","x":"w-4","action":"quadraticCurve","x1":"w","y":"h"},{"x":"4","action":"line","y":"h"},{"y1":"h","x":"0","action":"quadraticCurve","x1":"0","y":"h-4"},{"action":"close"}]}],"lineStyle":{},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"roundRectangle","fillStyle":{},"theme":{},"id":"eylwQzJALs204157","attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":true,"markerOffset":5},"category":"basic","locked":false,"group":""},"EuWypzMFNb181054":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w","x":0,"h":"h","y":0},"text":"Loops for 1.2 s."}],"anchors":[],"title":"","fontStyle":{"size":12},"dataAttributes":[],"props":{"zindex":61,"w":89.01851851851802,"x":866.9907407407414,"h":23.000000000000114,"y":944.8055477142336,"angle":0},"path":[{"lineStyle":{"lineWidth":0},"fillStyle":{"type":"none"},"actions":[{"x":"0","action":"move","y":"0"},{"x":"w","action":"line","y":"0"},{"x":"w","action":"line","y":"h"},{"x":"0","action":"line","y":"h"},{"action":"close"}]}],"lineStyle":{},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"standardText","fillStyle":{},"theme":{},"id":"EuWypzMFNb181054","attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":false,"markerOffset":5},"category":"standard","locked":false,"group":""},"DbetzvYcev176085":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w","x":0,"h":"h","y":0},"text":"Plays for 3 s."}],"anchors":[],"title":"","fontStyle":{"size":12},"dataAttributes":[],"props":{"zindex":60,"w":94.68518518518499,"x":766.6666666666667,"h":23,"y":944.8055477142336,"angle":0},"path":[{"lineStyle":{"lineWidth":0},"fillStyle":{"type":"none"},"actions":[{"x":"0","action":"move","y":"0"},{"x":"w","action":"line","y":"0"},{"x":"w","action":"line","y":"h"},{"x":"0","action":"line","y":"h"},{"action":"close"}]}],"lineStyle":{},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"standardText","fillStyle":{},"theme":{},"id":"DbetzvYcev176085","attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":false,"markerOffset":5},"category":"standard","locked":false,"group":""},"XPNpRTzEXZ529813":{"fontStyle":{"fontFamily":"黑体","size":14},"props":{"zindex":33},"dataAttributes":[],"points":[{"x":385,"y":351.64409255981445},{"x":542.0138854980469,"y":351.64409255981445}],"linkerType":"broken","lineStyle":{},"name":"linker","from":{"x":385,"y":303.7881851196289,"angle":4.71238898038469,"id":"LrfDSUkhXm666325"},"textPos":{"t":35,"pos":"in","x":502,"y":351},"to":{"x":542.0138854980469,"y":399.5,"angle":1.570796326794897,"id":"vGOfwwnBKx332586"},"id":"XPNpRTzEXZ529813","text":"③ Transition Condition is T2","locked":false,"group":""},"DSkMisjWOm425681":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w-20","x":10,"h":"h","y":0},"text":"State B"}],"anchors":[{"x":"w/2","y":"0"},{"x":"w/2","y":"h"},{"x":"0","y":"h/2"},{"x":"w","y":"h/2"}],"title":"圆角矩形","fontStyle":{"fontFamily":"黑体","size":16,"color":"255,255,255"},"dataAttributes":[{"name":"序号","id":"GnMJNreToX513402","type":"number","category":"default","value":""},{"name":"名称","id":"NyedfxulLk937048","type":"string","category":"default","value":""},{"name":"所有者","id":"TCeMmDPXDJ177212","type":"string","category":"default","value":""},{"name":"连接","id":"lAMTzTrEpp916241","type":"link","category":"default","value":""},{"name":"便笺","id":"XYMjxIlXzv579719","type":"string","category":"default","value":""}],"props":{"zindex":29,"w":100,"x":175.01388549804688,"h":51,"y":399.5,"angle":0},"path":[{"actions":[{"x":"0","action":"move","y":"4"},{"y1":"0","x":"4","action":"quadraticCurve","x1":"0","y":"0"},{"x":"w-4","action":"line","y":"0"},{"y1":"0","x":"w","action":"quadraticCurve","x1":"w","y":"4"},{"x":"w","action":"line","y":"h-4"},{"y1":"h","x":"w-4","action":"quadraticCurve","x1":"w","y":"h"},{"x":"4","action":"line","y":"h"},{"y1":"h","x":"0","action":"quadraticCurve","x1":"0","y":"h-4"},{"action":"close"}]}],"lineStyle":{"lineColor":"125,200,227","lineWidth":0},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"roundRectangle","fillStyle":{"color":"51,102,153","type":"solid"},"theme":{},"id":"DSkMisjWOm425681","attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":true,"markerOffset":5},"category":"basic","locked":false,"group":""},"jpuvdHUhVy414669":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w-20","x":10,"h":"h","y":0},"text":"State A"}],"anchors":[{"x":"w/2","y":"0"},{"x":"w/2","y":"h"},{"x":"0","y":"h/2"},{"x":"w","y":"h/2"}],"title":"圆角矩形","fontStyle":{"bold":true},"dataAttributes":[{"name":"序号","id":"riQgeTtery132433","type":"number","category":"default","value":""},{"name":"名称","id":"bJfLOfXqib044660","type":"string","category":"default","value":""},{"name":"所有者","id":"muQlwSsYUd247625","type":"string","category":"default","value":""},{"name":"连接","id":"loILkILonf339531","type":"link","category":"default","value":""},{"name":"便笺","id":"urwjujTXHo818864","type":"string","category":"default","value":""}],"props":{"zindex":57,"w":126.47743082046509,"x":793,"h":37.767356872558594,"y":887.2326431274414,"angle":0},"path":[{"actions":[{"x":"0","action":"move","y":"4"},{"y1":"0","x":"4","action":"quadraticCurve","x1":"0","y":"0"},{"x":"w-4","action":"line","y":"0"},{"y1":"0","x":"w","action":"quadraticCurve","x1":"w","y":"4"},{"x":"w","action":"line","y":"h-4"},{"y1":"h","x":"w-4","action":"quadraticCurve","x1":"w","y":"h"},{"x":"4","action":"line","y":"h"},{"y1":"h","x":"0","action":"quadraticCurve","x1":"0","y":"h-4"},{"action":"close"}]}],"lineStyle":{},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"roundRectangle","fillStyle":{},"theme":{},"id":"jpuvdHUhVy414669","attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":true,"markerOffset":5},"category":"basic","locked":false,"group":""},"iMNighSMHQ583553":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w","x":0,"h":"h","y":0},"text":"Plays for 3 s"}],"anchors":[],"title":"","fontStyle":{"size":12},"dataAttributes":[],"props":{"zindex":50,"w":84,"x":777.3518518518517,"h":39,"y":713.4814814814815,"angle":0},"path":[{"lineStyle":{"lineWidth":0},"fillStyle":{"type":"none"},"actions":[{"x":"0","action":"move","y":"0"},{"x":"w","action":"line","y":"0"},{"x":"w","action":"line","y":"h"},{"x":"0","action":"line","y":"h"},{"action":"close"}]}],"lineStyle":{},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"standardText","fillStyle":{},"theme":{},"id":"iMNighSMHQ583553","attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":false,"markerOffset":5},"category":"standard","locked":false,"group":""},"rNUmsWvSyG945511":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w-20","x":10,"h":"h","y":0},"text":"State A"}],"anchors":[{"x":"w/2","y":"0"},{"x":"w/2","y":"h"},{"x":"0","y":"h/2"},{"x":"w","y":"h/2"}],"title":"圆角矩形","fontStyle":{"bold":true},"dataAttributes":[{"name":"序号","id":"WSIubHDThP178530","type":"number","category":"default","value":""},{"name":"名称","id":"PhXHvppcko311621","type":"string","category":"default","value":""},{"name":"所有者","id":"KHOHNXqmnP773144","type":"string","category":"default","value":""},{"name":"连接","id":"bicQHSmgPf506557","type":"link","category":"default","value":""},{"name":"便笺","id":"rjugFMfNLN374927","type":"string","category":"default","value":""}],"props":{"zindex":48,"w":126.47743082046509,"x":793,"h":37.767356872558594,"y":663.8489646911621,"angle":0},"path":[{"actions":[{"x":"0","action":"move","y":"4"},{"y1":"0","x":"4","action":"quadraticCurve","x1":"0","y":"0"},{"x":"w-4","action":"line","y":"0"},{"y1":"0","x":"w","action":"quadraticCurve","x1":"w","y":"4"},{"x":"w","action":"line","y":"h-4"},{"y1":"h","x":"w-4","action":"quadraticCurve","x1":"w","y":"h"},{"x":"4","action":"line","y":"h"},{"y1":"h","x":"0","action":"quadraticCurve","x1":"0","y":"h-4"},{"action":"close"}]}],"lineStyle":{},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"roundRectangle","fillStyle":{},"theme":{},"id":"rNUmsWvSyG945511","attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":true,"markerOffset":5},"category":"basic","locked":false,"group":""},"wfKxHaQHWV679637":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w-20","x":10,"h":"h","y":0},"text":""}],"anchors":[{"x":"0","y":"h*0.5"},{"x":"0","y":"h*0.5"},{"x":"0","y":"h*0.5"},{"x":"0","y":"h*0.5"}],"title":"注释","fontStyle":{},"dataAttributes":[{"name":"序号","id":"coAPIVfOPt538260","type":"number","category":"default","value":""},{"name":"名称","id":"IkKOvcwkHP406545","type":"string","category":"default","value":""},{"name":"所有者","id":"UqxLxMoiiK828196","type":"string","category":"default","value":""},{"name":"连接","id":"PTgmSFCyLY968905","type":"link","category":"default","value":""},{"name":"便笺","id":"guBUjfiJTw426706","type":"string","category":"default","value":""},{"name":"成本","id":"JyDKRbpXuh400233","type":"number","category":"default","value":""},{"name":"时间","id":"tTKkVDVKPD165262","type":"number","category":"default","value":""},{"name":"部门","id":"BQqcsMOTTQ865175","type":"string","category":"default","value":""},{"name":"输入","id":"dBoLsFiMjh541980","type":"string","category":"default","value":""},{"name":"输出","id":"qMRbAwdWtn409176","type":"string","category":"default","value":""},{"name":"风险","id":"uMJLGXKpVU618435","type":"string","category":"default","value":""},{"name":"备注","id":"TOMQrNnuyk448030","type":"string","category":"default","value":""}],"props":{"zindex":49,"w":44,"x":874.5,"h":47,"y":677.5,"angle":4.71238898038469},"path":[{"fillStyle":{"type":"none"},"actions":[{"x":"Math.min(w/6, 20)","action":"move","y":"0"},{"x":"0","action":"line","y":"0"},{"x":"0","action":"line","y":"h"},{"x":"Math.min(w/6, 20)","action":"line","y":"h"}]},{"lineStyle":{"lineWidth":0},"fillStyle":{"type":"none"},"actions":[{"x":"0","action":"move","y":"0"},{"x":"w","action":"line","y":"0"},{"x":"w","action":"line","y":"h"},{"x":"0","action":"line","y":"h"},{"action":"close"}]}],"lineStyle":{},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"annotation","fillStyle":{},"theme":{},"id":"wfKxHaQHWV679637","attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":true,"markerOffset":5},"category":"flow","locked":false,"group":""},"cOovlqhAvB974537":{"fontStyle":{"size":12},"props":{"zindex":54},"dataAttributes":[],"points":[{"x":1048,"y":707.9218692779541},{"x":1048,"y":707.9218692779541}],"linkerType":"broken","lineStyle":{},"name":"linker","from":{"x":971,"y":707.9218692779541,"angle":3.141592653589793,"id":"TjeXVcYEDA847150"},"to":{"x":1125,"y":707.9218692779541},"id":"cOovlqhAvB974537","text":"Start Transitioning","locked":false,"group":""},"vfMAMAEdfU585662":{"fontStyle":{"size":12},"props":{"zindex":62},"dataAttributes":[],"points":[{"x":1049.5,"y":925.9218692779541},{"x":1049.5,"y":925.9218692779541}],"linkerType":"broken","lineStyle":{},"name":"linker","from":{"x":971,"y":925.9218692779541,"angle":3.141592653589793,"id":"eJraDwpUGc777013"},"to":{"x":1128,"y":925.9218692779541},"id":"vfMAMAEdfU585662","text":"Start Transitioning","locked":false,"group":""},"grihhKRoFz459452":{"linkerType":"broken","lineStyle":{},"name":"linker","from":{"x":869,"y":945},"to":{"x":919.4774308204651,"y":945},"id":"grihhKRoFz459452","text":"","locked":false,"props":{"zindex":59},"dataAttributes":[],"group":"","points":[{"x":894.2387154102325,"y":945},{"x":894.2387154102325,"y":945}]},"HMrWDfiIXv077034":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w-20","x":10,"h":"h","y":0},"text":"State B"}],"anchors":[{"x":"w/2","y":"0"},{"x":"w/2","y":"h"},{"x":"0","y":"h/2"},{"x":"w","y":"h/2"}],"title":"圆角矩形","fontStyle":{"bold":true},"dataAttributes":[{"name":"序号","id":"CmutjSuqBd983227","type":"number","category":"default","value":""},{"name":"名称","id":"AhcGkGJIFf625730","type":"string","category":"default","value":""},{"name":"所有者","id":"ufAieBEiym148768","type":"string","category":"default","value":""},{"name":"连接","id":"dYzQnpDfCR698604","type":"link","category":"default","value":""},{"name":"便笺","id":"naBDauKLHr554632","type":"string","category":"default","value":""}],"props":{"zindex":55,"w":126.47743082046509,"x":1130,"h":37.767356872558594,"y":689.0381908416748,"angle":0},"path":[{"actions":[{"x":"0","action":"move","y":"4"},{"y1":"0","x":"4","action":"quadraticCurve","x1":"0","y":"0"},{"x":"w-4","action":"line","y":"0"},{"y1":"0","x":"w","action":"quadraticCurve","x1":"w","y":"4"},{"x":"w","action":"line","y":"h-4"},{"y1":"h","x":"w-4","action":"quadraticCurve","x1":"w","y":"h"},{"x":"4","action":"line","y":"h"},{"y1":"h","x":"0","action":"quadraticCurve","x1":"0","y":"h-4"},{"action":"close"}]}],"lineStyle":{},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"roundRectangle","fillStyle":{},"theme":{},"id":"HMrWDfiIXv077034","attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":true,"markerOffset":5},"category":"basic","locked":false,"group":""},"NZAPcPzVpQ732100":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w-20","x":10,"h":"h","y":0},"text":"State B"}],"anchors":[{"x":"w/2","y":"0"},{"x":"w/2","y":"h"},{"x":"0","y":"h/2"},{"x":"w","y":"h/2"}],"title":"圆角矩形","fontStyle":{"fontFamily":"黑体","size":14,"bold":true},"dataAttributes":[{"name":"序号","id":"UBWmkFvEsl100123","type":"number","category":"default","value":""},{"name":"名称","id":"daeLZQzlZu890923","type":"string","category":"default","value":""},{"name":"所有者","id":"rwaZGiiTiX954509","type":"string","category":"default","value":""},{"name":"连接","id":"FJFnjBxCGz270128","type":"link","category":"default","value":""},{"name":"便笺","id":"YJQsKopFiI143414","type":"string","category":"default","value":""}],"props":{"zindex":35,"w":139.77777099609375,"x":481.74479818344116,"h":70,"y":636.8489646911621,"angle":0},"path":[{"actions":[{"x":"0","action":"move","y":"4"},{"y1":"0","x":"4","action":"quadraticCurve","x1":"0","y":"0"},{"x":"w-4","action":"line","y":"0"},{"y1":"0","x":"w","action":"quadraticCurve","x1":"w","y":"4"},{"x":"w","action":"line","y":"h-4"},{"y1":"h","x":"w-4","action":"quadraticCurve","x1":"w","y":"h"},{"x":"4","action":"line","y":"h"},{"y1":"h","x":"0","action":"quadraticCurve","x1":"0","y":"h-4"},{"action":"close"}]}],"lineStyle":{},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"roundRectangle","fillStyle":{},"theme":{},"id":"NZAPcPzVpQ732100","attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":true,"markerOffset":5},"category":"basic","locked":false,"group":""},"pexwZPjfQk789747":{"parent":"","link":"","shapeStyle":{"alpha":1},"textBlock":[{"position":{"w":"w-20","x":10,"h":"h","y":0},"text":"State B"}],"anchors":[{"x":"w/2","y":"0"},{"x":"w/2","y":"h"},{"x":"0","y":"h/2"},{"x":"w","y":"h/2"}],"title":"圆角矩形","fontStyle":{"bold":true},"dataAttributes":[{"name":"序号","id":"TINjkTVodC371430","type":"number","category":"default","value":""},{"name":"名称","id":"KvaEbizvRU877134","type":"string","category":"default","value":""},{"name":"所有者","id":"OdHfVqpYja209101","type":"string","category":"default","value":""},{"name":"连接","id":"gJJETHlUJD839151","type":"link","category":"default","value":""},{"name":"便笺","id":"bEdRACVLhP446660","type":"string","category":"default","value":""}],"props":{"zindex":63,"w":126.47743082046509,"x":1130,"h":37.767356872558594,"y":907.0381908416748,"angle":0},"path":[{"actions":[{"x":"0","action":"move","y":"4"},{"y1":"0","x":"4","action":"quadraticCurve","x1":"0","y":"0"},{"x":"w-4","action":"line","y":"0"},{"y1":"0","x":"w","action":"quadraticCurve","x1":"w","y":"4"},{"x":"w","action":"line","y":"h-4"},{"y1":"h","x":"w-4","action":"quadraticCurve","x1":"w","y":"h"},{"x":"4","action":"line","y":"h"},{"y1":"h","x":"0","action":"quadraticCurve","x1":"0","y":"h-4"},{"action":"close"}]}],"lineStyle":{},"children":[],"resizeDir":["tl","tr","br","bl"],"name":"roundRectangle","fillStyle":{},"theme":{},"id":"pexwZPjfQk789747","attribute":{"container":false,"rotatable":true,"visible":true,"collapsable":false,"collapsed":false,"linkable":true,"markerOffset":5},"category":"basic","locked":false,"group":""}},"page":{"padding":20,"backgroundColor":"transparent","orientation":"portrait","gridSize":15,"width":1622,"showGrid":false,"lineJumps":false,"height":2346}}},"meta":{"exportTime":"2021-12-13 14:59:06","member":"61b6e52c7d9c086a676ad789","diagramInfo":{"creator":"61b6e52c7d9c086a676ad789","created":"2021-12-13 14:16:39","modified":"2021-12-13 14:58:22","title":"flow-chart","category":"flow"},"id":"61b6e5470e3e7404518a1830","type":"ProcessOn Schema File","version":"1.0"}}
\ No newline at end of file
diff --git a/versions/4.0/en/animation/marionette/index.md b/versions/4.0/en/animation/marionette/index.md
new file mode 100644
index 0000000000..054b9d431c
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/index.md
@@ -0,0 +1,42 @@
+# Marionette Animation System
+
+Cocos Creator 3.5 introduces a new **Marionette** animation system that controls the skeletal animation of objects via state machines, enabling an automated, and reusable animation process.
+
+To distinguish from the animation system from prior to v3.4 which is also accessible in the later versions of Cocos Creator, the new animation system will be referred as the **Marionette** system in this documentation while the animation system from prior to v3.4 will be referred as the **legacy** system. In general, the distinctions between the two include:
+
+- **Legacy**: Powered by the **Animation** component, the legacy system animates objects with animation states containing animation clips (which are keyframe animations created in Cocos Creator) and skeletal animations imported from external sources in the format of `.fbx`, `.gltf` and `.glb`.
+
+- **Marionette**: Powered by the **Animation Controller** component, the Marionette system animate objects with pre-constructed animation graphs, which functions as a controller of multiple animation states that can only contain skeletal animations imported from external sources in the format of `.fbx`, `.gltf` and `.glb`.
+
+## Content
+
+The Marionette system consists of four modules:
+
+- [Animation Graph Assets](animation-graph.md)
+- [Animation Controller Reference](animation-controller.md)
+- [Animation Graph Panel](animation-graph-panel.md)
+- [Animation Graph Layer](animation-graph-layer.md)
+- [Animation State Machine](animation-graph-basics.md)
+- [State Transition](state-transition.md)
+- [Animation Mask](animation-mask.md)
+- [Animation Graph Variants](animation-variant.md)
+- [Procedural Animation](./procedural-animation/index.md)
+
+## Terminology
+
+| Function | Description |
+| :--- | :--- |
+| Animation Graph Assets | Asset that contains the flow chart of animation states, Can be created in the **Assets** panel. For more information, please refer to [Animation Graph Assets](animation-graph.md). |
+| Animation Controller Component | References to the Animation Graph Assets and applies it to a node in the scene. |
+| Animation Graph Panel |Animation clips can be imported and stored as animation states, which can be assembled into a flow chart to indicate the transition from one clip to another. This is done in the Animation Graph panel once an Animation Graph asset is created. For more information, please see [Animation Graph Panel](animation-graph-panel.md). |
+| State | A state is an action that is usually portrayed by an animation clip, such as standby, walk, move, attack, etc. This should be distinguished from an [animation state](../animation-state.md) as used in the legacy system. |
+| State Transition | An animated actor is likely to perform multiple actions, each portrayed by an animation clip and registered as an animation state. A [state transition](state-transition.md) contains the logical check for switching between different states. For instance, to create the death animation of a walking character, a state transition is needed to switch the walk state to the death state. |
+| Animated State Machine | Collectively, all the animation states and the transitions between them can be constructed in a flow chart, which is known as an [Animation State Machine](animation-graph-basics.md). |
+
+A state machine as displayed in the Animation Graph panel is demonstrated in the screenshot below. In it, each blue rectangle represents a state, while the arrows between them the transitions between different states.
+
+
+
+## Example Project
+
+Creator provides the [Ms.Amoy](https://github.com/cocos-creator/example-marionette) demo project, which demonstrates the use of the Marionette animation system, can be downloaded and used as needed.
diff --git a/versions/4.0/en/animation/marionette/preview-bar/end.png b/versions/4.0/en/animation/marionette/preview-bar/end.png
new file mode 100644
index 0000000000..c5c1cb1ff2
Binary files /dev/null and b/versions/4.0/en/animation/marionette/preview-bar/end.png differ
diff --git a/versions/4.0/en/animation/marionette/preview-bar/next.png b/versions/4.0/en/animation/marionette/preview-bar/next.png
new file mode 100644
index 0000000000..2a04bda7d8
Binary files /dev/null and b/versions/4.0/en/animation/marionette/preview-bar/next.png differ
diff --git a/versions/4.0/en/animation/marionette/preview-bar/pause.png b/versions/4.0/en/animation/marionette/preview-bar/pause.png
new file mode 100644
index 0000000000..059f6da6b9
Binary files /dev/null and b/versions/4.0/en/animation/marionette/preview-bar/pause.png differ
diff --git a/versions/4.0/en/animation/marionette/preview-bar/play.png b/versions/4.0/en/animation/marionette/preview-bar/play.png
new file mode 100644
index 0000000000..fdaf9c5103
Binary files /dev/null and b/versions/4.0/en/animation/marionette/preview-bar/play.png differ
diff --git a/versions/4.0/en/animation/marionette/preview-bar/prev.png b/versions/4.0/en/animation/marionette/preview-bar/prev.png
new file mode 100644
index 0000000000..d8de20e414
Binary files /dev/null and b/versions/4.0/en/animation/marionette/preview-bar/prev.png differ
diff --git a/versions/4.0/en/animation/marionette/preview-bar/start.png b/versions/4.0/en/animation/marionette/preview-bar/start.png
new file mode 100644
index 0000000000..be3e88ab98
Binary files /dev/null and b/versions/4.0/en/animation/marionette/preview-bar/start.png differ
diff --git a/versions/4.0/en/animation/marionette/preview-bar/stop.png b/versions/4.0/en/animation/marionette/preview-bar/stop.png
new file mode 100644
index 0000000000..623a23e7a7
Binary files /dev/null and b/versions/4.0/en/animation/marionette/preview-bar/stop.png differ
diff --git a/versions/4.0/en/animation/marionette/preview-bar/time.png b/versions/4.0/en/animation/marionette/preview-bar/time.png
new file mode 100644
index 0000000000..3ee904d103
Binary files /dev/null and b/versions/4.0/en/animation/marionette/preview-bar/time.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/auxiliary-curve/img/auxiliary-curve.png b/versions/4.0/en/animation/marionette/procedural-animation/auxiliary-curve/img/auxiliary-curve.png
new file mode 100644
index 0000000000..747d9aa672
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/auxiliary-curve/img/auxiliary-curve.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/auxiliary-curve/img/inspector-property.png b/versions/4.0/en/animation/marionette/procedural-animation/auxiliary-curve/img/inspector-property.png
new file mode 100644
index 0000000000..d52b7978a0
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/auxiliary-curve/img/inspector-property.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/auxiliary-curve/index.md b/versions/4.0/en/animation/marionette/procedural-animation/auxiliary-curve/index.md
new file mode 100644
index 0000000000..b43ac23e4d
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/procedural-animation/auxiliary-curve/index.md
@@ -0,0 +1,58 @@
+# Auxiliary Curves (experimental)
+
+
+
+> **Note**: auxiliary curve is an experimental feature, please use it with caution.Cocos Creator looks forward to your feedback.
+
+## Motivation
+
+Sometimes, when a character performs a certain action, it is accompanied by changes in some other associated attributes in addition to the visual changes in the bones. For example:
+
+- Selective use of IK to correct foot position: when the character is standing in place; not when the character is walking.
+
+- When starting a jump from a run, it may be necessary to decide whether to use a left-footed jump or a right-footed jump, depending on the orientation of the feet at the start of the jump. This is essentially a change in the orientation of the feet that needs to be reflected in the running movement.
+
+- Along with the movement, there are texture changes, particle effect changes, sound changes, and so on.
+
+Some of these changes can be visualized by [Embedded Player](../../../embedded-player.md). But sometimes the embedded player is not up to the task:
+
+- The changes described by the embedded player can't participate in the blending in the same way that bones can.
+
+ For example, when the action fades out, the embedded player stops abruptly; the embedded players for two actions are independent - even though they may be describing color changes in the same material, their effects cannot be blended with the action.
+
+- Changes in the values described by the embedded player cannot be used directly in the animation diagram.
+ It is not possible to read the results of the embedded player directly into the animation diagram. Even if it were possible, it would require a tedious setup step.
+
+> This is not to say that we no longer encourage the use of embedded players. When you don't have the blending needs described above, the embedded player is still a quick way to attach other effects to your actions.
+
+Therefore, Cocos Creator introduces a new feature to solve the above problem.
+
+## Concept: Auxiliary Curves
+
+An **Auxiliary Curve** is a named **float** curve whose value is used as an attribute of the pose in addition to the bones:
+
+- When sampling a pose from an animation clip, the auxiliary curve is also sampled;
+
+- When a pose is blended, the value of an auxiliary curve of the same name is also blended.
+
+As their name implies, auxiliary curves play a supporting role in skeletal animation. The source and application of auxiliary curves are defined by the user.
+
+> The main difference between auxiliary curves and skeletal animations is that the values of skeletal animations are written to the scene when applied, driving the bones to produce visual model animations, whereas auxiliary curves do not produce direct visual effects, they are only readable, and it is up to the user to determine their usefulness.
+
+## Editing Auxiliary Curves
+
+In the Animation Clip Editor, you can edit the [Auxiliary Curve](../../../animation-auxiliary-curve.md).
+
+In the pose graph, you can set the auxiliary curve nodes with [Set Auxiliary Curve Node](../pose-graph/pose-nodes/modify-pose.md##Set%20auxiliary%20curve) to set or modify the current value of the auxiliary curve for a pose.
+
+## Using Auxiliary curves
+
+Auxiliary curves can be read and used in animation graphs and animation controllers:
+
+- In [Transition Conditions](../../state-transition.md).
+
+- Some of the properties of the pose nodes in the pose map can be specified by the current value of the auxiliary curve. Example:
+
+- [apply-transition-node](../pose-graph/pose-nodes/modify-pose.md#Apply%20Transformations) The intensity value of [Apply Transformations Node](../pose-graph/pose-nodes/modify-pose.md#Apply%20Transformations) can be specified using an auxiliary curve.
+
+- [Animation Controller](../../animation-controller.md) component provides methods to read the current value of the auxiliary curve.
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/enabling.md b/versions/4.0/en/animation/marionette/procedural-animation/enabling.md
new file mode 100644
index 0000000000..8a50c3501b
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/procedural-animation/enabling.md
@@ -0,0 +1,14 @@
+# Enable Procedural Animation
+
+Procedural animation is currently an experimental feature, to enable it, find the **Laboratory** feature in **Preferences** and turn on the following options:
+
+- Animation auxiliary curve
+- Enable Pose-Express Function
+
+
+
+Open the **Project Settings** panel in the **Project** menu , and navigate to the **Feature Cropping** page, and enable the **Procedural Animation** option.
+
+
+
+Then restart the editor or use Ctrl + R to refresh.
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/index.md b/versions/4.0/en/animation/marionette/procedural-animation/index.md
new file mode 100644
index 0000000000..4a68d06390
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/procedural-animation/index.md
@@ -0,0 +1,19 @@
+# Procedural Animation (experimental)
+
+> **Note**: Procedural animation is an experimental feature, please use it with caution. Cocos Creator looks forward to your feedback.
+
+Cocos Creator 3.8 starts to experimentally support procedural animation effects, giving developers the ability to implement some complex skeletal animations.
+
+## Content
+
+- In [Introduction to Procedural Animation](./introduce.md) describes the origins and foundations of procedural animation.
+
+- Procedural animation is currently turned off by default as an experimental feature in Cocos Creator, and is described in [Enabling Procedural Animation](./enabling.md) describes how to turn it on.
+
+- [Pose Graph](./pose-graph/index.md) describes the pose graph, the core building block of procedural animation.
+
+- [Additive Animation](../additive-animation/index.md) is a means of reusing animation assets.
+
+- In addition to gesture maps, [auxiliary curve](. /auxiliary-curve/index.md) is also an effective means of implementing procedural animation.
+
+- [Pose Stash](./pose-stash/index.md) is used to realize the reuse of pose graphs.
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/index/cropping.png b/versions/4.0/en/animation/marionette/procedural-animation/index/cropping.png
new file mode 100644
index 0000000000..8f86942ac7
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/index/cropping.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/index/enable.png b/versions/4.0/en/animation/marionette/procedural-animation/index/enable.png
new file mode 100644
index 0000000000..55cf98a893
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/index/enable.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/introduce.md b/versions/4.0/en/animation/marionette/procedural-animation/introduce.md
new file mode 100644
index 0000000000..7da26974d1
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/procedural-animation/introduce.md
@@ -0,0 +1,43 @@
+# Introduction to Procedural Animation
+
+Before we can understand procedural animation, we need to understand the "Pose" referred to in animation, and I'm sure you've seen the pose in the image below:
+
+
+
+> Image from [https://sketchfab.com](https://sketchfab.com/3d-models/man-in-coat-character-human-riged-model-758a855697be47a1be0d707623e3907e)
+
+This is the *binding pose* in animation. It is also known as a T-Pose because the whole human figure stretches its arms out to make a shape like a T.
+
+> Besides T-Pose, A-Pose is also widely used on human skeleton.
+
+I don't know if you have ever thought about why there is such a "weird" pose as T-Pose.
+
+The original reason may not be known, but nowadays, T-Pose is the most suitable starting animation for animators to animate a character from. So the T-Pose has been preserved as part of the animation workflow.
+
+We can understand T-Pose as a mathematical concept. If the positive X-axis starts at 0, then the starting pose of the animation is T-Pose.
+
+Understanding this allows us to understand the "pose" of the character. We can understand this as the appearance that the character embodies at a given moment in time, and these appearances are determined by the transformations (position, rotation, etc.) provided within its animation information, as well as elements such as skinning. In other words, when we move the "cursor" on the numerical axis to a certain moment, we get the current value on the numerical axis. Similarly, if we move the animation on the timeline, the way the character looks when the timeline stops at a certain moment is called a pose.
+
+In the engine, a character's **pose**, is the information about all the transformations (positions, rotations) of all the character's bones at a given moment. The solved animation map will generate the poses, which are then written to the scene, along with skinned rendering to realize the skeletal animation.
+
+Procedural animation, which is a flowchart-like representation of the pose generation and changes.
+
+
+
+A typical procedural animation is shown above.
+
+The difference between procedural animation and normal animation is that normal animation usually means that the developer cannot intervene in the sampling behavior of the animation, whereas procedural animation provides additional capabilities for the developer to extract certain animation, blending, or pose information in the animation sampling to perform weighted blending and other operations on the current animation.
+
+The procedural animation system provides the ability to manipulate animation clips, blends, and poses, which allows the developer to dynamically adjust the animation sampling process according to the needs of the runtime and generate outputs, which can either be used as the final outputs to the screen or as inputs for other animation samples, thus forming a complex animation system.
+
+Let's take a simple example to illustrate procedural animation.
+
+For example, if a character walks on uneven ground, this is usually not taken into account when creating an animation clip because the producer of the art asset does not know what height the character's feet might be at, so an animation of the character walking on flat ground is created, and at runtime, due to the height of the ground, the height at which the feet should be located needs to be dynamically calculated, and the character's feet "Move" the character's feet to the corresponding height, which is usually done using Inverse Kinematic (IK) algorithms.
+
+With procedural animation, we only need to add IK-related nodes to the pose graph, and pass the information needed to calculate IK to the pose graph system at runtime, and then get the correct result through the IK solver.
+
+You can see that procedural animation makes the creation of complex animations easier to follow and understand by providing a visual view.
+
+## When you need procedural animation
+
+Simply put, you should consider using procedural animation capabilities when you need to modify bones dynamically, especially when you need to adjust bones to the environment. For example, when a humanoid character touches a switch, you need to move the hand bones to the switch position and make sure the arm adjusts accordingly.
\ No newline at end of file
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/introduce/flow.png b/versions/4.0/en/animation/marionette/procedural-animation/introduce/flow.png
new file mode 100644
index 0000000000..40ddcb7af1
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/introduce/flow.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/introduce/t-pose.png b/versions/4.0/en/animation/marionette/procedural-animation/introduce/t-pose.png
new file mode 100644
index 0000000000..66cd7278c8
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/introduce/t-pose.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/index.md b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/index.md
new file mode 100644
index 0000000000..d00eb4c12f
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/index.md
@@ -0,0 +1,79 @@
+# Pose Graph (Experimental)
+
+**Pose graph** are node graph that express the creation and transformation of a pose, and are the central building blocks for realizing procedural animation.
+
+The pose graph is dependent on the other building blocks of the animation graph:
+
+- In the state machine, each [procedural pose](../../state-machine/procedural-pose-state.md) (state) contains a pose graph.
+
+- Each [pose stash](../pose-stash/index.md) contains a pose graph.
+
+This section describes the structure of a pose-stash.
+
+Before getting started with procedural animation, we recommend that you read the documentation related to the [Marionette Animation System](.../../../index.md) and animation graph.
+
+## Values and Types
+
+Broadly speaking, a pose graph describes the flow of values. Every value has a type, and the types of values supported by the pose graph are listed below:
+
+| Type | Description |
+| :--- | :--- |
+| Pose | Role Pose. |
+| Floating Point | Floating point value. |
+| Integer | Integer values. |
+| Integer | Three-dimensional vectors. |
+| Quaternions | Quaternions. |
+
+Where pose objects cannot be generated and specified out of thin air and are only generated by pose nodes (see below).
+
+## Node
+
+
+
+A Pose Graph **Node** describes an operation. There may be zero or more **inputs** or zero or more **outputs** on the node. Some nodes have a variable number of inputs and can be deleted. Currently, all nodes have a fixed number of outputs and cannot be deleted.
+
+> A Pose Node is a node in the pose graph that is used to handle procedural animation, not a node of the engine.
+
+Inputs and outputs are associated with types. When a node has an input of a certain type, it means that the node can accept a value of that type from that input; when a node has an output of a certain type, it means that the node will output a value of that type to that output. When seeking a value, the node operates on the value of its inputs and produces the resulting value to the output.
+
+A node output can be connected to the **same type** input of another node, indicating that when seeking a value, it passes the value of its output to the other node's as input. Sometimes this behavior is called **binding**.
+
+> Note that such a connection is unidirectional - it is not possible to connect inputs to outputs, which makes no sense.
+
+The output of a node can be connected to the inputs of multiple nodes. An exception exists: graph outputs can be connected to only one node.
+
+> If you need to reference a pose in more than one place, consider using [pose-stash](../pose-stash/index.md).
+
+The following types of nodes exist in the pose graph:
+
+| Node Type | Description | Input | Output |
+| :-- | :-- | :-- | :-- |
+| Pose Output Node | Acts as the output pose for the entire pose graph. | A pose input | None |
+| Pose Node | An output pose object. | zero or more | A pose output |
+| Variable Get Node | Get the specified variable and output it | None | One output, of type variable |
+
+You can refer to the [Pose Graph View](./pose-nodes/node-operation.md) to see how to visualize the operation of a pose graph node.
+
+### Pose Graph Output Node
+
+
+
+The **Pose Graph Output Node** is a special kind of node that represents the output pose of the whole pose-graph. It is built into the pose graph and cannot be deleted or created.
+
+A pose graph output node has one and only one pose input. When a node is connected to that pose input, the input pose becomes the output pose of the pose graph.
+
+> If the pose graph output node is not connected, the pose graph output pose is the default pose.
+
+The pose graph output node has no output.
+
+### Pose Node
+
+**Pose nodes** are all nodes that output pose objects. Currently, all pose nodes produce only one pose output. However, a pose node may have zero or more inputs of any type depending on the node itself.
+
+[Pose Nodes](./pose-nodes/index.md) lists all types of pose nodes.
+
+### Variable Get Nodes
+
+The **Variable Get Node** gets the specified animation graph variable and outputs its value. This type of node has no inputs and only one output, which is the type of the variable.
+
+A variable get node cannot get trigger variables.
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/blend-poses.md b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/blend-poses.md
new file mode 100644
index 0000000000..b587040839
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/blend-poses.md
@@ -0,0 +1,72 @@
+# Blend Pose
+
+There are several type of blend nodes in pose graph.
+
+> All blend nodes are calculated in the local space.
+
+Blend poses can be created in the pose graph by right-clicking on the **Pose Nodes** -> **Blend**.
+
+
+
+## Blend Two Pose
+
+
+
+The **Blend Two Pose** will blend the two specified poses by ratio.
+
+| Input | Type | Description|
+| :-- | :-- | :-- |
+| **Pose 1** | Pose | First pose in the blend |
+| **Pose 2** | Pose | Second pose in the blend |
+| **Ratio** | Float | Blend ratio. For example, 0.2 means that the final pose will contain 80% of pose 1 and 20% of pose 2. |
+
+## Blend In Proportion
+
+
+
+The **Blend In Proportion** node blends the nodes by proportion of each pose.
+
+| Input | Type | Description|
+| :-- | :-- | :-- |
+| **Pose N** | Pose | Pose in the blend. |
+| **Pose N Proportion** | Float | The ratio of the poses to each other. For example, 0.2 means that the final pose will contain 20% of the pose N.|
+
+More poses can be added by clicking the "+" button on the right and selecting the **poses** menu.
+
+
+
+After adding a pose, enter the proportion in the input box to set the percentage of the pose in the final pose.
+
+
+
+> All proportional weighted results should be 1, otherwise there may be undefined behavior.
+
+## Filtering Blend
+
+
+
+The **Filtering Blend** node blends Pose 1 to Pose 2 by the specified ratio and mask.
+
+| Input | Type | Description|
+| :-- | :-- | :-- |
+| **Pose 1** | Pose | First pose engaged in the blend |
+| **Pose 2** | Pose | Second pose engaged in the blend|
+| **Ratio** | Float | Blend Ratio. For example. 0.2 means the final pose contains 80% from Pose1 and 20% from Pos2. |
+
+
+
+| Inspector | Description |
+| :-- | :-- |
+| **Mask** | The animation mask to use when blending.Only the parts of pose 2 that are bounded by the mask will be blended into pose 1. |
+
+## Additively Blend
+
+
+
+The **Additively Blend** node "adds" the additive blend to the base pose.
+
+| Input | Type | Description|
+| :-- | :-- | :-- |
+| **Base Pose** | Pose | The base pose. |
+| **Additive Pose** | Pose | The additive pose |
+| **Ratio** | Floating Point | Blend Ratio. For example, 0.2 means that only 20% of the stacked poses will be blended into the base pose. |
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/add-blend-in-proportion.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/add-blend-in-proportion.png
new file mode 100644
index 0000000000..0754b0cb76
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/add-blend-in-proportion.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/additively-blend.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/additively-blend.png
new file mode 100644
index 0000000000..a638e3616b
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/additively-blend.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/apply-transform-inspector.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/apply-transform-inspector.png
new file mode 100644
index 0000000000..92b66da80d
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/apply-transform-inspector.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/apply-transform.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/apply-transform.png
new file mode 100644
index 0000000000..9ebada5067
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/apply-transform.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/blend-in-proportion-ratio.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/blend-in-proportion-ratio.png
new file mode 100644
index 0000000000..5a65f42a8f
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/blend-in-proportion-ratio.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/blend-in-proportion.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/blend-in-proportion.png
new file mode 100644
index 0000000000..e5022cffc5
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/blend-in-proportion.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/blend-two-pose.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/blend-two-pose.png
new file mode 100644
index 0000000000..788e74a153
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/blend-two-pose.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/blend.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/blend.png
new file mode 100644
index 0000000000..9457f25506
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/blend.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/copy-transform-inspector.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/copy-transform-inspector.png
new file mode 100644
index 0000000000..7e41773c1c
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/copy-transform-inspector.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/copy-transform.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/copy-transform.png
new file mode 100644
index 0000000000..cfaabcdfb9
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/copy-transform.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/create-blend.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/create-blend.png
new file mode 100644
index 0000000000..cd5b40fee8
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/create-blend.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/create-link.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/create-link.png
new file mode 100644
index 0000000000..75d4fcc2a0
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/create-link.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/create-pose-node.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/create-pose-node.png
new file mode 100644
index 0000000000..1533975040
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/create-pose-node.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/curve.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/curve.png
new file mode 100644
index 0000000000..dd45865934
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/curve.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/filtering-blend-inspector.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/filtering-blend-inspector.png
new file mode 100644
index 0000000000..70d38b3399
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/filtering-blend-inspector.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/filtering-blend.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/filtering-blend.png
new file mode 100644
index 0000000000..4e7318cfac
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/filtering-blend.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/get-value.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/get-value.png
new file mode 100644
index 0000000000..478fea4f7c
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/get-value.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/input.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/input.png
new file mode 100644
index 0000000000..e53ae6fe1c
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/input.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/link-success.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/link-success.png
new file mode 100644
index 0000000000..4eb6e79b56
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/link-success.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/link.gif b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/link.gif
new file mode 100644
index 0000000000..b756c72d8d
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/link.gif differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/menu.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/menu.png
new file mode 100644
index 0000000000..79d45267bd
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/menu.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/name.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/name.png
new file mode 100644
index 0000000000..2b433ca041
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/name.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/node-options.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/node-options.png
new file mode 100644
index 0000000000..f3ff5fd8cc
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/node-options.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/nodes-type.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/nodes-type.png
new file mode 100644
index 0000000000..9a46862283
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/nodes-type.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/output.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/output.png
new file mode 100644
index 0000000000..65922277e9
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/output.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/remove-link.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/remove-link.png
new file mode 100644
index 0000000000..d1aa889788
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/remove-link.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/shrink.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/shrink.png
new file mode 100644
index 0000000000..400c2f662c
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/shrink.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/two-bone-ik-inspector.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/two-bone-ik-inspector.png
new file mode 100644
index 0000000000..121f5a8928
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/two-bone-ik-inspector.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/two-bone-ik-solver.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/two-bone-ik-solver.png
new file mode 100644
index 0000000000..17b7518ca1
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/img/two-bone-ik-solver.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/index.md b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/index.md
new file mode 100644
index 0000000000..90c93d0e70
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/index.md
@@ -0,0 +1,27 @@
+# Pose Nodes
+
+An animation graph allows you to create a pose node and edit the pose node, the result of which will be stored inside the animation graph as part of the animation graph assets.
+
+You can refer to the Animation Graph usage to create, delete, and modify a pose graph.
+
+In this chapter, we will introduce you to the concepts of pose graphs and their usage.
+
+A pose node outputs a pose. The engine provides pose nodes with the following roles:
+
+- [play-or-sample-animation](./play-or-sample-motion.md)
+
+- [Blend poses](./blend-poses.md)
+
+- [Choose Pose](./choose-pose.md)
+
+- [modify-pose](./modify-pose.md)
+
+- [State Machine](./state-machine.md)
+
+- [Use stashed pose](./use-stashed-pose.md)
+
+For the visualization of the pose graph node editor, see [pose graph node view](./node-operation.md).
+
+## Contents
+
+- [Pose graph node operation](./node-operation.md)
\ No newline at end of file
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/modify-pose.md b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/modify-pose.md
new file mode 100644
index 0000000000..857a17c195
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/modify-pose.md
@@ -0,0 +1,116 @@
+# Modify Poses
+
+The pose graph provides several nodes for modifying poses. Each of these nodes accepts an input pose and outputs the modified pose.
+
+| Input | Type | Description |
+| :-- | :-- | :-- |
+| `Pose` | Pose | The pose to be modified. |
+
+For the operation of a pose node, see [pose graph node view](./node-operation.md).
+
+## Apply Transform
+
+
+
+**Apply transform node** Applies a transform (translate and rotation) to the specified node of the input pose.
+
+| Input | Type | Description |
+| :-- | :-- | :-- |
+| `Position` | 3d-vector| The amount of modification to the position. |
+| `Rotation` | Quaternion | The amount of modification to the rotation. |
+| `Intensity` | Float |The intensity of application of the modification, in the range [0, 1]. 0 means that the modification is not applied at all, 1 means that the modification is applied completely. |
+
+
+
+| Properties | Description |
+| :---| :---|
+| `Node` | The name of the node to be modified. |
+| `Position Operation` | Specifies how to modify the position. See [Transform Operations](./modify-pose.md#Transform%Operation) |
+| `Rotation Operation` | Specifies how to modify the rotation. See [Transform Operation](./modify-pose.md#Transform%Operation) |
+| `Transform Space` | Specifies the space in which the modification occurs; that is, the space in which the specified `position` input and `rotation` input reside. |
+
+### Transform Operation
+
+The transform operation options specify how the applied transform node modifies the position or rotation. The options are listed below:
+
+| Properties | Description |
+| :-- | :-- |
+| **LEAVE_UNCHANGED** | No modification. |
+| **REPLACE** | When used as an application option for position, the `position` input is used directly as the new position of the node; when used as an application option for rotation, the `rotation` input is used directly as the new rotation of the node. |
+| **ADD** | Adds the `position` input to the node's current position when used as an application option for position, or the `rotation` input to the node's current rotation when used as an application option for rotation. |
+
+## Copy Transform
+
+
+
+The **Copy Transform** node copies the transform of a node in the input pose to another node.
+
+
+
+| Properties | Description |
+| :---| :---|
+|`Source node` | The name of the node to be copied. |
+|`Target Node` | The name of the node to copy to. |
+|`Space` |Specifies the space where the copy occurs. When `COMPONENT` indicates that the copy occurs in component space; when `LOCAL` indicates that the copy occurs in local space. |
+
+## Set Auxiliary Curves
+
+
+
+The **Set Auxiliary Curve** node modifies the current value of the specified auxiliary curve in the input pose.
+
+| Input | Type | Description |
+| :-- | :-- | :-- |
+| `Value` | Float | The amount of modification to the auxiliary curve. |
+
+
+
+| Properties | Description |
+| :---| :---|
+| `Curve Name` | The name of the auxiliary curve to be modified. |
+| `Flag` | Specifies how to modify the auxiliary curve. When `LEAVE_UNCHANGED` it is not modified; when `REPLACE` it means that the `Curve Value` input is used as the current value of the auxiliary curve; when `ADD` it means that the `Curve Value` input is added to the current value of the auxiliary curve. |
+
+## Double Skeleton IK
+
+
+
+IK solving is often used to move or rotate a bone to a target position and drive the parent bone so that it remains the same distance from the parent (or within an acceptable range). For example, when moving a foot, the knee bone and thigh bone should bend accordingly.
+
+**Two-bone IK solver node** solves IK problems consisting of two sections of (three bones) bones for the input pose. These three bones form a direct parent-child relationship, i.e. "child level - parent level - parent of parent level". The "child" is called the **end-effector** or **end-bone**, the "parent of parent" is called the **root-bone** (in this IK problem), and the "parent of parent " is called the **intermediate bone**.
+
+> Therefore, the "two" in "two-bone IK" should be interpreted as "two segments of bones" rather than "two bones".
+
+When evaluating, the solver will transform the end and middle bones, and rotate the root bone so that the end bone reaches the specified position; and keep the distance between the parent and child levels unchanged, and the position of the root bone unchanged in the process.
+
+
+
+For fixed end-bone and root-bone positions, an infinite number of solutions exist for the intermediate bones when solving. As shown in Fig:
+
+
+
+The solver will try to find the "best" solution, but there may still be more than one such solution, and it may not be the desired one.
+
+Therefore, in order to explicitly specify the orientation of the intermediate bones, the solver also allows to specify a **pole-target** to determine the bending direction of the skeletal chain.
+
+
+
+| Input | Type | Description |
+| :---| :---|---|
+| `End-effector-target` |3d-vector|Target position of the end-effector. |
+| `Polar target` |3d-vector | The position of the polar target. |
+
+| Attributes | Description |
+| :---| :---|
+| `End-effector node` | The name of the end-effector node. |
+| `End-Executor-Target` | The target setting of the end-effector. |
+| `Polar target` |The polar target setting. |
+
+### Target settings
+
+The target setting is used to describe the end-effector target or the poleward target. The options are as follows:
+
+| Attributes | Description |
+| :-- | :-- |
+|`Type` |Target type. When `VALUE`, it means that the target position is represented as the specified (3D vector) value; when `BONE`, it means that the position of another bone is used as the target position; and when `NONE`, it means that the current position is used as the target position, i.e., the target is not solved for. |
+|`Target Bone`| The name of the target bone when the target type is `BONE`. |
+|`Target Position Space` | The space of the target position when the target type is `VALUE`. |
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/node-operation.md b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/node-operation.md
new file mode 100644
index 0000000000..0a91b97149
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/node-operation.md
@@ -0,0 +1,95 @@
+# Pose Graph View
+
+## Create Node
+
+Before creating a node, you need to create a pose graph in the animation graph first, and then double-click the mouse to enter the visual editing interface of the pose graph.
+
+Right click on the pose graph and click on Post Nodes in the popup menu to create a node.
+
+
+
+| Menu | Description |
+| :-- | :-- |
+| **Play Animation** | See [play-or-sample-motion](./play-or-sample-motion.md)
+| **State Machine** | See [state machine](./state-machine.md)
+| **Sample Animation** | See [play-or-sample-motion](./play-or-sample-motion.md)
+| **Blend** | See [blend poses](./blend-poses.md)
+| **Select** | Developers can select poses and animations with different types of data, including booleans and indices |
+| **Apply Transform** | See [Apply Transformations](./modify-pose.md#%E5%BA%94%E7%94%A8%E5%8F%98%E6%8D%A2)| | **Copy Transform** | **Copy Transformations
+| **Copy Transform** | See [Copy Transformations](./modify-pose.md#%E6%8B%B7%E8%B4%9D%E5%8F%98%E6%8D%A2)| | **Copy Transform** | See [Copy Transform](.
+| **Set Auxiliary Curve** | See [Auxiliary Curve](../../auxiliary-curve/index.md) |
+| **Reverse Dynamics** | Calculate the reverse computation of the skeleton via the reverse dynamics checker, currently supported by [Two-Bone IK](./modify-pose.md#%E5%8F%8C%E9%AA%A8%E9%AA%BC-ik) |
+
+Once created, it will be displayed in the attitude graph as a rectangular box of a different color.
+
+
+
+We use **blend** node as an example to illustrate the structure of nodes, other types of nodes can be referred to.
+
+
+
+You can see that the node has several components:
+
+- Type: the type of the node displayed at the top.
+- Expand/collapse: click on the arrow symbols at the top left of some nodes to expand/collapse them to keep a cleaner view.
+
+ 
+
+- Inputs: usually on the left side of the node, indicates the inputs to the node, indicated by different colored hollow (unconnected)/solid (connected) diamonds, the outputs of other nodes can be used as inputs, and some of the nodes can also be input directly within the pose graph within the right **Inspector** panel. The inputs are different for different node types, please refer to the documentation for different types of nodes for details.
+
+ 
+
+ Some node types, such as variable nodes, have no inputs but only outputs.
+
+- Outputs: The output part is usually on the right side of the node, represented by a hollow (unconnected)/solid (connected) diamond, which can be formed by pressing and dragging the left mouse button to form a connection.
+
+ 
+
+ Generally speaking, a node's output can only be used on another node's input, and only once, which means that if the output has already been used, connecting to the other node through the input again will disconnect the previous connection.
+
+## Node Operations
+
+Clicking the right mouse button on any node brings up the node operations menu.
+
+
+
+- Copy this node: copy operation will copy the currently selected node for other use.
+- Clone this node: clones the selected node in the current pose map.
+- Delete this node: removes the selected node from the pose map.
+
+## Menus
+
+Clicking the right mouse button inside the empty space of the pose map will bring up the menu of the pose map.
+
+
+
+- Delete Pose Node: copy the node that was operated by copying this node above to this node
+- Pose node: create a new pose node, please refer to the **Create Node** section above
+- Get Variable: this menu can get the variables created in the animation graph, all the non-trigger variables configured in the animation graph can be obtained here.
+
+ 
+
+- Stash This Graph: the current pose graph will be dumped as a new pose graph
+- Return to center view: The view will automatically return to the center view with the appropriate viewpoint.
+
+## Create Connection
+
+
+
+The connection means taking the output of one node and passing it to another node as an input parameter.
+
+For different nodes, it is possible to connect the output of a node to the input of another node by dragging the node's output to the input of the other node, provided of course that the other node accepts the output type.
+
+By dragging and dropping the output of a node to the input of another node.
+
+
+
+Successful connection is indicated by a solid diamond shape on the node:
+
+
+
+## Delete Connections
+
+A connection can be deleted by clicking the right mouse button on the connected line. A blue highlighting flood light will be displayed around the selected line.
+
+
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/play-or-sample-motion.md b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/play-or-sample-motion.md
new file mode 100644
index 0000000000..f60e3d0b8f
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/play-or-sample-motion.md
@@ -0,0 +1,31 @@
+# Play or Sample Animation
+
+The pose graph provides two types of nodes for reading poses from animations: play animation nodes and sample animation nodes.
+
+In the following, "action" refers to animation clips or animation blends.
+
+## Play Animation
+
+The **Play animation node** node plays the specified action, updates it every frame, and gets the pose of the current frame of the animation as output.
+
+| Input | Description |
+| :-- | :-- |
+| `Start Time` | When to start playing the action from whenever this node is reentered. Unit is in seconds. |
+| `Speed Multiplier` | The playback rate of the action. |
+
+| Properties | Description |
+| :-- | :-- |
+| `Action` | The action to sample. |
+
+## Sampled Animation
+
+The **Sampled Animation Node** samples the pose of the specified action at a given moment as output.
+
+| Input | Description |
+|:-- |:-- |
+| `Time` | The time to sample. |
+
+| Properties | Description |
+| :-- |:-- |
+| `Action` | The action to sample. |
+| `Use Normalized Time` | Whether the node input `time` specifies a normalized time. The normalized time is the progress of the action in the range [0, 1]. For example, 1 means the last frame of the action, and 0.5 means 50% of the action progress. |
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/pole-target-demonstration.gif b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/pole-target-demonstration.gif
new file mode 100644
index 0000000000..d091cacf95
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/pole-target-demonstration.gif differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/two-bone-ik-demonstration.gif b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/two-bone-ik-demonstration.gif
new file mode 100644
index 0000000000..7ad832ade5
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-graph/pose-nodes/two-bone-ik-demonstration.gif differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/delete.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/delete.png
new file mode 100644
index 0000000000..a73a3a6dfd
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/delete.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/edit.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/edit.png
new file mode 100644
index 0000000000..a2dbd18aec
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/edit.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/index.md b/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/index.md
new file mode 100644
index 0000000000..476806099e
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/index.md
@@ -0,0 +1,63 @@
+# Pose Stash
+
+It is not possible to connect the output of a pose node to multiple nodes in a pose graph, when you try to connect a pose node to a new node, the old connection will be broken. If you need to reuse a pose in multiple places, you need to use pose stash.
+
+## Concepts
+
+**Pose stash** is a mechanism for storing the results of one pose graph and using the resulting poses in other pose graphs. A **pose stash** (hereafter referred to as a pose stash or stash) is a means of implementing such a mechanism, which associates a pose graph.
+
+> A visual, but incomplete, understanding of a pose stash is to think of a pose stash as a cache variable that holds pose objects.
+
+Pose stash is attributed to animation graph hierarchies. Multiple stashes can be created at each layer, and once created, the stash can be referenced in any pose graph in that layer via the **Use Stash Pose** node.
+
+> We can think of this as taking some already edited pose node and saving it as some sort of blueprint or resource for use elsewhere. It's just that this blueprint has a limited scope and can only be in a specific layer in this animation graph.
+> This also means that we can treat stash as some special pose node and use it just like a normal pose node.
+
+Pose stash is allowed to be referenced multiple times, and the associated pose graph will only be updated and evaluated once per frame.
+
+## Editing a pose stash
+
+The **Property Inspector** of a selected animation graph layer allows you to view, create, and edit all pose stash for that layer.
+
+Click on a layer in the animation graph and find the **Layer Stashes** property in the **Property Inspector**.
+
+
+
+Click the  button to start editing the pose graph associated with the selected stash. Click  to delete the temporary storage. Deletion is not restorable, so please be careful.
+
+The information text in this property below will indicate how many times the stash has been referenced, if it is greater than 0 then the stash has been referenced.
+
+Click the **New Stash** button to create a new stash.
+
+## Usage of Stashed Pose
+
+The **Use Stashed Pose** menu lists all the stash that can be used in the pose graph. Clicking on this will create the **Use Stashed Pose** node.
+
+
+
+
+
+The **Use Stashed Node** node outputs the pose generated by the specified stash; there are no additional inputs for this node.
+
+Double-click the **Use Stash** node to access the edit view for the pose stashed associated with that node.
+
+## Stash This Graph
+
+Often it is not always possible to think of which poses to stash at the beginning of the design; more often than not, a graph has been developed and it is realized that it needs to be reused in more than one place.
+To do this, right-click in any pose graph to access the context menu and click the Execute menu item **Stash This Graph**:
+
+
+
+When executed, the original contents of the current graph will be moved to a newly created pose stash, and a **Use Stashed Pose** node will be created in the current graph to reference the newly created pose stash.
+
+Clicking **Stash This Graph** creates a new Stashed Pose.
+
+Here is an example of a pose that plays an animation clip.
+
+
+
+Click the **Stash This Graph** menu, and you can see the change in the following image:
+
+
+
+You can observe that the previous pose node, the **Play Animation Clip** node, no longer exists, and has been replaced by a node named **Use Stash StashX** (X is the number, the name of the stash can be changed in the **Inspector** panel). This node is the new **Stashed Pose**.
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/layer-stashes.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/layer-stashes.png
new file mode 100644
index 0000000000..77d0fa5281
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/layer-stashes.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/menu-item-stash-this-pose.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/menu-item-stash-this-pose.png
new file mode 100644
index 0000000000..6e66e347ad
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/menu-item-stash-this-pose.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/original-graph.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/original-graph.png
new file mode 100644
index 0000000000..5bddbfe35c
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/original-graph.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/stash2.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/stash2.png
new file mode 100644
index 0000000000..951c84e220
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/stash2.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/use-stash-node-list.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/use-stash-node-list.png
new file mode 100644
index 0000000000..933fa117e7
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/use-stash-node-list.png differ
diff --git a/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/use-stash-node.png b/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/use-stash-node.png
new file mode 100644
index 0000000000..0c6277f206
Binary files /dev/null and b/versions/4.0/en/animation/marionette/procedural-animation/pose-stash/use-stash-node.png differ
diff --git a/versions/4.0/en/animation/marionette/state-machine/procedural-pose-state.md b/versions/4.0/en/animation/marionette/state-machine/procedural-pose-state.md
new file mode 100644
index 0000000000..fabcc116d0
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/state-machine/procedural-pose-state.md
@@ -0,0 +1,5 @@
+# Procedural Poses (states)
+
+
+
+A **Procedural Poses** (state) is a state in a state machine. The state holds a pose graph, and when the state machine runs into this state, the pose it produces is the output gesture of the pose graph.
\ No newline at end of file
diff --git a/versions/4.0/en/animation/marionette/state-machine/state-machine.png b/versions/4.0/en/animation/marionette/state-machine/state-machine.png
new file mode 100644
index 0000000000..49b159e94e
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-machine/state-machine.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition.md b/versions/4.0/en/animation/marionette/state-transition.md
new file mode 100644
index 0000000000..34f6c58ad8
--- /dev/null
+++ b/versions/4.0/en/animation/marionette/state-transition.md
@@ -0,0 +1,169 @@
+# State Transitions
+
+**Transition** represents a transition between two states, which can be classified depending on the source where the transition occurs.
+
+- **Ordinary Transition**: the source where the transition occurs is a pseudo-state **entry** or **sub-state machine**.
+
+ 
+
+- **Animation Transition**: the transition occurs with a source of a **State** or pseudo-state **Any**. Compared to ordinary transitions, animation transitions can also control the transition period to make the animation switch smoothly.
+
+ 
+
+## Creating Transition
+
+Right-click the state that is the source of the transition in the grid layout area, then select **Add Transition**, when the mouse leaves the current state, an arrow will be created, then select the state that is the target of the transition to create a transition between the two:
+
+
+
+Multiple same/reverse direction transitions are allowed between two states, and the number of same/reverse direction transitions is marked on the arrow, and the configuration items are displayed in the **Inspector** tab.
+When there are multiple transitions on the state that satisfy both, the transition at the top of the transition list is used first. However, Creator does not recommend relying on this prioritization, and it is best to filter the transitions using the **filter conditions** described below whenever possible.
+
+
+
+States also allow transitions to themselves:
+
+
+
+## Setting Transitions
+
+With the transition selected in the grid layout area, the **Inspector** tab on the left side allows you to set the trigger conditions associated with the transition, including **Duration**, **Enable Exit Times**, **Exit Times**, **Conditions**.
+
+> **Note**: **ordinary transition** can only specify **Conditions**, which is more like a selector.
+
+
+
+- **Duration**: set the period to complete the current transition, so the animation will switch smoothly. The unit is **seconds** or **times**, default is 0.3 seconds, you can click the unit after the input box to switch.
+
+ 
+
+ - When set to **seconds** (default): indicates that the state transition is completed within the set number of seconds
+
+ - When set to **times**: means the period of the state transition is based on the number of times the transition source state is played. For example, if the animation length of the transition source state is 3 s, when **Duration** is set to 0.9 times, it means the transition period is 0.9 ✖️ 3s = 2.7s.
+
+- **Enable Exit Times**: indicates whether the transition source state ends playing as one of the transition conditions. If checked, the transition needs to occur to meet the **Exit Times** condition set below. Play count is used as a special condition, when play count is enabled, the transition will happen only when both the play count condition and the transition condition are satisfied.
+
+- **Exit Times**: sets the total amount of time the animation plays before the transition source state begins (Total = Exit Times ✖️ Animation Length), defaults to 1 time, and takes effect only when **Enable Exit Times** is checked. It is important to note that animations that do not loop will stop when the first play is completed and wait for the remaining number of plays to complete before starting the transition. To loop the animation automatically according to the number of times, please set the wrap mode in the skeleton animation asset beforehand. For example:
+
+ - If the animation of the transition source is an **non-loop animation**, the playing time is 3 s, **Exit Times** is set to 1.4, then the animation of the transition source will continue to stay in the last frame for 1.2s (3s × 0.4) after playing for 3s, before starting the transition.
+
+ 
+
+ - If the animation of the transition source is an **loop animation**, playing time is 3 s, **Exit Times** is set to 1.4, then the animation of the transition source will continue to loop the animation to 1.2s (3s × 0.4) after playing 3s, before starting the transition.
+
+ 
+
+- **Condition**: there are certain conditions that need to be met when setting up transitions that occur between states, as described below:
+
+Without using other transition conditions, for the animation of the source state to gradually switch to other states when it is almost finished playing once, and the animation of the source state is just finished playing when the switch is done, then we can set **Duration** and **Exit Times** to achieve this, it is recommended to set the unit of **Duration** to **times**, and then make the sum of **Duration** and **Exit Times** sum to **1**.
+
+For example, if the animation length of the transition source state is 3 seconds, set **Duration** to 0.3 times, then **Exit Times** is 0.7. If **Duration** is set to 0.3 seconds, it is more troublesome, **Exit Times** need to convert seconds to times: (3 - 0.3)/ 3 = 0.9 times.
+
+
+
+### Transition Conditions
+
+Some transitions between states need to satisfy certain conditions to be triggered, such conditions are called **transition conditions**, or **conditions** for short. If no condition is set for the transition, it will be triggered directly. Conditions can be created in the [Variables](animation-graph-panel.md) tab of the Animation Graph panel.
+
+Once the transition is selected in the grid layout area, the condition can be added by selecting the gear icon button in the **Inspector** tab on the left. The added conditions are displayed below the **Inspector** tab on the left.
+
+
+
+The currently supported transition conditions include the following three:
+
+- **Boolean condition**: determines if a variable of Boolean type is true/false. Click the gear icon button on the right to remove the current condition.
+
+ 
+
+- **Numeric condition**: determines the logical relationship between a variable of numeric type and another fixed value, including **equal to**, **not equal to**, **greater than**, **less than**, **greater than or equal to**, **less than or equal to**. The condition is satisfied when the equation (inequality) holds. The type of the variable matches the type of the value. If the variable is set to Float type, the type of the value is also Float type.
+
+ 
+
+- **Trigger condition**: condition is satisfied when the trigger variable is triggered.
+
+ 
+
+**Transition supports specifying multiple transition conditions at the same time, and the transition will occur when and only when all conditions are satisfied.**
+
+### Unconditional Transitions
+
+For **ordinary transitions**, it is allowed to not specify any transition conditions, for example, many times **Entry** needs to transition to other states unconditionally.
+
+However, for **animation transitions**, transitions where neither **conditions** nor **Exit Times** conditions are specified are meaningless and the Creator will simply ignore the transition.
+
+## An edge case
+
+There are cases that cause a state machine to stay on **Entry** or **Exit**, e.g.
+
+- Transitioned to the **Entry** of a sub-state machine, but there is no transition in the sub-state machine that would satisfy the condition.
+
+- Transitioned to the **Exit** of a sub-state machine, but there is no transition in the parent state machine that would satisfy the condition for that sub-state machine.
+
+This situation is called **state machine hover**.
+
+When a state machine hover occurs, it directly interrupts the update until a subsequent transition to the state can be made, at which point it is represented as the animation being paused.
+
+> **Note**: it is not recommended to rely on this behavior, and subsequent adjustments may be made to this behavior.
+
+## Preview
+
+Once any transition is selected, a preview of the current transition is available in the **Inspector** panel.
+
+
+
+During the preview, the user can operate with the following buttons.
+
+
+
+The properties and descriptions are as follows.
+
+-  Skip to first frame
+-  Preview previous frame
+- / 开始/Start/pause playback
+-  Stop Play
+-  Jump to the next frame
+-  Jump to the last frame
+-  Display the current time
+
+A quick preview and adjustment of the duration of the transition can also be done via the progress bar:
+
+
+
+- Click or drag the puller at ① to quickly preview the transfer
+- At ② you can adjust the **Duration** by dragging the edge with the mouse
+
+ 
+
+- You can adjust the **Destination Start Time** of the transfer by dragging the left mouse button at the ③ sign
+
+ 
+
+After clicking on Play button, you can preview both in Preview view.
+
+
+
+## Transition Interruptions
+
+Transition interruptions are experimental features. Editing of transition interrupts can be enabled by checking **Transition interrupts** in **Preferences** -> **Laboratory**.
+
+
+
+> **Note**: This option only controls the editing of the **Transition Interruption** field in the Animation Transition panel; it is not a switch for global functionality. If **Transition Interruption** is checked, the **Transition Interruption** field will take effect even if the option is subsequently disabled.
+
+Once enabled, check **Transition Interruption** in the Animation Transition Configuration panel to configure the transition as interruptible:
+
+
+
+When an animation transition is configured to be interruptible, that animation transition in progress can be interrupted by the following transitions (in the priority listed).
+
+- All transitions originating from an **any** state.
+
+- All transitions originating from the starting state of the current transition, but not the transition itself.
+
+- All transitions originating from the end state of the current transition.
+
+When a transition is interrupted, the current transition is saved and the transition begins toward the end point of the new transition. During this process, the two states of the interrupted transition are not updated. For example, the following clip demonstrates the effect of a **Standby to Jump** transition (with a transition period of 0.5 seconds) being interrupted by a **Standby to Kick** transition.
+
+
+
+During the interruption, the standby animation and jump animation are no longer updated, while the kick animation continues to stay updated.
diff --git a/versions/4.0/en/animation/marionette/state-transition/add-condition.png b/versions/4.0/en/animation/marionette/state-transition/add-condition.png
new file mode 100644
index 0000000000..b11da6ccad
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/add-condition.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/add-more-transitions.png b/versions/4.0/en/animation/marionette/state-transition/add-more-transitions.png
new file mode 100644
index 0000000000..2ba7d07021
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/add-more-transitions.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/add-transition-for-self.png b/versions/4.0/en/animation/marionette/state-transition/add-transition-for-self.png
new file mode 100644
index 0000000000..04f6c27b26
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/add-transition-for-self.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/add-transition.gif b/versions/4.0/en/animation/marionette/state-transition/add-transition.gif
new file mode 100644
index 0000000000..fedbf66b82
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/add-transition.gif differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/animation-transition.png b/versions/4.0/en/animation/marionette/state-transition/animation-transition.png
new file mode 100644
index 0000000000..7cd34c1c3f
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/animation-transition.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/boolean-condition.png b/versions/4.0/en/animation/marionette/state-transition/boolean-condition.png
new file mode 100644
index 0000000000..190762062e
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/boolean-condition.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/change-duration.gif b/versions/4.0/en/animation/marionette/state-transition/change-duration.gif
new file mode 100644
index 0000000000..7828cdabc1
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/change-duration.gif differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/condition-properties.png b/versions/4.0/en/animation/marionette/state-transition/condition-properties.png
new file mode 100644
index 0000000000..0476987b32
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/condition-properties.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/dest-start-time.png b/versions/4.0/en/animation/marionette/state-transition/dest-start-time.png
new file mode 100644
index 0000000000..9b4475c87e
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/dest-start-time.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/duration.png b/versions/4.0/en/animation/marionette/state-transition/duration.png
new file mode 100644
index 0000000000..de3e9f31bf
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/duration.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/interruptible-inspector.png b/versions/4.0/en/animation/marionette/state-transition/interruptible-inspector.png
new file mode 100644
index 0000000000..55d1390fc4
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/interruptible-inspector.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/interruptible-laboratory.png b/versions/4.0/en/animation/marionette/state-transition/interruptible-laboratory.png
new file mode 100644
index 0000000000..bf9eb563c8
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/interruptible-laboratory.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/interruption-demo.gif b/versions/4.0/en/animation/marionette/state-transition/interruption-demo.gif
new file mode 100644
index 0000000000..13bcc90e80
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/interruption-demo.gif differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/loop.png b/versions/4.0/en/animation/marionette/state-transition/loop.png
new file mode 100644
index 0000000000..7c921635e5
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/loop.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/non-loop.png b/versions/4.0/en/animation/marionette/state-transition/non-loop.png
new file mode 100644
index 0000000000..a47c85f0f2
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/non-loop.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/number-condition.png b/versions/4.0/en/animation/marionette/state-transition/number-condition.png
new file mode 100644
index 0000000000..9186066424
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/number-condition.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/preview-bar.png b/versions/4.0/en/animation/marionette/state-transition/preview-bar.png
new file mode 100644
index 0000000000..d0bbbd8286
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/preview-bar.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/preview-overview.png b/versions/4.0/en/animation/marionette/state-transition/preview-overview.png
new file mode 100644
index 0000000000..1323f03cbf
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/preview-overview.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/preview-view.png b/versions/4.0/en/animation/marionette/state-transition/preview-view.png
new file mode 100644
index 0000000000..fdecb0b2f3
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/preview-view.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/progress.png b/versions/4.0/en/animation/marionette/state-transition/progress.png
new file mode 100644
index 0000000000..865bd66531
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/progress.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/set-example.png b/versions/4.0/en/animation/marionette/state-transition/set-example.png
new file mode 100644
index 0000000000..2a3f063e60
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/set-example.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/transition.png b/versions/4.0/en/animation/marionette/state-transition/transition.png
new file mode 100644
index 0000000000..32b89b075c
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/transition.png differ
diff --git a/versions/4.0/en/animation/marionette/state-transition/trigger-condition.png b/versions/4.0/en/animation/marionette/state-transition/trigger-condition.png
new file mode 100644
index 0000000000..1a8ee9073a
Binary files /dev/null and b/versions/4.0/en/animation/marionette/state-transition/trigger-condition.png differ
diff --git a/versions/4.0/en/animation/skeletal-animation.md b/versions/4.0/en/animation/skeletal-animation.md
new file mode 100644
index 0000000000..aa077d6a52
--- /dev/null
+++ b/versions/4.0/en/animation/skeletal-animation.md
@@ -0,0 +1,124 @@
+# Skeletal Animation
+
+Skeletal animation is a common but special type of animation. We provide two systems, **pre-baked skeletal animation** and **realtime computed skeletal animation**, optimized for different directions.
+
+The only switch between these two systems is the `useBakedAnimation` property in the **SkeletalAnimation** component, which can also be switched seamlessly at runtime.
+
+- When `useBakedAnimation` is enabled, the pre-baked skeletal animation system is used.
+- When `useBakedAnimation` is disabled, the real-time computed skeletal animation system will be used.
+
+For the component interface of skeletal animation, please refer to the [SkeletalAnimation API](%__APIDOC__%/en/class/SkeletalAnimation).
+
+## Pre-baked Skeletal Animation System
+
+The overriding purpose of this system is performance, so some of the sacrifice of expressiveness is considered acceptable. We have targeted a number of underlying optimizations, and the current runtime flow is roughly as follows:
+
+- All animation data is pre-sampled and baked in advance to a globally reused skeletal animation texture ensemble at a specified frame rate.
+- Depending on whether the runtime platform supports floating point textures or not, an alternate scheme in **RGBA32F** or **RGBA8** format is used (this step of the process is of no concern to the user and will have no impact on the final performance, but is only a final underwriting strategy for low-end platforms).
+- Each skeletal animation component (**SkeletalAnimation**) is responsible for maintaining the current playback progress, stored as a UBO (a Vec4).
+- Each skinning model component (**SkinnedMeshRenderer**) holds the pre-baked skinning model class (BakedSkinningModel), calculates culling based on the same pre-baked wrap-around box information, updates the UBO, and finishes skinning by fetching the current data from within the texture ensemble on the GPU.
+
+## Real-time Computed Skeletal Animation System
+
+The overwhelming purpose of this system is expressiveness, ensuring that all details are displayed correctly, and complete programmatic control.
+
+The current runtime flow is roughly as follows:
+
+- All animation data is dynamically interpolated and calculated based on the current global time.
+- Animation data is exported to the skeletal node tree of the scene.
+- The user and any other system can have an effect on the skinning effect by manipulating this skeleton node tree.
+- Each skinning model component (SkinnedMeshRenderer) holds the common skinning model class (SkinningModel), extracts the skeleton node tree information each frame to calculate culling, uploads the complete skeleton transformation information of the current frame to UBO, and finishes skinning inside the GPU. For more information about skinning, please refer to the **Skinning Algorithm** section below.
+
+This provides the most basic support for all the following functions:
+
+- blendshape support
+- Blending and masking of an arbitrary number of animation clips
+- IK, secondary physical effects
+- purely procedural control of joint positions
+
+## Selection of two systems and best practices
+
+Currently all model assets are imported with **pre-baking system** in Prefab by default for best performance. It is recommended to use the **real-time computing system** only when it becomes apparent that the performance of the pre-baking system is not up to par.
+
+> **Note**: although the two systems can be switched seamlessly at runtime, try not to do that at high frequencies, as each switch involves the reconstruction of the underlying rendering data.
+
+## Skinning Algorithms
+
+Creator provides two common standard skinning algorithms built-in, which have similar performance and only have an impact on the final performance.
+
+1. **LBS (Linear Blending Skinning)**: skeletal information is stored as a **3 x 4** matrix, and skinning is achieved by direct linear interpolation of the matrix. Currently there are typical known issues such as volume loss.
+2. **DQS (Dual Quaternion Skinning)**: skeletal information is interpolated as **Dual Quaternion**, which is more accurate and natural for skeletal animations that do not contain scaling transformations, but has approximate simplification for all scaling animations for performance reasons.
+
+The engine uses LBS by default, and the masking algorithm can be switched by modifying the `updateJointData` function reference in the engine `skeletal-animation-utils.ts` and the header file reference in `cc-skinning.chunk`.
+
+It is recommended that projects with high quality skinning animations try to enable DQS, but since there is no `fma` instruction until GLSL 400, operations such as `cross` cannot bypass the floating point offset problem on some GPUs and have large errors, which may introduce some visible defects.
+
+## Socket System
+
+If you need to attach some external nodes to a given skeletal joint, making them transform with skeletal joint together, you may need to use the **Socket System** of the skeletal animation component. Here is a simple example.
+
+### Implementing via the editor
+
+1. Create a new child node under the skeletal animation component to be docked (the immediate parent node should be the node where the animation component is located).
+2. Add an array element to the **Sockets** property of the skeletal animation component, select the **Path** of the skeleton to be attached from the drop-down list (note that the defaultClip of the skeletal animation component must have a value, the options in the drop-down list depend on this property), and specify the child node just created as the **Target**.
+3. This child node becomes the target socket, any external node can be put under this child node and will follow the transformation of the specified skeleton.
+
+
+
+### Implementing via code
+
+```ts
+let target = new Node();
+this.cubeNode.parent = target; // The cubeNode contains a cube model
+let skeletalAnimation = this.node.getComponent(SkeletalAnimation);
+target.parent = skeletalAnimation.node; // Setting target's parent node which contain a SkeletalAnimation component.
+let path = "root/_rootJoint/b_Root_00/b_Hip_01/b_Tail01_012/b_Tail02_013/b_Tail03_014";
+let socket = new SkeletalAnimation.Socket(path, target); // Create Socket object with path and target
+skeletalAnimation.sockets.push(socket);
+```
+Click the Preview button, you will see the cube handing from the fox's tail and shaking along with the fox's tail.
+
+
+
+The socket model in the **FBX** or **glTF** asset will automatically interface to the socket system without any manual operation.
+
+## About Dynamic Instancing
+
+Based on the framework design of the **pre-baking system**, instancing of the skinned model is also within reach, but there is some more underlying information that needs to be collected to ensure correctness.
+
+The fundamental problem here is that each model within the same drawcall must use the same skeleton texture, if not, the display will be completely misaligned. So how the animation data is assigned to each skeleton texture becomes a user-defined piece of information that can be configured in the [Joint Texture Layout](joint-texture-layout.md) panel in the editor menu bar **Panel -> Animation**.
+
+> **Notes**:
+>
+> 1. Instancing is only supported under the **pre-baking system**. we have not strictly forbidden to enable instancing under the **real-time computation framework** (only in-editor warnings), but the animation effect will definitely be problematic, depending on the actual material assignment of the model. In the best case, the animation will be identical from instance to instance, in the worst case it will cause the model to be completely misaligned.
+> 2. For models with instancing enabled in the material, the planar shading system will automatically draw with instancing as well. In particular, shading batches of skinned models require a higher level of joint texture layout, since the pipeline state of shading is uniform, and **all animations of skinned models with shadow enabled** need to be on the same texture (as opposed to drawing the model itself, which only requires consistent joint textures between instances within the same Drawcall).
+
+## Skinned Mesh Batch Renderer
+
+Currently, the joint textures uploaded to GPU on the bottom layer has been automatically batched and reused globally, and the upper layer data can now be combined by using the **SkinnedMeshBatchRenderer** component to merge all sub-skinned models controlled by the same skeletal animation component:
+
+
+
+The batched version of effect is a bit more complicated to write, but basically it can be based on the normal effect used for sub-materials, with some relatively straightforward preprocessing and interface changes. See `builtin-unlit` in the editor's built-in asset (`util/batched-unlit`).
+
+> **Note**: only the pre-baked system can guarantee correctness when using the batch skinned model component, although it can be used in the real-time computing framework, there will be rendering problems when the number of merged skeletons exceeds 30 (the maximum number of Uniform arrays).
+
+### SkinnedMeshBatchRenderer component properties
+
+| Property | Description |
+| :--- | :-- |
+| Operation | Any changes will not take effect until **Cook** button is clicked to recalculate and apply.
+| Materials | Custom effect is needed for this final material - the shader code should handle all the intricacies of the batching process.
+| LightmapSettings | Used for lightmapping, please refer to [Lightmapping](.../../../concepts/scene/light/lightmap.md) for details.
+| ShadowCastingMode | Specifies whether the current model will cast shadows, which needs to [enable shadow effect](.../../../concepts/scene/light/shadow.md#enable-shadow-effect) in the scene first.
+| ReceiveShadow | Specifies whether the current model will receive and display shadow effects generated by other objects, which needs to [enable shadow effect](.../../../concepts/scene/light/shadow.md#enable-shadow-effect) in the scene first. This property takes effect only when the type of shadows is ShadowMap.
+| SkinningRoot | The root node of the skeletal skin, usually the node where the SkeletalAnimationComponent is located.
+| AtlasSize | The side length of the generated final atlas.
+| BatchableTextureNames | The properties of the textures in the material that are actually involved in the atlas, and those are not involved use the texture of the first unit uniformly.
+| Units | The sub-model infos before batching, which is the main source of data.
+| Mesh | The model data of the current sub-model, usually from glTF or FBX.
+| Skeleton | The skeletal data of the current sub-model, usually from glTF or FBX.
+| Material | The "sub-material" used by the current sub-model is a non-batched version of the normal effect, and the effect used by different sub-models should be consistent.
+| Offset | The offset of the current sub-model's textures inside the atlas, with the top-left corner of the atlas as the origin, in the range [0, 1], e.g.: the data in the figure represents that the sub-texture overlaps with the top-left corner of the atlas.
+| Size | The size occupied by the current sub-model's textures inside the atlas, in the range [0, 1], e.g.: the data in the figure represents that the sub-texture occupies 1/2 of the entire atlas.
+| CopyFrom | The target properties (except offset and size) can be copied automatically by dragging in the SkinningModelComponent for easy operation.
diff --git a/versions/4.0/en/animation/use-animation-curve.md b/versions/4.0/en/animation/use-animation-curve.md
new file mode 100644
index 0000000000..aa48ab66be
--- /dev/null
+++ b/versions/4.0/en/animation/use-animation-curve.md
@@ -0,0 +1,323 @@
+# Using Animation Curves
+
+All keyframes added to an Animation Property of a node in an Animation Clip are shown as linear traces in the corresponding animation property track, which is an animation curve. That is, an Animation Curve describes the change in an Animation Property on an object over time.
+
+The Animation Curve stores internally a series of time points, each of which corresponds to a (curve) value, called a frame (keyframe). When the animation system runs, the Animation Component calculates the (result) value that should be assigned to the object at the specified time point based on the current animation state and completes the property change, a calculation process called sampling.
+
+The following code snippet demonstrates how to create Animation Clips programmatically:
+
+```ts
+import { AnimationClip, animation, js } from 'cc';
+const animationClip = new AnimationClip();
+animationClip.duration = 1.0; // The entire period of the animation clip, the frame time of any keyframe should not be greater than this property
+animationClip.keys = [ [ 0.3, 0.6, 0.9 ] ]; // The frame time shared by all curves of the clip
+animationClip.curves = [{ // Animation curves on the Animation component
+ modifiers: [ // Address the target object from the current node object. See the "Target Objects" section below for details
+ // The target object is the "Body" child of the current node.
+ HierarchyPath('Body'),
+ // The target object is the "MyComponent" component on the "Body" child of the current node.
+ ComponentPath(js.getClassName(MyComponent)),
+ // The target object is the "value" property on the "MyComponent" component of the "Body" child of the current node.
+ 'value',
+ ],
+ data: {
+ // Indexed to 'animationClip.keys', i.e. [ 0.3, 0.6, 0.9 ]
+ keys: 0,
+ // Keyframe data
+ values: [ 0.0, 0.5, 1.0 ],
+ },
+}];
+```
+
+The above Animation Clip contains an Animation Curve that controls the `value` property of the **MyComponent** component in the **Body** child node. The Animation Curve includes three keyframes that make the `value` property change to 0.0 at 0.3 seconds, 0.5 at 0.6 seconds, and 1.0 at 0.9 seconds.
+
+> **Note**: the frame times of the keyframes on the animation curve are indexed by reference to the `AnimationClip.keys` array. In this way, multiple curves can share frame times, which will result in additional performance optimization.
+
+## Target objects (`modifiers`)
+
+The target of an animation curve can be any JavaScript object. The `modifiers` field specifies how the target object is addressed from the current node object at **runtime**.
+
+`modifiers` is an array, each element of which expresses how to address an object from a higher level to another object, with the last element addressed as the target of the curve. This behavior is like a file system path, so each element is called a "target path".
+
+When the target path is `string` or `number`, it addresses the property of the higher-level object, which itself specifies the property name. Otherwise, the target path must be an object that implements the interface `animation.TargetPath`.
+
+Cocos Creator has the following built-in classes that implement the interface `animation.TargetPath`:
+- `animation.HierarchyPath` treats a higher-level object as a node and addresses one of its children
+- `animation.ComponentPath` treats a higher-level object as a node and addresses one of its components
+
+The target paths can be any combination, as long as they have the correct meaning:
+
+```ts
+modifiers: [
+ // The target object is the first element of the "names" property of the "BlahBlahComponent" component on the "nested_3" child node of the "nested_2" child node of the "nested_1" child node
+ new animation.HierarchyPath('nested_1/nested_2/nested_3'),
+ new animation.ComponentPath(js.getClassName(BlahBlahComponent)),
+ 'names',
+ 0,
+]
+```
+
+Custom target paths are useful when the target object is not an property, but must be returned from a method:
+
+```ts
+class BlahBlahComponent extends Component {
+ public getName(index: number) { return _names[index]; }
+ private _names: string[] = [];
+}
+
+modifiers: [
+ // The target object is the first "name" of the "BlahBlahComponent" component on the "nested_3" child node of the "nested_2" child node of the "nested_1" child node
+ new animation.HierarchyPath('nested_1/nested_2/nested_3'),
+ new animation.ComponentPath(js.getClassName(BlahBlahComponent)),
+ {
+ get: (target: BlahBlahComponent) => target.getName(0),
+ },
+]
+```
+
+For custom target paths to be serializable, declare them as classes:
+
+```ts
+@ccclass
+class MyPath implements animation.TargetPath {
+ @property
+ public index = 0;
+ constructor(index: number) { this.index = index; }
+ get (target: BlahBlahComponent) {
+ return target.getName(this.index);
+ }
+}
+
+modifiers: [
+ // The target object is the first "name" of the "BlahBlahComponent" component on the "nested_3" child node of the "nested_2" child node of the "nested_1" child node
+ new animation.HierarchyPath('nested_1/nested_2/nested_3'),
+ new animation.ComponentPath(js.getClassName(BlahBlahComponent)),
+ new MyPath(0),
+]
+```
+
+The addressing of the target object is done at runtime, a feature that allows animation clips to be reused on multiple objects.
+
+## Assignment
+
+When a value is sampled, by default the value will be set to the target object using the assignment operator `=`.
+
+Sometimes, the assignment operator cannot be used to complete the setting. For example, when setting the Uniform of a material object, it can't be done with the assignment operator. For this case, the curve field `valueAdapter` provides a mechanism to customize the value to the target object.
+
+Example:
+
+```ts
+class BlahBlahComponent {
+ public setUniform(index: number, value: number) { /* */ }
+}
+
+{ // Curve
+ valueAdapter: {
+ // Called when the curve is instantiated
+ forTarget(target: BlahBlahComponent) {
+ // Do something useful here
+ return {
+ // Called each time the value of the target object is set
+ set(value: number) {
+ target.setUniform(0, value);
+ }
+ };
+ }
+ },
+};
+```
+
+For the **custom assignment** to be serializable, declare them as classes:
+
+```ts
+@ccclass
+class MyValueProxy implements animation.
+ @property
+ public index: number = 0;
+ constructor(index: number) { this.index = index; }
+ // Called when the curve is instantiated
+ public forTarget(target: BlahBlahComponent) {
+ // Do something useful here
+ return {
+ // Called each time the value of the target object is set
+ set(value: number) {
+ target.setUniform(0, value);
+ }
+ };
+ }
+}
+```
+
+`UniformProxyFactory` is one such **custom assignment** class that implements setting the uniform value of a material:
+
+```ts
+{
+ modifiers: [
+ // The target object is the first material of the "sharedMaterials" property of the "MeshRenderer" component
+ ComponentPath(js.getClassName(MeshRenderer)),
+ 'sharedMaterials',
+ 0,
+ ],
+ valueAdapter: new animation.UniformProxyFactory(
+ 0, // Pass index
+ 'albedo', // Uniform name
+ ),
+};
+```
+
+## Sampling
+
+If the sampled time point is exactly equal to the time point of a keyframe, then the animation data on that keyframe is used. Otherwise, when the sampling time point is between two frames, the result value is affected by the data of both frames, and the scale of the sampling time point on the moment interval of the two keyframes (`[0, 1]`) reflects the extent of the effect.
+
+Cocos Creator allows this scale to be mapped to another scale to achieve a different "fade" effect. These mapping methods are called **fading methods** in Creator. After the scale is determined, the final result is calculated based on the specified **interpolation method**.
+
+> **Note**: both the fade method and the interpolation method affect the smoothness of the animation.
+
+### Fade method
+
+The fade method for each frame can be specified, or a uniform fade method can be used for all frames. The fade method can be the name of a built-in fade method or a Bessel control point.
+
+The following are some of the commonly used fade methods:
+
+- `linear`: maintains the original scale, i.e. linear gradient, which is used by default when no gradient is specified
+- `constant`: always use scale 0, i.e. no gradient, similar to interpolation `Step`.
+- `quadIn`: fade from slow to fast
+- `quadOut`: fade from fast to slow
+- `quadInOut`: fading from slow to fast to slow again
+- `quadOutIn`: fade from fast to slow to fast
+
+
+
+### Curve values and interpolation methods
+
+Some interpolation algorithms require additional data to be stored in the curve value for each frame, so the curve value is not necessarily the same as the value type of the target property. For numeric types or value types, Cocos Creator provides several general interpolation methods. Also, it is possible to define custom interpolation methods.
+
+- When the `interpolate` property of the curve data is `true`, the curve will try to use the interpolation function.
+
+ - If the curve value is of type `number`, `Number`, linear interpolation will be applied.
+ - If the curve value inherits from `ValueType`, the `lerp` function of `ValueType` will be called to complete the interpolation. `lerp` methods for most value types built into Cocos Creator are implemented as linear interpolation, e.g.: `Vec3`, `vec4`, etc.
+ - If the curve value is [interpolable](%__APIDOC__%/en/interface/ILerpable), the `lerp` function for the curve value will be called to complete the interpolation[^1].
+
+- If the curve value does not satisfy any of the above conditions, or when the `interpolate` property of the curve data is `false`, no interpolation will be performed and the curve value from the previous frame will always be used as the result.
+
+ ```ts
+ import { AnimationClip, color, IPropertyCurveData, SpriteFrame, Vec3 } from 'cc';
+
+ const animationClip = new AnimationClip();
+
+ const keys = [ 0, 0.5, 1.0, 2.0 ];
+ animationClip.duration = keys.length === 0 ? 0 : keys[keys.length - 1];
+ animationClip.keys = [ keys ]; // All curves share one column of frame time
+
+ // Linear interpolation using values
+ const numberCurve: IPropertyCurveData = {
+ keys: 0,
+ values: [ 0, 1, 2, 3 ],
+ /* interpolate: true, */ // "interpolate" property is on by default
+ };
+
+ // Using lerp() of value type Vec3
+ const vec3Curve: IPropertyCurveData = {
+ keys: 0,
+ values: [ new Vec3(0), new Vec3(2), new Vec3(4), new Vec3(6) ],
+ interpolate: true,
+ };
+
+ // No interpolation (because interpolation is explicitly disabled)
+ const colorCuve: IPropertyCurveData = {
+ keys: 0,
+ values: [ color(255), color(128), color(61), color(0) ],
+ interpolate: false, // No interpolation
+ };
+
+ // No interpolation (because SpriteFrame cannot be interpolated)
+ const spriteCurve: IPropertyCurveData = {
+ keys: 0,
+ values: [
+ new SpriteFrame(),
+ new SpriteFrame(),
+ new SpriteFrame(),
+ new SpriteFrame()
+ ],
+ };
+ ```
+
+- Custom interpolation algorithm
+
+ The sample code is as follows:
+
+ ```ts
+ import { ILerpable, IPropertyCurveData, Quat, quat, Vec3, vmath } from 'cc';
+
+ class MyCurveValue implements ILerpable {
+ public position: Vec3;
+ public rotation: Quat;
+
+ constructor(position: Vec3, rotation: Quat) {
+ this.position = position;
+ this.rotation = rotation;
+ }
+
+ /** This method will be called for interpolation
+ * @param this initial curve value
+ * @param to target curve value
+ * @param t interpolation ratio, in the range [0, 1]
+ * @param dt the frame time interval between the starting curve value and the target curve value
+ */
+ lerp (to: MyCurveValue, t: number, dt: number) {
+ return new MyCurveValue(
+ // The position property is not interpolated
+ this.position.clone(),
+ // The rotation property uses Quat's lerp() method
+ this.rotation.lerp(to.rotation, t), //
+ );
+ }
+
+ /** This method is called when not interpolating
+ * It is optional, if this method is not defined, then the curve value itself (i.e. this) is used as the result value
+ */
+ getNoLerp () {
+ return this;
+ }
+ }
+
+ /**
+ * Creates a curve that implements a smooth rotation but abrupt position change throughout the cycle.
+ */
+ function createMyCurve (): IPropertyCurveData {
+ const rotation1 = quat();
+ const rotation2 = quat();
+ const rotation3 = quat();
+
+ vmath.quat.rotateY(rotation1, rotation1, 0);
+ vmath.quat.rotateY(rotation2, rotation2, Math.PI);
+ vmath.quat.rotateY(rotation3, rotation3, 0);
+
+ return {
+ keys: 0 /* frame time */,
+ values: [
+ new MyCurveValue(new Vec3(0), rotation1),
+ new MyCurveValue(new Vec3(10), rotation2),
+ new MyCurveValue(new Vec3(0), rotation3),
+ ],
+ };
+ }
+ ```
+
+## Wrap mode
+
+Different wrap modes can be set for Animation Clips by setting `AnimationClip.wrapMode`. The following lists several common wrap modes:
+
+| Property | Description |
+| :--- | :--- |
+| Normal | Playback stops at the end |
+| WrapMode.Loop | Loop
+| PingPong | Play from the beginning to the end of the animation, then play back to the beginning from the end, and so on.
+
+For more wrap modes, please refer to the [WrapMode](%__APIDOC__%/en/class/AnimationState?id=wrapMode) API and the [Wrap Mode and Repeat Count](./animation-state.md#wrap-mode-and-repeat-count) documentation.
+
+[^1]: For numeric, quaternion, and various vectors, Cocos Creator provides the appropriate interpolate classes to implement [Cubic Spline Interpolation](https://en.wikipedia.org/wiki/Spline_interpolation).
diff --git a/versions/4.0/en/asset/asset-manager-upgrade-guide.md b/versions/4.0/en/asset/asset-manager-upgrade-guide.md
new file mode 100644
index 0000000000..dd5a26415f
--- /dev/null
+++ b/versions/4.0/en/asset/asset-manager-upgrade-guide.md
@@ -0,0 +1,380 @@
+# Asset Manager Upgrade Guide
+
+> This article details what to expect when upgrading from loader to assetManager.
+
+Before Creator v2.4, [Acquire and load asset](https://github.com/cocos/cocos-docs/blob/e02ac31bab12d3ee767c0549050b0e42bd22bc5b/en/scripting/load-assets.md) was implemented through the `loader` module (including the APIs `loader.load`, `loader.loadRes`, `loader.loadResDir`, etc.), which was primarily used to load resources. However, with the continuous development of Creator, developers' demands for resource management have been increasing. The original `loader` module has been unable to meet a large number of resource management needs, and a new resource management module is in the air.
+
+Therefore, Creator in **v2.4** introduced a new resource management module -- **Asset Manager**. Compared to the previous `loader` module, **Asset Manager** not only provides better loading performance, but also supports **Asset Bundle**, preload resources and more convenient resource release management. And **Asset Manager** also has strong extensibility, which greatly improves the development efficiency and user experience of developers. We recommend that all developers upgrade.
+
+To bring a smooth upgrade experience, we will maintain compatibility with `loader` related APIs, and most of the game project can run as usual, except for a few that use incompatible special usage APIs that must be manually upgraded. And we will only remove full compatibility with `loader` when the time comes. If developers are temporarily uncomfortable upgrading due to the project cycle, etc., keep the original writing while making sure the test passes.
+
+Currently, when using those old APIs, the engine will output warnings and suggestions for upgradation. Please adjust the code according to the warnings and the instructions in this document and upgrade to the new usage. Unfortunately, due to an upgrade of the underlying layer, we have left behind a few incompatible APIs that will output error messages while running. If deciding to make the upgrade, please read the following carefully:
+
+- For the **Artist and Game Designer**, all resources in your project (e.g.: scenes, animations, prefab) do not need to be modified or upgraded.
+- For **Programmers**, all APIs in the `loader` module that were used in the original code need to be changed to APIs from `assetManager`. The related content will be described in detail in this document.
+
+> **Note**: as v2.4 supports **Asset Bundle**, the subpackage feature in the project also needs to be upgraded, please refer to the [Subpackage Upgrade Guide](./subpackage-upgrade-guide.md) documentation for details.
+
+## Situations that require upgrading manually
+
+- Using APIs that start with `loader` in custom code, such as `loader.loaderRes`, `loader.loadResDir`, `loader.release`, etc.
+- Using APIs that start with `AssetLibrary` in custom code, such as `AssetLibrary.loadAsset`.
+- Using an API that starts with `url` in custom code, such as `url.raw`.
+- Using types such as `Pipeline`, `LoadingItems` in custom code.
+- Using the `macro.DOWNLOAD_MAX_CONCURRENT` property in custom code.
+
+## Upgrade steps
+
+- **Back up your old projects**
+- Use Cocos Creator **v2.4** in the **Dashboard** to open the project that needs to be upgraded, Creator will reimport the affected resources. The first import will take a little longer, and the main editor window will open after the import is complete. And more error or warning may appear on the **Console** panel, don't worry, open the code editor to update your code according to the error or warning message.
+
+### Replace the `loader` related API with the `assetManager` related API
+
+As of v2.4, `loader` is no longer recommended and will be completely removed in subsequent releases, please replace it with the new resource management module `assetManager`.
+
+#### The relevant interface replacement about loading
+
+If using `loader.loadRes`, `loader.loadResArray`, `loader.loadResDir` in custom code, use the corresponding API in `assetManager` for the replacement. Refer to the following replacements:
+
+- **loader.loadRes**
+
+ The parameters of `resources.load` are exactly equal to `loader.loadRes`. Replace with the following:
+
+ ```typescript
+ // before
+ loader.loadRes(...);
+
+ // after
+ resources.load(...);
+ ```
+
+- **loader.loadResArray**
+
+ For reducing learning costs, `loadResArray` has been merged with `load` and the first parameter of `resources.load` can support multiple paths, use `resources.load` to replace.
+
+ ```typescript
+ // before
+ loader.loadResArray(...);
+
+ // after
+ resources.load(...);
+ ```
+
+- **loader.loadResDir**
+
+ The parameters of `resources.loadDir` are equal to those of `loader.loadResDir`.
+
+ ```typescript
+ // before
+ loader.loadResDir(...);
+
+ // after
+ resources.loadDir(...);
+ ```
+
+ > **Note**: to simplify the interface, the load completion callback for `resources.loadDir` will **no longer** provide a list of paths. Please avoid using the following:
+
+ ```typescript
+ loader.loadResDir('images', Texture2D, (err, assets, paths) => console.log(paths));
+ ```
+
+ If you want to query the paths list, use the following form:
+
+ ```typescript
+ const infos = resources.getDirWithPath('images', Texture2D);
+ let paths = infos.map(function (info) {
+ return info.path;
+ });
+ ```
+
+- **loader.load**
+
+ If using `loader.load` to load remote images or audios in custom code, there is a special API for this in the `assetManager` for ease of understanding, as follows:
+
+ - **Loading remote images**
+
+ ```typescript
+ // before
+ loader.load('http://example.com/remote.jpg', (err, texture) => console.log(texture));
+
+ // after
+ assetManager.loadRemote('http://example.com/remote.jpg', (err, texture) => console.log(texture));
+ ```
+
+ - **Loading remote audio**
+
+ ```typescript
+ // before
+ loader.load('http://example.com/remote.mp3', (err, audioClip) => console.log(audioClip));
+
+ // after
+ assetManager.loadRemote('http://example.com/remote.mp3', (err, audioClip) => console.log(audioClip));
+ ```
+
+ - **Loading remote text**
+
+ ```typescript
+ // before
+ loader.load('http://example.com/equipment.txt', (err, text) => console.log(text));
+
+ // after
+ assetManager.loadRemote('http://example.com/equipment.txt', (err, textAsset) => console.log(textAsset.text));
+ ```
+
+> **Notes**:
+> 1. If using `loader.downloader.loadSubpackage` in custom code to load a subpackage, please refer to the [Subpackage Upgrade Guide](./subpackage-upgrade-guide.md) to upgrade it.
+> 2. To avoid unnecessary errors, `loader.onProgress` has no equivalent implementation in `assetManager`. To implement a custom global callback mechanism, but it is recommended to pass callbacks to each load function to avoid interfering with each other during concurrent loading.
+
+#### The relevant interface replacement about releasing
+
+If using `loader.release`, `loader.releaseAsset`, `loader.releaseRes`, `loader.releaseResDir` in custom code, please use the corresponding API in `assetManager` for replacement. Refer to the following replacements:
+
+- **loader.release**
+
+ `loader.release` can be replaced with `assetManager.releaseAsset`.
+
+ > **Note**: in order to avoid user attention to some obscure properties of the resource, `assetManager.releaseAsset` **no longer** accepts arrays, resource UUIDs, resource URLs for release, only the resource itself can be accepted for release.
+
+ ```typescript
+ // before
+ loader.release(texture);
+ // after
+ assetManager.releaseAsset(texture);
+
+ // before
+ loader.release([texture1, texture2, texture3]);
+ // after
+ [texture1, texture2, texture3].forEach(t => assetManager.releaseAsset(t));
+
+ // before
+ const uuid = texture._uuid;
+ loader.release(uuid);
+ // after
+ assetManager.releaseAsset(texture);
+
+ // before
+ const url = texture.url;
+ loader.release(url);
+ // after
+ assetManager.releaseAsset(texture);
+ ```
+
+ > **Note**: to increase ease of use, releasing resource dependencies in `assetManager` will **no longer require** manual access to resource dependencies, and an attempt will be made within `assetManager.releaseAsset` to automatically release the associated dependencies, for example:
+
+ ```typescript
+ // before
+ const assets = loader.getDependsRecursively(texture);
+ loader.release(assets);
+
+ // after
+ assetManager.releaseAsset(texture);
+ ```
+
+- **loader.releaseAsset**
+
+ `loader.releaseAsset` can be replaced directly with `assetManager.releaseAsset`.
+
+ ```typescript
+ // before
+ loader.releaseAsset(texture);
+
+ // after
+ assetManager.releaseAsset(texture);
+ ```
+
+- **loader.releaseRes**
+
+ `operator.releaseRes` can be replaced directly with `resources.release`.
+
+ ```typescript
+ // before
+ loader.releaseRes('images/a', Texture2D);
+
+ // after
+ resources.release('images/a', Texture2D);
+ ```
+
+- **loader.releaseAll**
+
+ `loader.releaseAll` can be replaced directly with `assetManager.releaseAll`.
+
+ ```typescript
+ // before
+ loader.releaseAll();
+
+ // after
+ assetManager.releaseAll();
+ ```
+
+> **Notse**:
+> 1. For security reasons, `loader.releaseResDir` does not have a corresponding implementation in `assetManager`, please use `assetManager.releaseAsset` or `resources.release` for individual resource releases.
+> 2. Since the `assetManager.releaseAsset` automatically releases dependent resources, it is no longer necessary to explicitly call `loader.getDependsRecursively`. If needing to find the dependency of the resource, please refer to the relevant API in `assetManager.dependUtil`.
+> 3. For security reasons, `assetManager` only supports the Auto Release property set in the scene, and `loader.setAutoRelease`, `loader.setAutoReleaseRecursively`, `loader.isAutoRelease` APIs have been removed. It is recommended to use the new auto-release mechanism based on reference counting. Please refer to the [Release Of Resources](release-manager.md) documentation for details.
+
+#### Extension-related interface replacements
+
+- **Pipeline**
+
+ If using methods in custom code that use `loader.insertPipe`, `loader.insertPipeAfter`, `loader.appendPipe`, `loader.addDownloadHandlers`, `loader.addLoadHandlers` series APIs to extend the loading process of `loader`, or directly use `loader.assetLoader`, `loader.md5Pipe`, `loader.downloader`, `loader.loader`, `loader.subPackPipe`, here are the detailed alternatives.
+
+ Because `assetManager` is a more general module and no longer inherits from `Pipeline`, `assetManager` no longer implements `handler.insertPipe`, `handler.insertPipeAfter`, `handler.appendPipe`. Please replace with the following code:
+
+ ```typescript
+ // before
+ const pipe1 = {
+ id: 'pipe1',
+ handle: (item, done) => {
+ let result = doSomething(item.uuid);
+ done(null, result);
+ }
+ };
+
+ const pipe2 = {
+ id: 'pipe2',
+ handle: (item, done) => {
+ let result = doSomething(item.content);
+ done(null, result);
+ }
+ };
+
+ loader.insertPipe(pipe1, 1);
+ loader.appendPipe(pipe2);
+
+ // after
+ function pipe1 (task, done) {
+ let output = [];
+ for (let i = 0; i < task.input.length; i++) {
+ let item = task.input[i];
+ item.content = doSomething(item.uuid);
+ output.push(item);
+ }
+
+ task.output = output;
+ done(null);
+ }
+
+ function pipe2 (task, done) {
+ let output = [];
+ for (let i = 0; i < task.input.length; i++) {
+ let item = task.input[i];
+ item.content = doSomething(item.content);
+ output.push(item);
+ }
+
+ task.output = output;
+ done(null);
+ }
+
+ assetManager.pipeline.insert(pipe1, 1);
+ assetManager.pipeline.append(pipe2);
+ ```
+
+ > **Notes**:
+ > 1. `assetManager` **no longer** inherits by `Pipeline`, but by multiple `Pipeline` instances owned under `assetManager`. Please refer to the [Pipeline and Task](pipeline-task.md) documentation for details.
+ > 2. For ease of use, the definition of Pipe no longer requires the definition of an object with a `handle` method and an `id`, just a single method. See [Pipeline and Task](pipeline-task.md) documentation for details.
+ > 3. In order to simplify the logic and improve performance, what is processed in Pipe is no longer a `item` but a `task` object, see [Pipeline and Task](pipeline-task.md) documentation for details.
+ > 4. In order to reduce learning costs, APIs in the form of `insertPipeAfter` are no longer supported in `Pipeline`, so please use `insert` to insert the specified location.
+
+- **addDownloadHandlers, addLoadHandlers**
+
+ For modularity reasons, `addDownloadHandlers` and `addLoadHandlers` are not implemented in `assetManager`, please refer to the following for replacement:
+
+ ```typescript
+ // before
+ const customHandler = (item, cb) => {
+ let result = doSomething(item.url);
+ cb(null, result);
+ };
+
+ loader.addDownloadHandlers({png: customHandler});
+
+ // after
+ const customHandler = (url, options, cb) => {
+ let result = doSomething(url);
+ cb(null, result);
+ };
+
+ assetManager.downloader.register('.png', customHandler);
+ ```
+
+ Or:
+
+ ```typescript
+ // before
+ const customHandler = (item, cb) => {
+ let result = doSomething(item.content);
+ cb(null, result);
+ };
+
+ loader.addLoadHandlers({png: customHandler});
+
+ // after
+ const customHandler = (file, options, cb) => {
+ let result = doSomething(file);
+ cb(null, result);
+ };
+
+ assetManager.parser.register('.png', customHandler);
+ ```
+
+ > **Notes**:
+ > 1. Since both the **download module** and the **parsing module** rely on **extensions** to match the corresponding processing method. So when calling `register`, the incoming first parameter needs to start with `.`.
+ > 2. For the sake of modularity, the custom processing method will no longer pass in an `item` object, but will pass in its associated information directly. The custom processing method of `downloader` passes in **the URL to be downloaded**, and `parser` passes in **the file to be parsed**. For more information about `downloader` and `parser`, please refer to the [Download and Parse](downloader-parser.md) documentation.
+ > 3. The new expansion mechanism provides an additional `options` parameter that can greatly increase flexibility. However, if it is not necessary to configure the engine's built-in or custom parameters, ignore it. Please refer to the [Optional parameter](options.md) documentation for details.
+
+- **downloader, loader, md5Pipe, subPackPipe**
+
+ `loader.downloader` can be replaced by `assetManager.downloader`, and `loader.loader` can be replaced by `assetManager.parser`. For details, see [Download and Parse](downloader-parser.md) documentation or the corresponding API documentation [assetManager.downloader](%__APIDOC__%/en/class/AssetManager?id=downloader) and [assetManager.parser](__APIDOC__/en/class/AssetManager?id=parser).
+
+ > **Note**: for performance, modularity and readability reasons, `loader.assetLoader`, `loader.md5Pipe`, `loader.subPackPipe` have been merged into `assetManager.transformPipeline`. Remember to avoid using any of the methods and properties in these three modules. Details about `assetManager.transformPipeline` can be found in [Pipeline and Tasks](pipeline-task.md) documentation.
+
+### Other changes
+
+The `url` and `AssetLibrary` have been removed, so avoid using any methods and properties of `url` and `AssetLibrary`.
+
+`Pipeline` can be replaced by `AssetManager.Pipeline`:
+
+```typescript
+// before
+const pipe1 = {
+ id: 'pipe1',
+ handle: function (item, cb) {
+ let result = doSomething(item);
+ cb(null, result);
+ }
+}
+
+const pipeline = new Pipeline([pipe1]);
+
+// after
+function pipe1 (task, cb) {
+ task.output = doSomething(task.input);
+ cb(null);
+}
+
+const pipeline = new AssetManager.Pipeline('test', [pipe1]);
+```
+
+> **Note**: `LoadingItem` is no longer supported in `assetManager`, please avoid using this type.
+
+To support more loading strategies, `macro.DOWNLOAD_MAX_CONCURRENT` has been removed from `macro` and replace it with the following:
+
+```typescript
+// before
+macro.DOWNLOAD_MAX_CONCURRENT = 10;
+
+// after
+assetManager.downloader.maxConcurrency = 10;
+```
+
+Or:
+
+```typescript
+// before
+macro.DOWNLOAD_MAX_CONCURRENT = 10;
+
+// after (set a preset value)
+assetManager.presets['default'].maxConcurrency = 10;
+```
+
+Please refer to the [Download and Parse](downloader-parser.md) documentation for details.
diff --git a/versions/4.0/en/asset/asset-manager.md b/versions/4.0/en/asset/asset-manager.md
new file mode 100644
index 0000000000..0fb355b612
--- /dev/null
+++ b/versions/4.0/en/asset/asset-manager.md
@@ -0,0 +1,151 @@
+# Asset Manager Overview
+
+> Author: Santy-Wang, Xunyi
+
+During the development of the game, it is generally necessary to use a large number of images, audio and other resources to enrich the entire game, and a large number of resources can cause management difficulties. That's why Creator provides the **Asset Manager** resource management module to help developers manage the use of their resources and greatly improve the development efficiency and experience.
+
+**Asset Manager** is a new resource manager from Creator in v2.4 that replaces the previous `loader`. The new **Asset Manager** resource management module has features for loading resources, finding resources, destroying resources, caching resources, Asset Bundle, and more. Compared with previous `loader`, Asset Manager has better performance, easier-to-use APIs, and greater extensibility. All functions and methods are accessible via `assetManager` and all types and enumerations are accessible via the `AssetManager` namespace.
+
+> **Note**: we will maintain compatibility with `loader` for a period of time, but we strongly recommend using **Asset Manager** consistently for new projects.
+
+Refer to the following documentations for upgrading:
+- [AssetManager Upgrade Guide](asset-manager-upgrade-guide.md)
+- [Asset Bundle Upgrade Guide](subpackage-upgrade-guide.md)
+
+## Load Resources
+
+### Dynamic Loading Of Resources
+
+In addition to applying resources to the corresponding components while editing scenes, Creator also supports dynamic loading and setting up of resources while the game is running. Asset Manager provides two ways to dynamically load resources:
+
+1. By placing resources in the `resources` directory, and working with APIs such as `resources.load` to achieve dynamic loading.
+2. developers can plan their own resource creation as Asset Bundle and load resources through the Asset Bundle's `load` family of APIs. For example:
+
+ ```typescript
+ resources.load('images/background/spriteFrame', SpriteFrame, (err, asset) => {
+ this.getComponent(Sprite).spriteFrame = asset;
+ });
+ ```
+
+The relevant APIs are listed below:
+
+| Type | Support | Loading | Releasing | Preloading | Querying | Search |
+| :-- | :-- | :-- | :-- | :-- | :-- |:-- |
+| **Single Asset** | Asset Bundle | load | release | preload | get | getInfoWithPath |
+| **Directory** | Asset Bundle | loadDir | releaseAsset | preloadDir | N/A | getDirWithPath |
+| **Scene** | Asset Bundle | loadScene | N/A | preloadScene | N/A | getSceneInfo |
+| **Single Asset** | `resources` | load | release | preload | get | getInfoWithPath |
+| **Directory** | `resources` | loadDir | releaseAsset | preloadDir | N/A | getDirWithPath |
+| **Remote Asset** | Asset Manager | loadRemote | releaseAsset | N/A | N/A | N/A |
+
+References documentations:
+
+- [Dynamic Load Asset](dynamic-load-resources.md)
+
+All loaded resources are cached in `assetManager`.
+
+### Preloading
+
+To reduce download latency, `assetManager` and Asset Bundle not only provides interfaces for loading resources, each interface also provides a corresponding preloaded version. Preloading in a game is an option that then allows finishing loading when it is really need it. Preloading will only download the necessary resources and will not perform deserialization or initialization. Therefore, it consumes less performance and is suitable for use during the game.
+
+```typescript
+start () {
+ resources.preload('images/background/spriteFrame', SpriteFrame);
+ setTimeOut(this.loadAsset.bind(this), 10000);
+}
+
+loadAsset () {
+ resources.load('images/background/spriteFrame', SpriteFrame, (err, asset) => {
+ this.getComponent(Sprite).spriteFrame = asset;
+ });
+}
+```
+
+For more information on preloading, please refer to the [Preloading and Loading](preload-load.md) documentation.
+
+## Asset Bundle
+
+Partitioning scenes, resources, and code into multiple Asset Bundles and the loading of resources dynamically at runtime results in modularity of resources and allows loading corresponding resources when needed. For example:
+
+```typescript
+assetManager.loadBundle('testBundle', function (err, bundle) {
+ bundle.load('textures/background/texture', (err, asset) => {
+ // ...
+ });
+});
+```
+
+Please refer to the [Asset Bundle](bundle.md) documentation for more information on Asset Bundle.
+
+## Release of resources
+
+Asset Manager provides a more convenient mechanism for releasing resources. When releasing a resource, you only need to focus on the resource itself and no longer on its dependent resources. The engine attempts to release its dependent resources based on the number of references, to reduce the complexity of managing resource releases for users. For example:
+
+```typescript
+resources.load('prefabs/enemy', Prefab, function (err, asset) {
+ assetManager.releaseAsset(asset);
+});
+```
+
+Creator also provides a reference counting mechanism to help you control the reference and release of resources. For example:
+
+- When you need to hold a resource, call `addRef` to add a reference to ensure that the resource is not automatically released by other references to it.
+
+ ```typescript
+ resources.load('textures/armor/texture', Texture2D, function (err, texture) {
+ texture.addRef();
+ this.texture = texture;
+ });
+ ```
+
+- When you no longer need to hold the resource, call `decRef` to reduce reference, `decRef` will also attempt an automatic release based on the reference count.
+
+ ```typescript
+ this.texture.decRef();
+ this.texture = null;
+ ```
+
+Please refer to the [Release of Resources](release-manager.md) documentation for more details.
+
+## Cache Manager
+
+On some platforms, such as WeChat, it is possible to use the file system to cache some remote resources because a file system exists. In this case, a cache manager is required to manage all cache resources, such as caching resources, clearing cache resources, modifying cache cycles, etc. . Creator provides a cache manager on all platforms where file systems exist that allows adding, deleting, changing, and checking the cache. For example:
+
+```typescript
+// Get the cache of a resource.
+assetManager.cacheManager.getCache('http://example.com/bundle1/import/9a/9aswe123-dsqw-12xe-123xqawe12.json');
+
+// Clear the cache of a resource.
+assetManager.cacheManager.removeCache('http://example.com/bundle1/import/9a/9aswe123-dsqw-12xe-123xqawe12.json');
+```
+
+Please refer to the [Cache Manager](cache-manager.md) documentation for more information on Cache Manager.
+
+## Optional Parameters
+
+Some of the interfaces for `assetManager` and Asset Bundle have an additional `options` parameter, which greatly increase the flexibility and extend the space. In addition to configuring the builtin parameters of Creator, it is also possible to customize any of the parameters in `options`, and these parameters will be provided to the downloader, parser, and loading pipeline.
+
+```typescript
+bundle.loadScene('test', {priority: 3}, callback);
+```
+
+For more information on `options` parameter, please refer to the [Optional Parameters](options.md) documentation.
+
+If it is not necessary to configure the engine's builtin parameters or custom parameters to extend the engine's functionality, ignore it and use the simpler API interfaces, such as `resources.load`.
+
+## Loading Pipeline
+
+To make it easier to extend the resource loading process, the underlying layer of Asset Manager uses mechanisms called **Pipeline and Task** and **Download and Parse** to load resources, greatly increasing flexibility and scalability. To expand the load pipeline or customize it, refer to the following documentation:
+
+- [Pipeline and Task](pipeline-task.md)
+- [Download and Parse](downloader-parser.md)
+
+## More Reference
+
+- [Asset Bundle](bundle.md)
+- [Release Of Resources](release-manager.md)
+- [Download and Parse](downloader-parser.md)
+- [Loading and Preloading](preload-load.md)
+- [Cache Manager](cache-manager.md)
+- [Optional Parameters](options.md)
+- [Pipeline and Task](pipeline-task.md)
diff --git a/versions/4.0/en/asset/asset-workflow.md b/versions/4.0/en/asset/asset-workflow.md
new file mode 100644
index 0000000000..a8f4386063
--- /dev/null
+++ b/versions/4.0/en/asset/asset-workflow.md
@@ -0,0 +1,43 @@
+# Assets workflow
+
+## Importing assets
+
+There are three ways to **import assets**:
+
+- Create a new file through the **Assets** panel in Cocos Creator. Use the **Create button** to start the importing process.
+- By copying files, in the **file manager of the operating system**, to the project asset folder, and then open the editor or activate the editor window to automatically refresh the asset list of the **Assets** panel to finish importing assets.
+- Drag and drop asset files from the **file manager of the operating system** to a folder location on the **Assets** panel. This will trigger an import of the selected assets.
+
+## Syncing Assets
+
+The assets in the **Assets** panel are synchronized with the project asset files seen in the **file manager of the operating system**. Assets are **moved**, **renamed**, and **deleted** in the **Assets** panel.
+- If deleted in Cocos Creator, it will be deleted in the **file manager of the operating system**.
+- If deleted in the **file manager of the operating system**, it will be deleted in Cocos Creator.
+
+## Asset Configuration Information `.meta` File
+
+All asset files will generate a `.meta` configuration file with the same name when imported. This configuration file provides the unique identification (**UUID**) of the asset in the project, small image references, cropping data of texture assets, as well as other configuration information. This data is a necessary factor in identifying a legitimate asset that Cocos Creator is using.
+
+The `.meta` file is not visible in the **Assets** panel. When operating in the **Assets** panel, the **renaming**, **moving**, and **deleting** of an __asset__ will automatically synchronize the `.meta` file that corresponds to the __asset__ by the Editor. To ensure that configuration information such as the **UUID** remains unchanged, that is, it does not affect existing references.
+
+It is not recommended to operate the asset file directly in the __file manager of the operating system__. If there is such an operation, please manually operate the corresponding `.meta` file along with the __asset__ file. The following suggestions are recommended:
+
+- Close the editor you are using to avoid update failures due to file locks or identical asset names.
+- When **deleting**, **renaming**, or **moving** assets, please **delete**, **rename**, and **move** the `.meta` file as needed.
+- When copying assets together with `.meta` files, the copied `.meta` files will be used directly instead of generating new `.meta` files; if only the asset files are copied, a new `.meta` file with the corresponding name will be generated when you re-open the editor. This asset will become a new asset to the editor.
+
+## Assets in Library
+
+After the asset is imported, new data will be generated and stored in the project's **Library** folder. The structure and assets of the files in **Library** are engine-oriented and the format required for the final game, that is, __machine-friendly__, but __not human-friendly__.
+
+When a library is lost or damaged, just delete the entire library folder and open the project, and the asset library will be rebuilt.
+
+## How to locate assets
+
+A asset has a unique **UUID**, used to locate the asset, but this method is not intuitive enough. There is another intuitive way: **Database URL** format, such as an `asset-db`. The corresponding protocol header is `db://assets`, the protocol header for `internal-db` is `db://internal`.
+
+There are folder-level asset formats, such as `db://assets/prefabs/fire.prefab`
+
+## SVN or GIT syncing of assets
+
+> **Note**: there are line breaks in the `.meta` file. It is recommended to unify the line break styles and rules of the team members' computers to avoid opening the project after synchronizing the project assets.
diff --git a/versions/4.0/en/asset/atlas.md b/versions/4.0/en/asset/atlas.md
new file mode 100644
index 0000000000..d614813b8f
--- /dev/null
+++ b/versions/4.0/en/asset/atlas.md
@@ -0,0 +1,47 @@
+# Atlas assets
+
+__Atlas__, also called a __Sprite Sheet__, is a common art asset in game development. __Atlas__ is an asset for merging multiple pictures into a large picture through a special tool, and indexing through a file such as a **.plist**. __Atlas__ assets available for __Cocos Creator__ consist of a **.plist** and at least one **.png** file, although usually many **.png** files make up an __Atlas__. The following is an image file used in an __Atlas__:
+
+
+
+## Why use atlas assets
+
+In a game, using an __Atlas__ composed of multiple pictures as art assets has the following advantages:
+
+- The blank area around each picture will be removed when synthesizing the __Atlas__, plus various optimization algorithms can be implemented as a whole. After synthesizing the __Atlas__, the game package and memory consumption can be greatly reduced.
+- When multiple __Sprites__ are rendering pictures from the same atlas, these __Sprites__ can be processed using the same rendering batch, which greatly reduces the CPU's computing time and improves operating efficiency.
+
+For a more comprehensive explanation, watch a teaching video: [__What is a Sprite Sheet__](https://www.codeandweb.com/what-is-a-sprite-sheet) from __CodeAndWeb__.
+
+## Atlas Assets
+
+To generate an __Atlas__, you should first prepare a set of original pictures. Example:
+
+
+
+__Next__, use special software to generate the __Atlas__. Examples:
+
+- [TexturePacker 4.x](https://www.codeandweb.com/texturepacker)
+
+
+When using these software packages to generate an __Atlas__, please select a `.plist` file in **Cocos2d-x** format. The resulting __Atlas__ files are a `.plist` and `.png` with the same name. Example: `myAtlas.plist` and `myAtlas.png`.
+
+
+
+When using __TexturePacker__ software, please note that use __v4.x__ only, v3.x and below is not supported.
+
+## Importing Atlas Assets
+
+Drag the **.plist** and the **.png** files shown above into the **Assets** panel at the same time. It is possible to generate __Atlas__ assets that can be used in the editor and scripts.
+
+### Atlas and SpriteFrame
+
+In the [Image Resource Document](../ui-system/components/editor/sprite.md), the relationship between __Texture__ and __SpriteFrame__ was introduced. After importing the __Atlas__, we can see that the __Atlas__ is of type __Atlas__ and can be expanded by clicking the triangle icon on the left. After expanding, we can see that the __Atlas__ contains many sub-assets of type __SpriteFrame__. Assets are pictures that can be used and referenced individually.
+
+
+
+The use of the __Sprite Frame__ is the same as that described in the image asset. Please refer to the related documents.
+
+
diff --git a/versions/4.0/en/asset/atlas/atlas_files.png b/versions/4.0/en/asset/atlas/atlas_files.png
new file mode 100644
index 0000000000..89a36353ce
Binary files /dev/null and b/versions/4.0/en/asset/atlas/atlas_files.png differ
diff --git a/versions/4.0/en/asset/atlas/sheep_atlas.png b/versions/4.0/en/asset/atlas/sheep_atlas.png
new file mode 100644
index 0000000000..4be0dbd0ee
Binary files /dev/null and b/versions/4.0/en/asset/atlas/sheep_atlas.png differ
diff --git a/versions/4.0/en/asset/atlas/single_sheep.png b/versions/4.0/en/asset/atlas/single_sheep.png
new file mode 100644
index 0000000000..f14dd4f2f4
Binary files /dev/null and b/versions/4.0/en/asset/atlas/single_sheep.png differ
diff --git a/versions/4.0/en/asset/atlas/spriteframes.png b/versions/4.0/en/asset/atlas/spriteframes.png
new file mode 100644
index 0000000000..fe647d1ac3
Binary files /dev/null and b/versions/4.0/en/asset/atlas/spriteframes.png differ
diff --git a/versions/4.0/en/asset/audio-clip.png b/versions/4.0/en/asset/audio-clip.png
new file mode 100644
index 0000000000..b37bd89d6d
Binary files /dev/null and b/versions/4.0/en/asset/audio-clip.png differ
diff --git a/versions/4.0/en/asset/audio.md b/versions/4.0/en/asset/audio.md
new file mode 100644
index 0000000000..1afa123381
--- /dev/null
+++ b/versions/4.0/en/asset/audio.md
@@ -0,0 +1,21 @@
+# Audio Assets
+
+Cocos Creator supports importing most common audio file formats, just drag and drop them directly into the **Assets** panel, and the corresponding **AudioClip** will be generated in the **Assets** panel after import.
+
+
+
+The audio can be divided into longer length **Music** and shorter length **Sound Effects** based on their length. Creator controls the playback of different audio assets through the AudioSource component to implement in-game background music and sound effects. For more details, please refer to the [AudioSource Component Reference](../audio-system/audiosource.md).
+
+## Supported Audio Formats
+
+Currently Cocos Creator supports importing audio files in the following formats:
+
+| Audio Format | Description |
+|:-- | :-- |
+| `.ogg` | `.ogg` is an open source lossy audio compression format, which has the advantage of supporting multi-channel encoding and using a more advanced acoustic model to reduce the loss of sound quality, while the file size is smaller than `.mp3` format under the same conditions. Currently all the built-in ringtones for Android also use `.ogg` files. [This format is not supported by iOS](https://developer.apple.com/documentation/audiotoolbox/audiofiletypeid) |
+|`.mp3` | `.mp3` is the most common digital audio encoding and lossy compression format. The purpose of compression is to compress PCM audio material into smaller files by discarding parts of the material that are not important to human hearing. MP3 is supported by a large number of hardware and software, and is widely used, and is currently the mainstream. |
+| `.wav` | `.wav` is a standard digital audio file developed by Microsoft and IBM specifically for Windows. This file can record various mono or stereo sound information, and can ensure that the sound is not distorted because the audio format is not compressed. However, the file size is relatively large. |
+| `.mp4` | `.mp4` is a set of compression coding standards for audio and video information. Different coding algorithms can be used for different objects to further improve the compression efficiency. |
+| `.m4a` | `.m4a` is an audio-only MP4 file. The audio quality is very high among the compression formats, and the file footprint is smaller at the same bit rate. |
+
+With different audio encoding formats, the generated audio files vary in size and sound quality under the same conditions.
diff --git a/versions/4.0/en/asset/auto-atlas.md b/versions/4.0/en/asset/auto-atlas.md
new file mode 100644
index 0000000000..2c4a410f75
--- /dev/null
+++ b/versions/4.0/en/asset/auto-atlas.md
@@ -0,0 +1,56 @@
+# Auto Atlas
+
+**Auto Atlas** is the picture-combining method that comes as part of Cocos Creator. **Auto Atlas** packs a specified series of images into a __sprite sheet__. This capability is very similar to the function of __Texture Packer__.
+
+## Creating Auto Atlas Assets
+
+Create a new **auto-atlas.pac** resource in the **Assets** panel by clicking the **+** Create button in the upper left corner and then selecting **Auto Atlas**.
+
+
+
+**AutoAtlas** will pack all **SpriteFrame** assets in the same folder into a big **Sprite Atlas** asset during the build process. We might add other ways to choose assets for packing in the future. If the original **SpriteFrame** asset have been configured, then all configurations will be preserved.
+
+## Configuring Auto Atlas Assets
+
+After selecting an **Auto Atlas Resource** in the __Assets__ panel, the **Inspector** panel will display all of the configurable items for the **Auto Atlas Resource**.
+
+
+
+| Property | Functional Description
+| :-------------- | :----------- |
+| **Max Width** | Single atlas maximum width |
+| **Max Height** | Maximum Height of a single atlas |
+| **Padding** | Spacing between shreds in the atlas |
+| **Allow Rotation** | Whether rotate fragments |
+| **Force Squared** | Whether to force the size of the atlas to be square |
+| **Power of Two** | Whether to set the size of the atlas to a multiple of a square |
+| **Algorithm** | Atlas packaging strategy, currently only one option `MaxRects` |
+| **Padding Bleed** | Expand a pixel outer frame outside the border of the broken image, and copy the adjacent broken image pixels to the outer frame. This feature is also called **Extrude**. |
+| **Filter Unused Resources** | If this option is checked, unreferenced assets will not be included when building. This option only takes effect after the build. |
+| **Remove unused texture force in Bundle** | If this option is checked, the unused Texture2D resources in the Bundle will be excluded when building.
+| **Remove unused image force in Bundle** | If this option is checked, the unused image resources in the Bundle will be excluded when building.
+| **Remove unused sprite atlas in Bundle** | If this option is checked, the unused sprite atlas in the Bundle will be excluded when building.
+| **UseCompressTexture** | Whether to use the compress texture, please refer to the [Texture Compression](compress-texture.md) for details.
+
+The rest of the properties are the same as Texture, please refer to the [Texture](./texture.md#sub-asset-texture2d-properties-panel) documentation for details.
+
+After the configuration is complete, click the **Preview** button to preview the packaged results. The related results generated according to the current automatic atlas configuration will be displayed in the area below the **Inspector** panel.
+
+> **Note**: after each configuration, re-click **Preview** to update the preview image. (Generating a preview is not required).
+
+The results are divided into:
+
+- __Packed Textures__: Display the packaged atlas pictures and picture-related information. If there are multiple pictures to be generated, they will be listed below in the **Inspector** panel.
+- __Unpacked Textures__: Display the broken image assets that cannot be packed into the atlas. The cause may be that the size of these broken image assets is larger than the size of the atlas assets. At this time, the configuration or fragmentation of the following atlas may need to be adjusted. The size of the figure is increased.
+
+## Generating an Atlas
+
+When inside the editor or previewing the project, __Cocos Creator__ is directly using the split **SpriteFrame** assets, only after building, the **Atlas** asset will be generated and be used instead of all split assets.
+
+In general, after **Atlas** asset is generated, the **Texture2D** assets and **Image** assets related by the original split assets will be deleted in the package. The following two special cases will have special process:
+
+1. When **Atlas** asset is in a `Bundle` directory, the **Texture2D** and **Image** assets related by the original **SpriteFrame** assets in the **AutoAtlas** asset's directory will also be generated. If you have a specific scope of use for the atlas, please check the corresponding exclusion option in the **Inspector** panel to avoid oversizing the package.
+
+2. When any **Texture2D** asset depended by **SpriteFrame** assets in the **Atlas** asset's folder is directly used by another asset, the dependent **Texture2D** asset and **Image** asset will also be generated.
+
+The two situations above will increase the package size, please do not use an **Atlas** like this unless necessary, **Builder** will also produce a console warning to prompt you to consider your package size.
diff --git a/versions/4.0/en/asset/auto-atlas/autoatlas-properties.png b/versions/4.0/en/asset/auto-atlas/autoatlas-properties.png
new file mode 100644
index 0000000000..6767a7b192
Binary files /dev/null and b/versions/4.0/en/asset/auto-atlas/autoatlas-properties.png differ
diff --git a/versions/4.0/en/asset/auto-atlas/create-auto-atlas.png b/versions/4.0/en/asset/auto-atlas/create-auto-atlas.png
new file mode 100644
index 0000000000..1b46867f85
Binary files /dev/null and b/versions/4.0/en/asset/auto-atlas/create-auto-atlas.png differ
diff --git a/versions/4.0/en/asset/bundle.md b/versions/4.0/en/asset/bundle.md
new file mode 100644
index 0000000000..a3c97662fa
--- /dev/null
+++ b/versions/4.0/en/asset/bundle.md
@@ -0,0 +1,448 @@
+# Asset Bundle Overview
+
+> Author: Santy-Wang, Xunyi
+
+Starting with v2.4, Creator officially supports **Asset Bundle**. The Asset Bundle is a modular resource tool that allows developers to divide the resources such as textures, scripts, scenes, etc. into different Asset Bundles according to the project requirements. Then, as the game runs, load different Asset Bundles as needed to minimize the number of resources to be loaded at startup. thus reducing the time required for the first download and loading of the game.
+
+The Asset Bundle can be placed in different places as needed, such as on a remote server, locally, or in a subpackage of a mini game platform.
+
+## The built-in Asset Bundle
+
+In addition to the custom Asset Bundle, there are three built-in Asset Bundles in the project, which like other custom Asset Bundles, can be configured for different platforms.
+
+
+
+| Built-in Asset Bundle | Function Explanation | Configuration |
+| :--------------- | :--------- | :-------- |
+| `main` | Store all scenes checked in the **Included Scenes** selection box of the **Build** panel and their dependent resources | By configuring the **Main Bundle Compression Type** and **Main Bundle Is Remote** options of the **Build** panel. |
+| `resources` | Store all resources in the `resources` directory and their dependent resources | By configuring the `assets -> resources` folder in the **Assets** panel. |
+| `start-scene` | If you check the **Start Scene Asset Bundle** option in the **Build** panel, the first scene will be built into the `start-scene` folder. | Cannot be configured. |
+| `internal` | Some default resources built into the engine module | Cannot be configured. |
+
+After the build, the built-in Asset Bundle will be generated in different locations depending on the configuration, see the [Configure the Asset Bundle](bundle.md#configuration) documentation for the configuration methods and generation rules.
+
+The built-in Asset Bundle is loaded in `application.js`, and you can modify the code in `application.js` by using the custom build template feature, as shown below.
+
+```typescript
+// ...
+
+function loadAssetBundle (hasResourcesBundle, hasStartSceneBundle) {
+ let promise = Promise.resolve();
+ const mainBundleRoot = 'http://myserver.com/assets/main';
+ const resourcesBundleRoot = 'http://myserver.com/assets/resources';
+ const bundleRoot = hasResourcesBundle ? [resourcesBundleRoot, mainBundleRoot] : [mainBundleRoot];
+ return bundleRoot.reduce((pre, name) => pre.then(() => loadBundle(name)), Promise.resolve());
+}
+
+function loadBundle (name) {
+ return new Promise((resolve, reject) => {
+ assetManager.loadBundle(name, (err, bundle) => {
+ if (err) {
+ return reject(err);
+ }
+ resolve(bundle);
+ });
+ });
+}
+```
+
+## Configuration
+
+The custom Asset Bundle is configured in **folders**. When we select a folder in the **Assets** panel, the **Properties** panel will show a **Is Bundle** option, if set, the folder-related configuration options will appear:
+
+
+
+| Configuration Options | Function Explanation |
+| :--- | :---- |
+| **Bundle Name** | The name of the Asset Bundle after it is built, which will use the name of this folder by default, can be modified as needed. |
+| **Bundle Priority** | Creator opens up 20 configurable priorities, and the Asset Bundle will be built in descending order of priority. For more detail, see [Asset Bundle -- Priority](bundle.md#priority) documentation. |
+| **Target Platform** | An Asset Bundle can have different settings on different platforms and the editor will choose the corresponding setting at build time. |
+| **Compression Type** | Determines the final output form of the Asset Bundle, including the five compression types **Merge Depend**, **None**, **Merge All JSON**, **Mini Game Subpackage** and **Zip**. For more detail, see [Asset Bundle -- Compression Type](bundle.md#compression-type) documentation. |
+| **Is Remote Bundle** | Whether to configure the Asset Bundle as a remote package. If checked, the Asset Bundle will be placed in the **remote** folder after the build, and you will need to place the entire **remote** folder on the remote server. When building mini game platforms such as OPPO, vivo, Huawei, etc., the Asset Bundle will not be packaged into rpk if this option is checked. |
+| **Bundle Filter Config** | Use **Bundle Filter Config** to filter some assets in a bundle, and to preview the assets in the bundle by clicking on the **Preview** button. For more, see [Bundle Filter Config](./bundle.md#Bundle%20Filter%20Config) below. |
+| **Build Bundle** | Click to build the selected or specified bundle. For [more](./bundle#Build%20Bundle) |
+
+After the configuration, click the **green tick button** at the top right of the panel, and the folder will be configured as an Asset Bundle, then select the corresponding platform in the **Build** panel to build.
+
+> **Notes**:
+>
+> 1. There are 4 [built-in Asset Bundles](bundle.md#the-built-in-asset-bundle) in Creator, including **internal**, **resources**, **main** and **start-scene**. When setting the **Bundle Name**, **do not** use these names.
+> 2. The [mini game subpackage](../editor/publish/subpackage.md) can only be placed locally and cannot be configured as remote packages. So the **Is Remote Bundle** option cannot be checked when the compression type is set to **Mini Game Subpackage**.
+> 3. The Zip compression type is primarily used to reduce the number of network requests and is used by default with the **Is Remote Bundle** option. Since the package doesn't need network requests if it's local, there's no need to use Zip compression.
+> 4. The folder configuration set to Bundle is used as a collection of options for the Asset Bundle and we do not recommend that you place all assets in it very directly. Similar to the previous version of resources, the Bundle configuration folder should preferably hold entry assets such as Scene, Prefab, or assets that need to be dynamically loaded within the script, and the final build phase will export all referenced assets based on dependencies to eventually populate the entire Asset Bundle.In this way, unnecessary resource exports can be minimized.
+
+## Priority
+
+When the folder is set to Asset Bundle, the resources in the folder and the related dependent resources outside the folder are merged into the same Asset Bundle. It is possible to have a resource that is not in the Asset Bundle folder, but belongs to both Asset Bundles, because it is depended upon by both Asset Bundles. As shown in the figure:
+
+
+
+Another possibility is that a resource is in one Asset Bundle folder, but is also depended upon by other Asset Bundles. As shown in the figure:
+
+
+
+In both cases, `resource c` belongs to both `Asset Bundle A` and `Asset Bundle B`. So which Asset Bundle does `resource c` actually exist in? This needs to be specified by adjusting the priority of the Asset Bundle.
+Creator opens up 20 configurable priorities, and the editor will build the Asset Bundle in **descending order** of priority at build time.
+
+- When the same resource is referenced by multiple Asset Bundles with **different priorities**, the resource will be placed in the high-priority Asset Bundle, while the lower-priority Asset Bundle stores only one record message. In this case the lower-priority Asset Bundle relies on the higher-priority Asset Bundle.
+If you want to load this shared resource in a lower-priority Asset Bundle, you must load the higher-priority Asset Bundle before loading the lower-priority Asset Bundle.
+
+- When the same resource is referenced by multiple Asset Bundles of the **same priority**, the resource will be copied in each Asset Bundle, with no dependencies between the different Asset Bundles, and they can be loaded in any order. So try to make sure that the Asset Bundle that the shared resource (e.g.: `Texture`, `SpriteFrame`, `Audio`, etc.) is in has a higher priority, so that more lower-priority Asset Bundles can share resources, thus minimizing the package size.
+
+The four built-in Asset Bundle folders are prioritized as follows:
+
+| Asset Bundle | Priority |
+| :--- | :--- |
+| `main` | 7 |
+| `resources` | 8 |
+| `start-scene` | 20 |
+| `internal` | 21 |
+
+When the four built-in Asset Bundles contain the same resources, the resources are stored in the higher priority Asset Bundle. It is recommended that other custom Asset Bundle priorities are not higher than the built-in Asset Bundle, so that the resources in the built-in Asset Bundle can be shared whenever possible.
+
+## Compression Type
+
+Creator currently provides **Merge Depend**, **None**, **Merge All Json**, **Mini Game Subpackage**, and **Zip** compression types for optimizing the Asset Bundle. All Asset Bundles use the **Merge Depend** compression type by default, and you can reset the compression type for all Asset Bundles including the built-in Asset Bundle.
+
+| Compression Type | Function Explanation |
+| :------ | :------ |
+| **Merge Depend** | When building the Asset Bundle, JSON files for interdependent resources are merged together to reduce the number of load requests at runtime. |
+| **None** | When building the Asset Bundle, there is no compression operation. |
+| **Merge All Json** | When building the Asset Bundle, the JSON files for all resources are merged into one, which minimizes the number of requests, but may increase the load time for a single resource. |
+| **Mini Game Subpackage** | On a mini game platform that provides subpackaging, the Asset Bundle will be set as a subpackage of the mini game. |
+| **Zip** | On some mini game platforms, the resource file will be compressed into a Zip file when building the Asset Bundle, reducing the number of load requests at runtime. |
+
+If you use different compression types for the Asset Bundle on different platforms, then the Asset Bundle will be built according to the settings of the corresponding platform.
+
+## Building of the Asset Bundle
+
+At build time, resources (including scenes, code, and other resources) in the folder configured as an Asset Bundle, as well as relevant dependent resources outside the folder, are merged into the same Asset Bundle folder. For example, if "scene A" is placed in "folder a", when "folder a" is configured as an Asset Bundle, "scene A" and its dependent resources will be merged into the "Asset Bundle a" folder.
+
+All the **code** and **resources** in the folder configured as the Asset Bundle are treated as follows.
+
+- **Code**: All the code in the folder is merged into an entry script file named `index.js` or `game.js`, depending on the release platform, and removed from the main package.
+- **Resources**: All resources in the folder and the related dependent resources outside the folder are placed in the `import` or `native` directory.
+- **Resource Configuration**: All resource configuration information including path, type, and version information is merged into a file named `config.json`.
+
+The structure of the Asset Bundle directory generated after build is shown below:
+
+
+
+After building, the Asset Bundle folder will be packaged into the **assets** folder in the release package directory of the corresponding platform. However, there are two special cases.
+
+- If the **Is Remote Bundle** option is checked when configuring the Asset Bundle, this Asset Bundle folder will be packaged into the **remote** folder in the release package directory of the corresponding platform.
+- If the **Compression Type** is set to **Mini Game Subpackage** when configuring the Asset Bundle, this Asset Bundle folder will be packaged into the **subpackages** folder in the release package directory of the corresponding platform.
+
+Each folder contained within these three folders **assets**, **remote** and **subpackages** is an Asset Bundle.
+
+**For example**, if the **cases/01_graphics** folder in the [example-case](https://github.com/cocos/cocos-example-projects) is configured as an Asset Bundle on the Web Mobile platform, then after the project is built, a **01_graphics** folder is generated in the **assets** folder in the release package directory, and the **01_graphics** folder is an Asset Bundle.
+
+
+
+### Scripts in the Asset Bundle
+
+The Asset Bundle supports script subpackaging. If your Asset Bundle includes the script files, then all the scripts will be merged into a single **js** file and removed from the main package. When loading the Asset Bundle, this **js** file will be attempted to be loaded.
+
+> **Notes**:
+> 1. Some platforms do not allow the loading of remote script files, such as the WeChat Mini Game, and Creator will copy the code of the Asset Bundle to the `src/bundle-scripts` directory to ensure normal loading.
+> 2. It is recommended that scripts in the different Asset Bundles do not reference each other, otherwise you may not find the corresponding script at runtime. If you need to reference certain classes or variables, you can share them by exposing them in your own global namespace.
+
+## Load the Asset Bundle
+
+The engine provides a unified API `assetManager.loadBundle` to load the Asset Bundle, which you need to pass in either the Asset Bundle's **URL** or the **Bundle Name** set in the Asset Bundle configuration panel, but if you want to reuse Asset Bundles from other projects, you can only do so through the **URL**. The usage is as follows:
+
+```typescript
+assetManager.loadBundle('01_graphics', (err, bundle) => {
+ bundle.load('xxx');
+});
+
+// Reuse Asset Bundles from other projects
+assetManager.loadBundle('https://othergame.com/remote/01_graphics', (err, bundle) => {
+ bundle.load('xxx');
+});
+```
+
+`assetManager.loadBundle` also supports loading an Asset Bundle from user space with the path in user space. Use the download interface provided by the corresponding platform to pre-download the Asset Bundle into your user space and then use `loadBundle` to load it, so that you can manage the download and cache process of the Asset Bundle by yourself.
+
+```typescript
+// Download an Asset Bundle in advance to the "pathToBundle" directory in your user space, and it's necessary to ensure
+// that the structure and content of the Asset Bundle in your user space is identical to that of the original Asset Bundle.
+// ...
+
+// Load with the path of the Asset Bundle in user space
+// On native platform
+assetManager.loadBundle(jsb.fileUtils.getWritablePath() + '/pathToBundle/bundleName', (err, bundle) => {
+ // ...
+});
+
+// On WeChat Mini Game
+assetManager.loadBundle(wx.env.USER_DATA_PATH + '/pathToBundle/bundleName', (err, bundle) => {
+ // ...
+});
+```
+
+> **Note**: if you check the **Is Remote Bundle** option when configuring the Asset Bundle, then please fill in the **Resource Server Address** in the **Build** panel when building.
+
+When you load the Asset Bundle via the API, instead of loading all the resources in the Asset Bundle, the engine loads the Asset Bundle's **resource manifest** and **all the scripts** it contains.
+When the Asset Bundle is loaded, the engine triggers a callback and returns an error message and an instance of `AssetManager.Bundle` class, which is the main entrance of the Asset Bundle API that can be used to load the various resources in the Asset Bundle.
+
+### Versions of the Asset Bundle
+
+Asset Bundle continues the MD5 scheme of Creator for updates. When you need to update the Asset Bundle on the remote server, check the **MD5 Cache** option in the **Build** panel. Then the filename of the `config.json` in the built Asset Bundle will come with a Hash value. As shown in the following figure:
+
+
+
+It is not necessary to provide an additional Hash value when loading the Asset Bundle, Creator will search for the corresponding Hash value in the `settings.json` and make adjustments automatically.
+However, if you want to store the relevant version configuration information on the server and dynamically fetch the version information at startup for hot updates, you can manually specify a version Hash value and pass in the `loadBundle`, and the Asset Bundle will be built based on the incoming Hash value:
+
+```typescript
+assetManager.loadBundle('01_graphics', {version: 'fbc07'}, function (err, bundle) {
+ if (err) {
+ return console.error(err);
+ }
+ console.log('load bundle successfully.');
+});
+```
+
+Then bypass the old version files in the cache and redownload the latest version of the Asset Bundle.
+
+## Load the resources in the Asset Bundle
+
+After the Asset Bundle is loaded, the engine returns an instance of `AssetManager.Bundle` class. Load the resources in the Asset Bundle by using `load` method of the instance, which has the same arguments as the `resources.load`, you just need to pass in the path of the resource relative to the Asset Bundle, and the end of the path **must not** contain the file extension.
+
+```typescript
+// Load Prefab
+bundle.load(`prefab`, Prefab, function (err, prefab) {
+ let newNode = instantiate(prefab);
+ director.getScene().addChild(newNode);
+});
+
+// Load Texture
+bundle.load(`image/texture`, Texture2D, function (err, texture) {
+ console.log(texture)
+});
+```
+
+Like the `resources.load`, the `load` method also provides a type parameter, which is useful for loading resources with the same name or loading a SpriteFrame.
+
+```typescript
+// Load SpriteFrame
+bundle.load(`image/spriteFrame`, SpriteFrame, function (err, spriteFrame) {
+ console.log(spriteFrame);
+});
+```
+
+### Bulk load resources
+
+The Asset Bundle provides `loadDir` method to bulk load multiple resources in the same directory. The arguments of this method are similar to the `resources.loadDir`, you just need to pass in the path of the directory relative to the Asset Bundle.
+
+```typescript
+// Load all resources in the "textures" directory
+bundle.loadDir("textures", function (err, assets) {
+ // ...
+});
+
+// Load all Texture resources in the "textures" directory
+bundle.loadDir("textures", Texture2D, function (err, assets) {
+ // ...
+});
+```
+
+### Load scenes
+
+The Asset Bundle provides `loadScene` methods for loading scenes from the specified bundle, you just need to pass in the **scene name**.
+The difference between `loadScene` and `director.loadScene` is that `loadScene` will only load the scene from the specified bundle and will not run the scene, you also need to use `director.runScene` to run the scene.
+
+```typescript
+bundle.loadScene('test', function (err, scene) {
+ director.runScene(scene);
+});
+```
+
+## Get the Asset Bundle
+
+After the Asset Bundle has been loaded, it will be cached, and the name can be used to get the Asset Bundle. For example:
+
+```typescript
+let bundle = assetManager.getBundle('01_graphics');
+```
+
+## Preload resources
+
+In addition to scenes, other resources can also be preloaded. The loading arguments for preloading are the same as for normal loading, but because preloading only downloads the necessary resources, and does not perform the resources' deserialization and initialization, so it consumes less performance and is suitable for use during gameplay.
+
+The Asset Bundle provides `preload` and `preloadDir` interfaces to preload the resources in the Asset Bundle, which are used in the same way as the `assetManager`, see [Loading and Preloading](preload-load.md) documentation for details.
+
+## Release resources in the Asset Bundle
+
+After loading the resources, all the resources are temporarily cached in `assetManager` to avoid reloading. Of course, the resources in the cache also occupy memory, and some resources you can release in the following three ways if they are no longer needed:
+
+1. Use the regular `assetManager.releaseAsset` method for release.
+
+ ```typescript
+ bundle.load(`image/spriteFrame`, SpriteFrame, function (err, spriteFrame) {
+ assetManager.releaseAsset(spriteFrame);
+ });
+ ```
+
+2. Use `release` method provided by the Asset Bundle, then pass in the path and type to release resources, but can only release the single resource in the Asset Bundle. The arguments can be the same as those used in the `load` method of the Asset Bundle.
+
+ ```typescript
+ bundle.load(`image/spriteFrame`, SpriteFrame, function (err, spriteFrame) {
+ bundle.release(`image`, SpriteFrame);
+ });
+ ```
+
+3. Use `releaseAll` method provided by the Asset Bundle, which is similar to the `assetManager.releaseAll`, but the `releaseAll` will release all resources that belong to the Asset Bundle (including resources in the Asset Bundle and the related dependent resources outside the Asset Bundle), so please use caution.
+
+ ```typescript
+ bundle.load(`image/spriteFrame`, SpriteFrame, function (err, spriteFrame) {
+ bundle.releaseAll();
+ });
+ ```
+
+> **Note**: when releasing a resource, Creator will automatically handle the resource's dependent resources, and you don't need to manage their dependency resources.
+
+For more information about releasing resources, see [Release of Resources](release-manager.md) documentation.
+
+## Remove the Asset Bundle
+
+After the Asset Bundle is loaded, it will remain in the entire gameplay, unless you manually remove it from the game. When an unneeded Asset Bundle is manually removed, the cache for the bundle is also removed. If you need to use it again, you must reload it again.
+
+```typescript
+let bundle = assetManager.getBundle('bundle1');
+assetManager.removeBundle(bundle);
+```
+
+> **Note**: when you destroy an Asset Bundle, the resources already loaded in the bundle are not released. If you need to release it, use the Asset Bundle's `release`/`releaseAll` method first.
+
+```typescript
+let bundle = assetManager.getBundle('bundle1');
+// Releases a single resource in the Asset Bundle.
+bundle.release(`image`, SpriteFrame);
+assetManager.removeBundle(bundle);
+
+let bundle = assetManager.getBundle('bundle1');
+// Releases all resources belonging to the Asset Bundle.
+bundle.releaseAll();
+assetManager.removeBundle(bundle);
+```
+
+## Bundle Filter Config
+
+The **Build Filter Config** allows you to config the selected bundle, and choose which asset should be included or excluded from the bundle.
+
+
+
+### Filter Type
+
+There are two types of filters, **Asset** and **URL**, the default value is **URL**.
+
+
+
+- **Asset**: Take an asset as a filter type. Drag an asset from the **Assets** panel or click the lock button  to select one.
+- **ULR**: Filter all assets in the selected bundle according to one of the four rules including **Glob Expression**, **Begin With**, **End With**, and **Containing**. After the rule is set, type any string in the right input box to filter assets.
+
+ 
+
+| Rule | Description |
+| :---| :---|
+| **Glob** | Glob Expression which can be referred by [npm](https://www.npmjs.com/package/glob).|
+| **Begin With** | Filter all assets beginning with what is in the input-box |
+| **End With** | Filter all assets end with what is in the input-box |
+| **Containing** | Filter all assets containing what in the input box |
+
+To add a new filter rule, click the "+" button on the right.
+Click the "-" button to delete the last added or selected rule.
+
+### Include
+
+A **Include** rule will include all the assets it configs.
+
+### Exclude
+
+A **Exclude** rule will exclude all the assets that meet the rule out of the bundle.
+
+### Preview
+
+Click the **Preview** button to preview all the assets in the bundle.
+
+## Build Bundle
+
+Since v3.8, Cocos Creator supports the Build Bundle feature which allows the users can build a specified bundle instead of building all the asset bundles.
+
+To open the **Build Bundle** panel, after selecting a bundle, click the **Build Bundle** button at the bottom of the **Inspector** panel.
+
+
+
+You need to have at least one build task to build a bundle. Click the **Open Build Panel** button to create a new build task.
+
+
+
+After a build task is created, now you can see the build bundle panel.
+
+
+
+Select a bundle from the drop-down list, and click the **Build** button at the bottom, and the Bundle will be built to the specified **Build Path**.
+
+
+
+There are two types of **Build Path**.
+
+
+
+- file: The absolute path of the output bundle.
+- project: A related path based on the project.
+
+
+
+To select a different path, click the selected button , or after the build task is finished, use the open button  to locate the output directory.。
+
+Select platforms to build on the **Publish Config** list.
+
+
+
+After clicking the **Build** button, it can be canceled by clicking on the **Cancel** button.
+
+
+
+This feature is designed for big projects or some time-consuming bundles. Developers can build these bundles separately to reduce the build time.
+
+### Bundle Build via Command Line
+
+Please refer to [Executing Independent Release Bundle in Command Line](./../editor/publish/publish-in-command-line.md) for details.
+
+## FAQ
+
+- **Q**: What is the difference between Asset Bundle and resource subpackage?
+ **A**:
+ 1. Resource subpackage is actually splitting out some textures, meshes into a separate packages, but the package is incomplete and illogical and cannot be reused.
+ while Asset Bundle is modularizing resources through logical division. The Asset Bundle includes resources, scripts, metadata and resource lists, so it is complete, logical and reusable, and we can load an entire scene or any other resources from Asset Bundle. By splitting the Asset Bundle, you can greatly reduce the number of `json` and the size of `settings.json` in the first package.
+
+ 2. Resource subpackage is essentially a basic function controlled by the mini game platform. For example, the WeChat Mini Game supports subpackage, and then Creator made a layer of encapsulation on top of that to help the developers set up resource subpackage. If the WeChat Mini Game doesn't support subpackage anymore, neither does Creator.
+ While the Asset Bundle is designed and implemented entirely by Creator, it is a modular tool to help developers divide their resources, independent of the platform, and can theoretically be supported on all platforms.
+
+ 3. Resource subpackage is related to the platform, meaning that it needs to be set up in the way required by the platform. For example, the subpackage of the WeChat Mini Game cannot be placed on the remote server, and can only be placed on Tencent's server.
+ While the Asset Bundle doesn't have these restrictions, the Asset Bundle can be placed locally, on a remote server, or even in a subpackage of the WeChat Mini Game.
+
+- **Q**: Does the Asset Bundle support the lobby plus sub games mode?
+ **A**: Absolutely, subgame scenes can be placed in the Asset Bundle and loaded when needed, and subgames can even be pre-built as an Asset Bundle in other projects and then loaded for use in the main project.
+
+- **Q**: Can the Asset Bundle reduce the size of `settings.json`?
+ **A**: Absolutely. In fact, as of v2.4, the packaged project is entirely based on the Asset Bundle, and the `settings.json` no longer stores any configuration information related to the resource, all configuration information are stored in the `config.json` of each Asset Bundle. Each `config.json` stores only the resource information in the respective Asset Bundle, which reduces the size of the first package. This can simply be understood as all the `config.json` combined equal to the previous `settings.json`.
+
+- **Q**: Does the Asset Bundle support cross project reuse?
+ **A**: The current version supports it, but we **do not recommend reusing**across projects. As the engine is updated and iterated, this can create all kinds of compatibility issues. cross-project reuse requires the following conditions to be met for now:
+ 1. The engine version is the same
+ 2. All scripts referenced in the Asset bundle are placed under the Asset bundle.
+ 3. The Asset Bundle has no other external dependency bundle, and if it does, it must be loaded.
+ 4. No reuse of scripts between Asset Bundles where possible
+
+- **Q**: Does the Asset Bundle support split first scene?
+ **A**: Currently only supported on mini game platforms. You can check the **Start Scene Asset Bundle** in the **Build** panel and the first scene will be put into the `start-scene` of the built-in Asset Bundle to separate the first scene.
+
+- **Q**: Does the Asset Bundle support nesting? For example, if there is a folder B in folder A, can both A and B be set as Asset Bundle?
+ **A**: Asset Bundle does not support nesting, please avoid using it as such.
+
+- **Q**: Why might placing an atlas inside an Asset Bundle cause the package to grow larger?
+ **A**:**When an atlas is placed in Bundle, by default the SpriteAtlas itself, the image of the atlas, the small image in the atlas folder, etc., may be loaded by the script, and all the resources contained in the Bundle will be packaged according to the established rules**. Therefore, it is not recommended to put the atlas directly in the Bundle, but to package it naturally into the final Asset Bundle by reference to the resources in the Bundle. There are currently some culling configurations open on the atlas resources, so if you really need to place them in the Bundle folder, you can do so as needed.
diff --git a/versions/4.0/en/asset/bundle/build-budle-withtask.png b/versions/4.0/en/asset/bundle/build-budle-withtask.png
new file mode 100644
index 0000000000..44a1b1cfa3
Binary files /dev/null and b/versions/4.0/en/asset/bundle/build-budle-withtask.png differ
diff --git a/versions/4.0/en/asset/bundle/build-path.png b/versions/4.0/en/asset/bundle/build-path.png
new file mode 100644
index 0000000000..53f4d12713
Binary files /dev/null and b/versions/4.0/en/asset/bundle/build-path.png differ
diff --git a/versions/4.0/en/asset/bundle/build-task.png b/versions/4.0/en/asset/bundle/build-task.png
new file mode 100644
index 0000000000..5fdce6b94d
Binary files /dev/null and b/versions/4.0/en/asset/bundle/build-task.png differ
diff --git a/versions/4.0/en/asset/bundle/building.png b/versions/4.0/en/asset/bundle/building.png
new file mode 100644
index 0000000000..841d3c6093
Binary files /dev/null and b/versions/4.0/en/asset/bundle/building.png differ
diff --git a/versions/4.0/en/asset/bundle/builtin-bundles.png b/versions/4.0/en/asset/bundle/builtin-bundles.png
new file mode 100644
index 0000000000..cc1447e38c
Binary files /dev/null and b/versions/4.0/en/asset/bundle/builtin-bundles.png differ
diff --git a/versions/4.0/en/asset/bundle/bundle-build.png b/versions/4.0/en/asset/bundle/bundle-build.png
new file mode 100644
index 0000000000..5f71ba2e43
Binary files /dev/null and b/versions/4.0/en/asset/bundle/bundle-build.png differ
diff --git a/versions/4.0/en/asset/bundle/export-config.png b/versions/4.0/en/asset/bundle/export-config.png
new file mode 100644
index 0000000000..ae97c802fa
Binary files /dev/null and b/versions/4.0/en/asset/bundle/export-config.png differ
diff --git a/versions/4.0/en/asset/bundle/exported.png b/versions/4.0/en/asset/bundle/exported.png
new file mode 100644
index 0000000000..a0591ef16e
Binary files /dev/null and b/versions/4.0/en/asset/bundle/exported.png differ
diff --git a/versions/4.0/en/asset/bundle/filter-rule.png b/versions/4.0/en/asset/bundle/filter-rule.png
new file mode 100644
index 0000000000..e70f232a6f
Binary files /dev/null and b/versions/4.0/en/asset/bundle/filter-rule.png differ
diff --git a/versions/4.0/en/asset/bundle/filter-type.png b/versions/4.0/en/asset/bundle/filter-type.png
new file mode 100644
index 0000000000..7b6165f841
Binary files /dev/null and b/versions/4.0/en/asset/bundle/filter-type.png differ
diff --git a/versions/4.0/en/asset/bundle/filter.png b/versions/4.0/en/asset/bundle/filter.png
new file mode 100644
index 0000000000..345a7b4f44
Binary files /dev/null and b/versions/4.0/en/asset/bundle/filter.png differ
diff --git a/versions/4.0/en/asset/bundle/lock.png b/versions/4.0/en/asset/bundle/lock.png
new file mode 100644
index 0000000000..53b80d9934
Binary files /dev/null and b/versions/4.0/en/asset/bundle/lock.png differ
diff --git a/versions/4.0/en/asset/bundle/open.png b/versions/4.0/en/asset/bundle/open.png
new file mode 100644
index 0000000000..5d607f2318
Binary files /dev/null and b/versions/4.0/en/asset/bundle/open.png differ
diff --git a/versions/4.0/en/asset/bundle/select-bundle.png b/versions/4.0/en/asset/bundle/select-bundle.png
new file mode 100644
index 0000000000..68c16b4385
Binary files /dev/null and b/versions/4.0/en/asset/bundle/select-bundle.png differ
diff --git a/versions/4.0/en/asset/bundle/select-open.png b/versions/4.0/en/asset/bundle/select-open.png
new file mode 100644
index 0000000000..4f61abe38a
Binary files /dev/null and b/versions/4.0/en/asset/bundle/select-open.png differ
diff --git a/versions/4.0/en/asset/bundle/select.png b/versions/4.0/en/asset/bundle/select.png
new file mode 100644
index 0000000000..f8932354f1
Binary files /dev/null and b/versions/4.0/en/asset/bundle/select.png differ
diff --git a/versions/4.0/en/asset/bundle/shared.png b/versions/4.0/en/asset/bundle/shared.png
new file mode 100644
index 0000000000..2c000537fd
Binary files /dev/null and b/versions/4.0/en/asset/bundle/shared.png differ
diff --git a/versions/4.0/en/asset/bundle/shared2.png b/versions/4.0/en/asset/bundle/shared2.png
new file mode 100644
index 0000000000..353024dd05
Binary files /dev/null and b/versions/4.0/en/asset/bundle/shared2.png differ
diff --git a/versions/4.0/en/asset/bundle/task.png b/versions/4.0/en/asset/bundle/task.png
new file mode 100644
index 0000000000..5f9390ab21
Binary files /dev/null and b/versions/4.0/en/asset/bundle/task.png differ
diff --git a/versions/4.0/en/asset/cache-manager.md b/versions/4.0/en/asset/cache-manager.md
new file mode 100644
index 0000000000..44ae6b6e5f
--- /dev/null
+++ b/versions/4.0/en/asset/cache-manager.md
@@ -0,0 +1,105 @@
+# Cache Manager
+
+> Author: Santy-Wang, Xunyi
+
+On the Web platforms, after resources are downloaded, the cache is managed by the browser, not the engine.
+On some non-Web platforms, such as WeChat Mini Game, such platforms have a file system that can be used to cache some remote resources but do not implement a caching mechanism for the resources. In this case, the engine needs to implement a set of caching mechanisms to manage the resources downloaded from the network, including caching resources, clearing cached resources, querying cached resources, and other features.
+
+Starting from v2.4, Creator provides a cache manager on all platforms with file systems to add, delete, and check caches, which can be accessed by developers through `assetManager.cacheManager`.
+
+## Resource downloading, caching and versioning
+
+The logic of downloading resources by the engine is as follows:
+
+1. Determine whether the resource is in the game package, and if so, use it directly.
+
+2. If not, query whether the resource is in the local cache, and if so, use it directly.
+
+3. If not, query if the resource is in the temporary directory, and if so, use it directly (the native platform does not have a temporary directory, skip this step).
+
+4. If not, download the resource from the remote server and use it directly after it is downloaded to the temporary directory (the native platform downloads the resource to the cache directory).
+
+5. The backend slowly saves the resources in the temporary directory to the local cache directory to be used when accessed again (the native platform skips this step)
+
+6. The resources will fail to be saved when the cache space is full, at which point the older resources will be deleted using the LRU algorithm (the native platform has no size limit on the cache space, so skip this step, and developers can manually invoke cleanup).
+
+For the mini-game platform, once the cache space is full, all resources that need to be downloaded cannot be saved, and only resources downloaded and saved in the temporary directory can be used. And when quitting the mini-game, all temporary directories will be cleaned up, and when running the game again, these resources will be downloaded again, and so on and so forth.
+
+> **Note**: the problem of file saving failure due to cache space exceeding the limit does not occur on WeChat Mini Game's **WeChat DevTools**, because WeChat DevTools does not limit the cache size, so testing the cache needs to be done in a real WeChat environment.
+
+When the engine's **md5Cache** feature is enabled, the URL of the file will change with the content of the file, so that when a new version of the game is released, the resources of the old version will be naturally invalidated in the cache and only new resources can be requested from the server, which also achieves the effect of versioning.
+
+### Uploading resources to a remote server
+
+When the package is too large (in size), it is necessary to upload resources to a remote server and configure the Asset Bundle where the resources are located as a remote package. Next, taking the WeChat Mini Game as an example, and look at the specific steps:
+
+1. Reasonably allocate resources, configure the resource folder that needs to be managed modularly as Asset Bundles, and check **Is Remote Bundle**. For additional details, please refer to the [Configure Asset Bundle](./bundle.md#configuration) documentation.
+
+ 
+
+2. If the main bundle needs to be configured as a remote bundle, check **Main Bundle is Remote** in the **Build** panel.
+
+3. Then check **MD5 Cache** in the **Build** panel, set **Resource Server Address**, and click **Build**.
+
+4. After the build is complete, upload the `remote` folder in the release package directory to the server which is filled in the previous step.
+
+5. Delete the `remote` folder from the local release package directory.
+
+> **Note**: During the testing phase of WeChat Mini Games, developers may not be able to deploy the project to the official server, and need to test it on the local server. Please open **Tools -> Details -> Local Settings** page in the menu bar of WeChat DevTools, and check the **Does not verify valid domain names, web-view (business domain names), TLS versions and HTTPS certificates** option.
+>
+> 
+
+### Querying cache files
+
+The cache manager provides the `getCache` interface to query all cached resources, and developers can query the cache path by passing in the original path of the resource.
+
+```typescript
+resources.load('images/background/texture', Texture2D, function (err, texture) {
+ const cachePath = assetManager.cacheManager.getCache(texture.nativeUrl);
+ console.log(cachePath);
+});
+```
+
+### Querying temporary files
+
+When a resource is downloaded locally, it may be stored as a temporary file in a temporary directory. The cache manager provides the `tempFiles` interface to query all resources downloaded into the temporary directory, and developers can do so by passing in the original path of the resource.
+
+```typescript
+assetManager.loadRemote('http://example.com/background.jpg', function (err, texture) {
+ const tempPath = assetManager.cacheManager.getTemp(texture.nativeUrl);
+ console.log(tempPath);
+});
+```
+
+## Caching resources
+
+A number of parameters are provided in the cache manager to control the caching of resources:
+
+- `cacheManager.cacheDir` -- controls the directory where the cached resources are stored.
+- `cacheManager.cacheInterval` -- controls the period of caching a single resource, default 500 ms once.
+- `cacheManager.cacheEnabled` -- controls whether to cache the resource, default is cache. Alternatively, developers can override the global setting by specifying the optional parameter `cacheEnabled`. Example:
+
+ ```typescript
+ assetManager.loadRemote('http://example.com/background.jpg', {cacheEnabled: true}, callback);
+ ```
+
+### Clearing cache resources
+
+If the cache resource exceeds the limit and the developer needs to clear the resource manually, use `removeCache`, `clearCache`, `clearLRU` provided by the cache manager `assetManager.cacheManager` to clear the cache resource.
+
+- `clearCache` -- clears all cache resources in the cache directory, please use with caution.
+- `clearLRU` -- clears the older resources in the cache directory. The mini-game platform will automatically call `clearLRU` when the cache space is full.
+- `removeCache` -- clears a single cache resource. To use it, provide the original path of the resource. Example:
+
+ ```typescript
+ assetManager.loadRemote('http://example.com/background.jpg', function (err, texture) {
+ assetManager.cacheManager.removeCache(texture.nativeUrl);
+ });
+ ```
+
+When the developer upgrades the engine version, the cached resources left locally are still the resources corresponding to the previous old version of the engine and are not automatically cleared. This may lead to problems such as errors in loading or rendering of resources. There are two solutions:
+
+1. Check the **MD5 Cache** option in the **Build** panel at build time, which will ensure that the latest version of resources are used.
+2. Manually clear the previously cached resources.
+ - Clear the cache with `assetManager.cacheManager.clearCache()` on the **physical device**.
+ - For WeChat Mini Game, clear the cache by clicking **Tools -> Clear Cache -> Clear All** in the menu bar in **WeChat DevTools**.
diff --git a/versions/4.0/en/asset/cache-manager/details.png b/versions/4.0/en/asset/cache-manager/details.png
new file mode 100644
index 0000000000..63d84ed764
Binary files /dev/null and b/versions/4.0/en/asset/cache-manager/details.png differ
diff --git a/versions/4.0/en/asset/cache-manager/remote-bundle.png b/versions/4.0/en/asset/cache-manager/remote-bundle.png
new file mode 100644
index 0000000000..cecc1ef8e0
Binary files /dev/null and b/versions/4.0/en/asset/cache-manager/remote-bundle.png differ
diff --git a/versions/4.0/en/asset/compress-texture.md b/versions/4.0/en/asset/compress-texture.md
new file mode 100644
index 0000000000..7c1cdac378
--- /dev/null
+++ b/versions/4.0/en/asset/compress-texture.md
@@ -0,0 +1,105 @@
+# Compressed Textures
+
+Cocos Creator allows you to directly set the compression method for textures in the editor, and then automatically compresses textures during project publishing. It supports exporting multiple image formats for the same platform simultaneously, and the engine will load the appropriate compressed texture based on the device's support for compressed texture formats.
+
+## Advantages of Compressed Textures
+
+* For compressed textures like PNG, JPG, WEBP, etc.
+ - Configuring compressed textures allows compressing texture pixel data during project build to reduce resource size and improve game resource download speed.
+* For GPU compressed textures like ASTC, ETC1, ETC2, PVRTC, etc.
+ - Configuring compressed textures allows converting texture pixel data into GPU-specific compressed formats during project build. These formats can be used directly in GPU memory without runtime decompression, significantly reducing memory usage, lowering bandwidth requirements, and improving game rendering performance and loading speed.
+
+> **Note**:
+> * For non-GPU compressed texture formats like PNG, JPG, WEBP, compressing image quality does not reduce the time to decode image resources or reduce game memory.
+> * Compressing PNG, JPG, WEBP and other format images uses the [sharp](https://github.com/lovell/sharp) open source library. Its compression ratio is slightly lower than [tinypng](https://tinypng.com/) and may result in larger images after compression. If you need to optimize this issue, it is recommended to use [Custom Texture Compression](../editor/publish/custom-build-plugin.md#custom-texture-compression-processing) to solve it yourself.
+
+## Compressed Texture Support
+
+Cocos Creator supports loading images in various formats (see table below for details).
+
+| Image Format | Android | iOS | Mini Games | Web | Windows | Mac |
+| :----------- | :------ | :-- | :--------- | :-- | :------ | :-- |
+| PNG | Supported | Supported | Supported | Supported | Supported | Supported |
+| JPG | Supported | Supported | Supported | Supported | Supported | Supported |
+| WEBP | Natively supported on Android 4.0+, other versions can use [parsing library](https://github.com/alexey-pelykh/webp-android-backport) | Can use [parsing library](https://github.com/carsonmcdonald/WebP-iOS-example) | Supported | [Partially supported](https://caniuse.com/#feat=webp) | Not supported | Not supported |
+| PVR | Not supported | Supported | Supported on iOS devices | Supported on iOS devices | Not supported | Not supported |
+| ETC1 | Supported | Not supported | Supported on Android devices | Supported on Android devices | Not supported | Not supported |
+| ETC2 | Partially supported, depends on mobile hardware | Not supported | Not supported | Supported on some Android devices | Not supported | Not supported |
+| ASTC | Supported (Android 5.0+) | Supported (iOS 9.0+/iPhone6+) | Supported on platforms like WeChat, Douyin, Alipay, Taobao, etc. For details, see [Compressed Texture Support Details for Each Platform](#Compressed-Texture-Support-Details-for-Each-Mobile-Platform). Note: Developer tools do not support, requires real device debugging | Partially supported | Not supported | Not supported |
+
+### Compressed Texture Support Details for Each Mobile Platform
+
+In addition to `JPG` and `PNG` which are supported across all platforms, the support for other texture compression formats is as follows:
+
+| Platform Name | Supported Compression Formats |
+| :------------ | :---------------------------- |
+| Web Mobile | ASTC / ETC1 / ETC2 / PVR / WEBP |
+| WeChat Mini Game | ASTC / ETC1 / ETC2 / PVR |
+| ByteDance Mini Game | ASTC / ETC1 / ETC2 / PVR |
+| Alipay Mini Game | ASTC / ETC1 / PVR |
+| Taobao Mini Game | ASTC / ETC1 / PVR |
+| OPPO Mini Game | ETC1 |
+| vivo Mini Game | ETC1 / ASTC |
+| Huawei Quick Game | ETC1 |
+| iOS | ASTC / ETC1 / ETC2 / PVR / WEBP |
+| Android / Huawei AGC | ASTC / ETC1 / ETC2 / WEBP |
+
+**Note**: Currently, adding ASTC compressed textures in the general configuration for mini game platforms temporarily does not support the vivo mini game platform, but you can use [Platform Override Configuration](#platform-override-configuration) to enable ASTC compressed textures for the vivo mini game platform as well.
+
+## About ASTC
+
+For projects that require GPU compressed texture formats, it is recommended to use the ASTC compression format because it has high compression ratio and better quality, while also supporting HDR textures. ASTC was released in 2012, 12 years ago, and has nearly 100% support rate on mobile devices.
+
+For games with higher quality requirements, you can choose ASTC 5x5 for 2D elements and UI, and ASTC 6x6 for model textures.
+
+For games with lower quality requirements, you can choose 6x6 for 2D elements and UI, and 8x8 for model textures.
+
+## Compressed Texture Configuration
+
+When no compressed texture configuration is set, the project build outputs the original images. If you need to compress image resources in the project or large images generated by auto-atlas, you can select the image or auto-atlas in the **Assets Manager**, then check `useCompressTexture` in the **Inspector**, and select the texture compression preset for the image in `presetId`. After setting, click the green checkmark button in the upper right corner, and then the image resource will become a compressed texture resource after project build.
+
+
+
+When configuring compressed texture presets, platform general configuration is used by default. This configuration will stop generating compressed textures of this format based on whether the build platform supports the configured compressed texture format.
+
+`presetId` provides the editor's default compressed texture presets, which cannot be edited. If you need to customize presets, click the **Edit Preset** button next to `presetId` to go to the [Project Settings -> Compressed Textures](../editor/project/index.md#compressed-textures) panel for configuration.
+
+The compressed texture options on image resources will be stored in the resource meta file, where `presetId` is the ID of the selected compressed texture preset. Projects with many images can manage the `presetId` used for image compression in batches through plugins or scripts.
+
+
+
+**Note**:
+After configuring compressed textures, only images of the corresponding format will be generated during build. If some image formats are not supported on certain devices, it may cause display abnormalities. To avoid this problem, when adding texture compression presets, please additionally select some general image formats (such as PNG, JPG) as default images.
+
+## Platform Override Configuration
+When configuring compressed texture presets for mini game platforms, if developers need to ignore internal rules to ensure that configured compressed texture resources are generated during build, they need to add platform override configuration.
+
+
+
+## Compressed Texture Details
+
+Cocos Creator 3.0, when building images, will check whether the current image has compressed texture configuration. If not, it will output the original image.
+
+If compressed texture configuration is found, it will perform texture compression on the image according to the found configuration. The compressed texture configuration in project settings is divided by platform categories, and there may be some differences in the actual support level for specific platforms. The build will perform certain filtering and priority selection on the configured texture formats based on the **actual build platform** and the current **transparency channel situation of the image texture**. You can refer to the examples below to understand these rules.
+
+Not all generated images will be loaded into the engine. The engine will select and load images of appropriate formats based on the configuration in [macro.SUPPORT_TEXTURE_FORMATS](%__APIDOC__%/en/interface/Macro?id=SUPPORT_TEXTURE_FORMATS). `macro.SUPPORT_TEXTURE_FORMATS` lists all image formats supported by the current platform. When loading images, the engine will find the format that is **higher in priority** (i.e., ranked higher) in this list from the generated images to load.
+
+Developers can modify `macro.SUPPORT_TEXTURE_FORMATS` to customize the image resource support situation of the platform and the loading order priority.
+
+## Smart Filtering
+
+### Example 1
+
+
+
+As shown in the figure above, for the compressed texture preset of the MiniGame platform, if **building for Huawei Quick Game or other platforms that only run on Android devices, PVR texture format will not be packaged during build**. For more platform filtering details, please refer to the [Compressed Texture Support Details for Each Platform](#Compressed-Texture-Support-Details-for-Each-Mobile-Platform) at the end of the document.
+
+### Example 2
+
+
+
+In the example diagram above, both ETC1 and PVR types have **configured both RGB and RGBA texture formats simultaneously. In this case, the build will prioritize one of the formats based on whether the current image has a transparency channel**. The image in the example diagram has a transparency channel, so the build will only package compressed texture formats with RGBA type. Of course, this filtering only occurs when both exist. If only RGB image format is configured in the configuration, even if the current image has a transparency channel, it will be packaged normally.
+
+## Custom Build Texture Compression Processing
+
+Texture compression currently takes effect after build, and the editor comes with a set of processing tools. If you need to customize compression tools, please refer to [Custom Texture Compression](../editor/publish/custom-build-plugin.md#custom-texture-compression-processing).
diff --git a/versions/4.0/en/asset/compress-texture/compress-1.png b/versions/4.0/en/asset/compress-texture/compress-1.png
new file mode 100644
index 0000000000..884bf938f6
Binary files /dev/null and b/versions/4.0/en/asset/compress-texture/compress-1.png differ
diff --git a/versions/4.0/en/asset/compress-texture/compress-2.png b/versions/4.0/en/asset/compress-texture/compress-2.png
new file mode 100644
index 0000000000..637aad67e6
Binary files /dev/null and b/versions/4.0/en/asset/compress-texture/compress-2.png differ
diff --git a/versions/4.0/en/asset/compress-texture/compress-3.jpg b/versions/4.0/en/asset/compress-texture/compress-3.jpg
new file mode 100644
index 0000000000..9c84cd6324
Binary files /dev/null and b/versions/4.0/en/asset/compress-texture/compress-3.jpg differ
diff --git a/versions/4.0/en/asset/compress-texture/compress-texture.png b/versions/4.0/en/asset/compress-texture/compress-texture.png
new file mode 100644
index 0000000000..7f6da63642
Binary files /dev/null and b/versions/4.0/en/asset/compress-texture/compress-texture.png differ
diff --git a/versions/4.0/en/asset/compress-texture/meta.png b/versions/4.0/en/asset/compress-texture/meta.png
new file mode 100644
index 0000000000..e53caa434e
Binary files /dev/null and b/versions/4.0/en/asset/compress-texture/meta.png differ
diff --git a/versions/4.0/en/asset/downloader-parser.md b/versions/4.0/en/asset/downloader-parser.md
new file mode 100644
index 0000000000..5f61d5d993
--- /dev/null
+++ b/versions/4.0/en/asset/downloader-parser.md
@@ -0,0 +1,167 @@
+# Download and Parse
+
+> Author: Santy-Wang, Xunyi
+
+The underlying of the Asset Manager uses multiple loading pipelines to load and parse resources, each of which uses the `downloader` and `parser` modules, that is, the downloader and the parser. You can access them via `assetManager.downloader` and `assetManager.parser`.
+
+## Downloader
+
+The downloader is a global single instance with features such as download retry, download priority, and download concurrency limits.
+
+### Download retry
+
+If the downloader fails to download a resource, it will automatically retry the download, and you can set the parameters for the download retry via `maxRetryCount` and `retryInterval`.
+
+- `maxRetryCount` is used to set the maximum number of retry downloads, the default is 3. If you do not need to retry the download, set to 0 and an error will be returned immediately if the download fails.
+
+ ```typescript
+ assetManager.downloader.maxRetryCount = 0;
+ ```
+
+- `retryInterval` is used to set the interval of retry downloads, the default is 2000 ms. If it is set to 4000 ms, it will wait for 4000 ms before re-downloading if the download fails.
+
+ ```typescript
+ assetManager.downloader.retryInterval = 4000;
+ ```
+
+### Download priority
+
+Creator opens up four download priorities, and the downloader will download resources in **descending order** of priority.
+
+| Resource | Priority | Explanation |
+| :-- | :---- | :--- |
+| **Script or Asset Bundle** | 2 | Highest priority first |
+| **Scene resource** | 1 | Include all resources in the scene, ensuring that the scene loads quickly |
+| **Manually loaded resource** | 0 | |
+| **Preload resource** | -1 | The lowest priority, because preloading is more like loading resources in advance, and time requirements are relatively lenient |
+
+You can also control the load order by passing a priority over the default setting with the optional parameter `priority`. For details, refer to the "Set by optional parameters" section below.
+
+### Set the number of concurrent downloads
+
+You can set limits such as the maximum number of concurrent downloads in the downloader via `maxConcurrency` and `maxRequestsPerFrame`.
+
+- `maxConcurrency` is used to set the maximum number of concurrent connections for the download, if the current number of connections exceeds the limit, a waiting queue will be entered.
+
+ ```typescript
+ assetManager.downloader.maxConcurrency = 10;
+ ```
+
+- `maxRequestsPerFrame` is used to set the maximum number of requests that can be initiated per frame, which spreads the CPU overhead of initiating requests, avoiding too much jams in a single frame. If the maximum number of connections initiated in this frame has been reached, the request will be delayed until the next frame.
+
+ ```typescript
+ assetManager.downloader.maxRequestsPerFrame = 6;
+ ```
+
+In addition, `downloader` uses an instance of the `jsb.Downloader` class to download resources from the server on **native platforms**. `jsb.Downloader` is similar to the Web's [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest). Currently the `jsb.Downloader` class instances have a default download concurrency limit of **32** and a default timeout of **30s**, if you want to change the default values, you can do so in `main.js`.
+
+```typescript
+// main.js
+assetManager.init({
+ bundleVers: settings.bundleVers,
+ remoteBundles: settings.remoteBundles,
+ server: settings.server,
+ jsbDownloaderMaxTasks: 32, // Max concurrency
+ jsbDownloaderTimeout: 60 // Timeout
+});
+```
+
+## Parser
+
+The parser is used to parse the files into the resources that can be recognized by the engine, and you can access them via `assetManager.parser`.
+
+## Set by optional parameters
+
+The settings in both the downloader and the parser are global, if you need to set up a resource individually, you can override the global settings by passing in the proprietary settings via the optional parameters. For example:
+
+```typescript
+assetManager.loadAny({'path': 'test'}, {priority: 2, maxRetryCount: 1, maxConcurrency: 10}, callback);
+```
+
+For details, refer to the [Optional Parameters](options.md) documentation.
+
+## Preset
+
+Creator presets the download/parsing parameters for the six load cases: normal loading, preloading, scene loading, Asset Bundle loading, remote resource loading, and script loading, and preloading is more restrictive because of performance considerations, and the maximum number of concurrency is smaller. As shown below:
+
+```typescript
+{
+ 'default': {
+ priority: 0,
+ },
+
+ 'preload': {
+ maxConcurrency: 2,
+ maxRequestsPerFrame: 2,
+ priority: -1,
+ },
+
+ 'scene': {
+ maxConcurrency: 8,
+ maxRequestsPerFrame: 8,
+ priority: 1,
+ },
+
+ 'bundle': {
+ maxConcurrency: 8,
+ maxRequestsPerFrame: 8,
+ priority: 2,
+ },
+
+ 'remote': {
+ maxRetryCount: 4
+ },
+
+ 'script': {
+ priority: 2
+ }
+}
+```
+
+In addition to the above, you can also set each preset via `assetManager.presets`. Note that the restrictions can be different for each preset, so `presets` is a table and you need to pass the name of the preset to access the corresponding parameter options, for example:
+
+```typescript
+// Modify the preset priority of the preload to 1.
+let preset = assetManager.presets.preload;
+preset.priority = 1;
+```
+
+You can also add custom presets and pass them in with the optional parameter `preset`.
+
+```typescript
+// Customize the preset and pass it in with the optional parameter preset.
+assetManager.presets.mypreset = {maxConcurrency: 10, maxRequestsPerFrame: 6};
+assetManager.loadAny({'path': 'test'}, {preset: 'mypreset'}, callback);
+```
+
+> **Note**: parameters related to the download and parsing process (e.g.: number of download concurrent, number of download retries, etc.) can be set via optional parameters, presets, and the downloader/parser itself. When the same parameter is set in multiple ways, the engine selects to use it in the order of selectable **optional parameter > preset > downloader/parser**. That is, if the engine can't find the relevant settings in the optional parameter, it will look in the preset, and if it can't find them in the preset, it will look in the downloader/parser.
+
+## Custom handlers
+
+Both the downloader and the parser have a registration table. When you use `downloader` or `parser`, the downloader and parser will look for the corresponding download and parsing methods in the registry based on the incoming suffix name, and pass the parameters into the corresponding handler, in order to extend the engine by registering the custom handlers when you need to add a custom format to your project, or modify the handlers of the current format. Both the downloader and the parser provide `register` interfaces for registration handlers, which are used as follows:
+
+```typescript
+assetManager.downloader.register('.myformat', function (url, options, callback) {
+ // Download the resource
+ ......
+});
+
+assetManager.parser.register('.myformat', function (file, options, callback) {
+ // Parsing a downloaded file
+ ......
+});
+```
+
+A custom handler needs to receive three arguments:
+
+- The first argument is the handler object, which is the URL in the downloader and the file in the parser.
+- The second argument is optional, and optional parameters can be specified when you call the load interface.
+- The third argument is to complete the callback, which needs to be called when you register the handler and pass in an error message or result.
+
+After registered the handler, the corresponding handler will be used if the downloader/parser encounters a request with the same extension, and these custom handlers will be available to all loading pipelines globally. For example:
+
+```typescript
+assetManager.loadAny({'url': 'http://example.com/myAsset.myformat'}, callback);
+```
+
+> **Note**: the handler can receive incoming optional parameters, which can be used to implement custom extensions, see the [Optional Parameters](options.md#expand-engine) documentation for details.
diff --git a/versions/4.0/en/asset/dragonbones.md b/versions/4.0/en/asset/dragonbones.md
new file mode 100644
index 0000000000..b8cbd30f0e
--- /dev/null
+++ b/versions/4.0/en/asset/dragonbones.md
@@ -0,0 +1,33 @@
+# Skeletal Animation Assets (DragonBones)
+
+DragonBones skeletal animation assets are data formats exported by [DragonBones](http://dragonbones.com/) (supports DragonBones v5.6.3 and below).
+
+## Import DragonBones Skeleton Animation Assets
+
+DragonBones skeletal animation assets include
+
+- `.json`/`.dbbin` skeleton data
+- `.json` atlas data
+- `.png` atlas textures
+
+ 
+
+## Create Skeletal Animation Assets
+
+Using DragonBones skeletal animation assets in a scene requires two steps:
+
+1. Create nodes and add DragonBones components
+
+ Drag the skeletal animation asset from the **Assets** panel to the Dragon Asset property of the created DragonBones component:
+
+ 
+
+2. Set the atlas data for the DragonBones component
+
+ Drag the atlas data from the **Assets** panel to the Dragon Atlas Asset property of the DragonBones component:
+
+ 
+
+## Storage in the Project
+
+For efficient asset management, it is recommended to store the imported asset files in a separate directory so that they won't mix with other assets.
diff --git a/versions/4.0/en/asset/dragonbones/import.png b/versions/4.0/en/asset/dragonbones/import.png
new file mode 100644
index 0000000000..2bc6358e3a
Binary files /dev/null and b/versions/4.0/en/asset/dragonbones/import.png differ
diff --git a/versions/4.0/en/asset/dragonbones/set_asset.png b/versions/4.0/en/asset/dragonbones/set_asset.png
new file mode 100644
index 0000000000..5415425b43
Binary files /dev/null and b/versions/4.0/en/asset/dragonbones/set_asset.png differ
diff --git a/versions/4.0/en/asset/dragonbones/set_atlas.png b/versions/4.0/en/asset/dragonbones/set_atlas.png
new file mode 100644
index 0000000000..404a1197ff
Binary files /dev/null and b/versions/4.0/en/asset/dragonbones/set_atlas.png differ
diff --git a/versions/4.0/en/asset/dynamic-load-resources.md b/versions/4.0/en/asset/dynamic-load-resources.md
new file mode 100644
index 0000000000..5cb3e2a935
--- /dev/null
+++ b/versions/4.0/en/asset/dynamic-load-resources.md
@@ -0,0 +1,179 @@
+# Asset Loading
+
+## Dynamic loading of resources
+
+Usually we will place the resources that need to be dynamically loaded in the project in the `resources` directory, along with interfaces such as `resources.load` to load them dynamically. You just need to pass in the path relative to `resources` directory, and the end of the path **must not** contain the file extension.
+
+```typescript
+// load Prefab
+resources.load("test_assets/prefab", Prefab, (err, prefab) => {
+ const newNode = instantiate(prefab);
+ director.getScene().addChild(newNode);
+});
+
+// load AnimationClip
+resources.load("test_assets/anim", AnimationClip, (err, clip) => {
+ this.node.getComponent(Animation).addClip(clip, "anim");
+});
+```
+
+- All resources that need to be dynamically loaded by **script** must be placed in the `resources` folder or one of its sub-folders. `resources` needs to be created manually in the `assets` folder and must be located in the `assets` root directory, like this:
+
+ 
+
+ > The assets in the `resources` folder can refer to other assets outside the folder, and can also be referenced by external scenes or assets. When the project is built, all assets in the `resources` folder, along with assets outside the `resources` folder they are associated with, will be exported, in addition to the scenes that have been checked in the **Build** panel.
+ >
+ > If an asset is only depended on by other assets in the `resources` and does not need to be called directly by `resources.load`, then please don't put it in the `resources` folder. Otherwise, the size of `config.json` will increase, and useless assets in the project will not be automatically culled during the build process. At the same time, in the build process, the automatic merge strategy of JSON will also be affected, unable to merge the fragmented JSON as much as possible.
+
+- The second to note is that compared to previous Cocos2d-JS, dynamic loading of resources in Creator is **asynchronous**, you need to get the loaded resources in the callback function. This is done because in addition to the resources associated with the scene, Creator has no additional resources preload list, and the dynamically loaded resources are really dynamically loaded.
+
+ > **Note**: as of v2.4, the `loader` interface is deprecated, please use `assetManager` instead. You can refer to the [Asset Manager Upgrade Guide](asset-manager-upgrade-guide.md) documentation for details.
+
+### Loading a SpriteFrame or a Texture2D
+
+After the image is set to a spriteframe, texture or other image types, an asset of the corresponding type will be generated in the **Assets Panel**. But if `test_assets/image` is loaded directly, and the type will be `ImageAsset`. You must specify the full path of sub asset, then the generated SpriteFrame can be loaded.
+
+```typescript
+// load a SpriteFrame, image is ImageAsset, spriteFrame is image/spriteFrame, texture is image/texture
+resources.load("test_assets/image/spriteFrame", SpriteFrame, (err, spriteFrame) => {
+ this.node.getComponent(Sprite).spriteFrame = spriteFrame;
+});
+```
+
+```typescript
+// load a texture
+resources.load("test_assets/image/texture", Texture2D ,(err: any, texture: Texture2D) => {
+ const spriteFrame = new SpriteFrame();
+ spriteFrame.texture = texture;
+ this.node.getComponent(Sprite).spriteFrame = spriteFrame;
+});
+```
+
+> **Note**: if a __type__ parameter is specified, an asset of the specified type will be found under the path. When you are in the same path includes multiple names simultaneously under a resource (for example, contains both `player.clip` and `player.psd`), should need to declare types. When you need to get a "sub-asset" (such as getting the sub-asset __SpriteFrame__ of __ImageAsset__), you need to specify the path of the sub-asset.
+
+### Load SpriteFrames from Atlas
+
+For an atlas imported from a third-party tool such as TexturePacker, if you want to load the SpriteFrame, you can only load the atlas first, and then get the SpriteFrame. This is a special case.
+
+```typescript
+// load SpriteAtlas, and get one of them SpriteFrame
+// Note Atlas resource file (plist) usually of the same name and a picture file (PNG) placed in a directory,
+// So should need to in the second parameter specifies the resource type.
+resources.load("test_assets/sheep", SpriteAtlas, (err, atlas) => {
+ const frame = atlas.getSpriteFrame('sheep_down_0');
+ this.node.getComponent(Sprite).spriteFrame = frame;
+});
+```
+
+### Load resources in the FBX or glTF model
+
+After importing the FBX model or glTF model into the editor, it will parse out the related resources which includes meshes, materials, skeletons, animations, etc. contained in the model, as shown in the following figure.
+
+
+
+It is possible to dynamically load a single resource in the model at runtime by simply specifying the path to a specific sub-resource, as follows.
+
+```typescript
+// Load the mesh in the model
+resources.load("Monster/monster", Mesh, (err, mesh) => {
+ this.node.getComponent(MeshRenderer).mesh = mesh;
+});
+
+// Load the material in the model
+resources.load("Monster/monster-effect", Material, (err, material) => {
+ this.node.getComponent(MeshRenderer).material = material;
+});
+
+// Load the skeleton in the model
+resources.load("Monster/Armature", Skeleton, (err, skeleton) => {
+ this.node.getComponent(SkinnedMeshRenderer).skeleton = skeleton;
+});
+```
+
+### Resource bulk loading
+
+`resources.loadDir` can load multiple resources under the same path:
+
+```ts
+// loading all resource in the test_assets directory
+resources.loadDir("test_assets", function (err, assets) {
+ // ...
+});
+
+// Load all SpriteFrames in the `test_assets` directory and get their urls
+resources.loadDir("test_assets", SpriteFrame, function (err, assets) {
+ // ...
+});
+```
+
+## Preload resources
+
+Starting with v2.4, in addition to scenes that can be preloaded, other resources can also be preloaded. Preloading has the same loading parameters as normal loading, but it will only download the necessary resources, and will not perform deserialization or initialization. Therefore, it consumes less performance and is suitable for use during the game.
+
+`resources` provides `preload` and `preloadDir` for preloading resources.
+
+```typescript
+resources.preload('test_assets/image/spriteFrame', SpriteFrame);
+ // wait for while
+resources.load('test_assets/image/spriteFrame', SpriteFrame, (err, spriteFrame) => {
+ this.node.getComponent(Sprite).spriteFrame = spriteFrame;
+});
+```
+
+Use the preload related interface to load resources in advance, without waiting for the preload to finish. Then use the normal load interface to load, the normal load interface will directly reuse the content that has been downloaded during the preload process to shorten the load time.
+
+For more information on preloading, please refer to the [Preloading and Loading](preload-load.md) documentation.
+
+## How to load remote assets or files in device
+
+Currently in Cocos Creator, we support loading the remote image files, which is very useful to load user picture from social network websites. To load files from such urls, you should call `assetManager.loadRemote`. At the same time the same API can be used to load resources on the local device storage. The `resources.load` APIs mentioned above only apply to the application package resources and hot update resources. Here is how to load remote assets and local
+device files:
+
+```typescript
+// Remote texture url with file extensions
+let remoteUrl = "http://unknown.org/someres.png";
+assetManager.loadRemote(remoteUrl, function (err, imageAsset) {
+ const spriteFrame = new SpriteFrame();
+ const texture = new Texture2D();
+ texture.image = imageAsset;
+ spriteFrame.texture = texture;
+ // ...
+});
+
+// Remote texture url without file extensions, then you need to define the file type explicitly
+remoteUrl = "http://unknown.org/emoji?id=124982374";
+assetManager.loadRemote(remoteUrl, {ext: '.png'}, function (err, imageAsset) {
+ const spriteFrame = new SpriteFrame();
+ const texture = new Texture2D();
+ texture.image = imageAsset;
+ spriteFrame.texture = texture;
+ // ...
+});
+
+// Use absolute path to load files on device storage
+let absolutePath = "/dara/data/some/path/to/image.png"
+assetManager.loadRemote(absolutePath, function (err, imageAsset) {
+ const spriteFrame = new SpriteFrame();
+ const texture = new Texture2D();
+ texture.image = imageAsset;
+ spriteFrame.texture = texture;
+ // ...
+});
+
+// Remote Audio
+remoteUrl = "http://unknown.org/sound.mp3";
+assetManager.loadRemote(remoteUrl, function (err, audioClip) {
+ // play audio clip
+});
+
+// remote Text
+remoteUrl = "http://unknown.org/skill.txt";
+assetManager.loadRemote(remoteUrl, function (err, textAsset) {
+ // use string to do something
+});
+```
+
+There still remains some restrictions currently, the most important are:
+
+1. This loading method supports only native resource types such as textures, audios, text, etc., and does not support direct loading and analysis of resources such as SpriteFrame, SpriteAtlas, TiledMap. (If you want to load all resources remotely, use the [Asset Bundle](bundle.md))
+2. Remote loading ability on Web is limited by the browser's [CORS cross-domain policy restriction](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS). If the server forbid cross-domain access, loading request will fail, and due to WebGL security policy restrictions, even if the server allows CORS http request, textures loaded can not be rendered.
diff --git a/versions/4.0/en/asset/font.md b/versions/4.0/en/asset/font.md
new file mode 100644
index 0000000000..280088ea2c
--- /dev/null
+++ b/versions/4.0/en/asset/font.md
@@ -0,0 +1,64 @@
+# Fonts
+
+There are three types of font assets available to games made with __Cocos Creator__: __system fonts__, __dynamic fonts__, and __bitmap fonts__.
+
+The __system font__ renders text by calling the __system font__ that comes with the game running platform, and does not require the user to add any related assets to the project. To use __system fonts__, use the __Use System Font__ property in the [Label](../ui-system/components/editor/label.md) documentation.
+
+## Importing font assets
+
+### Dynamic fonts
+
+__Cocos Creator__ currently supports dynamic fonts in __True Type__ format. Simply drag a font file with an extension of `.ttf` into the __Assets__ panel, and you can import the font asset.
+
+### Bitmap fonts
+
+The bitmap font is composed of a font file in `.fnt` format and a `.png` image. The `.fnt` file provides an index of each character thumbnail. Fonts in this format can be generated by specialized software, please refer to:
+
+- [Glyph Designer](https://71squared.com/glyphdesigner)
+- [Hiero](https://github.com/libgdx/libgdx/wiki/Hiero)
+- [BMFont (Windows)](http://www.angelcode.com/products/bmfont/)
+- [swnob-bmf](https://github.com/SilenceLeo/snowb-bmf)
+
+When importing bitmap fonts, be sure to drag both the `.fnt` file and the `.png` file into the __Assets__ panel at the same time.
+
+> __Note__: after importing the bitmap font, you need to change the type of the `.png` file to __sprite-frame__, otherwise the bitmap font will not work properly.
+
+The imported fonts are displayed in the __Assets__ panel, as follows:
+
+
+
+> __Note__: in order to improve the efficiency of asset management, it is recommended that the imported `.fnt` and `.png` files be stored in separate directories and not mixed with other assets.
+
+## Using font assets
+
+The font asset needs to be rendered through the `Label` component. Here is how to create a `Node` with a `Label` component in the scene.
+
+### Creating a Label (Font) Node Using the Menu
+
+Click on the __Create Node__ button in the upper left corner of the __Hierarchy__ panel and select `Create Render Node --> Label (Text)`, and a component with `Label` will be created in the `Scene` node.
+
+
+
+You can also complete the creation through `Node --> Create Render Node --> Label (Text)` of the main menu, the effect is the same as the above method.
+
+
+
+### Associated Font Assets
+
+The font components created using the above method use the __system font__ as the associated asset, by default. If you want to use a __TTF__ or __bitmap fonts__ in the project, you can drag your font assets to the created `Label` component.
+
+
+
+Currently, the font used in a scene will be immediately rendered using the font asset specified. You can also freely switch the `Font` property of the same `Label` component to use __TTF__ or __bitmap fonts__ according to the needs of the project. When switching font files, other properties of the `Label` component are not affected.
+
+If you want to restore the use of __system fonts__, you can click the property check box of __Use System Font__ to clear the font file specified in the __Font__ property.
+
+### Dragging and dropping to create a Label node
+
+Another quick way to create font nodes using specified assets is to directly __drag and drop__ font files, either __TTF__ or __bitmap fonts__, from the __Assets__ panel into the __Hierarchy__ panel. The only difference from the menu created above is that text nodes created using drag and drop will automatically use the dragged font asset to set the `Font` property of the __Label__ component.
+
+
+
+
diff --git a/versions/4.0/en/asset/font/assign_font_file.png b/versions/4.0/en/asset/font/assign_font_file.png
new file mode 100644
index 0000000000..afd049c6cd
Binary files /dev/null and b/versions/4.0/en/asset/font/assign_font_file.png differ
diff --git a/versions/4.0/en/asset/font/create_label.png b/versions/4.0/en/asset/font/create_label.png
new file mode 100644
index 0000000000..9b6b4154a4
Binary files /dev/null and b/versions/4.0/en/asset/font/create_label.png differ
diff --git a/versions/4.0/en/asset/font/create_label_main_menu.png b/versions/4.0/en/asset/font/create_label_main_menu.png
new file mode 100644
index 0000000000..fdfad297c8
Binary files /dev/null and b/versions/4.0/en/asset/font/create_label_main_menu.png differ
diff --git a/versions/4.0/en/asset/font/imported.png b/versions/4.0/en/asset/font/imported.png
new file mode 100644
index 0000000000..42d072368e
Binary files /dev/null and b/versions/4.0/en/asset/font/imported.png differ
diff --git a/versions/4.0/en/asset/image.md b/versions/4.0/en/asset/image.md
new file mode 100644
index 0000000000..5f7f73d24b
--- /dev/null
+++ b/versions/4.0/en/asset/image.md
@@ -0,0 +1,42 @@
+# Images
+
+__Image__ assets are generally created using image processing software (such as __Photoshop__, __Paint__ on Windows, etc) and output into file formats that __Cocos Creator__ can use, currently including __JPG__、__PNG__、__BMP__、__TGA__、__HDR__、__WEBBP__、__PSD__、__PSD__、__TIFF__.
+
+## Importing image assets
+
+After importing images into __Cocos Creator__, they can be seen in __Assets__ panel.
+
+
+
+The properties are described as follows:
+
+| Property | Description |
+| :--- | :--- |
+| __useCompressTexture__ | Whether to use compressed texture. For more information, please refer to [Texture Compression](compress-texture.md) |
+| __Type__ | Used to set the type of image resources, including __raw__, __texture__(default), __normal map__, __sprite-frame__, __texture cube__. For more information, please refer to the following section: __Types of image assets__ |
+| __Flip Vertical__ | Whether to flip the imported image vertically along the X axis |
+| __Bake Offline Mimmaps__ | Whether to bake offline mipmaps |
+| __Fix Alpha Transparency Artifacts__ | Fix alpha transparency artifacts Fill transparent pixels with color of nearest solid pixel. These filled pixels would fix the dark halos at transparent borders of textures. Please turn on this option when you use the Alpha transparency channel in textures. Only when __texture__, __raw__, __sprite-frame__ or __texture cube__ take effect |
+| __Is RGBE__ | Whether it is RGBE compression format. This option only works if the __Type__ property is [TextureCube](texture.md#TextureCube) |
+| __Flip Green Channel__ | Flip Green Channel The normal map used in Cocos Creator is OpenGL, if you are importing a DirectX based normal map, then check this option to fix the error if the depression occurs. |
+
+## Types of image assets
+
+On the right side of the __Inspector__ panel, you can choose different ways to use the image asset. There are currently 4 ways to use it for developers, as shown below:
+
+
+
+The details of each type of image asset are described in detail in the following sections:
+
+- The raw type is the original picture type. It has no effect and users do not need to use it.
+- The texture type is the image asset type, which is also the default type for import. For details, see: [Texture](texture.md)
+- normal map type is normal map type
+- The sprite-frame type is a sprite frame asset, which is used for 2D/UI production. For details, see: [SpriteFrame](sprite-frame.md)
+- The texture cube type is a cube map type, which is used on the panorama to make a sky box. For details, see: [Sky Box](../concepts/scene/skybox.md#Modifytheenvironmentmapoftheskybox)
+
+In the __Assets__ panel, a __triangle icon__ similar to a folder will be displayed on the left of the image. __Click__ to expand to see its __sub-assets__. After each image is imported, the editor will automatically create a __selected type__ asset of the same name. __Select__ the asset itself to __change the asset type__, __set the image flip__, and __set the quality__ of the image on each platform. For detailed descriptions of __sub-assets__, please refer to the [Sub-asset Properties Panel](texture.md#Sub-AssetTexture2D'sPropertyPanel) documentation.
+
+
\ No newline at end of file
diff --git a/versions/4.0/en/asset/index.md b/versions/4.0/en/asset/index.md
new file mode 100644
index 0000000000..0037ec9b68
--- /dev/null
+++ b/versions/4.0/en/asset/index.md
@@ -0,0 +1,40 @@
+# About Assets
+
+This section will introduce the overall workflow of the assets in __Cocos Creator__ in detail, and explain the use of various types of assets and items that may require attention.
+
+## Assets Manager
+
+The **Assets** panel is an important tool for accessing and managing assets, developers are recommended to familiarize themselves with the use of the **Assets** panel for managing assets. Read the [Assets Manager](../editor/assets/index.md) documentation for a detailed introduction.
+
+## Assets Workflow
+
+The general Assets workflow including importing assets, synchronizing assets, locating assets, etc. can be found in the [Assets Workflow](asset-workflow.md) documentation.
+
+## Common Assets type workflow
+
+Next we will introduce the main **Asset** types in __Cocos Creator__:
+
+- [Scene Assets](scene.md)
+- [Image Assets](image.md)
+ - [Texture Map Assets](texture.md)
+ - [Sprite Frame Assets](sprite-frame.md)
+ - [Cube Map Assets](../concepts/scene/skybox.md#cubemap)
+ - [Auto Crop of Image Assets](../ui-system/components/engine/trim.md)
+ - [Atlas Assets](atlas.md)
+ - [Render Texture](render-texture.md)
+- [Prefabricated Assets](prefab.md)
+- [Script Assets](script.md)
+- [Font Assets](font.md)
+- [Audio Assets](audio.md)
+- [Material Assets](material.md)
+- [Model Assets](./model/mesh.md)
+ - [Importing models exported from DCC tools](./model/dcc-export-mesh.md)
+ - [glTF](./model/glTF.md)
+- [Animation Assets](../animation/animation-clip.md)
+- [Spine Skeletal Animation Assets](spine.md)
+- [DragonBones Skeletal Animation Assets](dragonbones.md)
+- [TiledMap Assets](tiledmap.md)
+
+## Asset Manager
+
+For the section about asset management at runtime, please refer to the [Asset Manager](asset-manager.md) documentation.
diff --git a/versions/4.0/en/asset/label-atlas.md b/versions/4.0/en/asset/label-atlas.md
new file mode 100644
index 0000000000..c7c1315727
--- /dev/null
+++ b/versions/4.0/en/asset/label-atlas.md
@@ -0,0 +1,32 @@
+# LabelAtlas Asset
+
+**LabelAtlas** asset is a user-defined asset, it's used for configuring a **LabelAtlas**.
+
+## Create LabelAtlas Asset
+
+In the **Assets** panel right-click on a folder, and click the context menu item **Create -> Label Atlas**. It will create a **LabelAtlas.labelatlas** asset.
+
+
+
+Before using the **LabelAtlas** asset, it needs some configuration. Configure a pre-drawn picture that contains the font style, as shown below:
+
+
+
+## Configuration of LabelAtlas asset
+
+After selecting a **LabelAtlas** asset in the **Assets** panel, the **Inspector** panel will display all configurable properties for the **LabelAtlas** asset.
+
+| Property | Description
+| :-------------- | :-----------
+| **SpriteFrame** | Specify a pre-drawn picture that contains the font style you want
+| **Item Width** | Specify the width of each character
+| **Item Height** | Specify the height of each character
+| **Start Char** | Specify the start char, even if the start char is a *space*, you also need insert a space. |
+
+When the configuration is complete, click the tick button at the top right of the **Inspector** panel to save the settings.
+
+
+
+## Using LabelAtlas asset
+
+It's quite simple to use the **LabelAtlas** asset. Just setup a new Label component and drag the **LabelAtlas** asset to the **font** property of the Label component. Please refer to the [Label Component](../ui-system/components/editor/label.md) documentation for details.
diff --git a/versions/4.0/en/asset/label-atlas/create-label-atlas.png b/versions/4.0/en/asset/label-atlas/create-label-atlas.png
new file mode 100644
index 0000000000..288f02a86b
Binary files /dev/null and b/versions/4.0/en/asset/label-atlas/create-label-atlas.png differ
diff --git a/versions/4.0/en/asset/label-atlas/raw_texture_file.png b/versions/4.0/en/asset/label-atlas/raw_texture_file.png
new file mode 100644
index 0000000000..ff58433135
Binary files /dev/null and b/versions/4.0/en/asset/label-atlas/raw_texture_file.png differ
diff --git a/versions/4.0/en/asset/label-atlas/save-label-atlas.png b/versions/4.0/en/asset/label-atlas/save-label-atlas.png
new file mode 100644
index 0000000000..2c3152a36c
Binary files /dev/null and b/versions/4.0/en/asset/label-atlas/save-label-atlas.png differ
diff --git a/versions/4.0/en/asset/load-assets/asset-dep.png b/versions/4.0/en/asset/load-assets/asset-dep.png
new file mode 100644
index 0000000000..94dd9241b9
Binary files /dev/null and b/versions/4.0/en/asset/load-assets/asset-dep.png differ
diff --git a/versions/4.0/en/asset/load-assets/asset-in-inspector-dnd.jpg b/versions/4.0/en/asset/load-assets/asset-in-inspector-dnd.jpg
new file mode 100644
index 0000000000..d416b6fea8
Binary files /dev/null and b/versions/4.0/en/asset/load-assets/asset-in-inspector-dnd.jpg differ
diff --git a/versions/4.0/en/asset/load-assets/asset-in-inspector-null.jpg b/versions/4.0/en/asset/load-assets/asset-in-inspector-null.jpg
new file mode 100644
index 0000000000..150deff22f
Binary files /dev/null and b/versions/4.0/en/asset/load-assets/asset-in-inspector-null.jpg differ
diff --git a/versions/4.0/en/asset/load-assets/asset-in-inspector.jpg b/versions/4.0/en/asset/load-assets/asset-in-inspector.jpg
new file mode 100644
index 0000000000..75f123700e
Binary files /dev/null and b/versions/4.0/en/asset/load-assets/asset-in-inspector.jpg differ
diff --git a/versions/4.0/en/asset/load-assets/model.png b/versions/4.0/en/asset/load-assets/model.png
new file mode 100644
index 0000000000..6f6faf9ccc
Binary files /dev/null and b/versions/4.0/en/asset/load-assets/model.png differ
diff --git a/versions/4.0/en/asset/load-assets/resources-file-tree.jpg b/versions/4.0/en/asset/load-assets/resources-file-tree.jpg
new file mode 100644
index 0000000000..5aa5d3a4b8
Binary files /dev/null and b/versions/4.0/en/asset/load-assets/resources-file-tree.jpg differ
diff --git a/versions/4.0/en/asset/load-assets/resources-file-tree.png b/versions/4.0/en/asset/load-assets/resources-file-tree.png
new file mode 100644
index 0000000000..d44fcfdfe0
Binary files /dev/null and b/versions/4.0/en/asset/load-assets/resources-file-tree.png differ
diff --git a/versions/4.0/en/asset/material.md b/versions/4.0/en/asset/material.md
new file mode 100644
index 0000000000..836bd82bd3
--- /dev/null
+++ b/versions/4.0/en/asset/material.md
@@ -0,0 +1,29 @@
+# Material assets
+
+## Material creation
+
+__Material__ is created as follows:
+
+
+
+or
+
+
+
+The __Material__ controls the final shading of each model. The __Material__ is composed of __Effects__, and the shading process of an __Effect__ is controlled by the __Material__. The __Material__ itself can also be regarded as a container of __Effect__ assets. The __Material__ can switch the __Effect__ assets to be used at will. The following figure is the __Effect__ asset of the __Material__ we have selected by default.
+
+
+
+At the same time, we can also switch the __Effect__ of the current __Material__ by clicking the box to the right of the __Effect__ property.
+
+
+
+## Effect Creation
+
+__Effects__ are created in a similar way to `Materials`.
+
+
+
+The created __Effect__ is a __PBR Effect__ by default.
+
+
diff --git a/versions/4.0/en/asset/material/default-effect.png b/versions/4.0/en/asset/material/default-effect.png
new file mode 100644
index 0000000000..70f82a30da
Binary files /dev/null and b/versions/4.0/en/asset/material/default-effect.png differ
diff --git a/versions/4.0/en/asset/material/effect-create.png b/versions/4.0/en/asset/material/effect-create.png
new file mode 100644
index 0000000000..043a2cdcab
Binary files /dev/null and b/versions/4.0/en/asset/material/effect-create.png differ
diff --git a/versions/4.0/en/asset/material/effect-show.png b/versions/4.0/en/asset/material/effect-show.png
new file mode 100644
index 0000000000..b1f44fe73f
Binary files /dev/null and b/versions/4.0/en/asset/material/effect-show.png differ
diff --git a/versions/4.0/en/asset/material/effects.png b/versions/4.0/en/asset/material/effects.png
new file mode 100644
index 0000000000..5636540ab6
Binary files /dev/null and b/versions/4.0/en/asset/material/effects.png differ
diff --git a/versions/4.0/en/asset/material/material-create-menu.png b/versions/4.0/en/asset/material/material-create-menu.png
new file mode 100644
index 0000000000..03a151d45d
Binary files /dev/null and b/versions/4.0/en/asset/material/material-create-menu.png differ
diff --git a/versions/4.0/en/asset/material/material-create.png b/versions/4.0/en/asset/material/material-create.png
new file mode 100644
index 0000000000..8556ce84ca
Binary files /dev/null and b/versions/4.0/en/asset/material/material-create.png differ
diff --git a/versions/4.0/en/asset/meta.md b/versions/4.0/en/asset/meta.md
new file mode 100644
index 0000000000..9b32163a25
--- /dev/null
+++ b/versions/4.0/en/asset/meta.md
@@ -0,0 +1,141 @@
+# Resource Management Considerations --- meta files
+
+> **Note**: the full text of this article is reproduced from [WeChat Official Account: Quetta Planet [cn]](https://mp.weixin.qq.com/s/MykJaytb3t_oacude1cvIg), authorized by the author before reprinting
+> **Author**: Shawn Zhang
+
+Cocos Creator will generate a **meta** file with the same name for every file and directory in the **assets** directory. Understanding the role and mechanics of Cocos Creator's generation of **meta** files can help developers solve resource conflicts, file loss, and missing component properties that are often encountered with team development. What is the **meta** file used for? Let's take a look!
+
+
+
+## The Role of a Meta File
+
+Let's first look at what the **meta** file looks like in the scene:
+
+```json
+{
+ "ver": "1.0.0", //version
+ "uuid": "911560ae-98b2-4f4f-862f-36b7499f7ce3", //global unique id
+ "asyncLoadAssets": false, // asynchronous loading
+ "autoReleaseAssets": false, // automatically release resources
+ "subMetas": {} // child metadata
+}
+```
+
+The **meta** file for the prefab is the same as the scene. Let's take a look at the **meta** file of the png image:
+
+```json
+{
+ "ver": "1.0.0",
+ "uuid": "19110ebf-4dda-4c90-99d7-34b2aef4d048",
+ "type": "sprite",
+ "wrapMode": "clamp",
+ "filterMode": "bilinear",
+ "subMetas": {
+ "img_circular": {
+ "ver": "1.0.3",
+ "uuid": "a2d1f885-6c18-4f67-9ad6-97b35f1fcfcf",
+ "rawTextureUuid": "19110ebf-4dda-4c90-99d7-34b2aef4d048",
+ "trimType": "auto",
+ "trimThreshold": 1,
+ "rotated": false,
+ "offsetX": 0,
+ "offsetY": 0,
+ "trimX": 0,
+ "trimY": 0,
+ "width": 100,
+ "height": 100,
+ "rawWidth": 100,
+ "rawHeight": 100,
+ "borderTop": 0,
+ "borderBottom": 0,
+ "borderLeft": 0,
+ "borderRight": 0,
+ "subMetas": {}
+ }
+ }
+}
+```
+
+The **meta** file for the png image has more information. In addition to the basic `ver` and `uuid`, it also records the width, height, offset, and borders of the image. There is a lot of information that is stored. **UUID** and it is particularly important.
+
+> UUID: Universally Unique Identifier
+
+**UUIDs** in Cocos Creator are used to manage the resources of the game. It assigns a unique id to each file. This means that in the Cocos Creator engine, identifying a file is not simply by `path + filename`, but by **UUID**. Therefore, you can delete and move files at will in **Asset Resource Management**.
+
+## When will a meta file be updated
+
+Cocos Creator generates **meta** files the following situations:
+
+**1. when opening the project**
+
+ When you open a project, Cocos Creator, scans the **assets** directory first, and if it does not have a **meta** file, one will be generated.
+
+**2. when updating resources**
+
+Updating resources also triggers updates to the corresponding **meta** files:
+
+ - In **Assets**, you can modify the file name of a resource, change the directory a resource belongs in, delete resources, and add new resources. You can also drag files directly into **Assets** from your desktop or the operating system's file manager. Please refer to [Assets](../getting-started/basics/editor-panels/assets.md).
+
+ 
+
+ - Files in the `assets` directory can be added, deleted, changed, on your local **file-system**. When the changes are complete, switch to editor interface of Creator, where you can see the process of **Assets** panel refresh. The **Assets** panel is refreshed with each change, as to always show the current state of the resources.
+
+ 
+
+If a file's **meta** file does not exist, the above two conditions will trigger the engine to generate a new **meta** file automatically.
+
+## Meta File Error Cases And Solutions
+
+Let's analyze several possible cases that produce a **meta** file error.
+
+### UUID Conflicts
+
+**UUID** is globally unique. A conflict occurs if, by chance, two files have the same **UUID**. If this problem occurs, the Cocos Creator resource manager directory structure is incompletely loaded. As shown in the figure below, when this happens, the errors look scary:
+
+
+
+**UUID** conflicts can be viewed from the **Console**, and then opened from your local file-system or favorite code editor. Once opened you can search for the conflicting **UUID**:
+
+
+
+At this point, close the Cocos Creator editor then delete one of the meta files. Next, open the Cocos Creator editor.
+
+Even though this method can solve the problem, if the resource is referenced in the editor, a resource loss will occur. This means the resource needs to be re-edited or reconfigured again. It is best to restore this **meta** file with the version management tool.
+
+There are two reasons for this problem:
+
+ - When moving files on the **file-system**, copying and pasting operations also result in the **meta** file also being copied. This causes two identical **meta** files to appear simultaneously in the project.
+
+ - When you have multi-person collaboration, from the version management tool, when you update the resource, you may encounter that the **UUID** has been generated by someone else as well as by the file on your computer. This is a very rare occurence, but could still happen.
+
+In general, to reduce the occurrence of **UUID** conflicts, it is best to add and move files in the Cocos Creator resource management tool.
+
+### UUID Changes
+
+Another situation is when the **UUID** has changed, so that the resources corresponding to the old **UUID** cannot be found. In this case, the interface you have edited will have the resources, but the pictures may be lost as well as the components properties may also be lost.
+
+
+
+If you can't find the resources corresponding to the old **UUID**, you can see that Cocos Creator gives a very detailed warning message in the **console**. These details include the **scene file name**, **node path**, **component**, **UUID**, etc. The warning message allows you to quickly locate the error.
+
+How is this situation caused exactly? When someone adds a new resource to the project, they forget to switch to the editor interface to generate a **meta** file, and at the same time submit the new file to version management (without the **meta** file). Then, another person updates the resources he/she submitted and switches to the editor interface for editing. At this point, Cocos Creator will check that the new resource is generated without a **meta** file. The **meta** file is also generated when the first person switches to the editor, so that the two people have the same file on the computer, but the **UUID** in the generated **meta** file is different.
+
+In this case, those who submit or update resources later will certainly encounter conflicts. If they are unclear, they will forcibly resolve the conflicts, and the problems mentioned above will arise. The following sequence diagram depicts this erroneous workflow:
+
+
+
+A classmate forgets to submit the **meta** file to version control. Other classmates then edit the project resulting in everyone having the file on their computer, each with a different **UUID**.
+
+To solve this problem, note the following:
+
+ - When submitting resources, pre-check for new files. If there are new documents, pay attention to whether **meta** files need to be submitted together.
+
+ - When pulling files, pay attention to whether there are new files, and if there are **meta** files in pairs. If not, remind team-mates who submitted the files to submit the files and **meta** files together.
+
+ - When submitting, if you find that there is only one new **meta** file, then the **meta** file must have been generated by yourself. You need to pay attention to whether the resource corresponding to the **meta** file (the file with the same name) has been used. If you haven't used it, please submit the **meta** file to the first submitter. Never submit this **meta** file.
+
+Note that the above points can basically eliminate the engineering error caused by the **meta** file **UUID** change.
+
+## Summary
+
+The **meta** file is an important tool for Cocos Creator to use for resource management. It is easy to generate resource errors when it is slightly inadvertent in a multi-person collaborative development. To solve this problem, you not only need to understand the mechanism that generates the **meta** file but also the cause of the conflict. Proper thought and control of resource submission helps too.
diff --git a/versions/4.0/en/asset/meta/add.png b/versions/4.0/en/asset/meta/add.png
new file mode 100644
index 0000000000..a5d0bc042e
Binary files /dev/null and b/versions/4.0/en/asset/meta/add.png differ
diff --git a/versions/4.0/en/asset/meta/conflict.png b/versions/4.0/en/asset/meta/conflict.png
new file mode 100644
index 0000000000..ab79e55cbc
Binary files /dev/null and b/versions/4.0/en/asset/meta/conflict.png differ
diff --git a/versions/4.0/en/asset/meta/lost.png b/versions/4.0/en/asset/meta/lost.png
new file mode 100644
index 0000000000..f2859768c7
Binary files /dev/null and b/versions/4.0/en/asset/meta/lost.png differ
diff --git a/versions/4.0/en/asset/meta/missingscript.png b/versions/4.0/en/asset/meta/missingscript.png
new file mode 100644
index 0000000000..e6a8c96a2c
Binary files /dev/null and b/versions/4.0/en/asset/meta/missingscript.png differ
diff --git a/versions/4.0/en/asset/meta/refresh.png b/versions/4.0/en/asset/meta/refresh.png
new file mode 100644
index 0000000000..bfa510ff46
Binary files /dev/null and b/versions/4.0/en/asset/meta/refresh.png differ
diff --git a/versions/4.0/en/asset/meta/resources.png b/versions/4.0/en/asset/meta/resources.png
new file mode 100644
index 0000000000..ccedd691eb
Binary files /dev/null and b/versions/4.0/en/asset/meta/resources.png differ
diff --git a/versions/4.0/en/asset/meta/search_uuid.png b/versions/4.0/en/asset/meta/search_uuid.png
new file mode 100644
index 0000000000..25ab061545
Binary files /dev/null and b/versions/4.0/en/asset/meta/search_uuid.png differ
diff --git a/versions/4.0/en/asset/model/dcc-export-mesh.md b/versions/4.0/en/asset/model/dcc-export-mesh.md
new file mode 100644
index 0000000000..36ce563f38
--- /dev/null
+++ b/versions/4.0/en/asset/model/dcc-export-mesh.md
@@ -0,0 +1,53 @@
+# Importing Models Exported from DCC Tools
+
+Currently, most __Digital Content Creation (DCC)__ tools ([__3DS Max__](max-export-fbx.md), [__Maya__](maya-export-fbx.md), __Blender__) can export models in __FBX__ and __glTF__ formats. These formats, exported by these tools, can be well received in __Cocos Creator 3.0__.
+
+## Exporting FBX
+
+Because the coordinate system of the DCC tool and the game engine's coordinate system are not necessarily the same, some transformations are required when exporting a model to get the desired result in the engine. For example, Blender's coordinate system is __X-axis right__, __Y-axis inward__, and __Z-axis upward__, while Cocos Creator 3.x's coordinate system is __X-axis right__, __Y-axis upward__, and __Z-axis outward__, so the rotation needs to be adjusted to make the axes consistent.
+
+The following uses Blender 2.8 as an example to introduce the model import process. First, create a model in Blender.
+
+
+
+In [Blender's FBX Export Options](https://docs.blender.org/manual/en/2.80/addons/io_scene_fbx.html) documentation, choose __Up__ as __Y Up__ and __Forward__ as __-Z Forward__.
+
+
+
+Imported into __Cocos Creator__, notice that the nodes are rotated by __-90__ on the __X-axis__ in order to combine the __axis__ with __Cocos Creator__. The axes are aligned.
+
+
+
+To use a different rotation value, Blender's FBX export plugin provides an experimental function, __Apply Transform__, which can directly transform the rotation data into the model's vertex data.
+
+
+
+Notice that the rotation data is gone in __Cocos Creator 3.x__.
+
+
+
+## Exporting glTF
+
+Please read the following documents:
+
+- [glTF also uses a right-handed coordinate system](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#coordinate-system-and-units)
+- [Options for exporting glTF in Blender](https://docs.blender.org/manual/en/2.80/addons/io_scene_gltf2.html). It is relatively simple, as long as the __+Y Up__ option is checked, there is no rotation value in the exported data.
+
+ 
+
+## Possible issues
+
+During the game development process, the orientation of the model may be used. For example, if some objects should face the player (using the `LookAt()` method), consider the initial orientation of the model. Here are two methods to adjust the initial orientation of the model.
+
+1. In __Cocos Creator 3.x__, the __-Z-axis__ is used as the forward direction, while in Blender, the forward direction is __+Y-axis__, when making a model, the positive direction of the __Y-axis__ should be used as the orientation of the object, and the derived transformation later, in __Cocos Creator__, the __-Z-axis__ will be used as the front direction.
+2. To not change the orientation in the DCC tool, try adding a parent node to the imported model in the scene, and then rotate the model so that the initial orientation of the model is the __-Z-axis__. All subsequent rotation-related operations are based on the parent. A node is an operation object.
+
+## Artist's production specifications
+
+1. Reasonably formulating a sub-assets name under model assets (e.g __mesh__ or __material__). Each modification of the sub-assets name will result in the loss of the place associated with the sub-assets in the project.
+
+2. When a part of the model needs to be transparent and a part does not need to be transparent, it should be exported into two materials. If it is a material export that is prone to model penetration, you need to manually adjust the material.
+
+3. External asset references, use relative path when exporting. Otherwise, under the cooperation of multiple people, the original asset path will not be recognized, resulting in the model's built-in materials cannot obtain the texture correctly and appear yellow. __Autodesk 3ds Max__ export local path is modified as follows:
+
+ 
diff --git a/versions/4.0/en/asset/model/glTF.md b/versions/4.0/en/asset/model/glTF.md
new file mode 100644
index 0000000000..2a41a86212
--- /dev/null
+++ b/versions/4.0/en/asset/model/glTF.md
@@ -0,0 +1,163 @@
+# glTF Models
+
+Cocos Creator supports glTF 2.0 and earlier file formats.
+
+## URI Parsing
+
+Creator supports URIs in the following form specified in glTF:
+
+- Data URI
+
+- Relative URI path
+
+- File URL
+
+- File path
+
+## Conversion Relationships
+
+When importing a glTF model into Creator, the assets in glTF will be converted to assets in Creator according to the following relationships:
+
+| glTF Asset | Cocos Creator Asset |
+| :---------- | :---------------- |
+| [glTF Scene](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#reference-scene) | Prefab |
+| [glTF Mesh](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#reference-mesh) | Mesh |
+| [glTF Skin](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#reference-skin) | Skeleton |
+| [glTF Material](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#reference-material) | Material |
+| [glTF Texture](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#reference-texture) | Texture |
+| [glTF Image](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#reference-image) | Image |
+| [glTF Animation](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#reference-animation) | Animation Clip |
+
+### glTF Scene
+
+After import, the glTF scene will be converted to a prefab asset in Creator, and the nodes recursively contained in the glTF scene will be converted to nodes in the prefab one by one according to the same hierarchical relationship.
+
+#### Scene Root Node
+
+The prefab will use a node without any spatial transformation information as the root node, and all [root nodes](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#scenenodes) of the glTF scene will be the children of this node.
+
+#### Node Conversion
+
+The properties in the glTF node will be converted to properties in the prefab node according to the texture relationships in the following table:
+
+| glTF Node Property | Prefab Node Property |
+| :----------- | :----------- |
+| [Hierarchy](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodechildren) | Hierarchy |
+| [Displacement](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodetranslation) | Position |
+| [Rotation](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#noderotation) | Rotation |
+| [Scaling](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodescale) | Scaling |
+| [Matrix](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodematrix) | Decompress and set the position, rotation, and scaling respectively |
+| [Mesh](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodemesh) | MeshRenderer component |
+| [Skin](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodeskin) | SkinnedMeshRenderer component |
+| [Initial Weight](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodeweights) | (Skinned) MeshRenderer component weight |
+
+#### MeshRenderer
+
+If the glTF node references a mesh, then the corresponding prefab node will also have a MeshRenderer component added to it after import. If the glTF node also references a skin, then the corresponding prefab node will also have a SkinnedMeshRenderer added to it.
+
+The mesh, skeletons, and materials in the SkinnedMeshRenderer component correspond to the transformed glTF mesh, skin, and material assets.
+
+If the glTF node specifies an initial weight, the converted (skinned) MeshRenderer will also carry this weight.
+
+### glTF Mesh
+
+After import, the glTF mesh will be converted to a mesh asset in Cocos Creator.
+
+All [primitives](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#meshprimitives-white_check_mark) in the glTF mesh will be converted to sub-meshes in the Creator one by one.
+
+If [weight](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#meshweights) is specified for the glTF mesh, the corresponding weights will be stored in the converted Creator mesh.
+
+#### glTF Primitive
+
+The index arrays of the glTF primitives will correspond to the index arrays of the converted Cocos Creator sub-meshes.
+
+The glTF primitive schema will be converted to the Cocos Creator primitive schema according to the texture in the following table.
+
+| glTF Primitive Schema | Cocos Creator Primitive Schema |
+| :--------------- | :------------------------------- |
+| `POINTS` | `gfx.PrimitiveMode.POINT_LIST` |
+| `LINES` | `gfx.PrimitiveMode.LINE_LIST` |
+| `LINE_LOOP` | `gfx.PrimitiveMode.LINE_LOOP` |
+| `LINE_STRIP` | `gfx.PrimitiveMode.LINE_STRIP` |
+| `TRIANGLES` | `gfx.PrimitiveMode.TRIANGLE_LIST` |
+| `TRIANGLE_STRIP` | `gfx.PrimitiveMode.TRIANGLE_STRIP` |
+| `TRIANGLE_FAN` | `gfx.PrimitiveMode.TRIANGLE_FAN` |
+
+glTF vertex attributes will be converted to Cocos Creator vertex attributes, and the attribute names will be converted as shown in the following table:
+
+| glTF Vertex Attribute Name | Cocos Creator Vertex Attribute Name |
+| :------------------------ | :----------------------------------------------------------------------- |
+| `POSITION` | `gfx.AttributeName.ATTR_POSITION` |
+| `NORMAL` | `gfx.AttributeName.ATTR_NORMAL` |
+| `TANGENT` | `gfx.AttributeName.ATTR_TANGENT` |
+| `TEXCOORD_0` | `gfx.AttributeName.ATTR_TEX_COORD` |
+| `TEXCOORD_1`..`TEXCOORD_8` | `gfx.AttributeName.ATTR_TEX_COORD1`..`gfx.AttributeName.ATTR_TEX_COORD8` |
+| `COLOR_0` | `gfx.AttributeName.ATTR_COLOR` |
+| `COLOR_1`..`COLOR_2` | `gfx.AttributeName.ATTR_COLOR1`..`gfx.AttributeName.ATTR_COLOR2` |
+| `JOINTS_0` | `gfx.AttributeName.ATTR_JOINTS` |
+| `WEIGHTS_0` | `gfx.AttributeName.ATTR_WEIGHTS` |
+
+> **Note**: if there are other `JOINTS`, `WEIGHTS` vertex attributes in the glTF primitive, such as `JOINTS_1`, `WEIGHTS_1`, it means that the vertices of this glTF mesh may be affected by more than 4 skeletons.
+
+For each vertex, all the weight information determined by `JOINTS_{}`, `WEIGHTS_{}` will be sorted by weight value and the four skeletons with the highest influence weight will be taken as `gfx.AttributeName.ATTR_JOINTS` and `gfx.AttributeName.ATTR_WEIGHTS`.
+
+glTF deformation targets will be converted to Cocos Creator sub-mesh deformation data.
+
+### glTF Skins
+
+After import, glTF skins will be converted to skeletal assets in Cocos Creator.
+
+### glTF Material
+
+After import, glTF materials will be converted to material assets in Cocos Creator.
+
+### glTF Texture
+
+After import, glTF texture will be converted to a texture asset in Cocos Creator.
+
+The glTF image referenced in the glTF texture will be converted to a reference to the corresponding converted Cocos Creator image.
+
+glTF texture properties will be converted to Cocos Creator texture properties according to the texture in the following table:
+
+| glTF Texture Property | Cocos Creator Texture Property |
+| :----------------------- | :----------------------- |
+| [Magnification Filter](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#samplermagfilter) | Magnification Filter |
+| [Minification Filter](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#samplerminfilter) | Minification Filter, Mip Map Filter |
+| [S Wrap Mode](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#samplerwraps) | S Wrap Mode |
+| [T Wrap Mode](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#samplerwrapt) | Wrap Mode |
+
+The glTF texture magnification filter will be converted to the Cocos Creator texture magnification filter according to the texture in the following table:
+
+| glTF Texture Magnification Filter | Cocos Creator Texture Magnification Filter |
+| :---------------- | :--------------------------- |
+| `NEAREST` | `TextureBase.Filter.NEAREST` |
+| `LINEAR` | `TextureBase.Filter.LINEAR` |
+
+The glTF Texture Minification Filter will be converted to Cocos Creator Texture Minification Filter and Cocos Creator Texture Mip Map Filter according to the texture relationships in the following table:
+
+| glTF Texture Minification Filter | Cocos Creator Texture Minification Filter | Cocos Creator Mip Map Filter |
+|:------------------------ | :---------------------------- | :----------------------------- |
+| `NEAREST` | `TextureBase.Filter.NEAREST` | `TextureBase.Filter.NONE` |
+| `LINEAR_MIPMAP_LINEAR` | `TextureBase.Filter.LINEAR` | `TextureBase.Filter.LINEAR` |
+| `LINEAR_MIPMAP_NEAREST` | `TextureBase.Filter.LINEAR` | `TextureBase.Filter.NEAREST` |
+| `LINEAR` | `TextureBase.Filter.LINEAR` | `TextureBase.Filter.NONE` |
+| `NEAREST_MIPMAP_LINEAR` | `TextureBase.Filter.NEAREST` | `TextureBase.Filter.LINEAR` |
+| `NEAREST_MIPMAP_NEAREST` | `TextureBase.Filter.NEAREST` | `TextureBase.Filter.NEAREST` |
+
+glTF Texture Wrap mode will be converted to Cocos Creator Texture Wrap mode according to the texture in the following table:
+
+| glTF Texture Wrap Mode | Cocos Creator Texture Wrap Mode |
+| :---------------- | :------------------------------------- |
+| `CLAMP_TO_EDGE` | `TextureBase.WrapMode.CLAMP_TO_EDGE` |
+| `REPEAT` | `TextureBase.WrapMode.REPEAT` |
+| `MIRRORED_REPEAT` | `TextureBase.WrapMode.MIRRORED_REPEAT` |
+
+### glTF Image
+
+After import, the glTF image will be converted to an image asset in Cocos Creator.
+
+When the [URI](https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#imageuri) of the glTF image is a Data URI, the image data will be fetched from the Data URI. Otherwise, the image data will be resolved from the Data URI according to the [Cocos Creator Image Location Resolution Algorithm](./image-location-resolution.md), where `url` is the URI of the glTF image and `startDir` is the directory where the glTF file is located.
+
+### glTF Animation
+
+After import, glTF animations will be converted to Cocos Creator animation assets.
diff --git a/versions/4.0/en/asset/model/image-location-resolution.md b/versions/4.0/en/asset/model/image-location-resolution.md
new file mode 100644
index 0000000000..c0be3a8811
--- /dev/null
+++ b/versions/4.0/en/asset/model/image-location-resolution.md
@@ -0,0 +1,35 @@
+# Cocos Creator Image Location Resolution Algorithm
+
+The parameters given in the Cocos Creator image location resolution algorithm and their descriptions are as follows:
+
+| Parameter | Description |
+| :---- | :------ |
+| `url` | The desired URL |
+| `startDir` | The starting search directory |
+| `DEPTH` | Search depth, fixed to **2** |
+| `SEARCH_DIR_NAMES` | Array of texture folder names, default is: `textures`, `materials` |
+| `SEARCH_EXT_NAMES` | Array of extensions to search for, fixed to `.jpg`, `.jpeg`, `.png`, `.tga`, `.webp` |
+
+The Cocos Creator image location resolution algorithm is given by the following procedure:
+
+- If the file corresponding to `url` exists, return `url`.
+
+- Let `expectedExtName` be the extension of `url`.
+
+- let `expectedBaseName` be the extensionless filename of `url`.
+
+- Let `searchExtNames` be the array of `[expectedExtName, ...SEARCH_EXT_NAMES]` after de-duplication.
+
+- Let `currentDir` be `startDir` and loop for `DEPTH` times:
+
+ - If `currentDir` is outside the project's `assets` directory, then exit the loop.
+
+ - If none of the subdirectories in the `currentDir` directory have names matching `SEARCH_DIR_NAMES`, then the next loop is executed.
+
+ - Make `dir` a subdirectory of the `currentDir` directory with a name matching `SEARCH_DIR_NAMES`.
+
+ - Search `dir` for files with base names matching `expectedBaseName` and extensions matching `searchExtNames`, and if so, return their paths.
+
+ - Set `currentDir` to its parent directory.
+
+- Return search failure.
diff --git a/versions/4.0/en/asset/model/max-export-fbx.md b/versions/4.0/en/asset/model/max-export-fbx.md
new file mode 100644
index 0000000000..88ecb00f39
--- /dev/null
+++ b/versions/4.0/en/asset/model/max-export-fbx.md
@@ -0,0 +1,38 @@
+# Export FBX file from 3ds Max
+
+## Steps
+
+1. Select the model:
+
+ 
+
+2. Go to **File -> Export -> Export Selected**:
+
+ 
+
+3. Set **Save as type** to **.fbx**, click the **save** button:
+
+ 
+
+4. Set **Current Preset** to **Autodesk Media and Entertainment**:
+
+ 
+
+5. Enable **Embed Media** check box:
+
+ 
+
+6. Click **OK** to export the file:
+
+ 
+
+**Remarks** : For more information, please refer to [Max Fbx Files](https://help.autodesk.com/view/3DSMAX/2022/ENU/?guid=GUID-26E80277-1645-4C4E-A6B2-44399376490F)
+
+## Import fbx into your project
+
+1. Place the export file **simpleBox** in the **Asset** folder of your project directory. More info about [FBX Import](mesh.md).
+2. Comparison of import results.
+
+| 3ds Max Viewport | Cocos Creator Scene Viewport |
+|-----------------------------------------------------------------------------|-------------------------------------------------------------------------------|
+| | |
diff --git a/versions/4.0/en/asset/model/maya-export-fbx.md b/versions/4.0/en/asset/model/maya-export-fbx.md
new file mode 100644
index 0000000000..fe4e062777
--- /dev/null
+++ b/versions/4.0/en/asset/model/maya-export-fbx.md
@@ -0,0 +1,38 @@
+# Export FBX file from Maya
+
+## Steps
+
+1. Select the model:
+
+ 
+
+2. Go to **File -> Export Selection Option**:
+
+ 
+
+3. Set **File type** to **FBX export**, click **export selection**:
+
+ 
+
+4. Set **Current Preset** to **Autodesk Media and Entertainment**:
+
+ 
+
+5. Check on **Embed Media**:
+
+ 
+
+6. Name the file to **simpleBox**, click **Export Selection**:
+
+ 
+
+**Remarks**: For more information, please refer to [Maya FBX Plugin-in](https://help.autodesk.com/view/MAYAUL/2022/ENU/index.html?guid=GUID-BD85FA4C-4D40-457C-BE66-47BC08B82FC3).
+
+## Import fbx into your project
+
+1. Place the export file **simpleBox** in the **Asset** folder of your project directory. More info about [FBX import](mesh.md).
+2. Comparison of import results.
+
+| Maya Viewport | Cocos Creator Scene Viewport |
+|-------------------------------------------------------------------------------|--------------------------------------------------------------------------------|
+| | |
diff --git a/versions/4.0/en/asset/model/maya/01-select-mesh.png b/versions/4.0/en/asset/model/maya/01-select-mesh.png
new file mode 100644
index 0000000000..048de976e6
Binary files /dev/null and b/versions/4.0/en/asset/model/maya/01-select-mesh.png differ
diff --git a/versions/4.0/en/asset/model/maya/02-export-selection-option.png b/versions/4.0/en/asset/model/maya/02-export-selection-option.png
new file mode 100644
index 0000000000..9478922a90
Binary files /dev/null and b/versions/4.0/en/asset/model/maya/02-export-selection-option.png differ
diff --git a/versions/4.0/en/asset/model/maya/03-export-type-selection.png b/versions/4.0/en/asset/model/maya/03-export-type-selection.png
new file mode 100644
index 0000000000..b2f3f03d07
Binary files /dev/null and b/versions/4.0/en/asset/model/maya/03-export-type-selection.png differ
diff --git a/versions/4.0/en/asset/model/maya/04-export-preset-selection.png b/versions/4.0/en/asset/model/maya/04-export-preset-selection.png
new file mode 100644
index 0000000000..9d244a97bc
Binary files /dev/null and b/versions/4.0/en/asset/model/maya/04-export-preset-selection.png differ
diff --git a/versions/4.0/en/asset/model/maya/05-embed-media.png b/versions/4.0/en/asset/model/maya/05-embed-media.png
new file mode 100644
index 0000000000..1b5361d970
Binary files /dev/null and b/versions/4.0/en/asset/model/maya/05-embed-media.png differ
diff --git a/versions/4.0/en/asset/model/maya/06-export-file.png b/versions/4.0/en/asset/model/maya/06-export-file.png
new file mode 100644
index 0000000000..3876add5dc
Binary files /dev/null and b/versions/4.0/en/asset/model/maya/06-export-file.png differ
diff --git a/versions/4.0/en/asset/model/maya/07-1-maya-viewport.png b/versions/4.0/en/asset/model/maya/07-1-maya-viewport.png
new file mode 100644
index 0000000000..d3a7deaaf4
Binary files /dev/null and b/versions/4.0/en/asset/model/maya/07-1-maya-viewport.png differ
diff --git a/versions/4.0/en/asset/model/maya/07-2-cocos-viewport.png b/versions/4.0/en/asset/model/maya/07-2-cocos-viewport.png
new file mode 100644
index 0000000000..3de3e9c8f1
Binary files /dev/null and b/versions/4.0/en/asset/model/maya/07-2-cocos-viewport.png differ
diff --git a/versions/4.0/en/asset/model/mesh.md b/versions/4.0/en/asset/model/mesh.md
new file mode 100644
index 0000000000..f6fd37ea53
--- /dev/null
+++ b/versions/4.0/en/asset/model/mesh.md
@@ -0,0 +1,159 @@
+# Model Assets
+
+Currently, Creator supports model files in __FBX__ and __glTF__ formats.
+
+- FBX: FBX 2020 and earlier file formats are supported.
+- glTF: glTF 2.0 and earlier file formats are supported, please refer to the [glTF models](./glTF.md) documentation for details.
+
+For how to export these two model files from third-party tools, please refer to the [Importing Models Exported from DCC Tools](./dcc-export-mesh.md) documentation.
+
+## Model Import
+
+After importing into the editor, from the outside, the corresponding model asset file can be obtained in the __Assets__ panel. It's directory structure is as follows:
+
+- The structure of a model file without animations is as follows:
+
+ 
+
+- The structure of the model file that contains animations is as follows:
+
+ 
+
+ - `.material` -- Material files
+ - `.mesh` -- Model files
+ - `.texture` -- Model texture files
+ - `.animation` -- Model animation files
+ - `.skeleton` -- Model bone files
+ - `.prefab` -- Prefab files that are automatically generated on import
+
+### Mesh File
+
+Mesh File contains vertices, index, and texture coordinate data. When a mesh file is selected in the __Assets__, the __Inspector__ will show the information of the mesh, also the mesh can be previewed in the bottom panel.
+
+
+
+| Property | Description |
+| :-- | :-- |
+| Vertices | number of vertices |
+| Triangles | number of triangle |
+| UV | indices of texture coordinate |
+| MinPos | minimum position of mesh |
+| MaxPos | maximum position of mesh |
+
+## Using Models
+
+After importing a __model__ file, drag the __root node__ of the __model__ file directly from the __Assets__ panel to the __node__ you want to place in the __Hierarchy__ panel to complete the node creation. At this point the model is successfully created in the scene.
+Alternatively, to expand the node of the __model__ file, select the `.prefab` file under the model file node, and drag it from the __Assets__ panel into the __Hierarchy__ panel to complete the creation.
+
+
+
+## Model asset Properties
+
+When the model asset file (`.fbx` or `.gltf`) is selected in the __Assets__ panel, the properties of the model asset can be set in the __Inspector__ panel.
+
+There are four tabs to choose from:
+| Tab | Description |
+| :--- | :--- |
+| __Model__ | Used to set options related to model mesh import. |
+| __Animation__ | Used to view and edit model animation clips. |
+| __Material__ | Used to set options related to the import of model materials. |
+| __FBX__ | Used to set options related to FBX file. |
+
+### Model
+
+
+
+| Property | Description |
+| :--- | :--- |
+| Normals | Normals import setting, including the following four options: 1. __Optional__: Import normals only if the model file contains normals. 2. __Exclude__: Do not import normals. 3. __Required__: Import normals that are contained in the model file, or recalculate if not contained. It is recommended to use this option if the model data itself is fine, without additional processing. 4. __Recalculate__: Recalculate normals and import, ignoring whether if the model file contain normals. Selecting this option will increase the calculated amount, but it will eliminate the subsequent problems caused by the absence of normalization of the model's original normal data. |
+| Tangents | Tangents import setting, including Optional, Exclude, Require and Recalculate four options, option feature can refer to the description of __Normals__, the two are not very different. |
+| Morph Normals | Import the deformation normal information, including: __Optional__: Import only the deformation normals contained in the model file, for cases where you know your model data very well. __Exclude__: Not to import deformation normals. |
+| Skip Validation | Skip validation of the model file. |
+| Disable mesh split | Currently there is a joint-counting-based mesh splitting process during the import pipeline to workaround the max uniform vector limit problem for real-time calculated skeletal animation system on many platforms. This process has a preference impact on other runtime system too. So if it can be pre-determined that the real-time calculated skeletal animations (when `useBakedAnimation` option of the __SkeletalAnimation__ component is unchecked) will not be used, this option can be checked to improve preference. But note that toggling this would update the corresponding prefab, so all the references in the scene should be updated as well to accompany that. Please refer to the following for details. |
+| Allow Data Access| Identifies whether all mesh data in this model can be read or written. If unchecked, the grid data will be automatically released after it is committed to the CPU |
+| Promote Single Root Node| If enabled and there is only one root node at the top of the model scene, then that node will be the root node of the Prefab, otherwise all root nodes of the scene will be the children of the Prefab |
+
+### Disable Mesh Split
+
+The policy for Disable mesh split in v3.6 is as follows:
+
+- By default, the model is not split and no changes are made to the imported model data (the previous model settings are also maintained)
+- If the number of bones does not exceed the actual runtime drive limit, pass it directly using uniform
+- If the number of bones exceeds the limit, use texture pass
+
+
+
+### Mesh Optimize
+| Property | Desc |
+| :-- | :-- |
+| __Vetex Cache__ | Reorder triangles to improve the vertex cache hit rate.|
+| __Vertex Fetch__| Reorder triangles to improve the vertex fetch efficiency. |
+| __Overdraw__ | Reorder triangles to reduce overdraw. |
+
+> It is recommended to enable the above options for meshes with high vertex count.
+> If multiple options are enabled simultaneously, the optimization algorithm will automatically adjust parameters to achieve the best result.
+
+### Mesh Simplify
+| Property | Desc |
+| :-- | :-- |
+| __Target Ratio__ | Target ratio of the simplified mesh data, recommended to set to 0.5 |
+| __Auto Error Rate__ | Whether to calculate the error rate automatically |
+| __Error Rate__ | Tune it until you get a good result |
+| __Lock Boundary__ | Whether to lock the boundary of the simplified mesh data |
+
+> The known issue is that there may be a loss of UV layout after mesh reduction. Developers should pay attention to warnings at the bottom of the inspector to determine whether to use this option.
+
+### Mesh Cluster
+| Property | Desc |
+| :-- | :-- |
+| __Generate Bounding__ | Whether to generate bounding sphere and normal cone for clustered mesh |
+
+### Mesh Compress
+| Property | Desc |
+| :-- | :-- |
+| __Encode__ | Encode to binary format to reduce file size |
+| __Compress__ | Use zlib, which is based on LZ777 and Huffman coding, for compression |
+| __Quantize__ | Quantize the mesh data, compress float-point values to reduce file size |
+
+### LODS
+
+The mesh importer will automatically take sub-meshes end with _lodN as a LOD node, if none, you can use the auto LOD by checking the LOD check box.
+
+The LOD1 and LOD2 options are used to set the ratios of the triangle count for different levels.
+
+For more, please refer to [Level Of Details](../../editor/rendering/lod.md).
+
+>The algorithm details for the above options can be found in the open-source library: https://github.com/zeux/meshoptimizer
+
+### Animation
+
+
+
+The above image is all the animation asset information under the current model, and the editing area of the specific frame number information of the currently selected animation. You can change the animation name or perform simple animation cropping here. To do so:
+
+- Click the __+__ button in the red box on the image to add an animation clip asset. The new file added by default copies a complete clip data. You can input the number of frames in the `Start` and `End` input box to crop the animation. (Drag and drop animation is not currently supported)
+
+- Click the __-__ button in the red box on the image to delete the currently selected animation file
+
+### Material
+
+
+
+The top half of the properties are described below, while the bottom half shows the materials contained in the current model.
+
+| Property | Description |
+| :--- | :--- |
+| Dump material | It is possible to customize or modify the material that comes with the model file. Enable this option to dump the material files in the file structure directory out of the model assets for modifying the materials. |
+| Material dumper directory | Specify or view the directory location for the dumped files. |
+| Use vertex colors | Whether to use vertex colors. |
+| Depth-write if blending | Enable depth-write when Alpha mode is __Blend__. |
+
+### FBX
+
+
+
+| Property | Description |
+| :--- | :--- |
+| Animation Baking Rate | Units are __frames per second__ and options include __auto__, __24__, __25__, __30__ and __60__. |
+| Promote single root node | When this option is enabled, if the FBX asset contains a scene with only one root node, that root node will be used as the root node of the prefab when converting the FBX scene to a Creator's prefab. Otherwise, the FBX scene will be used as the root node. |
+| Prefer Local Time Span | If this option is checked, imported FBX animations will use the animation time range recorded in the FBX file as a priority. If this option is not checked, the animation time range from the FBX will not be used, and the animation time range will be calculated roughly. Some FBX tools may not export animation time range information, so the animation time range is also calculated roughly. |
diff --git a/versions/4.0/en/asset/model/mesh/blender_export_bake.png b/versions/4.0/en/asset/model/mesh/blender_export_bake.png
new file mode 100644
index 0000000000..be4bfc8568
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/blender_export_bake.png differ
diff --git a/versions/4.0/en/asset/model/mesh/blender_export_fbx_1.png b/versions/4.0/en/asset/model/mesh/blender_export_fbx_1.png
new file mode 100644
index 0000000000..c81837e020
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/blender_export_fbx_1.png differ
diff --git a/versions/4.0/en/asset/model/mesh/blender_export_gltf.png b/versions/4.0/en/asset/model/mesh/blender_export_gltf.png
new file mode 100644
index 0000000000..b58b289886
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/blender_export_gltf.png differ
diff --git a/versions/4.0/en/asset/model/mesh/blender_model.png b/versions/4.0/en/asset/model/mesh/blender_model.png
new file mode 100644
index 0000000000..13a4a92716
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/blender_model.png differ
diff --git a/versions/4.0/en/asset/model/mesh/blender_model_bake_c3d.png b/versions/4.0/en/asset/model/mesh/blender_model_bake_c3d.png
new file mode 100644
index 0000000000..9e3af8a0bd
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/blender_model_bake_c3d.png differ
diff --git a/versions/4.0/en/asset/model/mesh/blender_model_c3d.png b/versions/4.0/en/asset/model/mesh/blender_model_c3d.png
new file mode 100644
index 0000000000..39a391a4ca
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/blender_model_c3d.png differ
diff --git a/versions/4.0/en/asset/model/mesh/dynamic-mesh.gif b/versions/4.0/en/asset/model/mesh/dynamic-mesh.gif
new file mode 100644
index 0000000000..c9342983e1
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/dynamic-mesh.gif differ
diff --git a/versions/4.0/en/asset/model/mesh/mesh-advopts.jpg b/versions/4.0/en/asset/model/mesh/mesh-advopts.jpg
new file mode 100644
index 0000000000..b64bf7a7f5
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/mesh-advopts.jpg differ
diff --git a/versions/4.0/en/asset/model/mesh/mesh-asset-preview.png b/versions/4.0/en/asset/model/mesh/mesh-asset-preview.png
new file mode 100644
index 0000000000..50f53cff64
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/mesh-asset-preview.png differ
diff --git a/versions/4.0/en/asset/model/mesh/mesh-model.jpg b/versions/4.0/en/asset/model/mesh/mesh-model.jpg
new file mode 100644
index 0000000000..513b1865d1
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/mesh-model.jpg differ
diff --git a/versions/4.0/en/asset/model/mesh/mesh-optimizer-warn.png b/versions/4.0/en/asset/model/mesh/mesh-optimizer-warn.png
new file mode 100644
index 0000000000..e1d24f1478
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/mesh-optimizer-warn.png differ
diff --git a/versions/4.0/en/asset/model/mesh/mesh-optimizer.png b/versions/4.0/en/asset/model/mesh/mesh-optimizer.png
new file mode 100644
index 0000000000..b3b126092d
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/mesh-optimizer.png differ
diff --git a/versions/4.0/en/asset/model/mesh/mesh_animation.png b/versions/4.0/en/asset/model/mesh/mesh_animation.png
new file mode 100644
index 0000000000..e4c9e9e120
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/mesh_animation.png differ
diff --git a/versions/4.0/en/asset/model/mesh/mesh_fbx.png b/versions/4.0/en/asset/model/mesh/mesh_fbx.png
new file mode 100644
index 0000000000..8f25396e36
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/mesh_fbx.png differ
diff --git a/versions/4.0/en/asset/model/mesh/mesh_list.png b/versions/4.0/en/asset/model/mesh/mesh_list.png
new file mode 100644
index 0000000000..41fe8f050d
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/mesh_list.png differ
diff --git a/versions/4.0/en/asset/model/mesh/mesh_list_1.png b/versions/4.0/en/asset/model/mesh/mesh_list_1.png
new file mode 100644
index 0000000000..52db5e7097
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/mesh_list_1.png differ
diff --git a/versions/4.0/en/asset/model/mesh/mesh_material.png b/versions/4.0/en/asset/model/mesh/mesh_material.png
new file mode 100644
index 0000000000..ea787416d7
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/mesh_material.png differ
diff --git a/versions/4.0/en/asset/model/mesh/mesh_model.png b/versions/4.0/en/asset/model/mesh/mesh_model.png
new file mode 100644
index 0000000000..55bdf47e3d
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/mesh_model.png differ
diff --git a/versions/4.0/en/asset/model/mesh/mesh_use.gif b/versions/4.0/en/asset/model/mesh/mesh_use.gif
new file mode 100644
index 0000000000..64ddde3749
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/mesh_use.gif differ
diff --git a/versions/4.0/en/asset/model/mesh/relative_path.png b/versions/4.0/en/asset/model/mesh/relative_path.png
new file mode 100644
index 0000000000..a34cff8e8d
Binary files /dev/null and b/versions/4.0/en/asset/model/mesh/relative_path.png differ
diff --git a/versions/4.0/en/asset/model/scripting-mesh.md b/versions/4.0/en/asset/model/scripting-mesh.md
new file mode 100644
index 0000000000..863a5e1ac0
--- /dev/null
+++ b/versions/4.0/en/asset/model/scripting-mesh.md
@@ -0,0 +1,22 @@
+# Programmatically Create Meshes
+
+Meshes can be created through the API when the model created by the DCC (Digital Content Creation) software or by the in-engine terrain editor does not meet the needs. If you need to create some kind of snake that can grow at runtime, edit the model dynamically, or implement certain surfaces, you can create the mesh programmatically.
+
+## Create Mesh
+
+The engine supports two kinds of meshes: **static meshes** and **dynamic meshes** for different scenarios, which developers can use on demand.
+
+- Static mesh, created with `utils.MeshUtils.createMesh`, once created successfully, the geometry inside the mesh is not editable.
+- Dynamic mesh: created with `utils.MeshUtils.createDynamicMesh`, once created, the geometry inside the mesh can still be modified.
+
+The return value is the `Mesh` component, so it is convenient to assign it to the `mesh` property of the `MeshRenderer` so that it can be displayed on the screen.
+
+## API
+
+API please refer to [MeshUtils](%__APIDOC__%/zh/class/utils.MeshUtils).
+
+## Example
+
+
+
+See [GitHub](https://github.com/cocos/cocos-test-projects/tree/v3.8) for an example of a dynamic mesh.
diff --git a/versions/4.0/en/asset/model/vat.md b/versions/4.0/en/asset/model/vat.md
new file mode 100644
index 0000000000..8ed13dd3c9
--- /dev/null
+++ b/versions/4.0/en/asset/model/vat.md
@@ -0,0 +1,68 @@
+# Vertex Animation Texture (VAT)
+
+Vertex Animation Texture (VAT) is commonly used to express physics simulation animations such as rigid body fragmentation, fabric, fluid, etc. Physics simulation animations computed in PCG software such as Houdini can be baked into VAT data for export and playback in real-time rendering engines to reproduce complex physics effects with very low performance consumption.
+
+Currently, the supported VAT data formats are rigid body, flexible body and fluid data exported from Houdini, and fluid data from Zeno.
+
+## Data Export and Usage
+
+The exported VAT data contains three parts: fbx model, animation texture, and json file containing VAT material properties (frame count and box max/min value, etc.).
+
+### Rigid Body
+
+1、Export:After Houdini set up rigid body collision, crushing and other animations, choose **VAT2.0 version, UE mode, no paddle, LDR way** to export.
+
+2、Material:Create a material in Cocos Creator, choose **util/dcc/vat/houdini-rigidbody-v2** for Effect.
+
+3、Parameter:Check the exported json file, fill the data of Animation Speed, NumOfFrames, PivotMin/Max, PosMin/Max into the material.
+
+4, Texture: Expand the exported Position shape map, drag the body into PositionMap, and the subordinate Sign and Alpha into PosSignMap and PosAlphaMap respectively (if any).
+Rotation normal map is the same.
+
+### Softbody
+
+1, Export: After Houdini set up the animation of soft body collision and crushing, choose **VAT3.0 version, Unity mode, no paddle, LDR way** to export.
+
+2、Material:Create a material in Cocos Creator, choose **util/dcc/vat/houdini-softbody-v3** for Effect.
+
+3、Parameter:Check the exported json file, fill the data of Animation Speed and NumOfFrames into the material.
+
+4、Texture:Expand the exported Position shape map, drag the body into PositionMap, and the subordinate Sign and Alpha into PosSignMap and PosAlphaMap respectively (if any).
+Same for the Rotation normal map.
+
+### Fluid (Houdini)
+
+1、Export:After Houdini set up the fluid animation, choose **VAT3.0 version, Unity mode, no paddle, LDR way** to export.
+
+2、Material:Create a material in Cocos Creator, choose **util/dcc/vat/houdini-fluid-v3-liquid** for Effect.
+
+3、Parameter: Check the exported json file, fill the data of Animation Speed and NumOfFrames into the material.
+
+ - Check Use Lookup Texture, drag the exported lookup image into LookupMap.
+ - Check Use Lookup Auto Frame, fill the resolution of the exported lookup into LUTTextureWidth/Height.
+ - Select the exported fbx model, record its vertex count and fill in FBXVertexCount.
+
+4. Mapping: Expand the exported Position map, drag the body into PositionMap, and the subordinate Sign and Alpha into PosSignMap and PosAlphaMap respectively (if any).
+Same for Rotation normal map.
+
+### Fluid (Zeno)
+
+1, Export: After Zeno set up the fluid animation, choose **VAT mode** to export.
+
+2、Material:Create a material in Cocos Creator, choose **util/dcc/vat/zeno-fluid-liquid** for Effect.
+
+3、Parameters:Check the exported json file, and fill the data such as Animation Speed and NumOfFrames into the material.
+
+4、Texture:Expand the exported Position map and drag it to PositionMap, Rotation map and drag it to RotationMap.
+
+### Error effect debugging
+
+### Rigid Body
+
+If there are animation anomalies such as the pieces going around in circles, please make sure the export option is in VAT2.0 UE mode, if you choose the wrong Unity mode, it may lead to this situation.
+
+### Fluid
+
+If the faces are broken or even a little bit messed up, please check if the NumOfFrames are the same as the ones in the DCC software.
+
+If the whole fluid is shaking or has interspersed faces, make sure the filter mode of both maps is Nearest, and make sure fix alpha transparency artifacts is unchecked.
\ No newline at end of file
diff --git a/versions/4.0/en/asset/options.md b/versions/4.0/en/asset/options.md
new file mode 100644
index 0000000000..e8192f460a
--- /dev/null
+++ b/versions/4.0/en/asset/options.md
@@ -0,0 +1,61 @@
+# Optional Parameters
+
+> Author: Santy-Wang, Xunyi
+
+For added flexibility and extensibility, most of the load interfaces in Asset Manager, including `assetManager.loadAny` and `assetManager.preloadAny`, provide `options` parameters. In addition to configuring the built-in parameters of Creator, `options` also allows you to customize any parameters to extend engine functionality. If you do not need to configure the engine's built-in parameters or extend the engine's functionality, you can ignore it and just use the simpler API interfaces, such as `resources.load`.
+
+Parameters that are currently used by the engine in `options` include the following:
+
+`uuid`, `url`, `path`, `dir`, `scene`, `type`, `priority`, `preset`, `audioLoadMode`, `ext`,
+`bundle`, `onFileProgress`, `maxConcurrency`, `maxRequestsPerFrame`, `maxRetryCount`, `version`, `xhrResponseType`,
+`xhrWithCredentials`, `xhrMimeType`, `xhrTimeout`, `xhrHeader`, `reloadAsset`, `cacheAsset`, `cacheEnabled`,
+
+**DO NOT** use the above fields as your custom parameter names to avoid conflicts with engine functions.
+## Engine Extension
+
+You can extend the loading capabilities of the engine by using optional parameters in the [Pipeline](pipeline-task.md) and [Custom Handlers](downloader-parser.md#custom-handlers). For example:
+
+```typescript
+// Extend the pipeline
+assetManager.pipeline.insert(function (task, done) {
+ let input = task.input;
+ for (let i = 0; i < input.length; i++) {
+ if (input[i].options.myParam === 'important') {
+ console.log(input[i].url);
+ }
+ }
+ task.output = task.input;
+ done();
+}, 1);
+
+assetManager.loadAny({'path': 'images/background'}, {'myParam': 'important'}, callback);
+
+// Register the handler
+assetManager.downloader.register('.myformat', function (url, options, callback) {
+ // Download the resource
+ const img = new Image();
+ if (options.isCrossOrigin) {
+ img.crossOrigin = 'anonymous';
+ }
+
+ img.onload = function () {
+ callback(null, img);
+ };
+
+ img.onerror = function () {
+ callback(new Error('download failed'), null);
+ };
+
+ img.src = url;
+
+});
+
+assetManager.parser.register('.myformat', function (file, options, callback) {
+ // Parse the downloaded file
+ callback(null, file);
+});
+
+assetManager.loadAny({'url': 'http://example.com/myAsset.myformat'}, {isCrossOrigin: true}, callback);
+```
+
+The engine can be extremely extensible by using optional parameters, combined with pipelines and custom handlers, and Asset Bundle can be seen as the first instance of extension using optional parameters.
diff --git a/versions/4.0/en/asset/pipeline-task.md b/versions/4.0/en/asset/pipeline-task.md
new file mode 100644
index 0000000000..c3f725ce6a
--- /dev/null
+++ b/versions/4.0/en/asset/pipeline-task.md
@@ -0,0 +1,73 @@
+# Pipeline and Task
+
+> Author: Santy-Wang, Xunyi
+>
+> This article is for advanced developers who have customization needs for their loading process.
+
+To make it easier to modify or extend the loading process of engine, the underlying layer of Asset Manager uses a mechanism called **Pipeline and Task**, **Download and Parser** to load resources. This article will focus on **Pipeline and Task**.
+
+Although `loader` used before v2.4 already used the concept of **Pipeline** for resource loading, in Asset Manager we have refactored the pipeline to make the logic clearer and easier to extend. You can extend an existing pipeline, or customize a pipeline using the class `AssetManager.Pipeline` provided by the engine.
+
+## Pipeline
+
+The **Pipeline** (defined in `AssetManager.Pipeline`) can be understood as a series of processes in series, and as a request passes through the pipeline, it is processed in turn by each stage of the pipeline, with the result of the processing finally being output. The schematic is as follows:
+
+
+
+The advantage of a pipeline over a regular fixed process is that all the links in the pipeline are spliceable and combinable, which means you can insert new stages or remove old stages at any point in the existing pipeline, greatly increasing flexibility and scalability.
+
+### The built-in Pipeline
+
+There are three pipelines built into the Asset Manager, as shown in the figure:
+
+
+
+- The first pipeline is used to convert resource paths and find the real resource paths.
+- The second pipeline is used for the normal loading process.
+- The third pipeline is used for the preload process.
+
+> **Note**: the second pipeline uses a downloader and a parser, and the third pipeline uses a downloader. See document [Download and Parse](downloader-parser.md) for details.
+
+### Custom Pipeline
+
+You can extend the built-in pipeline to achieve your own customization needs:
+
+```typescript
+assetManager.pipeline.insert(function (task, done) {
+ task.output = task.input;
+ for (let i = 0; i < task.input; i++) {
+ console.log(task.input[i].content);
+ }
+ done();
+}, 1);
+```
+
+You can also build a new pipeline:
+
+```typescript
+const pipeline = new AssetManager.Pipeline('test', [(task, done) => {
+ console.log('first stage');
+ done();
+}, (task, done) => {
+ console.log('second stage');
+ done();
+}]);
+```
+
+Building the pipeline requires a series of methods, each of which requires passing in a task parameter and a completion callback parameter. You can access everything about the task in the method and just call the completion callback on completion.
+
+## Task
+
+**Task** is a request flowing in the pipeline, a task contains inputs, outputs, completion callbacks, [optional parameters](options.md) and so on. As the task flows through the pipeline, each stage of the pipeline takes out the input of the task, makes some processing and saves it back to the output. For example:
+
+```typescript
+assetManager.pipeline.insert(function (task, done) {
+ for (let i = 0; i < task.input.length; i++) {
+ task.input[i].content = null;
+ }
+ task.output = task.input;
+ done();
+}, 1);
+```
+
+For details, please refer to the type [AssetManager.Task](%__APIDOC__%/en/class/AssetManager.Task).
diff --git a/versions/4.0/en/asset/pipeline-task/builtin-pipeline.jpg b/versions/4.0/en/asset/pipeline-task/builtin-pipeline.jpg
new file mode 100644
index 0000000000..a0d18a27a6
Binary files /dev/null and b/versions/4.0/en/asset/pipeline-task/builtin-pipeline.jpg differ
diff --git a/versions/4.0/en/asset/pipeline-task/pipeline.png b/versions/4.0/en/asset/pipeline-task/pipeline.png
new file mode 100644
index 0000000000..d44c781b84
Binary files /dev/null and b/versions/4.0/en/asset/pipeline-task/pipeline.png differ
diff --git a/versions/4.0/en/asset/prefab.md b/versions/4.0/en/asset/prefab.md
new file mode 100644
index 0000000000..b0c81ba3c9
--- /dev/null
+++ b/versions/4.0/en/asset/prefab.md
@@ -0,0 +1,98 @@
+# Prefab
+
+Prefab is used to store some scene objects that can be reused, it can contain nodes, components, and data in components. The instances generated by the prefab asset can not only inherit the data of the template, but also have it's own customized data modification.
+
+## Basic Concepts
+
+| Name | Description | Example |
+| :--- | :--- | :--- |
+| Prefab Asset | The asset of prefab in __Assets__ panel, which is the serialize file of Prefab.|  |
+| Prefab Instance | When the __Prefab Asset__ is drag to the __Hierarchy__ panel, it will generate a __Prefab Instance__. Its root node is currently marked in dark green, and its child nodes are bright green |  |
+| Prefab Editing Mode | Double-click the __Prefab Asset__ to enter the prefab editing mode. At this time, all non-nested prefab nodes are displayed in bright green |  |
+| Nested Prefab Instance | When a child node in a __Prefab Asset__ is an instance of another __Prefab Asset__, we call this child prefab a nested prefab instance |  |
+
+## Creating a Prefab
+
+There are two ways to create a prefab:
+
+1. After editing the __Node__ in the __Scene__, drag the __Nodes__ directly from the __Hierarchy__ panel to the __Assets__ panel to complete the creation of the __Prefab__.
+
+2. Click the **+** button at the top left of __Assets__, or click the blank space of the panel, and then select __Node Prefab__. (New in v3.1.1)
+
+ 
+
+After the creation is complete, the original __Node__ will automatically become a __Prefab Instance__, its root node is currently marked in bright green, and its child nodes are dark green.
+
+
+
+## Prefab Preview
+
+In version 3.8.5, we have added preview support to the inspector panel of Prefab. After users select a certain prefab, they can view the rendering content of the Prefab in the panel, which can greatly improve the efficiency of resource inspection.
+
+
+
+## Using Prefabs
+
+Drag a __Prefab Asset__ from the __Assets__ panel to the __Hierarchy__ panel or __Scene__ panel to create a __Prefab Node__ in the __Scene__.
+
+In the __Scene__, the __Prefab Instance__ objects data source comes from the deserialization of the __Prefab Asset__ , so its data is synchronized with the __Prefab Asset__ by default. If the attributes in the prefab instance are modified, the modified data will be stored In the __Prefab Instance__, it will not affect the __Prefab Asset__ and the data of other __Prefab Instance__ generated by it.
+
+
+
+## Entering prefab editing mode
+
+__Double-click__ the __Prefab Asset__ in the __Assets__ panel to switch from __Scene__ editing mode to __Prefab editing__ mode. It is possible to edit the __Prefab Assets__ in the __Editor__. After editing, click __Save__ button in the __Scene__ panel to save the edited __Prefab Assets__. Next, click the __Close__ button to return to the Scene editing mode.
+
+> __Note__: please avoid multiple people modifying the same prefab asset at the same time, as this may lead to conflicts that cannot be resolved by `git` merging.
+
+
+
+## Status of prefab nodes
+
+__Prefab Nodes__ in the __Inspector__ panel render __green__ to indicate normal association with assets and render __red__ to indicate that the associated assets no longer exist.
+
+## Editing Prefab Nodes in a Scene
+
+### General Operations
+
+In the __Hierarchy__ panel, select the __Prefab Node__, and notice there are several buttons that can be clicked at the top of the __Inspector__ panel:
+
+
+
+| Button Icon | Description |
+| :--- | :--- |
+|  | Revert to __normal node__. __Prefab Instance__ can become ordinary __Nodes__, that is, completely separated from the relationship between assets. This function is also available in the top-level menu `Node`. Support batch disassociation in v3.4. |
+|  | Locating assets. It is convenient to quickly locate __Prefab Asset__ in the __Assets__ panel. |
+|  | Restore from asset. Restore the data of the current __Prefab Instance__ to the data in the __Prefab Asset__, but the name, location, and rotation will not be restored. |
+|  | Update to asset. Update all data of the current __Prefab Instance__ to the associated __Prefab Asset__. |
+
+### Add New Node
+
+A new node added under the __Prefab Instance__ will have a __+__ sign in the lower right corner of the node name, and its data is stored under the __Prefab Instance__, so it will not affect the data of the associated __Prefab Asset__.
+
+
+
+### Add New Component
+
+A new component added under the __Prefab Instance__ will have a **+** sign at the end of the node name, and its data is stored under the __Prefab Instance__, it will not affect the data of the associated __Prefab Asset__.
+
+
+
+### Remove Component
+
+A new component added under the __Prefab Instance__ will have a deleted data item show in the __Inspector__, its data is stored under the __Prefab Instance__, it will not affect the data of the associated __Prefab Asset__.
+
+
+
+It will show two buttons in the end of deleted data item:
+
+Button Icon | Description
+:--- | :---
+ | Revert the removed component.
+ | Apply the operation of removing the component to the associated __Prefab Asset__.
+
+## Some Current Restrictions
+
+- It is not allowed to delete the node created from the __Prefab Asset__ in the __Prefab Instance__.
+- It is not allowed to change the hierarchical relationship of nodes created from the __Prefab Asset__ in the __Prefab Instance__.
+- Do not allow prefabs to nest themselves.
diff --git a/versions/4.0/en/asset/prefab/apply-prefab-button.png b/versions/4.0/en/asset/prefab/apply-prefab-button.png
new file mode 100644
index 0000000000..14bbe2c0da
Binary files /dev/null and b/versions/4.0/en/asset/prefab/apply-prefab-button.png differ
diff --git a/versions/4.0/en/asset/prefab/apply-remove-component.png b/versions/4.0/en/asset/prefab/apply-remove-component.png
new file mode 100644
index 0000000000..e42783e37a
Binary files /dev/null and b/versions/4.0/en/asset/prefab/apply-remove-component.png differ
diff --git a/versions/4.0/en/asset/prefab/create-prefab.gif b/versions/4.0/en/asset/prefab/create-prefab.gif
new file mode 100644
index 0000000000..7b42b57359
Binary files /dev/null and b/versions/4.0/en/asset/prefab/create-prefab.gif differ
diff --git a/versions/4.0/en/asset/prefab/create.png b/versions/4.0/en/asset/prefab/create.png
new file mode 100644
index 0000000000..86ca61d3bd
Binary files /dev/null and b/versions/4.0/en/asset/prefab/create.png differ
diff --git a/versions/4.0/en/asset/prefab/edit-prefab.png b/versions/4.0/en/asset/prefab/edit-prefab.png
new file mode 100644
index 0000000000..83c10dbb9c
Binary files /dev/null and b/versions/4.0/en/asset/prefab/edit-prefab.png differ
diff --git a/versions/4.0/en/asset/prefab/instance-add-component.png b/versions/4.0/en/asset/prefab/instance-add-component.png
new file mode 100644
index 0000000000..b6c48344b0
Binary files /dev/null and b/versions/4.0/en/asset/prefab/instance-add-component.png differ
diff --git a/versions/4.0/en/asset/prefab/instance-remove-component.png b/versions/4.0/en/asset/prefab/instance-remove-component.png
new file mode 100644
index 0000000000..b192763ca7
Binary files /dev/null and b/versions/4.0/en/asset/prefab/instance-remove-component.png differ
diff --git a/versions/4.0/en/asset/prefab/locate-prefab-button.png b/versions/4.0/en/asset/prefab/locate-prefab-button.png
new file mode 100644
index 0000000000..bfd99f6179
Binary files /dev/null and b/versions/4.0/en/asset/prefab/locate-prefab-button.png differ
diff --git a/versions/4.0/en/asset/prefab/nested-prefab.png b/versions/4.0/en/asset/prefab/nested-prefab.png
new file mode 100644
index 0000000000..ed989bf6be
Binary files /dev/null and b/versions/4.0/en/asset/prefab/nested-prefab.png differ
diff --git a/versions/4.0/en/asset/prefab/persistent.png b/versions/4.0/en/asset/prefab/persistent.png
new file mode 100644
index 0000000000..e591262b53
Binary files /dev/null and b/versions/4.0/en/asset/prefab/persistent.png differ
diff --git a/versions/4.0/en/asset/prefab/prefab-asset.png b/versions/4.0/en/asset/prefab/prefab-asset.png
new file mode 100644
index 0000000000..a8fe20ce25
Binary files /dev/null and b/versions/4.0/en/asset/prefab/prefab-asset.png differ
diff --git a/versions/4.0/en/asset/prefab/prefab-edit-mode.gif b/versions/4.0/en/asset/prefab/prefab-edit-mode.gif
new file mode 100644
index 0000000000..2b3a543abf
Binary files /dev/null and b/versions/4.0/en/asset/prefab/prefab-edit-mode.gif differ
diff --git a/versions/4.0/en/asset/prefab/prefab-edit-mode.png b/versions/4.0/en/asset/prefab/prefab-edit-mode.png
new file mode 100644
index 0000000000..5204fc1a47
Binary files /dev/null and b/versions/4.0/en/asset/prefab/prefab-edit-mode.png differ
diff --git a/versions/4.0/en/asset/prefab/prefab-instance.png b/versions/4.0/en/asset/prefab/prefab-instance.png
new file mode 100644
index 0000000000..61a77415b7
Binary files /dev/null and b/versions/4.0/en/asset/prefab/prefab-instance.png differ
diff --git a/versions/4.0/en/asset/prefab/prefab-mounted-children.png b/versions/4.0/en/asset/prefab/prefab-mounted-children.png
new file mode 100644
index 0000000000..1721c66177
Binary files /dev/null and b/versions/4.0/en/asset/prefab/prefab-mounted-children.png differ
diff --git a/versions/4.0/en/asset/prefab/prefab-preview.png b/versions/4.0/en/asset/prefab/prefab-preview.png
new file mode 100644
index 0000000000..de89d431c4
Binary files /dev/null and b/versions/4.0/en/asset/prefab/prefab-preview.png differ
diff --git a/versions/4.0/en/asset/prefab/revert-prefab-button.png b/versions/4.0/en/asset/prefab/revert-prefab-button.png
new file mode 100644
index 0000000000..10107f5855
Binary files /dev/null and b/versions/4.0/en/asset/prefab/revert-prefab-button.png differ
diff --git a/versions/4.0/en/asset/prefab/revert-remove-component.png b/versions/4.0/en/asset/prefab/revert-remove-component.png
new file mode 100644
index 0000000000..0b10bbaff5
Binary files /dev/null and b/versions/4.0/en/asset/prefab/revert-remove-component.png differ
diff --git a/versions/4.0/en/asset/prefab/unlink-prefab-button.png b/versions/4.0/en/asset/prefab/unlink-prefab-button.png
new file mode 100644
index 0000000000..254f2ec0a5
Binary files /dev/null and b/versions/4.0/en/asset/prefab/unlink-prefab-button.png differ
diff --git a/versions/4.0/en/asset/prefab/use-prefab.gif b/versions/4.0/en/asset/prefab/use-prefab.gif
new file mode 100644
index 0000000000..bf9284a350
Binary files /dev/null and b/versions/4.0/en/asset/prefab/use-prefab.gif differ
diff --git a/versions/4.0/en/asset/preload-load.md b/versions/4.0/en/asset/preload-load.md
new file mode 100644
index 0000000000..7844d9676c
--- /dev/null
+++ b/versions/4.0/en/asset/preload-load.md
@@ -0,0 +1,26 @@
+# Loading and Preloading
+
+> Author: Santy-Wang, Xunyi
+
+In order to minimize download times, most of the loading interfaces in Asset Manager, including `load`, `loadDir`, and `loadScene` have their own corresponding preloaded versions. The parameters used for the loading interfaces and the preloading interfaces are exactly the same, with the following differences:
+
+1. Preloading will only download the resources and will not parse or initialize them.
+2. Preloading will be more limited during the loading process, e.g.: the maximum number of download concurrently will be smaller.
+3. Preloading has a lower priority, and when multiple resources are waiting to be downloaded, the preloaded resources will be downloaded last.
+4. Since the preload does not do any parsing, no available resources are returned when all the preloads load are complete.
+
+Compared to previous versions of Creator v2.4, these optimizations reduce the preloading performance loss and ensure a smooth gaming experience. You can make full use of the network bandwidth during the game to reduce the loading time of subsequent resources.
+
+Since the preload does not parse the resources, you need to parse and initialize the resources with the loading interface to complete the resource loading after the preload is complete. For example:
+
+```typescript
+resources.preload('images/background/spriteFrame', SpriteFrame);
+
+// Wait for while
+resources.load('images/background/spriteFrame', SpriteFrame, function (err, spriteFrame) {
+ spriteFrame.addRef();
+ self.getComponent(Sprite).spriteFrame = spriteFrame;
+});
+```
+
+> **Note**: loading does not need to wait until the preload is complete, you can load at any time. The normal loading interface will directly reuse the content that was already downloaded during the preload process, reducing the load time
diff --git a/versions/4.0/en/asset/release-manager.md b/versions/4.0/en/asset/release-manager.md
new file mode 100644
index 0000000000..24f903713e
--- /dev/null
+++ b/versions/4.0/en/asset/release-manager.md
@@ -0,0 +1,134 @@
+# Releasing of Resources
+
+> Author: Santy-Wang, Xunyi
+
+A resource release module is provided in Asset Manager to manage the release of resources.
+
+When a resource is loaded, it is temporarily cached in `assetManager` for the next reuse. However, this also causes a constant growth in memory and video memory, so some resources can be released either by **Auto Release** or **Manual Release** if you don't need to use them.
+
+Releasing a resource will destroy all internal properties of the resource, such as data associated with the rendering layer, and move out of the cache, thus freeing up memory and video memory (for textures).
+
+**First and most important: Resources depends on each other.**
+
+For example, in the following graph, the Prefab resource contains the Sprite component, the Sprite component depends on the SpriteFrame, the SpriteFrame resource depends on the Texture resource, then the Prefab, SpriteFrame, and Texture resources are all cached by the `assetManager`. The advantage of doing so is that there may be another SpriteAtlas resource that depends on the same SpriteFrame and Texture, then when you manually load the SpriteAtlas, `assetManager` do not need to request the existing SpriteFrame and Texture again it will use the cache directly.
+
+
+
+## Auto Release
+
+The automatic release of a scene can be set directly in the editor. When you select the scene in the **Assets** panel, the **Auto Release Assets** option appears in the **Properties** panel.
+
+
+
+Once checked, click the **Apply** button on the top right, and then all dependent resources of the scene will be automatically released when you switch the scene. It is recommended to check the **Auto Release Assets** option for all scenes to ensure low memory consumption, except for some high usage scenes (such as the main scene).
+
+In addition, all `Asset` instances have member functions `Asset.addRef` and `Asset.decRef` for increasing and decreasing the reference count, respectively. Once the reference count is 0, Creator will automatically release the resource (it needs to pass a release check first, see the following section for details)
+
+```typescript
+start () {
+ resources.load('images/background/texture', Texture2D, (err, texture) => {
+ this.texture = texture;
+ // Add references to resources when you need to use them.
+ texture.addRef();
+ // ...
+ });
+}
+
+onDestroy () {
+ // Reduce references to resources when you don't need to use them. Creator will try to auto-release them after calling decRef.
+ this.texture.decRef();
+}
+```
+
+The advantage of auto-release is that you don't have to explicitly call the release interface, you just need to maintain the reference count of the resource and Creator will release it automatically based on the reference count. This greatly reduces the possibility of releasing resources by mistake, and you don't need to understand the complex referencing relationships between resources. For projects with no special requirements, it is recommended that you use automatic release to release resources as much as possible.
+
+### Release Check
+
+To prevent rendering or other problems caused by incorrectly releasing resources being used, Creator will perform a series of checks before auto-releasing resources:
+
+1. If the reference count of the resource is 0, that is, there are no references to it elsewhere, then no follow-up check is required, the resource is destroyed directly and the cache is removed.
+
+2. Once the resource is removed, a release check for its dependent resources is triggered synchronously, and the reference counts of all direct dependent resources (excluding descendants) of the resource after the cache is removed are reduced by 1, and a release check is triggered synchronously.
+
+3. If the reference count of the resource is not 0, that is, there are references to it elsewhere, a circular reference check is required at this point to avoid having its own offspring refer to it. If the reference count is still not 0 after the cyclic reference check, terminate the release. Otherwise, destroy the resource directly, remove the cache, and trigger a release check for its dependent resources (as in step 2).
+
+### Manual Release
+
+When a more complex resource release mechanism is used in a project, you can call the relevant interfaces of the Asset Manager to manually release resources. For example:
+
+```typescript
+assetManager.releaseAsset(texture);
+```
+
+Since the resource management module was upgraded in v2.4, the release interface differs slightly from the previous version:
+
+1. The `assetManager.releaseAsset` interface can only release a single resource, and for the sake of uniformity, the interface can only release resources through the resource itself, not via attributes such as resource UUID, resource url, etc.
+
+2. When releasing a resource, you only need to focus on the resource itself and the engine will automatically release its dependent resources instead of fetching them manually via `getDependsRecursively`.
+
+> **Note**: the `release` series interfaces (such as `release`, `releaseAsset`, `releaseAll`) will release the resource directly without a release check, only resource's dependent resources will have a release check. So when the `release` series interfaces are called explicitly, you can be sure that the resource itself will always be released.
+
+## Reference Count Statistics
+
+Before v2.4, Creator chose to give the developer control over the release of all resources, both the resource itself and its dependencies, and the developer had to manually obtain all the dependencies of the resource and select the dependencies to be released. This way gave the developer the most control, and worked well for small projects. But as Creator grows, the size of the project grows, the resources referenced by the scene grows, and other scenes may reuse those resources, which causes increasing complexity in releasing resources and it is very difficult for the developer to master the usage of all resources.
+
+To address this pain point, the Asset Manager provides a set of resource release mechanism based on the reference counting, so that developers can release resources simply and efficiently, without worrying about rapid expansion of the project size.
+It should be noted that the Asset Manager only automatically counts static references between resources and does not truly reflect how the resources are dynamically referenced in the game, you need to control the dynamic references yourself to ensure that the resources are released correctly. The reasons are as follows:
+
+- JavaScript is a language with a garbage collection mechanism that manages its memory, so the engine has no way of knowing if a resource has been destroyed in the browser environment.
+- JavaScript does not provide the assignment operator overloading, which the reference count statistics are highly dependent on.
+
+### Static Referencing of Resources
+
+When you edit the resources in the editor (such as the scene, prefab, material, etc.), you need to configure some other resources in the properties of those resources, such as setting the texture in the materials, setting the SpriteFrame on the Sprite component of the scene. Then these references will be recorded in the serialized data of the resources, which the engine can use to analyze the list of dependent resources, and a reference relationship like this is the static reference.
+
+The statistics for the static references of resources by the engine are as follows:
+
+1. When loading a resource using `assetManager` or Asset Bundle, the engine records all **direct dependent resources** for the resource in the underlying load pipe, adds 1 to the reference count of all **direct dependent resources**, and then initializes the reference count to 0 for the resource.
+
+2. When releasing a resource, obtain all the **direct dependent resources** information recorded previous for the resource, and subtract the reference count of all dependent resources by 1.
+
+This is because a resource can only be auto-released if its reference count is 0 in the release check. So the above steps ensure that the dependent resources of the resource cannot be released before the resource itself, because the reference count of the dependent resources is definitely not 0. That is, as long as a resource itself is not released, its dependent resources will not be released, thus ensuring that the release will not be done incorrectly when reusing the resource. For example:
+
+1. Suppose you now have a Prefab A that depends on both Material a and Material b. Material a references Texture α, and Material b references Texture β. After loading Prefab A, the reference count for both Material a and Material b are 1, and the reference count for both Texture α and Texture β are also 1.
+
+ 
+
+2. Suppose you now add a Prefab B that depends on both Material b and Material c. After you load the Prefab B, the reference count to Material b is 2, because it is referenced by both the Prefab A and B. The reference count to Material c is 1, and the reference counts for Textures α and β are still 1.
+
+ 
+
+3. When the Prefab A is released, the reference count for the Materials a and b each decreases by 1.
+ - The reference count of the Material a changes to 0 and is released; so the reference count of the Texture α minus 1 changes to 0 and is also released.
+ - The reference count of the Material b changes to 1 and is retained, so the reference count of the Texture β is still 1 and is also retained.
+ - Because the Prefab B is not released, the reference count for the Material c remains at 1 and is retained.
+
+ 
+
+### Dynamic Referencing of Resources
+
+When you do not make any settings for a resource in the editor, but instead dynamically load the resource and set it to the component of the scene via code, the reference relationships of the resource are not recorded in the serialization data, and the engine cannot count this part of the reference relationships, which are dynamic references.
+
+If you are using dynamically loaded resources in your project for dynamic referencing, for example:
+
+```typescript
+resources.load('images/background/spriteFrame', SpriteFrame, function (err, spriteFrame) {
+ self.getComponent(Sprite).spriteFrame = spriteFrame;
+});
+```
+
+At this point, the SpriteFrame resource is set to the Sprite component and the engine does not do anything special, the reference count of the SpriteFrame remains 0. If the dynamically loaded resources need to be referenced, held, or reused over time, it is recommended to use the `addRef` interface to manually increase the reference count. For example:
+
+```typescript
+resources.load('images/background/spriteFrame', SpriteFrame, function (err, spriteFrame) {
+ self.getComponent(Sprite).spriteFrame = spriteFrame;
+ spriteFrame.addRef();
+});
+```
+
+Increasing the reference count ensures that the resource will not be released early by mistake. Always remember to use `decRef` to remove the reference count and set the resource reference to `null` if you do not need to reference the resource and related components, or if the node is destroyed. For example:
+
+```typescript
+this.spriteFrame.decRef();
+this.spriteFrame = null;
+```
diff --git a/versions/4.0/en/asset/release-manager/auto-release.png b/versions/4.0/en/asset/release-manager/auto-release.png
new file mode 100644
index 0000000000..23f6dddb3d
Binary files /dev/null and b/versions/4.0/en/asset/release-manager/auto-release.png differ
diff --git a/versions/4.0/en/asset/release-manager/pica.png b/versions/4.0/en/asset/release-manager/pica.png
new file mode 100644
index 0000000000..b51f82075d
Binary files /dev/null and b/versions/4.0/en/asset/release-manager/pica.png differ
diff --git a/versions/4.0/en/asset/release-manager/picb.png b/versions/4.0/en/asset/release-manager/picb.png
new file mode 100644
index 0000000000..dd0f43d691
Binary files /dev/null and b/versions/4.0/en/asset/release-manager/picb.png differ
diff --git a/versions/4.0/en/asset/release-manager/picc.png b/versions/4.0/en/asset/release-manager/picc.png
new file mode 100644
index 0000000000..063aacc9d4
Binary files /dev/null and b/versions/4.0/en/asset/release-manager/picc.png differ
diff --git a/versions/4.0/en/asset/render-texture.md b/versions/4.0/en/asset/render-texture.md
new file mode 100644
index 0000000000..8a56955b9b
--- /dev/null
+++ b/versions/4.0/en/asset/render-texture.md
@@ -0,0 +1,147 @@
+# Render Texture
+
+A render texture is a texture on the GPU. Usually, we set it to the camera's **target texture**, so that the content illuminated by the camera is drawn to the texture via an off-screen `frambuffer`. This can typically be used to create car mirrors, dynamic shadows, etc.
+
+## Creating a RenderTexture
+
+Click the __+__ button in the top left of the __Assets__ panel and select __RenderTexture__ to create a Render Texture:
+
+
+
+The properties associated with the render texture asset can then be set in the __Inspector__ panel.
+
+
+
+| Property | Description |
+| :--- | :--- |
+| __Width__ | Set the width of the render texture. |
+| __Height__ | Set the height of the render texture. |
+| __Anisotropy__ | Anisotropy value. |
+| __Min Filter__ | Narrowing filtering algorithm. |
+| __Mag Filter__ | Amplification filtering algorithm. |
+| __Mip Filter__ | Multi-level texture filtering algorithm. |
+| __Wrap Mode S__ | S(U) direction texture addressing mode. |
+| __Wrap Mode T__ | T(V) direction texture addressing mode. |
+
+## Use RenderTexture in editor
+
+In the camera component, assigning RenderTexture to the camera's __TargetTexture__ property will draw the result of the camera's illumination onto the RenderTexture.
+
+
+
+### Use RenderTexture in 2D / UI
+
+RenderTexture can be used like a normal texture. Take __Sprite Component__ as an example, drag and drop from __Assets__ panel onto the __SpriteFrame__ property on Sprite's __Inspector__ panel.
+
+
+
+## Use RenderTexture in material
+
+To use RenderTexture in material includes the following two steps:
+
+1. Handle uv in __effect__ asset. Determine `SAMPLE_FROM_RT`, and call the `CC_HANDLE_RT_SAMPLE_FLIP` function:
+
+ ```
+ #if USE_TEXTURE
+ v_uv = a_texCoord * tilingOffset.xy + tilingOffset.zw;
+ #if SAMPLE_FROM_RT
+ CC_HANDLE_RT_SAMPLE_FLIP(v_uv);
+ #endif
+ #endif
+ ```
+
+2. Select the corresponding material in the __Assets__ panel, then check `SAMPLE FROM RT` in the __Inspector__ panel:
+
+ 
+
+## RenderTexture program guide
+
+There are two ways to use RenderTexture programmatically:
+
+- __Method 1__: Draw the contents illuminated by the 3D camera to the sprite frame of the UI.
+
+ ```typescript
+ import { _decorator, Component, RenderTexture, SpriteFrame, Sprite, Camera } from 'cc';
+ const { ccclass, property } = _decorator;
+
+ @ccclass('CaptureToWeb')
+ export class CaptureToWeb extends Component {
+ @property(Sprite)
+ sprite: Sprite = null;
+ @property(Camera)
+ camera: Camera = null;
+
+ protected _renderTex: RenderTexture = null;
+
+ start() {
+ const sp = new SpriteFrame();
+ const renderTex = this._renderTex = new RenderTexture();
+ renderTex.reset({
+ width: 256,
+ height: 256,
+ });
+ this.camera.targetTexture = renderTex;
+ sp.texture = renderTex;
+ this.sprite.spriteFrame = sp;
+ }
+ }
+ ```
+
+- __Method 2__: Draw the contents illuminated by the 3D camera to the 3D model.
+
+ ```typescript
+ import { _decorator, Component, MeshRenderer, RenderTexture, Camera, Material } from 'cc';
+ const { ccclass, property, requireComponent } = _decorator;
+
+ @ccclass("RenderCameraToModel")
+ @requireComponent(Camera)
+ export class RenderCameraToModel extends Component {
+ @property(MeshRenderer)
+ model: MeshRenderer = null;
+
+ start() {
+ const renderTex = new RenderTexture();
+ renderTex.reset({
+ width: 256,
+ height: 256,
+ });
+ const cameraComp = this.getComponent(Camera);
+ cameraComp.targetTexture = renderTex;
+ const pass = this.model.material.passes[0];
+ // The purpose of setting the 'SAMPLE_FROM_RT' Macro to 'true' is to enable the RenderTexture to display correctly on all platforms
+ const defines = { SAMPLE_FROM_RT: true, ...pass.defines };
+ const renderMat = new Material();
+ renderMat.initialize({
+ effectAsset: this.model.material.effectAsset,
+ defines,
+ });
+ this.model.setMaterial(renderMat, 0);
+ renderMat.setProperty('mainTexture', renderTex, 0);
+ }
+ }
+ ```
+- __Method 3__:Read the content drawn by the 3D camera into the ArrayBuffer through the readPixels method
+
+ ```typescript
+ import { _decorator, Component, RenderTexture } from 'cc';
+ const { ccclass, property } = _decorator;
+
+ @ccclass("RenderReadPixels")
+ export class RenderReadPixels extends Component {
+ @property(RenderTexture)
+ public renderTexture: RenderTexture;
+ start() {
+ const width = this.renderTexture.width;
+ const height = this.renderTexture.height;
+ const texPixels = new Uint8Array(width * height * 4);
+ this.renderTexture.readPixels(0, 0,
+ this.renderTexture.width, this.renderTexture.height,
+ texPixels);
+ }
+ }
+ ```
+ Make sure that the shader has a `mainTexture` property and is enabled in the material if you want to display the drawing results correctly. For example, if using the `builtin-standard` shader, make sure the __USE ALBEDO MAP__ option is checked:
+
+ 
+
+For more information about the usage, please refer to the example **RenderTexture** ([GitHub](https://github.com/cocos/cocos-test-projects/tree/v3.8/assets/cases/rendertexture)).
diff --git a/versions/4.0/en/asset/render-texture/SampleFormRT.png b/versions/4.0/en/asset/render-texture/SampleFormRT.png
new file mode 100644
index 0000000000..82da886d34
Binary files /dev/null and b/versions/4.0/en/asset/render-texture/SampleFormRT.png differ
diff --git a/versions/4.0/en/asset/render-texture/add-render-texture.png b/versions/4.0/en/asset/render-texture/add-render-texture.png
new file mode 100644
index 0000000000..904f5cf6f3
Binary files /dev/null and b/versions/4.0/en/asset/render-texture/add-render-texture.png differ
diff --git a/versions/4.0/en/asset/render-texture/camera.png b/versions/4.0/en/asset/render-texture/camera.png
new file mode 100644
index 0000000000..71368ff093
Binary files /dev/null and b/versions/4.0/en/asset/render-texture/camera.png differ
diff --git a/versions/4.0/en/asset/render-texture/render-texture-property.png b/versions/4.0/en/asset/render-texture/render-texture-property.png
new file mode 100644
index 0000000000..6c61f52114
Binary files /dev/null and b/versions/4.0/en/asset/render-texture/render-texture-property.png differ
diff --git a/versions/4.0/en/asset/render-texture/sprite-rt.png b/versions/4.0/en/asset/render-texture/sprite-rt.png
new file mode 100644
index 0000000000..a4c23ed7b9
Binary files /dev/null and b/versions/4.0/en/asset/render-texture/sprite-rt.png differ
diff --git a/versions/4.0/en/asset/render-texture/use-albedo.png b/versions/4.0/en/asset/render-texture/use-albedo.png
new file mode 100644
index 0000000000..553c3883d6
Binary files /dev/null and b/versions/4.0/en/asset/render-texture/use-albedo.png differ
diff --git a/versions/4.0/en/asset/scene.md b/versions/4.0/en/asset/scene.md
new file mode 100644
index 0000000000..0e662bfcfa
--- /dev/null
+++ b/versions/4.0/en/asset/scene.md
@@ -0,0 +1,73 @@
+# Scene Assets
+
+In **Cocos Creator**, the **Scene** is the cornerstone for organizing game content during development, and presenting all game content to the players. The **Scene** itself is a file, also considered a game asset, and saves most of the game's information.
+
+> **Note**: please avoid multiple people modifying the same scene asset at the same time, as this may lead to conflicts that cannot be resolved by `git` merging.
+
+## Creating a Scene
+
+There are **three** ways to create a **Scene**:
+
+1. Select the folder to create the **Scene** file in the **Assets** panel. On the folder right-click and select **Create -> Scene**, and then type the desired **Scene** name.
+
+ 
+
+ In order to have a good directory structure in the project, it is strongly recommended that use this method to create a **Scene**.
+
+2. Click the **Create (+)** button in the upper left corner of the **Assets** panel, and then select **Scene**.
+
+ 
+
+3. Select **File -> New Scene** in the top menu bar, a new scene will be created directly in the **Scene** panel. But the new scene file will not appear in the **Assets** panel, it is required to save the scene file manually in the **Save Scene** window that pops up when saving the scene, and the `scene.scene` file will appear in the root directory of the **Assets** panel only after the saving is done.
+
+ 
+
+## Saving a Scene
+
+Method 1: Use the shortcut keys Ctrl + S (Windows) or Command + S (MacOS) to quickly save the scene.
+
+Method 2: Select **File -> Save Scene** in the top menu bar.
+
+## Switching Scenes
+
+In the **Assets** panel, **double-click** the **Scene** to be opened.
+When needing to switch **Scenes** in the game, use the [director.loadScene()](%__APIDOC__%/en/class/Director?id=loadScene) API to implement dynamic scene loading and switching in the game.
+
+## Scene Properties
+
+After double-clicking to open the **scene** file, the `scene` is the root node of the scene node tree in the **Hierarchy** panel. Select the `scene` node, and set whether the scene is automatically released or not in the **Inspector** panel, as well as the whole scene related properties, including **ambient light** settings, **shadows** settings, **global fog** and **sky box** settings.
+
+
+
+Automatic release of scene assets, please refer to section **Change the policy of auto releasing assets from previous scene** below for details.
+
+For a detailed description of each property, see the following documentations:
+
+- [Ambient light](../concepts/scene/light/lightType/ambient.md)
+- [Shadow](../concepts/scene/light/shadow.md)
+- [Global Fog](../concepts/scene/fog.md)
+- [Skybox](../concepts/scene/skybox.md)
+- [Native Scene Culling](../advanced-topics/native-scene-culling.md)
+
+## Change the Policy of Auto Releasing Assets from Previous Scene
+
+In a large game where there are many scenes, as the engine continues to load different scenes, the memory usage will continue to increase. Besides using API such as `assetManager.releaseAsset` to accurately release unused assets, one can also use scene's auto releasing feature.
+
+After double-clicking to open the scene file, select the `scene` node in the **Hierarchy** panel to set whether the scene is automatically released in the **Inspector** panel:
+
+
+
+When switching from current scene to the next scene, if current scene disabled the auto releasing, then all assets (directly or indirectly) referenced by current scene (except loaded dynamically in scripts) will not release by default. On the other hand, if enable the auto releasing, then these assets will release by default.
+
+### Prevent auto releasing for some specified assets
+
+With the auto releasing enabled for a scene, if some of the scene's assets are saved in the script as "special reference", these references will become invalid once the scene switched, since the asset has been released, may cause rendering problems. To prevent these assets from being released automatically, we can use [Asset.addRef](%__APIDOC__%/en/class/Asset?id=addRef) to retain them.
+
+> "Special reference" refer to references in the form of global variables, singleton, closures, "dynamic assets", and so on.
+> "Dynamic assets" refer to assets that are dynamically created or dynamically modified in a script.
+
+The above content of the automatic release of scene assets can be summed up in the following diagram of several cases:
+
+
+
+For additional information on asset release, please refer to the [Release of Assets](./release-manager.md#auto-release) documentation.
diff --git a/versions/4.0/en/asset/scene/enable-extension.png b/versions/4.0/en/asset/scene/enable-extension.png
new file mode 100644
index 0000000000..ae6450541f
Binary files /dev/null and b/versions/4.0/en/asset/scene/enable-extension.png differ
diff --git a/versions/4.0/en/asset/scene/new_scene_1.png b/versions/4.0/en/asset/scene/new_scene_1.png
new file mode 100644
index 0000000000..e601708be7
Binary files /dev/null and b/versions/4.0/en/asset/scene/new_scene_1.png differ
diff --git a/versions/4.0/en/asset/scene/new_scene_2.png b/versions/4.0/en/asset/scene/new_scene_2.png
new file mode 100644
index 0000000000..64be724193
Binary files /dev/null and b/versions/4.0/en/asset/scene/new_scene_2.png differ
diff --git a/versions/4.0/en/asset/scene/new_scene_3.png b/versions/4.0/en/asset/scene/new_scene_3.png
new file mode 100644
index 0000000000..565c953d4b
Binary files /dev/null and b/versions/4.0/en/asset/scene/new_scene_3.png differ
diff --git a/versions/4.0/en/asset/scene/release-assets.png b/versions/4.0/en/asset/scene/release-assets.png
new file mode 100644
index 0000000000..c9b59857b7
Binary files /dev/null and b/versions/4.0/en/asset/scene/release-assets.png differ
diff --git a/versions/4.0/en/asset/scene/scene_node.png b/versions/4.0/en/asset/scene/scene_node.png
new file mode 100644
index 0000000000..fd090ce009
Binary files /dev/null and b/versions/4.0/en/asset/scene/scene_node.png differ
diff --git a/versions/4.0/en/asset/scene/scene_node_set.png b/versions/4.0/en/asset/scene/scene_node_set.png
new file mode 100644
index 0000000000..af7dbe2d37
Binary files /dev/null and b/versions/4.0/en/asset/scene/scene_node_set.png differ
diff --git a/versions/4.0/en/asset/script.md b/versions/4.0/en/asset/script.md
new file mode 100644
index 0000000000..00ab1ddc9e
--- /dev/null
+++ b/versions/4.0/en/asset/script.md
@@ -0,0 +1,7 @@
+# Script Assets
+
+In __Cocos Creator__, scripts are also part of the __Asset__.
+
+For a detailed introduction to __scripting__, please refer to the [Scripting Guide](../scripting/index.md) documentation.
+
+For details on the creation and use of __script assets__, please refer to the [Script Creation](../scripting/setup.md) documentation.
diff --git a/versions/4.0/en/asset/spine.md b/versions/4.0/en/asset/spine.md
new file mode 100644
index 0000000000..3fc543583c
--- /dev/null
+++ b/versions/4.0/en/asset/spine.md
@@ -0,0 +1,82 @@
+# Skeletal Animation Assets (Spine)
+
+Skeletal animation assets in Creator are exported from [Spine](http://esotericsoftware.com/), which currently supports the [JSON](http://esotericsoftware.com/spine-export/#JSON) and [binary](http://esotericsoftware.com/spine-export/#%E4%BA%8C%E8%BF%9B%E5%88%B6) data formats.
+
+The supported Spine versions for each Creator version are as follows:
+
+| Creator Version | Spine Version |
+| :---------- | :-------- |
+| v3.0 and above | v3.8 (v3.8.75 is not supported on the native platform) |
+| v2.3 and above | v3.8 |
+| v2.2 | v3.7 |
+| v2.0.8 to v2.1 | v3.6 |
+| v2.0.7 and below | v2.5 |
+
+## Import Skeletal Animation Assets
+
+The assets required for skeletal animation are:
+
+- `.json/.skel` skeletal data
+- `.png` atlas textures
+- `.txt/.atlas` atlas data
+
+ 
+
+## Spine Preview
+
+In version 3.8.5, we have added preview support to the inspector panel of Spine. After users select a certain Spine file, they can see the corresponding rendering content in the panel, which can greatly improve the efficiency of resource inspection.
+
+
+
+## Create Skeletal Animation
+
+Drag the skeletal animation asset from the **Assets** panel to the `SkeletonData` property of the spine component in the **Inspector** panel.
+
+
+
+## How to load Spine remotely from a server
+
+### Load the Spine assets in json format
+
+```ts
+let comp = this.getComponent('sp.Skeleton') as sp.Skeleton;
+
+let image = "http://localhost/download/spineres/1/1.png";
+let ske = "http://localhost/download/spineres/1/1.json";
+let atlas = "http://localhost/download/spineres/1/1.atlas";
+assetManager.loadAny([{ url: atlas, ext: '.txt' }, { url: ske, ext: '.txt' }], (error, assets) => {
+ assetManager.loadRemote(image, (error, img: ImageAsset) => {
+ let texture = new Texture2D();
+ texture.image = img;
+ asset.skeletonJson = assets[1];
+ asset.atlasText = assets[0];
+ asset.textures = [texture];
+ asset.textureNames = ['1.png'];
+ asset._uuid = ske; // Any string can be passed in, but it cannot be empty.
+ skeleton.skeletonData = asset;
+ });
+});
+```
+
+### Load the Spine assets in binary format
+
+```ts
+let comp = this.getComponent('sp.Skeleton') as sp.Skeleton;
+
+let image = "http://localhost/download/spineres/1/1.png";
+let ske = "http://localhost/download/spineres/1/1.skel";
+let atlas = "http://localhost/download/spineres/1/1.atlas";
+assetManager.loadAny([{ url: atlas, ext: '.txt' }, { url: ske, ext: '.bin' }], (error, assets) => {
+ assetManager.loadRemote(image, (error, texture: Texture2D) => {
+ let asset = new sp.SkeletonData();
+ asset._nativeAsset = assets[1];
+ asset.atlasText = assets[0];
+ asset.textures = [texture];
+ asset.textureNames = ['1.png'];
+ asset._uuid = ske; // Any string can be passed in, but it cannot be empty.
+ asset._nativeURL = ske; // Pass in a binary path to be used as the 'filePath' parameter when using 'initSkeleton'.
+ comp.skeletonData = asset;
+ let ani = comp.setAnimation(0, 'walk', true);
+ });
+});
+```
diff --git a/versions/4.0/en/asset/spine/import.png b/versions/4.0/en/asset/spine/import.png
new file mode 100644
index 0000000000..a1f2340347
Binary files /dev/null and b/versions/4.0/en/asset/spine/import.png differ
diff --git a/versions/4.0/en/asset/spine/set_skeleton.png b/versions/4.0/en/asset/spine/set_skeleton.png
new file mode 100644
index 0000000000..61e9dfbc63
Binary files /dev/null and b/versions/4.0/en/asset/spine/set_skeleton.png differ
diff --git a/versions/4.0/en/asset/spine/spine-preview.png b/versions/4.0/en/asset/spine/spine-preview.png
new file mode 100644
index 0000000000..fe8a1c69bc
Binary files /dev/null and b/versions/4.0/en/asset/spine/spine-preview.png differ
diff --git a/versions/4.0/en/asset/sprite-frame.md b/versions/4.0/en/asset/sprite-frame.md
new file mode 100644
index 0000000000..1828ed7df8
--- /dev/null
+++ b/versions/4.0/en/asset/sprite-frame.md
@@ -0,0 +1,110 @@
+# Sprite Frame Assets
+
+**Sprite Frame** is a container for UI rendering and basic graphics, which manages the clipping and tiling data. It by default holds a reference to a Texture2D asset of the same level as it.
+
+## Importing Sprite Frame Assets
+
+Use the default [asset import](asset-workflow.md) method to import image assets into the project, then set the type of image as **sprite-frame** in the **Inspector**, and save it by clicking the green checkmark button in the upper right corner.
+
+
+
+Creator will automatically create a **spriteFrame** asset under the imported image assets as shown below.
+
+
+
+An image asset will have a thumbnail of its own image as icon in **Assets**. When an image sub-asset is selected in **Assets**, a thumbnail of the image is displayed below the **Inspector**.
+
+## Property
+
+The `spriteFrame` has the following properties:
+
+| Property | Description |
+| :--- | :--- |
+| Packable | Whether to participate in Dynamic Atlas and automatic atlas building processes. Please refer to the **Packable** section below for details. |
+| Rotated | Read-only property, cannot be changed. Used to see if the sub-asset in the Texture Packer asset is rotated. |
+| Offset X, Y | Read-only property, cannot be changed. Used to view the offset of the rectangle in Texture Packer asset. |
+| Trim Type | Set the trim type, including: 1. Auto -- Automatic trim. For details, please refer to the [Auto Trim for SpriteFrame](../ui-system/components/engine/trim.md) documentation. 2. Custom -- Custom trim 3. None -- No trim, use original texture. |
+| Trim Threshold | Set the transparency threshold, trim off the pixels whose transparency is below the set value. The default value is 1, and the range of values is 0~1. Only takes effect when **Trim Type** is set to **Auto**. |
+| Trim X, Y, Width, Height | Sets the trim rect, only takes effect when **Trim Type** is set to **Custom**. |
+| Border Top, Bottom, Left, Right | Set the texture margins of the 9-sliced, which can be edited visually by clicking on the **Edit** button below. |
+
+### Packable
+
+If the engine has [Dynamic-Atlas](../advanced-topics/dynamic-atlas.md) enabled, Dynamic-Atlas will automatically merge the appropriate textures into one large texture at the start of the scene to reduce Drawcall. If the UV coordinates of the texture are used in the custom `effect`, the UV calculation in the `effect` will be wrong and the **Packable** property of the texture needs to be set to **false** to prevent the texture from being packed into the Dynamic-Atlas.
+
+## Using a Sprite Frame
+
+### The object contained in the container is using textures
+
+In the editor, drag the SpriteFrame assets into the **SpriteFrame** property of the [Sprite Component](../ui-system/components/editor/sprite.md) to switch the image displayed by Sprite.
+
+
+
+At runtime, taking the imported image named **content** above as an example, the entire asset is divided into three parts:
+
+- **content**:Image source assets ImageAsset
+- Sub-asset **spriteFrame** of **content**, the sprite frame asset SpriteFrame
+- Sub-asset **texture** of **content**, the mapping asset Texture2D
+
+When assets are stored in the `resources` directory, we can load directly to the spriteFrame asset with the following code example.
+
+```typescript
+const url = 'test_assets/test_atlas/content/spriteFrame';
+resources.load(url, SpriteFrame, (err: any, spriteFrame) => {
+ const sprite = this.getComponent(Sprite);
+ sprite.spriteFrame = spriteFrame;
+});
+```
+
+In some cases only the source ImageAsset can be loaded, so we provide the [createWithImage](%__APIDOC__%/en/class/SpriteFrame?id=createWithImage) method to help users create a SpriteFrame asset from the loaded ImageAsset. Depending on the source of the ImageAsset, there are two ways to create it:
+
+1. Assets on the server can only be loaded to the source ImageAsset. For specific methods, please refer to the [dynamic load asset](./dynamic-load-resources.md) documentation. The code example for creating a SpriteFrame asset is as follows:
+
+ ```typescript
+ const self = this;
+ const url = 'test_assets/test_atlas/content';
+ resources.load(url, ImageAsset, (err: any, imageAsset) => {
+ const sprite = this.getComponent(Sprite);
+ sprite.spriteFrame = SpriteFrame.createWithImage(imageAsset);
+ });
+ ```
+
+ Users can also fill in the information manually. Example:
+
+ ```typescript
+ const self = this;
+ const url = 'test_assets/test_atlas/content';
+ resources.load(url, ImageAsset, (err: any, imageAsset) => {
+ const sprite = this.getComponent(Sprite);
+ const spriteFrame = new SpriteFrame();
+ const tex = new Texture2D();
+ tex.image = imageAsset;
+ spriteFrame.texture = tex;
+ sprite.spriteFrame = spriteFrame;
+ });
+ ```
+
+2. Create from an ImageAsset drawn by Canvas. Example:
+
+ ```typescript
+ const sprite = this.getComponent(Sprite);
+ sprite.spriteFrame = SpriteFrame.createWithImage(canvas);
+ ```
+
+ Users can also fill in the information manually. Example:
+
+ ```typescript
+ const sprite = this.getComponent(Sprite);
+ const img = new ImageAsset(canvas);
+ const tex = new Texture2D();
+ tex.image = img;
+ const sp = new SpriteFrame();
+ sp.texture = tex;
+ sprite.spriteFrame = sp;
+ ```
+
+### The container contains objects that are used by RenderTexture
+
+RenderTexture is a rendering texture that renders content from the camera directly to a texture instead of the screen. SpriteFrame can easily display 3D camera content on the UI by managing RenderTexture. For specific usage and code example, please refer to [Render Texture](render-texture.md).
+
+For API information, please refer to the [SpriteFrame](%__APIDOC__%/en/class/SpriteFrame) documentation.
diff --git a/versions/4.0/en/asset/sprite-frame/set-spriteframe.png b/versions/4.0/en/asset/sprite-frame/set-spriteframe.png
new file mode 100644
index 0000000000..7b0e3924e1
Binary files /dev/null and b/versions/4.0/en/asset/sprite-frame/set-spriteframe.png differ
diff --git a/versions/4.0/en/asset/sprite-frame/spriteframe.png b/versions/4.0/en/asset/sprite-frame/spriteframe.png
new file mode 100644
index 0000000000..f7abdeee29
Binary files /dev/null and b/versions/4.0/en/asset/sprite-frame/spriteframe.png differ
diff --git a/versions/4.0/en/asset/sprite-frame/use-spriteframe.png b/versions/4.0/en/asset/sprite-frame/use-spriteframe.png
new file mode 100644
index 0000000000..0bb011a738
Binary files /dev/null and b/versions/4.0/en/asset/sprite-frame/use-spriteframe.png differ
diff --git a/versions/4.0/en/asset/subpackage-upgrade-guide.md b/versions/4.0/en/asset/subpackage-upgrade-guide.md
new file mode 100644
index 0000000000..a656a41623
--- /dev/null
+++ b/versions/4.0/en/asset/subpackage-upgrade-guide.md
@@ -0,0 +1,41 @@
+# Subpackage upgrade guide
+
+> Author: Santy-Wang, Xunyi
+> This article details the considerations for upgrading mini game sub-package to the Asset Bundle.
+
+Prior to v2.4, [Subpackage Loading](https://github.com/cocos/cocos-docs/blob/e02ac31bab12d3ee767c0549050b0e42bd22bc5b/en/scripting/subpackage.md) was only supported various mini game platforms, such as WeChat Mini Games, OPPO Mini Games, etc.. However, with the continuous development of Creator, developers' demands for subpackage have been increasing, such as multi-platform support, and the original subpackage loading is no longer enough. Therefore, starting from v2.4, Creator officially supports the more complete **Asset Bundle**.
+
+- For the **Artist and Game Designer**, all resources in your project (e.g.: scenes, animations, prefab) do not need to be modified or upgraded.
+- For **Programmers**, the `loader.downloader.loadSubpackage` needs to be changed to the `assetManager.loadBundle` from **Asset Manager**. The related content will be described in detail in this document.
+
+> **Note**: if you used Subpackage Loading in your old project, that is, if you checked the **Subpackage** option in the **Properties** panel, then when the project is upgraded to the v3.0, it will automatically convert to an normal folder. You can configure the Asset Bundle as following reference.
+
+[Configura Asset Bundle](bundle.md)
+
+## Situations that require upgrading manually
+
+Use the `loader.downloader.loadSubpackage` API to load the subpackage.
+
+## Upgrade steps
+
+- **Back up your old projects**
+- Use Cocos Creator **v3.0** in the **Dashboard** to open an old project that needs to upgrade the subpackage, Creator will reimport the affected resources. The first import will take a little longer, and the main editor window will open after the import is complete. And then open the code editor to replace all `loader.downloader.loadSubpackage` with `assetManager.loadBundle`.
+
+ ```typescript
+ // before
+ loader.downloader.loadSubpackage('sub1', (err) => {
+ loader.loadRes('sub1/sprite-frames/background', SpriteFrame);
+ });
+
+ // after
+ assetManager.loadBundle('sub1', (err, bundle) => {
+ // The relative path to the Asset Bundle root
+ bundle.load('sprite-frames/background/spriteFrame', SpriteFrame);
+ });
+ ```
+
+## How to use the Asset Bundle
+
+For details on how to use the **Asset Bundle**, please refer to the [Asset Bundle](bundle.md) documentation.
+
+For APIs related to the **Asset Bundle**, please refer to the [Asset Bundle API](%__APIDOC__%/en/class/AssetManager.Bundle) documentation.
diff --git a/versions/4.0/en/asset/subpackage/asset-bundle.png b/versions/4.0/en/asset/subpackage/asset-bundle.png
new file mode 100644
index 0000000000..965b850792
Binary files /dev/null and b/versions/4.0/en/asset/subpackage/asset-bundle.png differ
diff --git a/versions/4.0/en/asset/subpackage/bundle1.png b/versions/4.0/en/asset/subpackage/bundle1.png
new file mode 100644
index 0000000000..11f78be994
Binary files /dev/null and b/versions/4.0/en/asset/subpackage/bundle1.png differ
diff --git a/versions/4.0/en/asset/subpackage/bundle_md5.png b/versions/4.0/en/asset/subpackage/bundle_md5.png
new file mode 100644
index 0000000000..0683a785a2
Binary files /dev/null and b/versions/4.0/en/asset/subpackage/bundle_md5.png differ
diff --git a/versions/4.0/en/asset/subpackage/inspector.png b/versions/4.0/en/asset/subpackage/inspector.png
new file mode 100644
index 0000000000..29410362f2
Binary files /dev/null and b/versions/4.0/en/asset/subpackage/inspector.png differ
diff --git a/versions/4.0/en/asset/subpackage/package.jpg b/versions/4.0/en/asset/subpackage/package.jpg
new file mode 100644
index 0000000000..3536c73f68
Binary files /dev/null and b/versions/4.0/en/asset/subpackage/package.jpg differ
diff --git a/versions/4.0/en/asset/subpackage/profile.png b/versions/4.0/en/asset/subpackage/profile.png
new file mode 100644
index 0000000000..57818c878c
Binary files /dev/null and b/versions/4.0/en/asset/subpackage/profile.png differ
diff --git a/versions/4.0/en/asset/subpackage/subpackage.jpg b/versions/4.0/en/asset/subpackage/subpackage.jpg
new file mode 100644
index 0000000000..2159a988f1
Binary files /dev/null and b/versions/4.0/en/asset/subpackage/subpackage.jpg differ
diff --git a/versions/4.0/en/asset/subpackage/subpackage2.png b/versions/4.0/en/asset/subpackage/subpackage2.png
new file mode 100644
index 0000000000..aecb36c8e3
Binary files /dev/null and b/versions/4.0/en/asset/subpackage/subpackage2.png differ
diff --git a/versions/4.0/en/asset/texture-cube.md b/versions/4.0/en/asset/texture-cube.md
new file mode 100644
index 0000000000..418e5787e9
--- /dev/null
+++ b/versions/4.0/en/asset/texture-cube.md
@@ -0,0 +1,21 @@
+# Texture Cube
+
+TextureCube is a cube texture, often used to set the scene's [skybox](../concepts/scene/skybox.md). The cube texture can be obtained by setting the panorama ImageAsset to the TextureCube type, or it can be generated in the Creator.
+
+## Set to Cube Mapping
+
+After [importing](asset-workflow.md#) the ImageAsset into Creator, you can set it to **texture cube** type in the **Inspector** panel, and click the green checkbox in the upper right corner to save the changes.
+
+
+
+Once set up, you can see in the **Assets** panel that a **textureCube** subresource has been created below the original image resource, along with the six textures that make up the TextureCube.
+
+
+
+## Create CubeMap
+
+The TextureCube obtained by making a CubeMap in Creator is as follows:
+
+
+
+For the specific use of TextureCube and how to make CubeMap, please refer to [Skybox - Setting up CubeMap](../concepts/scene/skybox.md).
diff --git a/versions/4.0/en/asset/texture.md b/versions/4.0/en/asset/texture.md
new file mode 100644
index 0000000000..aac942152a
--- /dev/null
+++ b/versions/4.0/en/asset/texture.md
@@ -0,0 +1,127 @@
+# Texture Assets
+
+**Texture** assets are assets used for procedural sampling, such as **textures on models** and the **UI on Sprites**. When the UI or model are rendered, the corresponding texture is sampled, then filled on the model grid, plus a series of processing such as lighting to render the entire scene.
+
+**Texture assets** can be generated from **ImageAsset**. Some common image formats, including `.png`, `.jpeg`, etc. can be used in **ImageAsset**.
+
+## Texture2D
+
+Texture2D is a type of texture mapping asset, usually used for rendering 3D models, such as reflection mapping in model materials, ambient light mask mapping, etc.
+
+After you [import](asset-workflow.md) the image asset into Creator, you can set it to **texture** type in **Inspector** panel, the texture type is the Texture2D asset.
+
+
+
+## Properties
+
+When importing an image asset, the editor sets it to **texture** type by default, and one or more sub-assets will be created automatically under the imported image asset, click the triangle icon to the left of the image asset in **Asset Manager** to expand it to see all the sub-assets, as shown in the following figure:
+
+
+
+When the generated Texture2D sub-asset is selected, the relevant properties can be set in the **Inspector** panel.
+
+
+
+| Properties | Description |
+| :----------------- |:--- |
+| **Anisotropy** | Anisotropy value, applying the maximum threshold of the anisotropy filtering algorithm |
+| **Filter Mode** | Filter mode, options are **Nearest (None)**, **Bilinear**, **Bilinear with mipmaps**, **Trilinear with mipmaps** and **Advanced**, please refer to **Filter mode** below for more information |
+| **Wrap Mode** | Set the addressing mode, the options are **Repeat**, **Clamp**, **Mirror**, and **Advanced** When selecting **Advanced**, set the texture addressing mode in the S(U)/T(V) direction, that is, the pixel-to-texture mapping mode in the S(U) or T(V) direction, see **Addressing Mode** below for more information |
+
+> **Note**: Since the default Wrap Mode may show black edges when rendering transparent edges of images, the Creator automatically adjusts the Wrap Mode S and Wrap Mode T properties of texture asset to **clamp-to-edge** automatically when setting the image asset type to **sprite-frame**. Developers can change this if they have special needs.
+
+Next we give a brief explanation of some of the properties.
+
+### Filter Mode
+
+
+
+When the original size of Texture2D does not match the size of the texture image mapped to the screen, different texture filtering methods for texture cell-to-pixel mapping will produce different results.
+
+The **Min Filter** and **Mag Filter** properties in Texture2D are used to set the texture filtering method to be used when scaling down or scaling up the mapping, respectively.
+
+1. Neareast
+
+ Neareast filtering is the **default** texture filtering method used. The color value of the texture cell whose center position is closest to the sample point is used as the color value of that sample point, without considering the influence of other adjacent pixels.
+ It should be noted that the use of proximity filtering may result in uneven edges and more pronounced jaggedness.
+
+2. Linear
+
+ Linear filtering uses a 2 x 2 matrix of texture cells nearest to the sampling point for sampling. The average of the four texture cell color values is taken as the color of the sampling point, and the color value transition between pixels will be smoother.
+ Note that using the linear filtering method may result in black edges and, in the case of pixel-based games, may result in blurring.
+
+### Generate Mipmaps
+
+In order to speed up 3D scene rendering and reduce image jaggies, the mapping is processed as a sequence of pre-computed and optimized images, called a mipmap. mipmap is a scaled-down detailed replica of the original image at each level of the mipmap, and when the mapping is scaled down or only needs to be viewed from a distance, the mipmap is converted to the appropriate level.
+
+
+
+When the **Generate Mipmaps** property is checked or **Filter Mode** for texture is selected as **Bilinear with mipmaps** or **Trilinear with mipmaps**, the mipmap is automatically generated by interpolating between two similar layers. mipmap mapping is smaller than the original image when rendering distant objects, which improves the cache hit rate during graphics card sampling, so the rendering speed is improved. At the same time, the mipmap mapping is less precise, which reduces moiré and reduces jaggedness on the screen. In addition, mipmap takes up about a third of the memory space because of the extra mipmap generation.
+
+Texture2D can dynamically select the range of the mipmap at runtime. After setting the mipmap range, only the mipmaps within the range can be used. This allows us to save bandwidth by skipping low levels and avoid using too many high levels to reduce the effect.
+
+The mipmap level range for Texture2D can be set as follows.
+
+```Javascript
+texture.setMipRange(minLevel, maxLevel);
+```
+
+Where `minLevel` specifies the minimum limit and `maxLevel` specifies the maximum limit.
+
+> **Note**.
+> 1. The limit cannot exceed the existing mipmap level.
+> This method is not available for WebGL and GLES2 backends.
+
+### Wrap Mode
+
+In general, the texture coordinates in the horizontal (U) and vertical (V) axes are in the range `[0, 1]`. When the texture coordinates in the passed vertex data are out of the range `[0, 1]`, different addressing modes can be used to control how the out-of-range texture coordinates are mapped.
+
+The **Wrap Mode S** and **Wrap Mode T** properties in Texture2D are used to set the addressing mode of the texture in the UV direction, respectively.
+
+1. Repeat
+
+ Repeat addressing mode is the default texture addressing mode used. For texture coordinates outside the `[0, 1]` range, the contents of the texture coordinates inside `[0, 1]` are repeated, i.e. the texture map is repeatedly placed outside the texture coordinate range.
+
+ > **Note**: On WebGL 1.0, the `repeat` addressing mode is disabled when the texture width and height are not powers of two. The runtime will automatically switch it to `clamp-to-edge` addressing mode, which will disable properties like `tilingOffset` of the material.
+
+ When the **Wrap Mode S** and **Wrap Mode T** properties of Texture2D are both set to `repeat`, the effect looks like this.
+
+ 
+
+2. Clamp-to-edge
+
+ Constrain the texture coordinates to be between 0 and 1, copying the texture coordinates of `[0, 1]` only once. For the part outside of `[0, 1]`, the texture coordinate content of the edge will be used to extend, producing an effect similar to the edge being stretched.
+
+ When both properties are set to `clamp-to-edge`, the effect looks like this.
+
+ 
+
+3. Mirrored-repeat
+
+ Similar to repeat-addressing mode, except that the mapping is mirrored and repeated.
+
+ When both properties are set to `mirrored-repeat`, the effect looks like this.
+
+ 
+
+## Use Texture2D
+
+Texture2D is a very widely used asset, and its use in Creator consists of using it in the editor and getting it dynamically.
+
+- In the editor's **Inspector** panel, any property marked as Texture2D type can be used by dragging and dropping a Texture2D asset into the property box. For example, to set a Texture2D type asset for a material asset.
+
+ 
+
+ > **Note**: If `USE TEXTURE` is not defined in the material, there is no such property.
+
+- To use it dynamically, you need to get the ImageAsset first, and then instantiate the Texture2D asset based on the ImageAsset you got.
+
+ ```ts
+ resources.load("testAssets/image/texture", Texture2D, (err: any, texture: Texture2D) => {
+ const spriteFrame = new SpriteFrame();
+ spriteFrame.texture = texture;
+ this.node.getComponent(Sprite).spriteFrame = spriteFrame;
+ });
+ ```
+
+ For more details, please refer to [Asset Loading](./dynamic-load-resources.md)。
diff --git a/versions/4.0/en/asset/texture/clamp-to-edge.png b/versions/4.0/en/asset/texture/clamp-to-edge.png
new file mode 100644
index 0000000000..4d27cd9d6b
Binary files /dev/null and b/versions/4.0/en/asset/texture/clamp-to-edge.png differ
diff --git a/versions/4.0/en/asset/texture/filter-mode.png b/versions/4.0/en/asset/texture/filter-mode.png
new file mode 100644
index 0000000000..3486273560
Binary files /dev/null and b/versions/4.0/en/asset/texture/filter-mode.png differ
diff --git a/versions/4.0/en/asset/texture/generate-mipmaps.png b/versions/4.0/en/asset/texture/generate-mipmaps.png
new file mode 100644
index 0000000000..e75acbcc24
Binary files /dev/null and b/versions/4.0/en/asset/texture/generate-mipmaps.png differ
diff --git a/versions/4.0/en/asset/texture/imported.png b/versions/4.0/en/asset/texture/imported.png
new file mode 100644
index 0000000000..d319b4992e
Binary files /dev/null and b/versions/4.0/en/asset/texture/imported.png differ
diff --git a/versions/4.0/en/asset/texture/mirrored-repeat.png b/versions/4.0/en/asset/texture/mirrored-repeat.png
new file mode 100644
index 0000000000..1e07ceac2a
Binary files /dev/null and b/versions/4.0/en/asset/texture/mirrored-repeat.png differ
diff --git a/versions/4.0/en/asset/texture/normal-map.png b/versions/4.0/en/asset/texture/normal-map.png
new file mode 100644
index 0000000000..2d28fc5c03
Binary files /dev/null and b/versions/4.0/en/asset/texture/normal-map.png differ
diff --git a/versions/4.0/en/asset/texture/repeat.png b/versions/4.0/en/asset/texture/repeat.png
new file mode 100644
index 0000000000..203af666f4
Binary files /dev/null and b/versions/4.0/en/asset/texture/repeat.png differ
diff --git a/versions/4.0/en/asset/texture/set-texture-cube.png b/versions/4.0/en/asset/texture/set-texture-cube.png
new file mode 100644
index 0000000000..cbd7e68270
Binary files /dev/null and b/versions/4.0/en/asset/texture/set-texture-cube.png differ
diff --git a/versions/4.0/en/asset/texture/set-texture.png b/versions/4.0/en/asset/texture/set-texture.png
new file mode 100644
index 0000000000..b26e343336
Binary files /dev/null and b/versions/4.0/en/asset/texture/set-texture.png differ
diff --git a/versions/4.0/en/asset/texture/sub-texture-pro.png b/versions/4.0/en/asset/texture/sub-texture-pro.png
new file mode 100644
index 0000000000..a78a4b9437
Binary files /dev/null and b/versions/4.0/en/asset/texture/sub-texture-pro.png differ
diff --git a/versions/4.0/en/asset/texture/sub-texture.png b/versions/4.0/en/asset/texture/sub-texture.png
new file mode 100644
index 0000000000..1dc1b8b828
Binary files /dev/null and b/versions/4.0/en/asset/texture/sub-texture.png differ
diff --git a/versions/4.0/en/asset/texture/texture-cube.png b/versions/4.0/en/asset/texture/texture-cube.png
new file mode 100644
index 0000000000..f9fb7100c0
Binary files /dev/null and b/versions/4.0/en/asset/texture/texture-cube.png differ
diff --git a/versions/4.0/en/asset/texture/type-change.png b/versions/4.0/en/asset/texture/type-change.png
new file mode 100644
index 0000000000..3107a3a43d
Binary files /dev/null and b/versions/4.0/en/asset/texture/type-change.png differ
diff --git a/versions/4.0/en/asset/texture/use-texture2d.png b/versions/4.0/en/asset/texture/use-texture2d.png
new file mode 100644
index 0000000000..1a7242ad4f
Binary files /dev/null and b/versions/4.0/en/asset/texture/use-texture2d.png differ
diff --git a/versions/4.0/en/asset/tiledmap.md b/versions/4.0/en/asset/tiledmap.md
new file mode 100644
index 0000000000..17a6fef0a0
--- /dev/null
+++ b/versions/4.0/en/asset/tiledmap.md
@@ -0,0 +1,104 @@
+# Tiled Map Resources (TiledMap)
+## Problem
+When using a texture atlas, if a 1-pixel stretch is not applied, adjacent images may blend together, leading to incorrect edge colors, such as the appearance of black edges. Therefore, when creating the texture atlas, it is necessary to stretch each image by one pixel to serve as the edge pixel.
+
+The previous implementation of the engine handled this automatically and would indent by 1 pixel. The code implementation was as follows:
+```javascript
+if (spFrame) {
+ grid._name = spFrame.name;
+ const lm = spFrame.unbiasUV[0];
+ const bm = spFrame.rotated ? spFrame.unbiasUV[1] : spFrame.unbiasUV[5];
+ grid.l = lm + (grid.x + 0.5) / texWidth;
+ grid.t = bm + (grid.y + 0.5) / texHeight;
+ grid.r = lm + (grid.x + grid.width - 0.5) / texWidth;
+ grid.b = bm + (grid.y + grid.height - 0.5) / texHeight;
+ grid._rect = new Rect(grid.x, grid.y, grid.width, grid.height);
+}
+```
+
+But there's another problem, it makes the UI design of a good map may look indented, as seen in this [issue](https://github.com/cocos/cocos-engine/issues/17257).
+
+To fix this, in version **3.8.5** we are removing the code that automatically indents by 1 pixel, and will need to require the user to make a texture altas that needs to be set to extend by 1 pixel.
+
+## Creating a Texture Atlas for Tiled Maps
+
+Generally, you'll need to create a texture atlas. You can use the [TexturePacker](https://www.codeandweb.com/texturepacker) tool for this.
+
+- Add the materials to the tool, as shown in the image below:
+ 
+
+- Arrange the exported atlas layout and set the parameters.
+ 
+
+ **Note: You need to stretch by 1 pixel here. If you don't stretch by one pixel, the edges of adjacent textures may appear abnormal when used.**
+
+- Export the sprite sheet and then set the save path.
+ 
+
+## Creating and Editing Maps Using Tiled
+
+Tiled map resources are exported in a data format by the [Tiled Editor](https://www.mapeditor.org/).
+
+| Creator Version | Tiled Version |
+| :------------- | :----------- |
+| v3.0 and above | v1.4 |
+| v2.2 and above | v1.2.0 |
+| v2.1 and below | v1.0.0 |
+
+- Create map tiles.
+ 
+
+- Set the tile size.
+ 
+ 
+
+- Create a new tileset.
+ 
+
+- Select the texture atlas created using TexturePacker.
+ 
+
+ **Set the size to match the original image, i.e., 32x32 pixels. Also, set the margin to 1 (offset the image by 1 pixel on all sides) and set the spacing to 2 (1 pixel on each side, making it 2 pixels total).If you haven't set stretching in TexturePacker, you need to set the margin to 0 and the spacing to 0 here**
+
+- Complete the map, as shown below:
+ 
+
+- Save the `.tmx` file.
+
+## Importing Map Resources
+
+The resources required for the map include:
+
+- `.tmx` map data
+- `.png` texture atlas
+- `.tsx` tileset configuration file (required by some `.tmx` files)
+
+ 
+
+## Creating Tiled Map Resources
+
+Drag the map resources from the **Assets** panel to the Tmx File property of the created TiledMap component:
+
+
+
+## Organizing in the Project
+
+To improve resource management efficiency, it is recommended to store the imported `.tmx`, `.tsx`, and `.png` files in a separate directory, rather than mixing them with other resources. Make sure to keep the `.tmx` and `.tsx` files in the same directory; otherwise, the resources might not load correctly.
+
+### Notes
+
+1. If the texture is not stretched in the TexturePacker, the result may be an error.
+
+ Without stretching, the effect is as shown below:
+ 
+
+ With stretching, the effect is as shown below:
+ 
+
+2. If you have existing atlases and maps, you can update the atlas without having to recreate it.
+
+ (1) Add a new atlas with new configurations, making sure not to embed it in the map.
+ 
+
+ (2) In the old atlas tab, select and click Replace Tileset, then choose the new atlas created in step (1) to complete the update.
+ 
\ No newline at end of file
diff --git a/versions/4.0/en/asset/tiledmap/image-1.png b/versions/4.0/en/asset/tiledmap/image-1.png
new file mode 100644
index 0000000000..9c6c7bfa3b
Binary files /dev/null and b/versions/4.0/en/asset/tiledmap/image-1.png differ
diff --git a/versions/4.0/en/asset/tiledmap/image-12.png b/versions/4.0/en/asset/tiledmap/image-12.png
new file mode 100644
index 0000000000..a7a73477b8
Binary files /dev/null and b/versions/4.0/en/asset/tiledmap/image-12.png differ
diff --git a/versions/4.0/en/asset/tiledmap/image-14.png b/versions/4.0/en/asset/tiledmap/image-14.png
new file mode 100644
index 0000000000..8f09ceabb6
Binary files /dev/null and b/versions/4.0/en/asset/tiledmap/image-14.png differ
diff --git a/versions/4.0/en/asset/tiledmap/image-15.png b/versions/4.0/en/asset/tiledmap/image-15.png
new file mode 100644
index 0000000000..9d4c72d889
Binary files /dev/null and b/versions/4.0/en/asset/tiledmap/image-15.png differ
diff --git a/versions/4.0/en/asset/tiledmap/image-16.png b/versions/4.0/en/asset/tiledmap/image-16.png
new file mode 100644
index 0000000000..07e5b59f19
Binary files /dev/null and b/versions/4.0/en/asset/tiledmap/image-16.png differ
diff --git a/versions/4.0/en/asset/tiledmap/image-2.png b/versions/4.0/en/asset/tiledmap/image-2.png
new file mode 100644
index 0000000000..db3b0f9ccc
Binary files /dev/null and b/versions/4.0/en/asset/tiledmap/image-2.png differ
diff --git a/versions/4.0/en/asset/tiledmap/image-3.png b/versions/4.0/en/asset/tiledmap/image-3.png
new file mode 100644
index 0000000000..4e46fd421b
Binary files /dev/null and b/versions/4.0/en/asset/tiledmap/image-3.png differ
diff --git a/versions/4.0/en/asset/tiledmap/image-4.png b/versions/4.0/en/asset/tiledmap/image-4.png
new file mode 100644
index 0000000000..40b0ad4dbb
Binary files /dev/null and b/versions/4.0/en/asset/tiledmap/image-4.png differ
diff --git a/versions/4.0/en/asset/tiledmap/image-5.png b/versions/4.0/en/asset/tiledmap/image-5.png
new file mode 100644
index 0000000000..cbe1f952a9
Binary files /dev/null and b/versions/4.0/en/asset/tiledmap/image-5.png differ
diff --git a/versions/4.0/en/asset/tiledmap/image-6.png b/versions/4.0/en/asset/tiledmap/image-6.png
new file mode 100644
index 0000000000..9bae80d7e3
Binary files /dev/null and b/versions/4.0/en/asset/tiledmap/image-6.png differ
diff --git a/versions/4.0/en/asset/tiledmap/image-7.png b/versions/4.0/en/asset/tiledmap/image-7.png
new file mode 100644
index 0000000000..71666db7aa
Binary files /dev/null and b/versions/4.0/en/asset/tiledmap/image-7.png differ
diff --git a/versions/4.0/en/asset/tiledmap/image-8.png b/versions/4.0/en/asset/tiledmap/image-8.png
new file mode 100644
index 0000000000..ce19449306
Binary files /dev/null and b/versions/4.0/en/asset/tiledmap/image-8.png differ
diff --git a/versions/4.0/en/asset/tiledmap/image-9.png b/versions/4.0/en/asset/tiledmap/image-9.png
new file mode 100644
index 0000000000..6d4f2a1078
Binary files /dev/null and b/versions/4.0/en/asset/tiledmap/image-9.png differ
diff --git a/versions/4.0/en/asset/tiledmap/image.png b/versions/4.0/en/asset/tiledmap/image.png
new file mode 100644
index 0000000000..553e7ac8e0
Binary files /dev/null and b/versions/4.0/en/asset/tiledmap/image.png differ
diff --git a/versions/4.0/en/asset/tiledmap/import.png b/versions/4.0/en/asset/tiledmap/import.png
new file mode 100644
index 0000000000..ad4698cdab
Binary files /dev/null and b/versions/4.0/en/asset/tiledmap/import.png differ
diff --git a/versions/4.0/en/asset/tiledmap/set_asset.png b/versions/4.0/en/asset/tiledmap/set_asset.png
new file mode 100644
index 0000000000..a5844582bf
Binary files /dev/null and b/versions/4.0/en/asset/tiledmap/set_asset.png differ
diff --git a/versions/4.0/en/audio-system/audio/audioEdit.png b/versions/4.0/en/audio-system/audio/audioEdit.png
new file mode 100644
index 0000000000..f9c7f5677b
Binary files /dev/null and b/versions/4.0/en/audio-system/audio/audioEdit.png differ
diff --git a/versions/4.0/en/audio-system/audio/audiocilp.gif b/versions/4.0/en/audio-system/audio/audiocilp.gif
new file mode 100644
index 0000000000..869f06cbcf
Binary files /dev/null and b/versions/4.0/en/audio-system/audio/audiocilp.gif differ
diff --git a/versions/4.0/en/audio-system/audio/audiocontroller.png b/versions/4.0/en/audio-system/audio/audiocontroller.png
new file mode 100644
index 0000000000..02cfaece28
Binary files /dev/null and b/versions/4.0/en/audio-system/audio/audiocontroller.png differ
diff --git a/versions/4.0/en/audio-system/audio/audiosource.png b/versions/4.0/en/audio-system/audio/audiosource.png
new file mode 100644
index 0000000000..fbbd089f84
Binary files /dev/null and b/versions/4.0/en/audio-system/audio/audiosource.png differ
diff --git a/versions/4.0/en/audio-system/audioExample.md b/versions/4.0/en/audio-system/audioExample.md
new file mode 100644
index 0000000000..c5b03f2693
--- /dev/null
+++ b/versions/4.0/en/audio-system/audioExample.md
@@ -0,0 +1,124 @@
+# Exapmle of AudioMgr
+
+Since Cocos Creator 3.x removed the v2.x `cc.audioEngine` related API, only AudioSource can be used to control audio playback.
+
+However, in actual project development, we still need an audio playback manager that can be conveniently called anytime and anywhere, which can refer to or directly use the following code.
+
+```typescript
+//AudioMgr.ts
+import { Node, AudioSource, AudioClip, resources, director } from 'cc';
+/**
+ * @en
+ * this is a sington class for audio play, can be easily called from anywhere in you project.
+ * @zh
+ * 这是一个用于播放音频的单件类,可以很方便地在项目的任何地方调用。
+ */
+export class AudioMgr {
+ private static _inst: AudioMgr;
+ public static get inst(): AudioMgr {
+ if (this._inst == null) {
+ this._inst = new AudioMgr();
+ }
+ return this._inst;
+ }
+
+ private _audioSource: AudioSource;
+ constructor() {
+ //@en create a node as audioMgr
+ //@zh 创建一个节点作为 audioMgr
+ let audioMgr = new Node();
+ audioMgr.name = '__audioMgr__';
+
+ //@en add to the scene.
+ //@zh 添加节点到场景
+ director.getScene().addChild(audioMgr);
+
+ //@en make it as a persistent node, so it won't be destroied when scene change.
+ //@zh 标记为常驻节点,这样场景切换的时候就不会被销毁了
+ director.addPersistRootNode(audioMgr);
+
+ //@en add AudioSource componrnt to play audios.
+ //@zh 添加 AudioSource 组件,用于播放音频。
+ this._audioSource = audioMgr.addComponent(AudioSource);
+ }
+
+ public get audioSource() {
+ return this._audioSource;
+ }
+
+ /**
+ * @en
+ * play short audio, such as strikes,explosions
+ * @zh
+ * 播放短音频,比如 打击音效,爆炸音效等
+ * @param sound clip or url for the audio
+ * @param volume
+ */
+ playOneShot(sound: AudioClip | string, volume: number = 1.0) {
+ if (sound instanceof AudioClip) {
+ this._audioSource.playOneShot(sound, volume);
+ }
+ else {
+ resources.load(sound, (err, clip: AudioClip) => {
+ if (err) {
+ console.log(err);
+ }
+ else {
+ this._audioSource.playOneShot(clip, volume);
+ }
+ });
+ }
+ }
+
+ /**
+ * @en
+ * play long audio, such as the bg music
+ * @zh
+ * 播放长音频,比如 背景音乐
+ * @param sound clip or url for the sound
+ * @param volume
+ */
+ play(sound: AudioClip | string, volume: number = 1.0) {
+ if (sound instanceof AudioClip) {
+ this._audioSource.stop();
+ this._audioSource.clip = sound;
+ this._audioSource.play();
+ this.audioSource.volume = volume;
+ }
+ else {
+ resources.load(sound, (err, clip: AudioClip) => {
+ if (err) {
+ console.log(err);
+ }
+ else {
+ this._audioSource.stop();
+ this._audioSource.clip = clip;
+ this._audioSource.play();
+ this.audioSource.volume = volume;
+ }
+ });
+ }
+ }
+
+ /**
+ * stop the audio play
+ */
+ stop() {
+ this._audioSource.stop();
+ }
+
+ /**
+ * pause the audio play
+ */
+ pause() {
+ this._audioSource.pause();
+ }
+
+ /**
+ * resume the audio play
+ */
+ resume(){
+ this._audioSource.play();
+ }
+}
+```
diff --git a/versions/4.0/en/audio-system/audioLimit.md b/versions/4.0/en/audio-system/audioLimit.md
new file mode 100644
index 0000000000..12397fab43
--- /dev/null
+++ b/versions/4.0/en/audio-system/audioLimit.md
@@ -0,0 +1,21 @@
+# Compatibility Notes
+
+## Loading modes for audio assets on the Web platform
+
+Audio assets on the Web platform are special because the Web standard supports loading audio assets in two different ways, namely:
+- Web Audio: provides a relatively more modern sound control interface, which is cached in the engine as an audio buffer. The advantage of this approach is good compatibility and fewer problems.
+- DOM Audio: plays audio assets by generating a standard audio element, which is cached in the engine. When using standard audio elements to play audio assets, you may encounter some compatibility issues in some browsers, for example, iOS browsers do not support adjusting the volume, and all volume related properties will not take effect.
+
+Currently, Cocos Creator loads audio assets as Web Audio by default, but if it detects that the current browser does not support loading Web Audio, it will switch to load audio as DOM Audio.
+
+If the project needs to force audio assets to be loaded via DOM Audio, please load them dynamically using the following way:
+
+```typescript
+assetManager.loadRemote('http://example.com/background.mp3', {
+ audioLoadMode: AudioClip.AudioType.DOM_AUDIO
+}, (err, clip: AudioClip) => {
+ if(err){
+ console.log(err);
+ }
+});
+```
diff --git a/versions/4.0/en/audio-system/audiosource.md b/versions/4.0/en/audio-system/audiosource.md
new file mode 100644
index 0000000000..e2ebf20dfd
--- /dev/null
+++ b/versions/4.0/en/audio-system/audiosource.md
@@ -0,0 +1,156 @@
+# AudioSource Component Reference
+
+The AudioSource component is used to control the playback of music and sound effects.
+
+
+
+Select the node in the **Hierarchy** panel, then click the **Add Component** button at the bottom of the **Inspector** panel and select **Audio -> AudioSource** to add the AudioSource component to the node.
+
+## AudioSource Properties
+
+| Property | Description |
+| :-- | :-- |
+| Clip | The added [audio asset](../asset/audio.md) for playback , default is empty, click the arrow button behind it to select. |
+| Loop | Whether to loop. |
+| PlayOnAwake | Whether the audio will be played automatically when the game is running (component is active). |
+| Volume | Volume, in the range 0~1. |
+
+## Audio Playback
+
+Cocos Creator 3.x uses AudioSource to control the playback of audio, which is a component that can be added to the scene, set by the **Editor**, or called in a **script**.
+
+In addition, Creator divides audio into longer **music** and shorter **sound effects** based on their length.
+
+- If you control audio playback through the editor, there is no difference between playing music and sound effects, but long music is recommended. See the **Playback via Editor** section below for details.
+- If audio playback is controlled via script, the AudioSource component additionally provides the `playOneShot` interface for playing short sound effects, see the **Sound Effect Playback** section below for details.
+
+> **Note**: Cocos Creator 3.x removes the `audioEngine` API from v2.x and uses the AudioSource component for audio playback.
+
+### Via the editor
+
+1. Add the AudioSource component to the node.
+
+2. Drag and drop the required audio asset from the **Assets** panel into the **Clip** property box of the AudioSource component as follows:
+
+ 
+
+3. Set the other properties of the AudioSource component as needed.
+
+### Via script
+
+For more flexible control of AudioSource playback, you can add a custom script to the node where the **AudioSource component** is located and then call the appropriate API to control audio playback.
+
+1. Add the AudioSource component to the node and specify the audio asset.
+
+2. [Create script](../scripting/setup.md) in the **Assets** panel and name it (e.g. `AudioController`), then double-click to open the script for writing, as follows:
+
+ ```typescript
+ import { _decorator, Component, Node, AudioSource, assert } from 'cc';
+ const { ccclass, property } = _decorator;
+
+ @ccclass("AudioController")
+ export class AudioController extends Component {
+
+ @property(AudioSource)
+ public _audioSource: AudioSource = null!
+
+ onLoad () {
+ // Get the AudioSource component
+ const audioSource = this.node.getComponent(AudioSource)! ;
+ // Check if it contains AudioSource, if not, output an error message
+ assert(audioSource);
+ // Assign the component to the global variable _audioSource
+ this._audioSource = audioSource;
+ }
+
+ play () {
+ // Play the music
+ this._audioSource.play();
+ }
+
+ pause () {
+ // Pause the music
+ this._audioSource.pause();
+ }
+ }
+ ```
+
+3. Select the node in the **Hierarchy** panel, then drag and drop the script from the **Assets** panel to the **Inspector** panel to add the script component to the node. As shown below:
+
+ 
+
+#### Audio Playback
+
+Compared to long music playback, sound effect playback has the following characteristics:
+
+- Short playback time
+- Large number of simultaneous playback
+
+The **AudioSource** component provides the `playOneShot` interface to play sound effects. The specific code implementation is as follows:
+
+```typescript
+// AudioController.ts
+
+import { AudioClip, AudioSource, Component, _decorator } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass("AudioController")
+export class AudioController extends Component {
+
+ @property(AudioClip)
+ public clip: AudioClip = null!
+
+ @property(AudioSource)
+ public audioSource: AudioSource = null!
+
+ playOneShot () {
+ this.audioSource.playOneShot(this.clip, 1);
+ }
+}
+```
+
+> **Note**: `playOneShot` is a one-time play operation, the sound after playing cannot be paused or stopped, and cannot listen to the end-of-play event callback.
+
+For more audio-related scripting interfaces, please refer to [AudioSource API](%__APIDOC__%/en/class/AudioSource).
+
+For more control over audio playback, please refer to the [AudioSource playback example](./audioExample.md) documentation.
+
+## Register AudioSource Event Callback
+
+Cocos Creator supports registering event callbacks on AudioSource components, with the following usage examples:
+
+```typescript
+import { _decorator, Component, Node, AudioSource } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass('AudioDemo')
+export class AudioDemo extends Component {
+
+ @property(AudioSource)
+ audioSource: AudioSource = null!;
+
+ onEnable () {
+ // Register the started event callback
+ this.audioSource.node.on(AudioSource.EventType.STARTED, this.onAudioStarted, this);
+ // Register the ended event callback
+ this.audioSource.node.on(AudioSource.EventType.ENDED, this.onAudioEnded, this);
+ }
+
+ onDisable () {
+ this.audioSource.node.off(AudioSource.EventType.STARTED, this.onAudioStarted, this);
+ this.audioSource.node.off(AudioSource.EventType.ENDED, this.onAudioEnded, this);
+ }
+
+ onAudioStarted () {
+ // TODO...
+ }
+
+ onAudioEnded () {
+ // TODO...
+ }
+}
+```
+
+## Web platform playback restrictions
+
+Audio playback on the Web platform currently requires compliance with the latest [Audio Play Policy](https://www.chromium.org/audio-video/autoplay), and even if the **AudioSource** component has `playOnAwake` set, It also needs to be played after the first user click event occurs.
diff --git a/versions/4.0/en/audio-system/overview.md b/versions/4.0/en/audio-system/overview.md
new file mode 100644
index 0000000000..919eddaef3
--- /dev/null
+++ b/versions/4.0/en/audio-system/overview.md
@@ -0,0 +1,8 @@
+# Audio System
+
+Music is an integral part of a game, and good music makes a game more realistic and immersive. the audio system in Cocos Creator supports importing and playing most common audio file formats, for details please refer to the following:
+
+- [Audio Assets](../asset/audio.md)
+- [AudioSource Component Reference](./audiosource.md)
+- [AudioSource Playback Example](./audioExample.md)
+- [Compatibility Notes](./audioLimit.md)
diff --git a/versions/4.0/en/book.json b/versions/4.0/en/book.json
new file mode 100644
index 0000000000..11a0c4ee1b
--- /dev/null
+++ b/versions/4.0/en/book.json
@@ -0,0 +1,108 @@
+{
+ "structure": {
+ "summary": "SUMMARY.md",
+ "readme": "index.md"
+ },
+ "variables": {
+ "docType": "Manual",
+ "products": [
+ {
+ "name": "Cocos Creator",
+ "links": [
+ {
+ "name": "Manual",
+ "link": "https://docs.cocos.com/creator/4.0/manual/en"
+ },
+ {
+ "name": "API Ref",
+ "link": "https://docs.cocos.com/creator/4.0/api/en/"
+ }
+ ]
+ },
+ {
+ "name": "Cocos2d-x",
+ "links": [
+ {
+ "name": "Manual",
+ "link": "https://docs.cocos.com/cocos2d-x/manual/en"
+ },
+ {
+ "name": "API Ref",
+ "link": "http://docs.cocos2d-x.org/api-ref/index.html"
+ }
+ ]
+ }
+ ],
+ "version": [
+ {
+ "name": "3.8",
+ "links": [
+ {
+ "name": "3.8",
+ "link": "https://docs.cocos.com/creator/4.0/manual/en"
+ },
+ {
+ "name": "3.7",
+ "link": "https://docs.cocos.com/creator/3.7/manual/en"
+ },
+ {
+ "name": "3.6",
+ "link": "https://docs.cocos.com/creator/3.6/manual/en"
+ },
+ {
+ "name": "3.5",
+ "link": "https://docs.cocos.com/creator/3.5/manual/en"
+ },
+ {
+ "name": "3.4",
+ "link": "https://docs.cocos.com/creator/3.4/manual/en"
+ },
+ {
+ "name": "3.3",
+ "link": "https://docs.cocos.com/creator/3.3/manual/en"
+ },
+ {
+ "name": "3.2",
+ "link": "https://docs.cocos.com/creator/3.2/manual/en"
+ },
+ {
+ "name": "3.1",
+ "link": "https://docs.cocos.com/creator/3.1/manual/en"
+ },
+ {
+ "name": "3.0",
+ "link": "https://docs.cocos.com/creator/3.0/manual/en"
+ },
+ {
+ "name": "2.4",
+ "link": "https://docs.cocos.com/creator/2.4/manual/en"
+ },
+ {
+ "name": "2.3",
+ "link": "https://docs.cocos.com/creator/2.3/manual/en"
+ },
+ {
+ "name": "2.2",
+ "link": "https://docs.cocos.com/creator/2.2/manual/en"
+ },
+ {
+ "name": "2.1",
+ "link": "https://docs.cocos.com/creator/2.1/manual/en"
+ },
+ {
+ "name": "2.0",
+ "link": "https://docs.cocos.com/creator/2.0/manual/en"
+ },
+ {
+ "name": "1.10",
+ "link": "https://docs.cocos.com/creator/1.10/manual/en"
+ },
+ {
+ "name": "1.9",
+ "link": "https://docs.cocos.com/creator/1.9/manual/en"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/versions/4.0/en/cases-and-tutorials/index.md b/versions/4.0/en/cases-and-tutorials/index.md
new file mode 100644
index 0000000000..f412bc0adc
--- /dev/null
+++ b/versions/4.0/en/cases-and-tutorials/index.md
@@ -0,0 +1,37 @@
+# Examples and Tutorials
+
+## Examples
+
+- **One Step, Two Steps**([GitHub](https://github.com/cocos/tutorial-mind-your-step-3d)): A game with step-by-step tutorial in the [Quick Start](../getting-started/first-game/index.md).
+- **Material Examples**([GitHub](https://github.com/cocos/cocos-example-materials)): Shows a variety of engine-built and customized material effects, including standard PBR, cartoon rendering, and also includes advanced materials such as skin, hair, eyeballs, leaves, and more.
+- **Render Pipeline Usage Demo**([GitHub](https://github.com/cocos/cocos-example-render-pipeline)): Demonstrates in Sponza how to use builtin post process render pipeline with all post-process features enabled.
+- **Examples of Physics**([GitHub](https://github.com/cocos/cocos-example-physics)): Includes 2D and 3D physics test cases and examples, such as **Engulfing Black Hole**, **Simple Car**, **Falling ball**, etc. The test cases introduce some basic functions and usage methods. It helps you understand the physical functions with documentation easily.
+- **Marionette Animation Examples**([GitHub](https://github.com/cocos/cocos-example-marionette)): Demonstrates how to use [Marionette Aniamtion System](../animation/marionette/index.md) in details, including state machine, pose graph, events, IK, etc.
+- **UI Example**([GitHub](https://github.com/cocos/cocos-example-ui/) | [Cocos Store](https://store.cocos.com/app/detail/2799)): A complex UI example, including the home page, store, backpack, and other common game UI interface.
+- **Example Cases**([GitHub](https://github.com/cocos/cocos-example-projects)): Includes examples of networking, npm modules, and other features.
+- **Modules Test Cases**([GitHub](https://github.com/cocos/cocos-test-projects)): The example project of each function of the engine, which basically covers most of the function modules of the engine. Users can refer to the usage in this project when using the functions for development.
+- **Practical Solutions**([GitHub](https://github.com/cocos/cocos-awesome-tech-solutions)): A collection of practical solutions provided by technical support engineers.
+- **Jump Ball 3D**([GitHub](https://github.com/cocos/cocos-example-ball) | [Cocos Store](https://store.cocos.com/app/detail/2802)): Users can make jump ball games through this project.
+- **Taxi Game 3D**([GitHub](https://github.com/cocos/cocos-tutorial-taxi-game) | [Cocos Store](https://store.cocos.com/app/en/detail/2796)): A physics-based 3d game, users can make taxi games through this project.
+
+> All cases and examples on GitHub are updated with the version, and the main branch corresponds to the latest **Cocos Creator** version, so please pay attention when downloading.
+
+## Tutorials
+
+### Videos
+
+- [Cocos Creator 3.x for Beginners](https://www.youtube.com/watch?v=JSOXYPqZ1-8&list=PLbvpmJKjO3NA4dlW43GzhJUMaXyIp3xpc)
+- [Cocos Quick Look](https://www.youtube.com/watch?v=R4Mxm55x56Q&list=PLbvpmJKjO3NCgicfQ_N32Oo62LgPVs4kf)
+- [Introduction to Shaders with Cocos Creator](https://www.youtube.com/watch?v=tUQHK42UcHc&list=PLbvpmJKjO3ND91HTUSKWNzMboob-7J_wq)
+- [Introduction to Cocos Creator 3.0](https://www.youtube.com/watch?v=3v4pq0tDo5g&list=PLbvpmJKjO3NDv_eb6vlN70Zo-pdAv8MNW)
+
+### Articles
+
+- [Best Tutorials - Part One](https://www.cocos.com/en/post/33e9da7fc3825a8aeb66ff6fbb7f5dd4)
+- [Best Tutorials - Part Two](https://www.cocos.com/en/post/52fnhtaqlEYYTafjBYjMMYWKyA6d3qIZ)
+
+## More
+
+- [Cocos Forum](https://discuss.cocos2d-x.org/c/creator/33): ask questions, find answers, communicate with other developers.
+- [Cocos Store](http://store.cocos.com/): various art assets, extensions, source codes and learning demos.
+- [Youtube channel — Cocos](https://www.youtube.com/@CocosEngine):news and tutorials.
diff --git a/versions/4.0/en/concepts/scene/coord.md b/versions/4.0/en/concepts/scene/coord.md
new file mode 100644
index 0000000000..3ba1fa1e07
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/coord.md
@@ -0,0 +1,85 @@
+# Coordinate Systems and Node Transformation Properties
+
+In the documents, [Scene Panel](../../editor/scene/index.md), and [Nodes and Components](node-component.md), the ability to change the display behavior of nodes by using the **transformation tool Gizmo** and editing the properties of nodes in the **Inspector** panel was introduced. This document will take a deeper look at the coordinate system of the scene space in which the node is located and how the **Position**, **Rotation**, and **Scale** transformation properties of the node work.
+
+## Coordinate Systems
+
+Position properties for nodes can be set, but where will a node with a specific position property be rendered on the screen when the game is running? Just as longitude and latitude specify coordinates for a location on a planet it is necessary to understand the coordinate system of Cocos Creator 3.x to understand the meaning of node positions.
+
+### World Coordinate
+
+The world coordinate system, also called absolute coordinate system, represents a unified coordinate system in the scene space in Cocos Creator game development, and "world" is used to represent our game scene.
+
+The world coordinate system of Creator 3.x uses a Cartesian right-handed coordinate system with default **x** to the right, **y** to the top, **z** to the outside, and the **-z** axis for the front.
+
+
+
+### Local Coordinate
+
+The local coordinate system, also called the relative coordinate system, is the coordinate system associated with the node. Each node has a separate coordinate system, and when the node moves or changes direction, the coordinate system associated with that node will move or change direction with it.
+
+Creator has a hierarchy of parent-child relationships between **Nodes**, and the position of a node set by modifying its `Position` property is the node's **local coordinate system** with respect to its parent, not the world coordinate system.
+
+Finally when drawing the whole scene, Creator will map the local coordinates of these nodes to world coordinate system coordinates.
+Suppose there are three nodes in the scene: NodeA, NodeB, and NodeC. The structure of the nodes is shown in the following figure.
+
+
+
+When the scene contains nodes at different levels, the position of each node under the world coordinate system is determined according to the following steps:
+
+1. Process each node starting from the root level, NodeA in the above figure is a root level node. The first step is to determine the position of the origin of NodeA's local coordinate system (i.e. `Position`) in the world coordinate system based on NodeA's **Position** property.
+2. Next, process all the direct children of NodeA, which is NodeB in the above figure (as well as other nodes of the same level as NodeB). Based on NodeB's `Position` property, determine NodeB's position in the world coordinate system in NodeA's local coordinate system.
+3. Each node uses the parent's coordinate system and its own position property to determine its position in the world coordinate system.
+
+## Transformation Properties
+
+Nodes include three main transformation properties, **Position**, **Rotation** and **Scale**, which are described below in turn.
+
+
+
+### Position
+
+**Position** consists of the `X`, `Y` and `Z` properties, which specify the coordinates of the node on the X-axis, Y-axis and Z-axis of the current coordinate system, respectively, and default to `(0, 0, 0)`.
+
+
+
+
+
+In the above figure, the world coordinates of NodeA are `(50, 50, 50)` and the local coordinates of child NodeB are `(0, 2, 0)`. If NodeB is moved to the root of the scene, the world coordinates of NodeB become `(50, 52, 50)`.
+
+
+
+The `Position` of the child NodeB is based on the `Position` of the parent NodeA as the origin of the coordinate system.
+
+If the parent NodeA changes its `Position`, the child NodeB will also change its position (world coordinate system), but the `Position` property of the child NodeB will not change, because the child NodeB does not change in the local coordinate system with the parent NodeA's `Position` as the origin.
+
+In the **Scene** panel, use the [Move Transform Tool](../../editor/toolbar/index.md) to change the node position.
+
+### Rotation
+
+**Rotation** consists of the `X`, `Y` and `Z` properties, which default to `(0, 0, 0)`, and is another important property that affects the node's local coordinate system. When the `X` property is changed, it means that the node will be rotated counterclockwise/clockwise around the x-axis, and so on, and the same applies when the `Y` or `Z` property is changed.
+
+- When the property value is **positive**, the node rotates **counterclockwise**.
+- When the property value is **negative**, the node rotates **clockwise**.
+
+
+
+The node hierarchy shown above is the same as the previous figure, except that the **Rotation** property of NodeA on the z-axis is set to **60** degrees, notice that in addition to NodeA itself being **counterclockwise** rotated by 60 degrees on the z-axis, its child NodeB is also **centered** on the z-axis. NodeB is also rotated **counterclockwise** on NodeA's z-axis. This also means that the rotation property affects the child nodes.
+
+> **Note**: the quaternion [rotation](%__APIDOC__%/en/class/Node?id=rotation) property on a node represents the angle of rotation about any axis. The property corresponding to `Rotation` in the **Inspector** panel is the property [EulerAngles](__APIDOC__/en/class/Node?id=eulerAngles), and the value of `Rotation` can be obtained in the script via `Node.eulerAngles`. These two properties can be used separately according to your needs. When using the API, make sure to pay attention to the difference between them and the editor panel property names.
+
+In the **Scene** panel, use the [Rotate Transform Tool](../../editor/toolbar/index.md) to set the rotation of the node.
+
+### Scale
+
+The **Scale** property also consists of the `X`, `Y` and `Z` properties, which represent the scaling of the node on the x-axis, y-axis and z-axis, respectively, and defaults to `(1, 1, 1)`.
+
+
+
+The node hierarchy shown above is the same as when `Position` was introduced. Setting the scale property of NodeA to `(2, 1, 1)` means that NodeA is scaled to **2** times its original size in the x-axis direction, while the y-axis and z-axis remain unchanged. You can see that the child node NodeB is also scaled to twice its original size in the x-axis direction, so the scaling property affects all child nodes.
+
+The `Scale` property set on a child node are superimposed on its parent node's scaling, and the child nodes of the child node **multiply** all the `Scale` properties at each level to obtain the scaling multiplier displayed in the world coordinate system. This is actually the same as the **position** and **rotation** properties, except that the **position** and **rotation** properties are **additive**, while the **scaling** property is **multiplicative**, which has a more pronounced effect.
+
+The **Scale** property does not affect the **Position** and **Rotation** of the current node, but it does affect the **Position** of the child nodes.
+
+In the **Scene** panel, use the [Scale Transform Tool](../../editor/toolbar/index.md) to modify the node scaling.
diff --git a/versions/4.0/en/concepts/scene/coord/node-tree.png b/versions/4.0/en/concepts/scene/coord/node-tree.png
new file mode 100644
index 0000000000..8dcab96f23
Binary files /dev/null and b/versions/4.0/en/concepts/scene/coord/node-tree.png differ
diff --git a/versions/4.0/en/concepts/scene/coord/position-nodeA.png b/versions/4.0/en/concepts/scene/coord/position-nodeA.png
new file mode 100644
index 0000000000..e444abf77f
Binary files /dev/null and b/versions/4.0/en/concepts/scene/coord/position-nodeA.png differ
diff --git a/versions/4.0/en/concepts/scene/coord/position-nodeB-world.png b/versions/4.0/en/concepts/scene/coord/position-nodeB-world.png
new file mode 100644
index 0000000000..5d53d779e4
Binary files /dev/null and b/versions/4.0/en/concepts/scene/coord/position-nodeB-world.png differ
diff --git a/versions/4.0/en/concepts/scene/coord/position-nodeB.png b/versions/4.0/en/concepts/scene/coord/position-nodeB.png
new file mode 100644
index 0000000000..1caae1b87d
Binary files /dev/null and b/versions/4.0/en/concepts/scene/coord/position-nodeB.png differ
diff --git a/versions/4.0/en/concepts/scene/coord/right_hand.png b/versions/4.0/en/concepts/scene/coord/right_hand.png
new file mode 100644
index 0000000000..ff5af90ef8
Binary files /dev/null and b/versions/4.0/en/concepts/scene/coord/right_hand.png differ
diff --git a/versions/4.0/en/concepts/scene/coord/rotation.png b/versions/4.0/en/concepts/scene/coord/rotation.png
new file mode 100644
index 0000000000..aafc29915e
Binary files /dev/null and b/versions/4.0/en/concepts/scene/coord/rotation.png differ
diff --git a/versions/4.0/en/concepts/scene/coord/scale.png b/versions/4.0/en/concepts/scene/coord/scale.png
new file mode 100644
index 0000000000..ec40dc4e7d
Binary files /dev/null and b/versions/4.0/en/concepts/scene/coord/scale.png differ
diff --git a/versions/4.0/en/concepts/scene/coord/transform-properties.png b/versions/4.0/en/concepts/scene/coord/transform-properties.png
new file mode 100644
index 0000000000..c0c1807d32
Binary files /dev/null and b/versions/4.0/en/concepts/scene/coord/transform-properties.png differ
diff --git a/versions/4.0/en/concepts/scene/fog.md b/versions/4.0/en/concepts/scene/fog.md
new file mode 100644
index 0000000000..6e5909f2c3
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/fog.md
@@ -0,0 +1,119 @@
+# Global Fog
+
+Global fog is used to simulate fog effects in outdoor environments in games. In addition to fog effects in the game, it can also be used to hide the model outside the camera's far clipping plane to improve the rendering performance.
+
+The global fog currently includes four types: Linear Fog, Exponential Fog, Exponential Squared Fog, and Layer Fog, please refer to the **Global Fog Types** section below for additional details.
+
+## Enable Global Fog
+
+Check **Scene** in the **Hierarchy** panel, then check the **Enabled** property in the **Fog** component of the **Inspector** panel to enable global fog.
+
+
+
+## Accurate Fog Computing
+
+Prior to v3.4, Creator used vertex fog by default, which caused unusual fog transitions on objects with a few vertices and a large volume. Starting with v3.4, Creator added the **Accurate** option to enable pixel fog to solve this problem.
+
+
+
+The effect when the **Accurate** option is unchecked, i.e., the pixel fog is not enabled, is as follows:
+
+
+
+The effect when the **Accurate** option is checked, i.e., the pixel fog is enabled, is as follows:
+
+
+
+### Version Upgrade - `Effect` Migration
+
+When a project is upgraded to v3.4, all the Effect code that calls to `CC_APPLY_FOG` needs to be modified to add a second parameter, `worldPos`. e.g.:
+
+- The original code is as follows:
+
+ ```ts
+ CC_APPLY_FOG(finalColor);
+ ```
+
+- After upgrading to v3.4, the original code needs to be changed to the following:
+
+ ```ts
+ CC_APPLY_FOG(finalColor, v_position.xyz);
+ ```
+
+## Types of Global Fog
+
+The types of global fog include Linear Fog, Exponential Fog, Exponential Squared Fog, and Layer Fog. The type depends on the calculation result of **Camera** and **Model Vertex**, which is called **Fog Blend Factor**. The fog blend factor determines how the fog color and the model color are blended, resulting in a different global fog effect.
+
+### Linear Fog
+
+
+
+| Property | Description |
+| :--- | :--- |
+| **Enabled** | Whether to enable the global fog. |
+| **Accurate** | Whether to enable accurate fog computing. |
+| **FogColor** | The color of the global fog. |
+| **Type** | The type of the global fog. |
+| **FogStart** | The starting position of the fog effect. |
+| **FogEnd** | The end position of the fog effect. |
+
+The fog blend factor of Linear Fog is calculated by the formula:
+
+**f = (FogEnd - Cam_dis) / (FogEnd - FogStart)**
+
+- When `Cam_dis = FogEnd`, i.e., the distance between the camera and the model vertex is equal to `FogEnd`, the blend factor is calculated as 0, and the object is fully fogged.
+
+- When `Cam_dis = FogStart`, i.e. the distance between the camera and the model vertex is equal to `FogStart`, the blend factor is calculated as 1, and the object is not affected by fogging.
+
+To increase the density of Linear Fog when the distance between the camera and the model vertex is fixed, there are two ways:
+
+1. Fix the value of `FogStart` and decrease the value of `FogEnd`.
+2. Decrease the value of `FogStart` and fix the value of `FogEnd`.
+
+To adjust the fog effect to the right consistency, it is best to adjust both the `FogStart` and `FogEnd` properties appropriately.
+
+### Exponential Fog and Exponential Squared Fog
+
+
+
+The properties of Exponential Fog and Exponential Squared Fog are the same, and the Exponential Fog is used here as an example:
+
+| Property | Description |
+| :--- | :--- |
+| **Enabled** | Whether to enable the global fog. |
+| **Accurate** | Whether to enable accurate fog computing. |
+| **FogColor** | The color of the global fog. |
+| **Type** | The type of the global fog. |
+| **FogDensity** | The fog density, the value range is 0 ~ 1, the larger the value the higher the density. |
+| **FogStart** | The starting position of the fog effect. |
+| **FogAtten** | Fog attenuation coefficient, the smaller the value the denser the fog. |
+
+The fog blend factor for Exponential Fog is calculated as:
+
+**f = e^(-max(0, distance-fogStart) * fogDensity)**
+
+The fog blend factor for Exponential Squared Fog is calculated as:
+
+**f = e^(-max(0, distance-fogStart) * fogDensity)²**
+
+Developers can adjust the distribution of global fog in the near and far distance with `FogStart`, and the fog concentration at different locations with `FogDensity` and `FogAtten`.
+
+### Layered Fog
+
+Layered Fog is parallel to the horizontal plane and has a specific height. The height of the fog can be determined by setting the top of the Layered Fog at any position in the vertical direction of the scene world coordinate system.
+
+
+
+| Property | Description |
+| :--- | :--- |
+| **Enabled** | Whether to enable the global fog. |
+| **Accurate** | Whether to enable accurate fog computing. |
+| **FogColor** | The color of the global fog. |
+| **Type** | The fog type of the global fog. |
+| **FogAtten** | Fog attenuation coefficient, the smaller the value the denser the fog. |
+| **FogTop** | The position of the model vertices in the vertical direction of the world coordinate system, below which all vertices will be affected by the fog effect. |
+| **FogRange** | The range of the fog effect from the set **FogTop** downwards. |
+
+The fog calculation of Layered Fog is a bit more complicated than the other three fog types, as it introduces the concept of `FogTop` and also requires distance calculation in the **X-Z** plane.
+
+Layered Fog is more common in reality, with towering mountains and buildings. If it is used wisely, it is believed to have a good effect on scene presentation, but at the same time, the computation will be increased, developers can decide according to their needs.
diff --git a/versions/4.0/en/concepts/scene/fog/accuracy_off.png b/versions/4.0/en/concepts/scene/fog/accuracy_off.png
new file mode 100644
index 0000000000..8d6fbfb2cc
Binary files /dev/null and b/versions/4.0/en/concepts/scene/fog/accuracy_off.png differ
diff --git a/versions/4.0/en/concepts/scene/fog/accuracy_on.png b/versions/4.0/en/concepts/scene/fog/accuracy_on.png
new file mode 100644
index 0000000000..7adf8b8eee
Binary files /dev/null and b/versions/4.0/en/concepts/scene/fog/accuracy_on.png differ
diff --git a/versions/4.0/en/concepts/scene/fog/accurate.png b/versions/4.0/en/concepts/scene/fog/accurate.png
new file mode 100644
index 0000000000..227d445a05
Binary files /dev/null and b/versions/4.0/en/concepts/scene/fog/accurate.png differ
diff --git a/versions/4.0/en/concepts/scene/fog/enable-fog.png b/versions/4.0/en/concepts/scene/fog/enable-fog.png
new file mode 100644
index 0000000000..ef4b189ba2
Binary files /dev/null and b/versions/4.0/en/concepts/scene/fog/enable-fog.png differ
diff --git a/versions/4.0/en/concepts/scene/fog/exp-properties.png b/versions/4.0/en/concepts/scene/fog/exp-properties.png
new file mode 100644
index 0000000000..7dbf579a74
Binary files /dev/null and b/versions/4.0/en/concepts/scene/fog/exp-properties.png differ
diff --git a/versions/4.0/en/concepts/scene/fog/layerfog.png b/versions/4.0/en/concepts/scene/fog/layerfog.png
new file mode 100644
index 0000000000..ad1f81f339
Binary files /dev/null and b/versions/4.0/en/concepts/scene/fog/layerfog.png differ
diff --git a/versions/4.0/en/concepts/scene/fog/linear_fog.png b/versions/4.0/en/concepts/scene/fog/linear_fog.png
new file mode 100644
index 0000000000..a297a51ab0
Binary files /dev/null and b/versions/4.0/en/concepts/scene/fog/linear_fog.png differ
diff --git a/versions/4.0/en/concepts/scene/index.md b/versions/4.0/en/concepts/scene/index.md
new file mode 100644
index 0000000000..cdf162b27f
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/index.md
@@ -0,0 +1,21 @@
+# Scene Creation Workflow
+
+A scene is an abstract collection of environmental factors in a game, a local unit for creating a game environment. Game developers represent a part of the game's world content by creating a scene in the editor.
+
+
+
+## Scene Structure
+
+Cocos Creator implements a free scene structure using a node tree and a node component system. The **Node** is responsible for managing the parent-child relationship of the node tree and the spatial matrix transformation **Transform**, so that all entity nodes can be easily managed and placed in the scene.
+
+The component system gives nodes a variety of advanced features, such as **MeshRenderer** component, **Animation** component, **Light** component, **Terrain** component, and more. One of the necessary elements of the 3D scene is the **Camera** component, which represents the player's viewpoint in the game, without which nothing can be seen. Therefore, when creating a scene, Creator will create a node with the **Camera** component mounted by default.
+
+## Scene Creation Related Workflow
+
+- [Nodes and Components](node-component.md)
+- [Coordinate System and Transformations](coord.md)
+- [Node Hierarchy and Display Order](node-tree.md)
+- [Building a Scene with the Scene Panel](scene-editing.md)
+- [Skybox](skybox.md)
+- [Global Fog](fog.md)
+- [Shadows](./light/shadow.md)
diff --git a/versions/4.0/en/concepts/scene/layer.md b/versions/4.0/en/concepts/scene/layer.md
new file mode 100644
index 0000000000..0e560fc4b2
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/layer.md
@@ -0,0 +1,26 @@
+# Layer
+
+The `Layer` property of the Node is an unsigned 32-bit integer, supporting up to 32 different types of `Layer`, which can be set in **Project -> Project Settings -> [Layers](../../editor/project/index.md#layers)** in the menu bar above the editor. The developer can customize the Layer **0 ~ 19**, and the remaining 12 Layers are the engine's built-in ones.
+
+The `Visibility` property of the Camera and the `Layer` property of the Node are both used to control the visibility of nodes. However, a node can only be seen by the camera if the `Layer` property set in the node is included in the `Visibility` of the camera. The `Visibility` property of the camera uses bitwise operators (such as `|` and `&`) to determine whether a node's `Layer` should be visible, and supports selecting multiple Layers at the same time. See the [Camera — Set the Visibility property](../../editor/components/camera-component.md) documentation for details.
+
+## The engine's built-in Layers
+
+
+
+| Property | Description | Property Value |
+| :--- | :--- | :--- |
+| **NONE** | Set all invisible | 0 |
+| **IGNORE_RAYCAST** | Setting to ignore ray detection | 1 << 20 |
+| **GIZMOS** | Set gizmo information visible | 1 << 21 |
+| **EDITOR** | Set editor visible | 1 << 22 |
+| **UI_3D** | Set the `3D UI` node to be visible | 1 << 23 |
+| **SCENE_GIZMO** | Set scene gizmo visible | 1 << 24 |
+| **UI_2D** | Set `2D UI` nodes visible | 1 << 25 |
+| **PROFILER** | Set the profiler node to be visible | 1 << 28 |
+| **DEFAULT** | Set the default node to be visible | 1 << 30 |
+| **ALL** | Set all nodes to be visible | 0xffffffff |
+
+## User-defined Layers
+
+
diff --git a/versions/4.0/en/concepts/scene/light.md b/versions/4.0/en/concepts/scene/light.md
new file mode 100644
index 0000000000..e1641c4352
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/light.md
@@ -0,0 +1,17 @@
+# Lighting
+
+This section introduces how lighting works and how to use it in Cocos Creator.
+
+The implementation of lighting in Creator simulates the effect of light on the real world. Adding lights to the scene can make the scene produce corresponding lighting and shading effects to get better visual effects.
+
+
+
+## Additional References
+
+- [Physically Based Lighting](light/pbr-lighting.md)
+- [Types of Light](light/lightType/index.md)
+- [Additive per-pixel lights](light/additive-per-pixel-lights.md)
+- [Shadows](light/shadow.md)
+- [Lightmapping](light/lightmap.md)
+
+Cocos Creator provides some [lighting examples](https://github.com/cocos/cocos-test-projects/tree/v3.8/assets/cases/light), which mainly introduces some common editing operations for lighting and code examples for reference.
diff --git a/versions/4.0/en/concepts/scene/light/additive-per-pixel-lights.md b/versions/4.0/en/concepts/scene/light/additive-per-pixel-lights.md
new file mode 100644
index 0000000000..6d2e14db55
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/light/additive-per-pixel-lights.md
@@ -0,0 +1,39 @@
+# Additive Per-Pixel Lights
+
+Uber Shader is still the dominant solution on some performance-constrained platforms, but as hardware performance increases and the demand for higher picture quality increases, a fixed number of lights can no longer meet the needs of practical applications, so there is a solution that supports multiple lights -- **Multi-Pass Drawing**.
+
+The following is an example of how to implement multiple lights based on multiple `Pass` with the default lighting material `default-material.mtl` in Cocos Creator.
+
+
+
+First, create a new **Sphere** node in the **Hierarchy** panel, then continue to add a Directional Light and two Spotlights, setting them to surround the Sphere, as shown in the following image:
+
+
+
+After the scene is built, select the browser preview above the editor and you can see the draw call in the bottom left corner of the web preview:
+
+
+
+We can use a third party software such as RenderDoc to open the Frame Debug to see how these lights are rendered to the screen:
+
+
+
+As shown in the image above, the first rendering is the lighting of **Directional Light**:
+
+
+
+The second rendering is the lighting of **Spotlight 1**:
+
+
+
+The third rendering is the lighting of **Spotlight 2**:
+
+
+
+This type of rendering is the **Forward-Pipeline** that supports multiple lighting models, and **Forward** generally consists of two `Pass`:
+
+- The first `Pass` is **BasePass**, which is used to render the lighting of Directional Light.
+
+- The second `Pass` is **LightPass**, which is used to render the lighting of the remaining lights.
+
+Therefore, when an object is illuminated by more than one light at the same time, the Draw Call will also increase.
diff --git a/versions/4.0/en/concepts/scene/light/additivelights/debug.png b/versions/4.0/en/concepts/scene/light/additivelights/debug.png
new file mode 100644
index 0000000000..4f4c480978
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/additivelights/debug.png differ
diff --git a/versions/4.0/en/concepts/scene/light/additivelights/default-material.png b/versions/4.0/en/concepts/scene/light/additivelights/default-material.png
new file mode 100644
index 0000000000..86d522a9b0
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/additivelights/default-material.png differ
diff --git a/versions/4.0/en/concepts/scene/light/additivelights/drawCall.png b/versions/4.0/en/concepts/scene/light/additivelights/drawCall.png
new file mode 100644
index 0000000000..65cb910191
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/additivelights/drawCall.png differ
diff --git a/versions/4.0/en/concepts/scene/light/additivelights/pass1.png b/versions/4.0/en/concepts/scene/light/additivelights/pass1.png
new file mode 100644
index 0000000000..3951c220c0
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/additivelights/pass1.png differ
diff --git a/versions/4.0/en/concepts/scene/light/additivelights/pass2.png b/versions/4.0/en/concepts/scene/light/additivelights/pass2.png
new file mode 100644
index 0000000000..a13ad81e76
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/additivelights/pass2.png differ
diff --git a/versions/4.0/en/concepts/scene/light/additivelights/pass3.png b/versions/4.0/en/concepts/scene/light/additivelights/pass3.png
new file mode 100644
index 0000000000..98f80309ea
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/additivelights/pass3.png differ
diff --git a/versions/4.0/en/concepts/scene/light/additivelights/usingLight.png b/versions/4.0/en/concepts/scene/light/additivelights/usingLight.png
new file mode 100644
index 0000000000..e339d31af7
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/additivelights/usingLight.png differ
diff --git a/versions/4.0/en/concepts/scene/light/light-bulbs.jpg b/versions/4.0/en/concepts/scene/light/light-bulbs.jpg
new file mode 100644
index 0000000000..6ea594a3f0
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/light-bulbs.jpg differ
diff --git a/versions/4.0/en/concepts/scene/light/light-cd.jpeg b/versions/4.0/en/concepts/scene/light/light-cd.jpeg
new file mode 100644
index 0000000000..346d24fbf1
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/light-cd.jpeg differ
diff --git a/versions/4.0/en/concepts/scene/light/lightType/ambient.md b/versions/4.0/en/concepts/scene/light/lightType/ambient.md
new file mode 100644
index 0000000000..4c73e7d50f
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/light/lightType/ambient.md
@@ -0,0 +1,23 @@
+# Ambient Light
+
+In life, intricate light and uneven object surfaces reflect off each other, making the entire environment illuminated as if by an even layer of light, this light is generally called **ambient light**, also known as **diffuse ambient light**.
+
+Because the ambient light can evenly illuminate all objects in the scene, it is often used to solve the problem of the backlight surface of the model is completely black, generally need to be used with other types of lights together. For example, if there is only directional light in the scene, it will look very dark at the backlight of the model.
+
+
+
+Check **Scene** in the **Hierarchy** panel, and then set the ambient light property in the **ambient** component of the **Inspector** panel.
+
+> **Note**: since ambient light is undirected, it cannot produce shadows.
+
+## Ambient Light Properties
+
+
+
+| Property | Description |
+| :--- | :--- |
+| SkyLightingColor | Sets the sky color. |
+| SkyIllum | Adjusts the sky brightness. |
+| GroundLightingColor | Sets the color of the reflected light from the ground. |
+
+The ambient light can be used together with the sky box, for details, please refer to the [Skybox](../../skybox.md) documentation.
diff --git a/versions/4.0/en/concepts/scene/light/lightType/ambient/ambient-prop.png b/versions/4.0/en/concepts/scene/light/lightType/ambient/ambient-prop.png
new file mode 100644
index 0000000000..e6300390ba
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightType/ambient/ambient-prop.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightType/ambient/ambient.png b/versions/4.0/en/concepts/scene/light/lightType/ambient/ambient.png
new file mode 100644
index 0000000000..b289dbff97
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightType/ambient/ambient.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightType/dir-light.md b/versions/4.0/en/concepts/scene/light/lightType/dir-light.md
new file mode 100644
index 0000000000..6e3f3bbd7b
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/light/lightType/dir-light.md
@@ -0,0 +1,83 @@
+# Directional Lights
+
+Directional Light is the most common type of light that simulates the light emitted by a source at infinity and is often used to simulate sunlight.
+
+
+
+Because the distance between the light and the illuminated target is undefined (infinite distance), the lighting effect is not affected by the **position** and **orientation** of the light (as shown below, directional light produces the same lighting brightness in all planes). However, **rotation** affects the direction of directional light, which in turn affects the extent to which the model receives light and where the model produces shadows. This can be done with the [Rotate Gizmo](../../../../editor/toolbar/index.md#rotate-gizmo) in the upper left corner of the editor to adjust the direction of directional light.
+
+
+
+Adding directional lights to the scene can be done as described in [Adding Lights](index.md#adding-lights).
+
+> **Note**: Cocos Creator currently supports only one directional light. If adding more than one at the same time, the last one added will prevail.
+
+A directional light node `Main Light` will be created automatically by default when creating a new scene.
+
+For the interface of the directional light component, please refer to [DirectionalLight API](%__APIDOC__%/en/class/DirectionalLight).
+
+> **Note**: Starting with v3.5, **Parallel Light Shadows** are separated from the Scene Settings panel and do not set shadow properties globally.
+
+## Directional Light Properties
+
+
+
+| Property | Description |
+| :------ | :-- |
+| Color | Sets the light color. |
+| UseColorTemperature | Whether to enable the color temperature. |
+| ColorTemperature | Adjusts the color temperature. |
+| StaticSettings | Sets static lighting, please refer to the [Lightmapping](../lightmap.md) documentation for details. |
+| Illumination | Illumination in **lux (lx)**. |
+
+### Directional Light Shadow Properties
+
+
+
+| Property | Explanation |
+| :--- | :--- |
+| ShadowEnabled | Whether to enable the shadow effect. |
+| ShadowPcf | Set the anti-aliasing level of the shadow edge, currently including **HARD**, **SOFT**, **SOFT_2X**. Please refer to the section **PCF Soft Shadow** below for details. |
+| ShadowBias | Set the shadow offset value to prevent z-fitting. |
+| ShadowNormalBias | Set the normal offset value. |
+| ShadowSaturation | Set the shadow saturation. It is recommended to set as **1**. If it is necessary to reduce the saturation of the directional light shadows, it is recommended to do it by increasing the ambient light instead of adjusting this value. |
+| ShadowInvisibleOcclusionRange | Set whether shadows from objects outside of the Camera's visible range are cast into the visible range, and if so, turns up the value. |
+| ShadowDistance | Set the range of shadow effects displayed within the visible range of the Camera, with the shadow quality inversely proportional to the size of this value. |
+| Enable CSM | Whether to enable Cascaded Shadow Map mode. |
+| FixedArea | Whether to manually control the display of shadow effects within the visible range of the Camera. |
+
+#### Enable CSM Mode
+
+The Cascaded Shadow Maps (CSM) method solves this problem by providing depth textures in chunks based on the distance from the object to the observer. It splits the camera's view cone into several parts, and then generates separate depth maps for each part of the split.
+
+A higher quality shadow map is used for near scenes, and a lower quality shadow map is used for far scenes, with one of the two shadow maps chosen for use where they transition. This ensures that the observer sees higher quality shadows in the near area and lower quality shadows in the far area, because the distant objects occupy only a small fraction of the screen, while the near objects occupy a large fraction of the screen.
+
+- CSM OFF:
+
+ 
+
+- CSM ON:
+
+ 
+
+#### FixedArea Mode
+
+FixedArea mode is used to set whether to manually control the range of shadow effects displayed within the visible range of the Camera:
+
+- If this option is unchecked (default), the engine uses the same crop process and camera calculations as CSM (Cascaded Shadow Maps), calculating the range of shadows generated based on the orientation and position of the Camera.
+- If this option is checked, the range of shadow generation is controlled according to the `Near`, `Far`, and `OrthoSize` properties set manually. The shadows follow the position of the directional light nodes and are distributed around the directional light bounding box, rather than following the camera.
+
+
+
+| Property | Explanation |
+| :--- | :--- |
+| ShadowFixedArea | Set whether to manually set the following properties to control the range of shadow effects displayed within the visible range of the Camera, as described in the **FixedArea Mode** section below. |
+| ShadowNear | Set the near clipping plane of the main lights shadow camera. |
+| ShadowFar | Set the far clipping plane of the main lights shadow camera. |
+| ShadowOrthoSize | Set the ortho viewport size of the main lights shadow camera, with the shadow quality inversely proportional to the size of this value. |
+
+#### PCF Soft Shadow
+
+Percentage Closer Filtering (PCF) is a simple, common technique used to achieve shadow edge desampling, by smoothing shadow edges to eliminate jaggedness in shadow mapping. The principle is to sample around the current pixel (also called a fragment), then calculate the ratio of the sample closer to the lights compared to the fragment, use this ratio to scale the scattered light and specular light, and then color the fragment to blur the shadow edges.
+
+Cocos Creator currently supports **hard sampler (HARD mode)**, **4x sampler (SOFT mode)**, **9x sampler (SOFT_2X mode)**. The larger the magnification, the larger the sampling area and the more softer the shadow edges.
diff --git a/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-fixedarea.png b/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-fixedarea.png
new file mode 100644
index 0000000000..2bfcb576fd
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-fixedarea.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-light-fixed-shadow-prop.png b/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-light-fixed-shadow-prop.png
new file mode 100644
index 0000000000..68b215a6ef
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-light-fixed-shadow-prop.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-light-panel.png b/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-light-panel.png
new file mode 100644
index 0000000000..d38d31542d
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-light-panel.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-light-prop.png b/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-light-prop.png
new file mode 100644
index 0000000000..7d9cc8d8f1
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-light-prop.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-light-scene.jpg b/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-light-scene.jpg
new file mode 100644
index 0000000000..95d8adcb49
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-light-scene.jpg differ
diff --git a/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-light-shadow-prop.png b/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-light-shadow-prop.png
new file mode 100644
index 0000000000..02ed89695f
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-light-shadow-prop.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-light.jpg b/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-light.jpg
new file mode 100644
index 0000000000..c8c096791e
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightType/dirlights/dir-light.jpg differ
diff --git a/versions/4.0/en/concepts/scene/light/lightType/dirlights/spot-light-shadow-prop.png b/versions/4.0/en/concepts/scene/light/lightType/dirlights/spot-light-shadow-prop.png
new file mode 100644
index 0000000000..84d44759f3
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightType/dirlights/spot-light-shadow-prop.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightType/index.md b/versions/4.0/en/concepts/scene/light/lightType/index.md
new file mode 100644
index 0000000000..efc4a764d9
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/light/lightType/index.md
@@ -0,0 +1,20 @@
+# Lights
+
+The light determines the color, color temperature, intensity, direction, and shadow effect of the light to which the object is exposed. The types of lights currently supported by Creator include:
+
+- [Directional Lights](dir-light.md)
+- [Spherical Lights](sphere-light.md)
+- [Spotlights](spot-light.md)
+- [Ambient Light](ambient.md)
+
+## Adding Lights
+
+There are two ways to add lights:
+
+1. Click the **+** button in the top left corner of the **Hierarchy** panel, select **Light**, and then select the light type as needed to create a node with the corresponding type of **Light Component** to the scene.
+
+ 
+
+2. In the **Hierarchy** panel, select the node to which you want to add a light, then click the **Add Component** button under the **Inspector** panel and select **Light** to select the desired light component to the node.
+
+ 
diff --git a/versions/4.0/en/concepts/scene/light/lightType/index/add-light.png b/versions/4.0/en/concepts/scene/light/lightType/index/add-light.png
new file mode 100644
index 0000000000..135f0d33f6
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightType/index/add-light.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightType/index/add-light2.png b/versions/4.0/en/concepts/scene/light/lightType/index/add-light2.png
new file mode 100644
index 0000000000..a2ef6ed771
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightType/index/add-light2.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightType/sphere-light.md b/versions/4.0/en/concepts/scene/light/lightType/sphere-light.md
new file mode 100644
index 0000000000..3d95d3f512
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/light/lightType/sphere-light.md
@@ -0,0 +1,35 @@
+# Spherical Lights
+
+Cocos Creator 3.x's spherical light is similar to v2.x's point light.
+
+Spherical light spreads light evenly in all directions, similar to the light produced by a candle. The intensity of light on an object decreases as the distance from the light increases, and is zero when the distance exceeds the set light effect range.
+
+In practical applications, it can be used to simulate lights such as torches, candles, and light bulbs to illuminate the surrounding environment within a certain distance.
+
+
+
+The light location and color, as well as its illumination range can be clearly seen in the editor, as shown in the image below. The light range of the spherical light can be adjusted by modifying the `Range` property of the spherical light component in the **Inspector** panel.
+
+
+
+Adding spherical lights to the scene can be done as described in [Adding Lights](index.md#adding-lights).
+
+For the spherical light component interface, please refer to [SphereLight API](%__APIDOC__%/en/class/SphereLight).
+
+## Sphere Light Properties
+
+
+
+| Property | Description |
+| :---- | :---- |
+| Color | Sets the light color. |
+| UseColorTemperature | Whether to enable the color temperature. |
+| ColorTemperature |Adjusts the color temperature.|
+| Size | Sets the light size. |
+| Range | Sets the range of light effect. |
+| Term | Sets the type of light intensity unit, including **LUMINOUS_POWER** and **LUMINANCE**.
+| LuminousPower | Luminous flux in **lumens (lm)**. Effective when **Term** is set to **LUMINOUS_POWER**. |
+| Luminance | Brightness in **Candela per square meter (cd/m2)**. Effective when **Term** is set to **LUMINANCE**. |
+| StaticSettings | Static lighting settings, please refer to [Lightmapping](../lightmap.md). |
+
+> **Note**: currently, the `Size` property of the spherical light does not take effect in actual operation, as well as the display of shadows is not supported for now, we will optimize it in subsequent versions, please pay attention to the update announcement.
diff --git a/versions/4.0/en/concepts/scene/light/lightType/spherelight/sphere-light-edit.png b/versions/4.0/en/concepts/scene/light/lightType/spherelight/sphere-light-edit.png
new file mode 100644
index 0000000000..5db157a9a1
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightType/spherelight/sphere-light-edit.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightType/spherelight/sphere-light-prop.png b/versions/4.0/en/concepts/scene/light/lightType/spherelight/sphere-light-prop.png
new file mode 100644
index 0000000000..a2932b9234
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightType/spherelight/sphere-light-prop.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightType/spherelight/sphere-light.jpg b/versions/4.0/en/concepts/scene/light/lightType/spherelight/sphere-light.jpg
new file mode 100644
index 0000000000..f1dcee109b
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightType/spherelight/sphere-light.jpg differ
diff --git a/versions/4.0/en/concepts/scene/light/lightType/spot-light.md b/versions/4.0/en/concepts/scene/light/lightType/spot-light.md
new file mode 100644
index 0000000000..19462d21fa
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/light/lightType/spot-light.md
@@ -0,0 +1,65 @@
+# Spotlights
+
+A **Spotlight** is a cone-shaped beam of light emitted from a point in one direction, similar to the light produced by a flashlight or stage lighting. Compared to other lights, spotlights have an additional `SpotAngle` property, which is used to adjust the light range of the spotlight.
+
+
+
+In the editor, one can clearly see the position, color and light range of the light as well as its spot angle, as shown in the following image. With the [Transform Gizmos](../../../../editor/toolbar/index.md) in the upper left corner of the editor, it is possible to adjust the position and direction of the spotlight.
+
+
+
+See [Adding Lights](index.md#adding-lights) for how to add spotlights to a scene.
+
+For the Spotlight component interface, please refer to [SpotLight API](%__APIDOC__%/en/class/SpotLight).
+
+> **Note**: Starting with v3.5, **Spotlight Shadows** are separated from the Scene Settings panel and are no longer affected by the Global Shadows parameter.
+
+## Spotlight Properties
+
+
+
+| Property | Description |
+| :------ | :--- |
+| Color | Sets the color of the light. |
+| UseColorTemperature | Whether to enable the color temperature. |
+| ColorTemperature |Adjusts the color temperature. |
+| Size | Sets the light size. |
+| Range | Sets the range of light effect. |
+| SpotAngle | Adjusts the spot angle to control the light range. |
+| AngleAttenuationStrength | The larger the value, the softer the edge, and the smaller the value, the harder the edge. |
+| Term | Sets the light intensity unit type, including **LUMINOUS_POWER** and **LUMINANCE**.
+| LuminousPower | Luminous flux in **lumens (lm)**. Effective when **Term** is set to **LUMINOUS_POWER**. |
+| Luminance | Brightness in **Candela per square meter (cd/m2)**. Effective when **Term** is set to **LUMINANCE**. |
+| StaticSettings | Static lighting settings, please refer to the [Lightmapping](../lightmap.md) documentation. |
+
+### **Note**:
+* Due to the significant performance overhead of real-time shadows in 3D scenes on mobile native platforms such as openharmony, harmonyNext, android, and ios, the engine by default does not allow multiple spot lights to enable shadows on these platforms. To lift this restriction, you need to call the relevant modification code before the engine completes rendering pipeline initialization. Refer to the following code example:
+ ```ts
+ import { _decorator, Component, macro, rendering } from 'cc';
+ const { ccclass, property } = _decorator;
+
+ // Lift the restriction on multiple spot lights enabling shadows on mobile platforms
+ var builder = rendering.getCustomPipeline(macro.CUSTOM_PIPELINE_NAME) as any;
+ builder._configs.isMobile = false;
+
+ @ccclass('NewComponent')
+ export class NewComponent extends Component {}
+ ```
+* If the game enables MSAA anti-aliasing, it will also prevent multiple spot lights from enabling shadows on mobile native platforms.
+
+### Spotlight Shadow Properties
+
+
+
+| Property | Explanation |
+| :--- | :--- |
+| ShadowEnabled | Whether to enable the shadow effect. |
+| ShadowPcf | Set the anti-aliasing level of the shadow edge, currently including **HARD**, **SOFT**, **SOFT_2X**. Please refer to the section **PCF Soft Shadow** below for details. |
+| ShadowBias | Set the shadow offset value to prevent z-fitting. |
+| ShadowNormalBias | Set the normal offset value. |
+
+#### PCF Soft Shadow
+
+Percentage Closer Filtering (PCF) is a simple, common technique used to achieve shadow edge desampling, by smoothing shadow edges to eliminate jaggedness in shadow mapping. The principle is to sample around the current pixel (also called a fragment), then calculate the ratio of the sample closer to the lights compared to the fragment, use this ratio to scale the scattered light and specular light, and then color the fragment to blur the shadow edges.
+
+Cocos Creator currently supports **hard sampler (HARD mode)**, **4x sampler (SOFT mode)**, **9x sampler (SOFT_2X mode)**. The larger the magnification, the larger the sampling area and the more softer the shadow edges.
diff --git a/versions/4.0/en/concepts/scene/light/lightType/spotlight/spot-light-prop.png b/versions/4.0/en/concepts/scene/light/lightType/spotlight/spot-light-prop.png
new file mode 100644
index 0000000000..ee1df2c401
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightType/spotlight/spot-light-prop.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightType/spotlight/spot-light-scene.jpg b/versions/4.0/en/concepts/scene/light/lightType/spotlight/spot-light-scene.jpg
new file mode 100644
index 0000000000..2334e5a24d
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightType/spotlight/spot-light-scene.jpg differ
diff --git a/versions/4.0/en/concepts/scene/light/lightType/spotlight/spot-light-shadow-prop.png b/versions/4.0/en/concepts/scene/light/lightType/spotlight/spot-light-shadow-prop.png
new file mode 100644
index 0000000000..b38952d612
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightType/spotlight/spot-light-shadow-prop.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightType/spotlight/spot-light.jpg b/versions/4.0/en/concepts/scene/light/lightType/spotlight/spot-light.jpg
new file mode 100644
index 0000000000..f9866e9bcc
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightType/spotlight/spot-light.jpg differ
diff --git a/versions/4.0/en/concepts/scene/light/lighting.png b/versions/4.0/en/concepts/scene/light/lighting.png
new file mode 100644
index 0000000000..b759377766
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lighting.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightmap.md b/versions/4.0/en/concepts/scene/light/lightmap.md
new file mode 100644
index 0000000000..caf9b64e95
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/light/lightmap.md
@@ -0,0 +1,91 @@
+# Lightmapping
+
+The **Baking System** pre-calculates the lighting, shadows, etc. that a static object with a stable light will receive. The result of this calculation is stored in a texture map, which is called a **lightmap**.
+
+Cocos Creator automatically processes and uses the generated lightmap at runtime. In scenes with fixed lights, using lightmaps instead of real-time lighting calculations can reduce resource consumption and thus increase the efficiency of the scene.
+
+## Lightmapping Panel
+
+Click **Project -> Lightmapping** in the editor menu bar to open the Lightmapping panel. The panel consists of two pages, **Scene** and **Baked**.
+
+
+
+- **Scene**: mainly used to configure the parameters related to generating the lightmap.
+- **Baked**: mainly used to display the generated lightmap and its related information.
+
+For details, please see the **Generating Lightmaps** section below.
+
+### Property Description
+
+The description of each property on the **Scene** page is as follows:
+
+| Property | Description |
+| :--- | :--- |
+| MSAA | Multiple Sampling, optional values include: 1, 2, 4, 8 |
+| Resolution | The resolution of the generated lightmap, optional values are 128, 256, 512, 1024, 2048 |
+| Gamma | Gamma correction value |
+| GIScale | Global lighting scaling factor |
+| GISamples | Global illumination sampling factor |
+| AOLevel | AO (Ambient Occlusion) level |
+| AOStrength | AO intensity |
+| AORadius | AO radius |
+| AOColor | AO color |
+
+## Generating lightmaps
+
+1. Select the node with the light component in the **Hierarchy** panel, then set the **StaticSettings** of the light component in the **Inspector** panel, and check the `Bakeable` property (currently multiple [Directional Lights](./lightType/dir-light.md) are not supported).
+
+ 
+
+ - **EditorOnly**: whether to take effect only in the editor
+
+ - **Bakeable**: whether to bake static lighting
+
+ - **CastShadow**: whether to cast static shadows
+
+2. Select the node with the [MeshRenderer component](./../../../engine/renderable/model-component.md) in the **Hierarchy** panel to generate the lightmap, then set **LightmapSettings** in the **Inspector** panel and check the `Bakeable` property.
+
+ 
+
+ - **Bakeable**: whether to bake static lighting
+
+ - **CastShadow**: whether to cast static shadows
+
+ - **ReceiveShadow**: whether to receive static shadows
+
+ - **LightmapSize**: the size of the model lightmap
+
+ > **Notes**: to generate lightmaps for a model, there are two requirements:
+ >
+ > 1. When the artist creates a model resource, in addition to the UVs of the model itself, another set of UVs for lightmapping needs to be included.
+ >
+ > 2. The model's Materials need to have the **USE LIGHTMAP** rendering option turned on, for example:
+ >
+ > 
+
+3. lightmap UVs
+ Unlike texture UVs, lightmap UVs cannot overlap
+
+ > **Notes**:Incorrect UVs produce errors:
+ >
+ > 1. UV of different planes are interlaced
+ >
+ > 
+ > 
+ > 
+ >
+ > 2. There is no reserved interval between UV blocks
+ >
+ > 
+
+4. Open the **Lightmapping** panel and set the corresponding properties. Then click the **Lightmap Generate** button, a file storage dialog will pop up, you need to specify a folder (must be in the `assets` directory) to store the generated lightmap data information. Notice the baking progress log at the bottom of the **Lightmapping** panel.
+
+ 
+
+5. After baking, the generated lightmap, as well as the file name, size and other related information can be viewed on the **Baked** page of the **Lightmapping** panel. The generated lightmaps are automatically processed by the engine and do not need to be manipulated by the developer.
+
+ 
+
+ 1. **Bake result**: shows the generated lightmap after baking, in format **RGBE8**, with **R**/**G**/**B** options to view the corresponding channels of the lightmap as required.
+ 2. **Lightmap clear**: used to delete the generated lightmap and related information.
+ 3. **Information output panel**: shows the generated lightmap file name, size and other related information.
diff --git a/versions/4.0/en/concepts/scene/light/lightmap/bake-menu.png b/versions/4.0/en/concepts/scene/light/lightmap/bake-menu.png
new file mode 100644
index 0000000000..265a3e2ffe
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightmap/bake-menu.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightmap/light-bakeable.png b/versions/4.0/en/concepts/scene/light/lightmap/light-bakeable.png
new file mode 100644
index 0000000000..dd986c3278
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightmap/light-bakeable.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightmap/lightmap-generate.png b/versions/4.0/en/concepts/scene/light/lightmap/lightmap-generate.png
new file mode 100644
index 0000000000..34bbd0383e
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightmap/lightmap-generate.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightmap/lightmap-panel.png b/versions/4.0/en/concepts/scene/light/lightmap/lightmap-panel.png
new file mode 100644
index 0000000000..99434dbc39
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightmap/lightmap-panel.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightmap/lightmap-result.png b/versions/4.0/en/concepts/scene/light/lightmap/lightmap-result.png
new file mode 100644
index 0000000000..ad77c5f2b4
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightmap/lightmap-result.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightmap/materials.png b/versions/4.0/en/concepts/scene/light/lightmap/materials.png
new file mode 100644
index 0000000000..5a777e91c5
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightmap/materials.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightmap/meshrenderer-bakeable.png b/versions/4.0/en/concepts/scene/light/lightmap/meshrenderer-bakeable.png
new file mode 100644
index 0000000000..d1f6927d4f
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightmap/meshrenderer-bakeable.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightmap/overlap_back.png b/versions/4.0/en/concepts/scene/light/lightmap/overlap_back.png
new file mode 100644
index 0000000000..149465e671
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightmap/overlap_back.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightmap/overlap_front.png b/versions/4.0/en/concepts/scene/light/lightmap/overlap_front.png
new file mode 100644
index 0000000000..4f89856ac8
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightmap/overlap_front.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightmap/overlap_lightmap.png b/versions/4.0/en/concepts/scene/light/lightmap/overlap_lightmap.png
new file mode 100644
index 0000000000..f9e77b4d15
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightmap/overlap_lightmap.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lightmap/uvspace_lightmap.png b/versions/4.0/en/concepts/scene/light/lightmap/uvspace_lightmap.png
new file mode 100644
index 0000000000..9b4f9e4ad9
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lightmap/uvspace_lightmap.png differ
diff --git a/versions/4.0/en/concepts/scene/light/lux-outdoor.jpg b/versions/4.0/en/concepts/scene/light/lux-outdoor.jpg
new file mode 100644
index 0000000000..971e3ec7b3
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/lux-outdoor.jpg differ
diff --git a/versions/4.0/en/concepts/scene/light/pbr-lighting.md b/versions/4.0/en/concepts/scene/light/pbr-lighting.md
new file mode 100644
index 0000000000..cb09eba094
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/light/pbr-lighting.md
@@ -0,0 +1,58 @@
+# Physically Based Lighting
+
+The light parameters are described in Cocos Creator using photometric units. Based on the photometric units, all the relevant parameters of the light can be converted into real-world physical values. In this way, designers can adjust the **light intensity**, **color**, **range**, and other information based on lighting-related industrial parameters and the actual physical parameters of the real environment to make the overall lighting effect more in line with the real natural environment.
+
+
+
+## Lights in the Real World
+
+The physically based lighting matches the description of lights in the real world. In real environments, light products have their own industrial parameters:
+
+
+
+The product packaging states many important industrial parameters of a bulb:
+- **Luminous Flux**
+- **Color Temperature**
+- **Size**
+
+These three important parameters affect the performance of lights in the real world, and it is important to focus on the physical meaning of these three parameters below.
+
+## Photometric Units
+
+**Photometric Units** are used to calculate the intensity (size) and direction of light.
+
+- **Luminous Flux**
+
+ The unit is **lumens (lm)**, the total light energy emitted by a light or received by an illuminated object per unit of time. Changing the size of the light will not affect the scene lighting effect.
+
+- **Luminance**
+
+ The unit is **Candela per square meter (cd/m2)**, the total luminous flux emitted by a light per unit area in a given direction, per unit area. Changing the size of the light affects the scene lighting effect.
+
+- **Illuminance**
+
+ The unit is **lux or lx**, the amount of luminous flux received per unit area. This value is affected by the distance the light travels, and for the same light, when the light is twice as far away, the illuminance is reduced to one-fourth of the original, in an inverse square relationship.
+
+In the real world, because the important physical parameters describing lights are different, we usually use **Luminous Flux** and **Luminance** to describe common household lights with illuminated areas, and **Illuminance** to describe sunlight.
+
+
+
+## Color Temperature
+
+**Color Temperature** is the color of an absolute blackbody after it has been warmed from absolute zero (-273°C).
+
+Color temperature is an important property that affects the color of a light and is an optional property that also participates in the color component of the light when color temperature is enabled.
+
+The ambient color temperature also changes dynamically in real-world environments at different times of the day:
+
+
+
+Refer to the following table:
+
+
+
+## Size
+
+Real-world lights have real physical dimensions, and for the **same luminous flux**, the size of the light affects **brightness** and **illuminance**.
+
+
diff --git a/versions/4.0/en/concepts/scene/light/pbrlighting/color-temp-of-day.jpg b/versions/4.0/en/concepts/scene/light/pbrlighting/color-temp-of-day.jpg
new file mode 100644
index 0000000000..31a1d979a2
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/pbrlighting/color-temp-of-day.jpg differ
diff --git a/versions/4.0/en/concepts/scene/light/pbrlighting/kelvin.jpg b/versions/4.0/en/concepts/scene/light/pbrlighting/kelvin.jpg
new file mode 100644
index 0000000000..68607c7a6d
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/pbrlighting/kelvin.jpg differ
diff --git a/versions/4.0/en/concepts/scene/light/pbrlighting/light-bulb-size.png b/versions/4.0/en/concepts/scene/light/pbrlighting/light-bulb-size.png
new file mode 100644
index 0000000000..bd9a644d4b
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/pbrlighting/light-bulb-size.png differ
diff --git a/versions/4.0/en/concepts/scene/light/pbrlighting/light-bulb.jpg b/versions/4.0/en/concepts/scene/light/pbrlighting/light-bulb.jpg
new file mode 100644
index 0000000000..668c5057b9
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/pbrlighting/light-bulb.jpg differ
diff --git a/versions/4.0/en/concepts/scene/light/pbrlighting/light-power.jpg b/versions/4.0/en/concepts/scene/light/pbrlighting/light-power.jpg
new file mode 100644
index 0000000000..a370edb2b3
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/pbrlighting/light-power.jpg differ
diff --git a/versions/4.0/en/concepts/scene/light/pbrlighting/pbr-lighting.jpg b/versions/4.0/en/concepts/scene/light/pbrlighting/pbr-lighting.jpg
new file mode 100644
index 0000000000..5e919970b4
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/pbrlighting/pbr-lighting.jpg differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/example.md b/versions/4.0/en/concepts/scene/light/probe/example.md
new file mode 100644
index 0000000000..5062a78f87
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/light/probe/example.md
@@ -0,0 +1,90 @@
+# IBL Example
+
+In Cocos Creator developers can combine image lighting based features. These features include.
+
+- via [skybox](../../skybox.md) with baked reflection convolution to provide better ambient reflection effects
+- Bake lighting information into the environment with [Lightmapping](../lightmap.md) to bake lighting information into the map to improve lighting performance
+- Bake lighting information into maps to improve lighting performance via [light-probe](./light-probe.md)/[reflection-probe](./reflection-probe.md) to detect reflections between objects
+
+This article will demonstrate how to bake image-based lighting into your scenes from an art asset worker's workflow.
+
+## Preparation
+
+Since both Light Probe and Reflection Probe are for physically based lighting models, please follow the PBR workflow when creating art resources.
+
+Please prepare the material file in advance using the following shaders; or import the model exported from the DCC tool via [Importing Models Exported from DCC Tools](../../../../asset/model/dcc-export-mesh.md). Importing to **Resource Manager** will automatically recognize the materials in the model and convert its shaders to PBR shaders supported by the engine.
+
+ 
+
+- builtin-standard: built-in standard PBR shader
+- dcc/imported-metallic-roughness: shader for models exported based on the metallic-roughness workflow
+- dcc/imported-specular-glossiness: shader for models exported based on the specular-glossiniess workflow
+- surface/standard: built-in standard surface PBR shader
+- dcc/surface-imported-metallic-roughness: built-in shader for models exported from the metallic-roughness workflow based on the standard surface
+- dcc/surface-imported-specular-glossiness: built-in shader for models exported from the specular-glossiniess workflow for standard surfaces
+
+It can also be manually adjusted to use the above standard shaders after the model has been imported into **Assets Manager**.
+
+Developers can also review the following documentation to understand the entire PBR workflow.
+
+- [Physically Based Lighting](../pbr-lighting.md)
+- [Physically Based Rendering (PBR)](../../../../shader/effect-builtin-pbr.md)
+- [Importing Models Exported from DCC Tools](../../../../asset/model/dcc-export-mesh.md).
+- [FBX Smart Material Conversion](../../../../importer/materials/fbx-materials.md)
+
+## Bake Lights
+
+The [light-probe panel](light-probe-panel.md), and [lightmap](../lightmap.md) can be used for light baking to generate image-based lighting.
+
+### Bakeing Process
+
+As an example of a manually built scene.
+
+
+
+- Add [light-probe](light-probe.md)
+
+ 
+
+- Add [reflection probes](relfection-probe.md)
+
+ 
+
+- Adjusting the properties of a node
+ - For the nodes that need to use the baked results, adjust their properties as follows:
+
+ 
+
+ 
+
+ - For the node to be baked
+ - Ensure that the **Mobility** property within its **Inspector** is **Static**.
+
+ 
+
+ - Check the **Bake To Light Probe** and **Bake To Reflection Probe** properties of its **MeshRenderer** property and select **Reflection Probe** wisely
+
+ 
+
+- Open the **Reflection Probe** and **Light Probe** panels.
+
+ - Click the **Bake** button on the above panel and wait for the baking process to finish.
+
+ 
+
+- Optionally, you can bake [lightmap] via the **Light Baking** panel (../lightmap.md):
+
+ 
+
+- Within **Hierarchy** **Scene Node**, find [Skybox](../../skybox.md) on its **Inspector** component and adjust the corresponding properties to get better results
+
+ 
+
+ - Adjust **Env Lighting Type** to **AUTOGEN_HEMISPHERE_DIFFUSE_WITH_REFLECTION**
+ - Click the **Bake** button on the **Skybox** component to bake the reflection convolution map.
+
+ This will give you a more realistic ambient reflection lighting effect
+
+- Check the baking result:
+
+ 
diff --git a/versions/4.0/en/concepts/scene/light/probe/example/bake-option.png b/versions/4.0/en/concepts/scene/light/probe/example/bake-option.png
new file mode 100644
index 0000000000..85113581e5
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/example/bake-option.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/example/baking-panels.png b/versions/4.0/en/concepts/scene/light/probe/example/baking-panels.png
new file mode 100644
index 0000000000..9f1f80c000
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/example/baking-panels.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/example/baking-result.png b/versions/4.0/en/concepts/scene/light/probe/example/baking-result.png
new file mode 100644
index 0000000000..11f9070bf8
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/example/baking-result.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/example/basic.png b/versions/4.0/en/concepts/scene/light/probe/example/basic.png
new file mode 100644
index 0000000000..679b0d823b
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/example/basic.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/example/effects.png b/versions/4.0/en/concepts/scene/light/probe/example/effects.png
new file mode 100644
index 0000000000..c259a50011
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/example/effects.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/example/light-probe.png b/versions/4.0/en/concepts/scene/light/probe/example/light-probe.png
new file mode 100644
index 0000000000..a540ddb2f0
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/example/light-probe.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/example/lightmap-panel.png b/versions/4.0/en/concepts/scene/light/probe/example/lightmap-panel.png
new file mode 100644
index 0000000000..dabf9de4a0
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/example/lightmap-panel.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/example/mobility.png b/versions/4.0/en/concepts/scene/light/probe/example/mobility.png
new file mode 100644
index 0000000000..55af8a6b7b
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/example/mobility.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/example/probe-setting.png b/versions/4.0/en/concepts/scene/light/probe/example/probe-setting.png
new file mode 100644
index 0000000000..94767bc455
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/example/probe-setting.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/example/reflection-probe.png b/versions/4.0/en/concepts/scene/light/probe/example/reflection-probe.png
new file mode 100644
index 0000000000..7e63463705
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/example/reflection-probe.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/example/scene.png b/versions/4.0/en/concepts/scene/light/probe/example/scene.png
new file mode 100644
index 0000000000..e4a0525763
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/example/scene.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/example/skybox.png b/versions/4.0/en/concepts/scene/light/probe/example/skybox.png
new file mode 100644
index 0000000000..a8648e1557
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/example/skybox.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/example/static.png b/versions/4.0/en/concepts/scene/light/probe/example/static.png
new file mode 100644
index 0000000000..bee765c372
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/example/static.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/example/surface-standard-effect.png b/versions/4.0/en/concepts/scene/light/probe/example/surface-standard-effect.png
new file mode 100644
index 0000000000..556a0828b4
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/example/surface-standard-effect.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/img/index.png b/versions/4.0/en/concepts/scene/light/probe/img/index.png
new file mode 100644
index 0000000000..0862cae2e6
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/img/index.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/index.md b/versions/4.0/en/concepts/scene/light/probe/index.md
new file mode 100644
index 0000000000..ecc64d4cf5
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/light/probe/index.md
@@ -0,0 +1,40 @@
+# Imaged Based Lighting
+
+
+
+Since computing lighting in real time is too demanding for hardware, most of the games or 3D simulations use Image Based Lighting (IBL) for higher performance, which means that the lighting information is stored on the computer's storage media and the lighting is reconstructed by sampling the information in the graphics at runtime.
+
+In the engine, image based lighting usually consists of the following functions.
+
+## Light Mapping
+
+With [Lightmapping](../lightmap.md) developers can record the lighting information of the scene on the mapping and use it at runtime. Thus, the use of real time within the scene can be avoided or reduced and rendering efficiency can be improved.
+
+## Skybox
+
+In [Skybox](../../skybox.md), **Bake Reflection Convolution Map** can be used to generate a pre-convolved reflection effect for the environment map to improve the quality of the ambient lighting.
+
+## Light Probe
+
+Starting from v3.7, Cocos Creator supports [light-probe](light-probe.md) and [reflection-probe](reflection-probe.md).
+
+The light-probe is part of the global illumination. The probe is placed inside the scene to detect the light bouncing around the scene and store the offline results to improve the lighting effect and enhance the rendering quality.
+
+## Reflection Probe
+
+The [reflection-probe](reflection-probe.md) currently supports both real-time and baked cases. In the real-time case, developers can configure the reflection-probe to render the reflection effect of objects in real time. The baked case allows the
+
+By combining [Skybox](../../skybox.md), [Lightmapping](../lightmap.md), [Light Probe](./light-probe.md) and [Reflection Probe](reflection-probe.md) to get more realistic and reliable lighting effects with performance.
+
+## Contents
+
+This chapter will contain the following.
+
+- [Light Probe](light-probe.md)
+ - [Light Probe Panel](light-probe-panel.md)
+- [Reflection Probe](reflection-probe.md)
+ - [Reflection Probe Panel](reflection-probe-panel.md)
+ - [Art workflow example](reflection-art-workflow.md)
+- [Skybox](../../skybox.md)
+- [lightmap](../lightmap.md)
+- [Image Based lighting Example](example.md)
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe-panel.md b/versions/4.0/en/concepts/scene/light/probe/light-probe-panel.md
new file mode 100644
index 0000000000..e4008e55f4
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/light/probe/light-probe-panel.md
@@ -0,0 +1,36 @@
+# Light Probe Panel
+
+From the top menu of the editor, select **Projects** -> **Light Baking** -> **Light Probe** to open the Light Probe Baking Panel.
+
+The **Light Baking Panel** will bake the [light-probe](light-probe.md) already laid out in the **Scene Editor**. After baking, the indirect light information of the static object will be recorded to the storage medium; all nodes configured with the **Movable** property will have access to more detailed and realistic indirect light effects.
+
+## Properties
+
+
+
+| Properties | Description |
+| :-- | :-- |
+| **GIScale** | GI([Global Illumination](https://en.wikipedia.org/wiki/Global_illumination))scale factor |
+| **GISample** | GI sample count of each light probe |
+| **Bounces** | Number of light bounces, in the range [1, 4] The meaning of bounce is the process of the current light source hitting an object and bouncing back to the probe. If the number of light bounces exceeds this property, it will not be recorded in the baking result |
+| **Reduceing Ringing** | In some cases, the light from the light probe may penetrate from bright to dark areas thus forming a ring. Modifying this property may improve the situation, but may result in unrealistic lighting |
+| **Show Probe** | Whether to show light probes The node with the **LightProbeGroup** component needs to be selected in the **Hierarchy**  |
+| **Show Wireframe** | Whether to display the connection between light probes The node with the **LightProbeGroup** component needs to be selected in the **Hierarchy**  |
+| **Show Convex** | Whether to display the convex wrapping frame and vertex normals The node with the **LightProbeGroup** component needs to be selected in the **Hierarchy** |
+| **Bake Light Probe** | Bake light probes |
+| **Clear Result** | Clear bake results |
+| **Cancel** | Cancel the baking process, this button will only be enabled when **Bake Light Probe** is clicked |
+
+## Sample
+
+Click **Bake Light Probe** to bake the light probe, and click **Clear Result** to clear the baked result.
+
+You can click **Cancel** to cancel the baking process.
+
+The progress of baking can be viewed in the information panel below.
+
+
+
+Developers can also use the **Show Probe**, **Show Wireframe**, and **Show Convex** options to see within the scene if the probe matches the expected results.
+
+See the [IBL Example](example.md) to see the art workflow.
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe-panel/bake-panel.png b/versions/4.0/en/concepts/scene/light/probe/light-probe-panel/bake-panel.png
new file mode 100644
index 0000000000..0a1956b249
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/light-probe-panel/bake-panel.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe-panel/convex.png b/versions/4.0/en/concepts/scene/light/probe/light-probe-panel/convex.png
new file mode 100644
index 0000000000..3aaf09cb30
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/light-probe-panel/convex.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe-panel/info.png b/versions/4.0/en/concepts/scene/light/probe/light-probe-panel/info.png
new file mode 100644
index 0000000000..d2a80c9fb4
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/light-probe-panel/info.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe-panel/probe.png b/versions/4.0/en/concepts/scene/light/probe/light-probe-panel/probe.png
new file mode 100644
index 0000000000..c1022530a4
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/light-probe-panel/probe.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe-panel/wireframe.png b/versions/4.0/en/concepts/scene/light/probe/light-probe-panel/wireframe.png
new file mode 100644
index 0000000000..083dd7c9df
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/light-probe-panel/wireframe.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe.md b/versions/4.0/en/concepts/scene/light/probe/light-probe.md
new file mode 100644
index 0000000000..bd9f0a946d
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/light/probe/light-probe.md
@@ -0,0 +1,102 @@
+# Light Probes
+
+
+
+The Light Probe is designed to provide high quality light information for objects in the scene by pre-calculating; it also provides light information for objects that require LOD.
+
+After hitting an object in a scene, light may bounce back to another object, and such bounces may occur multiple times.
+
+The following figure demonstrates how light bounces once in the scene and is captured by the light probe.
+
+
+
+After the light hits the surface of object A, it is reflected to object B. Through the light probe, the reflection of this light from object B is captured on the map, and then the light is reconstructed at runtime to get the indirect reflected light information of static objects in the scene.
+
+Cocos Creator supports up to 4 bounces, please refer to [Light Probe Panel](light-probe-panel.md) for details.
+
+## Add light probe group
+
+In the **Main Menu** select **Nodes** -> **Light** -> **Light Probe Group** to add light probes to the scene.
+
+
+
+## Properties
+
+
+
+| Properties | Description |
+| :-- | :-- |
+| **Generating Method** | Generated in a way that currently only supports built-in |
+| **Generating Min Pos** | The minimum value of the bounding box at the time of generation |
+| **Generating Max Pos** | The maximum value of the bounding box at the time of generation |
+| **Number Of Probes X** | Number of probes on the X-axis |
+| **Number Of Probes Y** | Number of probes on the Y-axis |
+| **Number Of Probes Z** | Number of probes on the Z-axis |
+| **Edit Area Box** | Editing the generated enclosing box Clicking this button will put you in the editing mode of the probe enclosing box in the scene, please refer to the editing documentation below for more detailed information The editing process will affect the values of **Generating Min Pos** and **Generating Max Pos** above |
+| **Generate Probes** | Generate Light Probes Clicking on the button will regenerate all probes and the old ones will be deleted The generated probes are uniform, if you need to adjust them manually, please click the decentralized **Enter Probe Edit Mode** button |
+| **Enter Probe Edit Mode** | Enter edit probe mode Click this button to select different probes in the scene editor with **left mouse button** and modify the probe position with **transform tool** |
+
+## Edit Probes
+
+### Edit Probe Range
+
+Clicking on **Edit Area Box** to edit the bounding box. The scene will be displayed as a **Green** box, which can be resized by clicking the green Gizmo on the box.
+
+
+
+Click the **Done Edit** button to exit edit mode.
+
+
+
+You can then click **Generate Probes** to regenerate the probes.
+
+### Generate Probes
+
+Probes can be generated by clicking the **Generate Probes** button. At this point the old probes will be deleted, if you need to re-bake the probes, please refer to the **Bake Light Probes** section below.
+
+
+
+### Edit Probe Position
+
+After generating a probe, you can click the **Enter Probe Edit Mode** button to enter the probe editing mode.
+
+Only then the probe of the scene can be selected.
+
+
+
+The position of the probes can be adjusted by dragging and dropping these Gizmo's with the mouse.
+
+
+
+## Use Probes
+
+Check **Use Light Probe** in the node's **Inspector** panel and set the node's **Mobility** property to **Movable** to enable node probes.
+
+
+
+
+
+When enabled, select the node within **Hierarchy** to see which probes the node is affected by. The white dots in the illustration are light probes.
+
+
+
+## Bake Light Probes
+
+For nodes that need to be baked, check the node's **Bake To Light Probe**.
+
+
+
+After editing the light probe, you can open the [Light Probe Panel](light-probe-panel.md) by selecting **Project** -> **Light-Bake** -> **Light-Probe**.
+
+
+
+More examples can be found in [IBL Example](example.md).
+
+## Theoretical reference
+
+Usually light probes are calculated by means of spherical harmonic functions. For developers interested in technical details, we have also prepared some reference documents.
+
+- [Spherical Harmonic Lighting: The Gritty Details](http://www.cse.chalmers.se/~uffe/xjobb/Readings/GlobalIllumination/Spherical%20Harmonic%20Lighting%20-%20the%20gritty%20details.pdf)
+- [Spherical harmonic lighting Wiki](https://en.wikipedia.org/wiki/Spherical_harmonic_lighting)
+- [Fourier Transform Wiki](https://en.wikipedia.org/wiki/Fourier_transform)
+- [Spherical Harmonic](https://en.wikipedia.org/wiki/Spherical_Harmonic#:~:text=.%20In%20mathematics%20and%20physical%20science%2C%20spherical%20harmonics,solving%20partial%20differential%20equations%20in%20many%20scientific%20fields.)
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe/bake-to-light-probe.png b/versions/4.0/en/concepts/scene/light/probe/light-probe/bake-to-light-probe.png
new file mode 100644
index 0000000000..70525dedb2
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/light-probe/bake-to-light-probe.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe/done-edit.png b/versions/4.0/en/concepts/scene/light/probe/light-probe/done-edit.png
new file mode 100644
index 0000000000..570fa2b7de
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/light-probe/done-edit.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe/edit-area-box.gif b/versions/4.0/en/concepts/scene/light/probe/light-probe/edit-area-box.gif
new file mode 100644
index 0000000000..5f2aa74e8c
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/light-probe/edit-area-box.gif differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe/edit-probe.gif b/versions/4.0/en/concepts/scene/light/probe/light-probe/edit-probe.gif
new file mode 100644
index 0000000000..af09f34a78
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/light-probe/edit-probe.gif differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe/generate-probes.png b/versions/4.0/en/concepts/scene/light/probe/light-probe/generate-probes.png
new file mode 100644
index 0000000000..c1b83c142d
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/light-probe/generate-probes.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe/light-probe.png b/versions/4.0/en/concepts/scene/light/probe/light-probe/light-probe.png
new file mode 100644
index 0000000000..04bd4381d4
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/light-probe/light-probe.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe/mobility.png b/versions/4.0/en/concepts/scene/light/probe/light-probe/mobility.png
new file mode 100644
index 0000000000..ce3d1265e1
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/light-probe/mobility.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe/node-probes.png b/versions/4.0/en/concepts/scene/light/probe/light-probe/node-probes.png
new file mode 100644
index 0000000000..3b23c51be4
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/light-probe/node-probes.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe/probe-property.png b/versions/4.0/en/concepts/scene/light/probe/light-probe/probe-property.png
new file mode 100644
index 0000000000..ec1e973d75
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/light-probe/probe-property.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe/probe.png b/versions/4.0/en/concepts/scene/light/probe/light-probe/probe.png
new file mode 100644
index 0000000000..80f68402a8
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/light-probe/probe.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe/result.png b/versions/4.0/en/concepts/scene/light/probe/light-probe/result.png
new file mode 100644
index 0000000000..46cd209a21
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/light-probe/result.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe/select-probe.png b/versions/4.0/en/concepts/scene/light/probe/light-probe/select-probe.png
new file mode 100644
index 0000000000..1576153cd3
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/light-probe/select-probe.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/light-probe/use-light-probe.png b/versions/4.0/en/concepts/scene/light/probe/light-probe/use-light-probe.png
new file mode 100644
index 0000000000..fd6482a280
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/light-probe/use-light-probe.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-art-workflow.md b/versions/4.0/en/concepts/scene/light/probe/reflection-art-workflow.md
new file mode 100644
index 0000000000..a3948ec910
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/light/probe/reflection-art-workflow.md
@@ -0,0 +1,53 @@
+# Reflection Probe Art Workflow
+
+## Bake Reflection Probe Workflow
+
+- Create **Reflection Probe** nodes within the scene
+
+- Modify the **Mobility** property of the node that needs to bake the reflection to **Static**
+
+ 
+
+- Find **Reflection Probe Settings** by scrolling down on the **Inspector** of the node where the reflection needs to be baked, and adjust its corresponding property to.
+
+ 
+
+ - **Reflection Probe**: Select the type of reflection probe
+ - **Bake To Reflection Probe**: Check whether to bake the reflection information of this mesh renderer to the reflection probe related map
+
+ For detail, please refer to [MeshRenderer Component Reference](../../../../engine/renderable/model-component.md)
+
+- Bake
+
+ - Click the **Bake** button on the **Inspector** to bake the currently selected reflection probe.
+
+ 
+
+ - Select **Projects** -> **Light** -> **Reflection Probe** on the main menu to open the [Reflection Probe Panel](reflection-probe-panel.md) and bake by clicking the bake button on the panel.
+
+- Check baking results
+
+ After baking is complete, **Asset Manager** creates mappings named starting with **reflectionProbe_** within the **Asset Manager**. Developers can see if these mappings meet expectations.
+
+For more examples, please refer to [IBL Example](example.md).
+
+## Real-time Reflection Probe Workflow
+
+- Build the scene as shown in the figure.
+
+ 
+
+- Create **Reflection Probe** nodes in the scene:
+
+ - Modify **Probe Type** to **PLANNAR**
+ - Configure the **Source Camera** property to be the **Main Camera** node created in the above step
+
+ 
+
+- Modify the **Reflection Probe** of the **MeshRenderer** property of the **Plane** node in the scene to **PLANNAR_REFLECTION**.
+
+ 
+
+- At this point it can be observed that within the scene, the reflection of the plane changes.
+
+ 
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe-panel.md b/versions/4.0/en/concepts/scene/light/probe/reflection-probe-panel.md
new file mode 100644
index 0000000000..908951315b
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/light/probe/reflection-probe-panel.md
@@ -0,0 +1,23 @@
+# Reflection Probe Panel
+
+The Reflection Probe Baking panel can be opened via **Projects** -> **Light Baking** -> **Reflection Probe** on the main menu.
+
+
+
+The Reflection Probe Baking panel bakes all nodes in the project that contain the [Reflection Probe](reflection-probe.md) component.
+
+The baked results are placed in the project's **Resource Manager** under the name **reflectionProbe_**.
+
+## Properties
+
+
+
+| Properties | Description |
+| :-- | :-- |
+| **Bake All Reflection Probes** | Bake button, when clicked, will start baking all the reflection probes in the whole scene |
+| **Clear All Bake Results** | Clear baked results, when clicked, will bake the results of reflection probes that already exist in the project |
+| **Cancel** | Cancels the current baking process, which only takes effect when the bake button is pressed  |
+
+## Art Workflow
+
+Please refer to [reflection-probe](reflection-probe.md) or [IBL Example](example.md) for the art workflow.
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe-panel/baking.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe-panel/baking.png
new file mode 100644
index 0000000000..9f582f6d04
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe-panel/baking.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe-panel/open-panel.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe-panel/open-panel.png
new file mode 100644
index 0000000000..0b88de90e3
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe-panel/open-panel.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe-panel/reflection-panel.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe-panel/reflection-panel.png
new file mode 100644
index 0000000000..948bbfe4e4
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe-panel/reflection-panel.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe.md b/versions/4.0/en/concepts/scene/light/probe/reflection-probe.md
new file mode 100644
index 0000000000..0d2eef8f90
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/light/probe/reflection-probe.md
@@ -0,0 +1,52 @@
+# Reflection Probe
+
+Starting from v3.7, Cocos Creator supports reflection probes.
+
+A reflection probe is a component that takes reflected light from a selected range and applies it to the current scene using baking or realtime to improve the scene lighting confidence.
+
+You can create reflection probes within a scene by selecting **Light** -> **Reflection Probes** in the **Hierarchy** or on the top menu.
+
+
+
+## Properties
+
+
+
+| Properties | Description |
+| :-- | :-- |
+| **Size** | The range of the reflection probe, which can be adjusted by manipulating Gizmo within the scene |
+| **Probe Type** | Types of Reflection Probes Options: **CUBE**: Reflection probe with baking support **PLANNAR**: Reflection probe with real-time reflection support |
+| **Resolution** | Resolution of each face of the cube mapping after reflective probe baking Options: **Low_256x256**/**Medium_512x512**/**Hight_768x768** This option is only available when **Probe Type** is **CUBE**. |
+| **Background Color** | Background color, effective only when **Probe Type** is **PLANNAR** |
+| **Clear Flag** | The clear flag of the camera specifies which part of the frame buffer is to be cleared each frame. Contains SOLID_COLOR: clears the color, depth, and stencil buffers SKYBOX: enables the skybox and only clears the depth |
+| **Visibility** | Visibility mask declaring the set of node hierarchies visible in the current reflection probe Selectable via drop-down menu |
+| **Source Camera** | Specify the camera for real-time reflections This property is only available when **Probe Type** is **PLANNAR** |
+| **Bake** | Bake button, click it to bake the reflection probe
+
+### Probe Type
+
+
+
+There are two types of reflection probes for Cocos Creator.
+
+- **CUBE**:Bake the reflection information in the area onto a CUBE Map.
+
+ 
+
+ With the reflection probe selected as **CUBE**, developers can select the size of the final baked map via the **RESOLUTION** drop-down menu below.
+
+- **PLANNAR**:Real-time relection probe type.
+
+ Commonly used to simulate the surface of water, mirrors, marble or wet floors, etc.
+
+ 
+
+ When the type of the reflection probe is modified to **PLANNAR**, the developer needs to configure the **Source Camera** property to determine which camera to use as the camera for the reflection probe.
+
+The **Size** property can be adjusted via Gizmo within the **Scene Editor** as a way to modify the range of the reflection probe.
+
+
+
+## Art Workflow
+
+The two art workflows supported by Reflection Probe can be found in [Reflection Probe Art Workflow](./reflection-art-workflow.md) and [IBL Example](example.md).
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe/add-reflect-probe.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/add-reflect-probe.png
new file mode 100644
index 0000000000..523f86bb58
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/add-reflect-probe.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe/bake-result.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/bake-result.png
new file mode 100644
index 0000000000..25f40a0610
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/bake-result.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe/bake.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/bake.png
new file mode 100644
index 0000000000..f45923b3ca
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/bake.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe/clear-flag.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/clear-flag.png
new file mode 100644
index 0000000000..53ad29b4b5
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/clear-flag.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe/cube.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/cube.png
new file mode 100644
index 0000000000..4eef5eea91
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/cube.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe/edit-area-box.gif b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/edit-area-box.gif
new file mode 100644
index 0000000000..f16e1d4503
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/edit-area-box.gif differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe/mesh-renderer-reflect-probe.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/mesh-renderer-reflect-probe.png
new file mode 100644
index 0000000000..7c70d8483a
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/mesh-renderer-reflect-probe.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe/plane-reflection-probe-property.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/plane-reflection-probe-property.png
new file mode 100644
index 0000000000..5813c67182
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/plane-reflection-probe-property.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe/plannar-camera-config.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/plannar-camera-config.png
new file mode 100644
index 0000000000..40863d64e7
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/plannar-camera-config.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe/plannar-probe-property.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/plannar-probe-property.png
new file mode 100644
index 0000000000..96ba9c3d90
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/plannar-probe-property.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe/plannar-reflection-result.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/plannar-reflection-result.png
new file mode 100644
index 0000000000..8b26fe39a4
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/plannar-reflection-result.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe/plannar-scene.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/plannar-scene.png
new file mode 100644
index 0000000000..cd769af020
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/plannar-scene.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe/plannar.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/plannar.png
new file mode 100644
index 0000000000..6001be79f2
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/plannar.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe/probe-type.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/probe-type.png
new file mode 100644
index 0000000000..69abda969f
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/probe-type.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe/property.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/property.png
new file mode 100644
index 0000000000..093069f0c7
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/property.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe/reflection-camera.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/reflection-camera.png
new file mode 100644
index 0000000000..b1b43037d5
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/reflection-camera.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe/resolution.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/resolution.png
new file mode 100644
index 0000000000..961ffcf403
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/resolution.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe/static.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/static.png
new file mode 100644
index 0000000000..84ff2ac170
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/static.png differ
diff --git a/versions/4.0/en/concepts/scene/light/probe/reflection-probe/visibility.png b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/visibility.png
new file mode 100644
index 0000000000..209f5ea1b2
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/probe/reflection-probe/visibility.png differ
diff --git a/versions/4.0/en/concepts/scene/light/shadow.md b/versions/4.0/en/concepts/scene/light/shadow.md
new file mode 100644
index 0000000000..576fc1141f
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/light/shadow.md
@@ -0,0 +1,134 @@
+# Shadow
+
+In the 3D world, light and shadow have always been extremely important components that enrich the entire environment. High quality shadows can make the game world look more realistic.
+
+Cocos Creator 3.0 currently supports both **Planar** and **ShadowMap** shadow types.
+
+
+
+## Enable Shadow Effect
+
+To enable the shadow effect for an object, proceed as follows:
+
+1. Check **Scene** in the **Hierarchy** panel, and then check the **Enabled** property in the **Shadows** component of the **Inspector** panel.
+
+ 
+
+2. Check **light** in the **Hierarchy** panel, and then check the **Shadow Enabled** property in the **Dynamic Shadow Settings** component of the **Inspector** panel.
+
+ 
+
+3. Select the 3D node that needs to display shadows in the **Hierarchy** panel, and then set the **Cast Shadows** property to **ON** in the **MeshRenderer** component of the **Inspector** panel.
+
+ If the shadow type is **ShadowMap**, set the **Receive Shadows** property on the **MeshRenderer** component to **ON**.
+
+> **Note**: if the shadows are not displayed properly, adjust the direction of the directional light.
+
+## Shadow Type
+
+The shadow type can be set in the **Type** property of the **Shadows** component.
+
+### Planar Shadow
+
+The Planar shadow type is generally used for simpler scenes.
+
+
+
+| Property | Description |
+| :--- | :--- |
+| **Enabled** | Whether to enable shadow effect |
+| **Type** | Shadow type |
+| **Saturation** | Set the shadow saturation, it is recommended to set it as **1**. If it is necessary to reduce the saturation of the directional light shadows, it is recommended to do it by increasing the ambient light instead of adjusting this value |
+| **ShadowColor** | Shadow color |
+| **Normal** | The normal line perpendicular to the shadow, used to adjust the slope of the shadow |
+| **Distance** | The distance of the shadow in the direction of the normal to the origin of the coordinate |
+
+Adjust the direction of the directional light to adjust the position of the shadow.
+
+> **Note**: planar shadows are only cast on planar surfaces, not on objects, which means that the **ReceiveShadow** property in the **MeshRenderer** component is invalid.
+
+### ShadowMap
+
+ShadowMap renders the scene with the lights as the viewpoint. From the position of the lights, the places in the scene that are not visible are where the shadows are created.
+
+
+
+| Property | Explanation |
+| :--- | :--- |
+| **Enabled** | Whether to enable the shadow effect. |
+| **Type** | Choose the shadow type. |
+| **MaxReceived** | The maximum number of lights supported for shadow generation, default is 4, can be adjusted as needed. |
+| **ShadowMapSize** | Set the texture size of the shadow, Currently supports **Low_256x256**, **Medium_512x512**, **High_1024x1024**, **Ultra_2048x2048** four kinds of precision textures. |
+
+> **Note**: starting with v3.3, the **Linear** and **Packing** options for Shadows in the **Inspector** panel have been removed, and Creator will automatically determine the hardware capabilities and choose the best way to render the shadows.
+
+ShadowMap receives and displays shadow effects generated by other objects when **ReceiveShadow** on the object **MeshRenderer** component is enabled.
+
+ShadowMap is generally used for scenes that require more realistic and complex light and shadow effects. The downside is that if the lights is not moved, then the previously generated Shadow Map can be reused, while once the lights is moved, then a new ShadowMap needs to be recalculated.
+
+## Shadow Properties
+
+After enabling shadows of type **ShadowMap**, the **Dynamic Shadow Settings** option will appear in the light source's **Inspector**. If not properly enabled, please refer to the **Enable Shadows** section above.
+
+The current engine support for **ShadowMap** across different light sources is as follows:
+
+| Light Type | Support |
+| :-- | :-- |
+| Directional Light | Supported |
+| Spot Light | Supported |
+| Sphere Light | Not Supported |
+
+### Directional Light Shadow Properties
+
+
+
+| Property | Description |
+| :------ | :-- |
+| ShadowEnabled | Whether to enable directional light shadows |
+| ShadowPcf | Sets shadow edge anti-aliasing level, currently supporting **HARD**, **SOFT**, **SOFT_2X**, **SOFT_4X**. See **PCF Soft Shadows** section below for details. |
+| ShadowBias | Sets shadow offset value to prevent Z-Fighting |
+| ShadowNormalBias | Sets normal offset value to prevent jagged edges on curved surfaces |
+| ShadowSaturation | Adjusts shadow saturation, recommended to set to **1.0**. To reduce directional light shadow saturation, increase ambient light instead of adjusting this value |
+| ShadowInvisibleOcclusionRange | Sets whether shadows from objects outside Camera's visible range should be cast into visible range. Increase value if needed |
+| ShadowDistance | Sets shadow effect range within Camera's visible range. Shadow quality is inversely proportional to this value |
+
+For directional light usage, refer to [Directional Light](./lightType/dir-light.md).
+
+#### FixedArea Mode
+
+FixedArea mode controls whether to manually set the shadow effect range within Camera's visible range:
+
+- When unchecked (default), engine uses same clipping process and camera calculations as CSM (Cascaded Shadow Map) mode, calculating shadow range based on Camera's direction and position.
+- When checked, shadow range is controlled by manually setting `Near`, `Far`, and `OrthoSize` properties. Shadows follow directional light node's position, distributed near its bounding box rather than following camera.
+
+
+
+| Property | Description |
+| :------ | :-- |
+| ShadowFixedArea | Whether to enable fixed area shadows |
+| ShadowNear | Sets main light camera's near clipping plane |
+| ShadowFar | Sets main light camera's far clipping plane |
+| ShadowOrthoSize | Sets main light camera's orthographic viewport size. Shadow quality is inversely proportional to this value |
+
+### Spot Light Shadow Properties
+
+
+
+| Property | Description |
+| :------ | :-- |
+| ShadowEnabled | Whether to enable spot light shadows |
+| ShadowPcf | Sets shadow edge anti-aliasing level, currently supporting **HARD**, **SOFT**, **SOFT_2X**, **SOFT_4X**. See **PCF Soft Shadows** section below for details. |
+| ShadowBias | Sets shadow offset value to prevent z-fighting |
+| ShadowNormalBias | Sets normal offset value to prevent jagged edges on curved surfaces |
+
+For spot light usage, refer to [Spot Light](./lightType/spot-light.md).
+
+### PCF Soft Shadows
+
+Percentage Closer Filtering (PCF) is a simple, common technique for shadow edge anti-aliasing that smooths shadow edges to eliminate jagged artifacts in shadow maps. It works by sampling around the current pixel (fragment), calculating the proportion of samples closer to the light source compared to the fragment, then using this proportion to scale diffuse and specular light components before shading the fragment to achieve blurred shadow edges.
+
+Currently Cocos Creator supports **Hard Sampling**, **4x Sampling (SOFT mode)**, **9x Sampling (SOFT_2X mode)**, and **16x Sampling (SOFT_4X mode)**. Higher multipliers mean larger sampling areas and softer shadow edges.
+
+## Support dynamic batching to improve performance
+
+For models with `instancing` enabled in the material, the planar shadow will automatically draw with `instancing` as well, see the [Dynamic Batching](../../../engine/renderable/model-component.md#about-dynamic-batching) documentation for details.
diff --git a/versions/4.0/en/concepts/scene/light/shadow/csm-off.png b/versions/4.0/en/concepts/scene/light/shadow/csm-off.png
new file mode 100644
index 0000000000..f9f18ae337
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/shadow/csm-off.png differ
diff --git a/versions/4.0/en/concepts/scene/light/shadow/csm-on.png b/versions/4.0/en/concepts/scene/light/shadow/csm-on.png
new file mode 100644
index 0000000000..232f280df1
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/shadow/csm-on.png differ
diff --git a/versions/4.0/en/concepts/scene/light/shadow/enable-light-shadow.png b/versions/4.0/en/concepts/scene/light/shadow/enable-light-shadow.png
new file mode 100644
index 0000000000..5e3a98f25d
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/shadow/enable-light-shadow.png differ
diff --git a/versions/4.0/en/concepts/scene/light/shadow/enable-shadow.png b/versions/4.0/en/concepts/scene/light/shadow/enable-shadow.png
new file mode 100644
index 0000000000..cb889f1b36
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/shadow/enable-shadow.png differ
diff --git a/versions/4.0/en/concepts/scene/light/shadow/planar-properties.png b/versions/4.0/en/concepts/scene/light/shadow/planar-properties.png
new file mode 100644
index 0000000000..9e9286f903
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/shadow/planar-properties.png differ
diff --git a/versions/4.0/en/concepts/scene/light/shadow/set-meshrenderer.png b/versions/4.0/en/concepts/scene/light/shadow/set-meshrenderer.png
new file mode 100644
index 0000000000..4e4d627634
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/shadow/set-meshrenderer.png differ
diff --git a/versions/4.0/en/concepts/scene/light/shadow/shadowExample.png b/versions/4.0/en/concepts/scene/light/shadow/shadowExample.png
new file mode 100644
index 0000000000..ac1f48447f
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/shadow/shadowExample.png differ
diff --git a/versions/4.0/en/concepts/scene/light/shadow/shadowmap-properties.png b/versions/4.0/en/concepts/scene/light/shadow/shadowmap-properties.png
new file mode 100644
index 0000000000..9b2d91c9da
Binary files /dev/null and b/versions/4.0/en/concepts/scene/light/shadow/shadowmap-properties.png differ
diff --git a/versions/4.0/en/concepts/scene/node-component.md b/versions/4.0/en/concepts/scene/node-component.md
new file mode 100644
index 0000000000..bc2ff8fbdb
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/node-component.md
@@ -0,0 +1,114 @@
+# Nodes and Components
+
+The workflow of Cocos Creator is centered on component-based development, also known as an **Entity-Component System**, which simply means that the various elements of the game are built in a combinatorial rather than an inherited manner.
+
+In Cocos Creator, a **Node** is an entity that hosts a component, and we mount **Component** with various functions on it to give it a variety of representations and functions. Let's see how to create nodes and add components to a scene.
+
+## Nodes
+
+Nodes are the basic building blocks of a scene. Nodes are organized in a tree-like relationship, and each node can have multiple children:
+
+
+
+Nodes have the following properties:
+
+- A node contains a set of base attributes (Position, Rotation, Scale), and nodes are organized together by a set of relative transformation relationships, as described in [coordinate systems and node transformation properties](./coord.md).
+- The update order between nodes is cascading. The update of child nodes depends on the parent node, and child nodes follow the parent node transformations.
+- Components can be added to a node to associate multiple components with the node.
+
+### Create Nodes
+
+The quickest way to get a node with a specific function is to use the **Create Node** button in the top left corner of the **Hierarchy** panel. Take the simplest example of creating a Sphere node by clicking on the **+**, creating a Node button in the upper left corner and then selecting **Create 3D Object -> Create Sphere**.
+
+
+
+Notice the newly added Sphere node in the **Scene** and **Hierarchy** panel. The new node is named `Sphere` by default, indicating that it is a node whose functionality is primarily provided by the **Sphere** component. Try clicking the **Create Node** button again to select another node type and see that they will be named and behave differently. Also, note that creating a UI node automatically creates a Canvas node as the root node of the UI node, as described in the document [UI Structure Description](../../2d-object/ui-system/index.md).
+
+For more information about the operations of single-select, multi-select, copy, delete, etc. of nodes in the **Hierarchy** panel, please refer to the [Hierarchy Panel](../../editor/hierarchy/index.md) documentation.
+
+To create nodes dynamically in a script, refer to the [Create and Destroy Nodes](../../scripting/create-destroy.md) documentation.
+
+## Node Properties
+
+
+
+- **Mobility**:Mobility of nodes. Different mobility can lead to different properties and performance of nodes in terms of illumination
+
+ 
+
+ For nodes containing light components, Mobility behaves slightly differently, as described separately below.
+ - For nodes holding light components
+ - Static: bakes direct and indirect light, and does not participate in the calculation at runtime after baking
+ - Stationary: only indirect light is baked, and only direct light is calculated at runtime
+ - Movable: does not bake, only calculates direct light at runtime
+ - For nodes with MeshRenderer component
+ - Static & Stationary Static objects: can use light mapping
+ - Movable dynamic objects: can use light probes
+ In general it is possible to add a light component to a node that holds a MeshRenderer component, but it is not recommended, consider separating multiple nodes to achieve such a requirement.
+
+- **Layer**:Sets the visibility capability of the node. Please refer to the following **Setting the visibility of nodes** for details.
+
+## Components
+
+What are components and how do they relate nodes?
+
+Select the `Sphere` node, created above, and notice what the **Inspector** panel shows:
+
+
+
+The part of the **Inspector** panel that starts with the `Node` title is the node's properties, which include information about the node's `Position`, `Rotation`, `Scale`, and other transformations. This is covered in detail in the [Coordinate Systems and Node Transformation Properties](coord.md) documentation.
+
+Starting with the `cc.MeshRenderer` title is the property of the MeshRenderer component mounted on the Sphere. In Cocos Creator, the **MeshRenderer** component is used to render static 3D models, where the `Mesh` property is used to specify the mesh resources used for rendering. As the Sphere node was just created the default is `sphere.mesh`.
+
+The `Materials` property is used to specify the [material](../../asset/material.md) used for rendering. You can try dragging any material from the **Assets** into the `Materials` property of the **Inspector** panel and you can see that the default material just became the specified material.
+
+> **Note**: any resources set on the component, such as `sphere.mesh` in this case, will be loaded automatically at the same time as the scene loads. Types of resources that need to be set and automatically loaded can also be declared in custom components, refer to the [Getting and loading resources](../../scripting/load-assets.md) documentation.
+
+In addition to adding components manually in the editor, they can also be added via scripts, for more details see the [Component creation and destruction](../../scripting/component.md) documentation.
+
+### Effect of Node Properties on Components
+
+Once the node and **MeshRenderer** component are combined, the rendering of the mesh resources can be controlled by modifying the node properties. The node can also be adjust according to the properties marked by the red line in the figure below, notice that the rotation and scaling of the model have changed.
+
+**Before adjustment**:
+
+
+
+**After adjustment**:
+
+
+
+As previously mentioned, component-based structure is combined to achieve functional extensions. The combination of the node and **MeshRenderer** component is shown in the following figure:
+
+
+
+## Add Additional Components
+
+Multiple components can be added to a node to add more functionality to the node.
+
+For example, select the node `Sphere` in the above example, then click the **Add Component** button at the bottom of the **Inspector** panel and select **Light -> DirectionalLight** to add a **Directional Light** component.
+
+Next, set the properties of the **Directional Light** component, e.g.: adjust the `Color` property of the directional light to red, and notice that the color of the sphere model has changed, i.e. the **DirectionalLight** component that was added to the node has taken effect!
+
+
+
+> **Notes**:
+>
+> 1. This is just a brief example of a more obvious effect. It is not recommended to add a **DirectionalLight** component to a sphere node.
+> 2. That only one renderable component can be added to a node. Renderable components include: **MeshRenderer**, **Sprite**, **Label**, **Graphics**, **Mask**, **RichText**, **UIStaticBatch**, etc.
+
+## Setting the visibility of nodes
+
+The engine uses more generic nodes that match the camera to control the visibility of nodes. When the `Layer` property set in the node is included in the [Visibility property](../../editor/components/camera-component.md) of the camera, the node can be seen by the camera, and it supports mixed rendering of 3D and 2D components. This allows more flexibility in controlling the visibility of node components and diversifying the group display.
+
+For details on the implementation of layers, please refer to the [layer](layer.md) documentation.
+
+### Set the layer property of the node
+
+
+
+The `Layer` property of a node is global and unique, but different nodes can set the same `Layer` property so that they are viewed by the same camera. Developers can use the `Layer` property built-in with the engine, or they can use a custom `Layer` property, which can be set by clicking the **Edit** button in the image below and going to the **Project Settings -> Layers** page. Please refer to the [Layer](layer.md) documentation for details.
+
+
+
+Where `User Layer 0` - `User Layer 19` are layer properties provided for user-defined settings, the user only needs to fill in the custom layer name after the layer to enable this layer property and edit it on the node.
diff --git a/versions/4.0/en/concepts/scene/node-tree.md b/versions/4.0/en/concepts/scene/node-tree.md
new file mode 100644
index 0000000000..98c7add8e9
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/node-tree.md
@@ -0,0 +1,43 @@
+# Node Hierarchy and Rendering Order
+
+Combining Nodes and Components together creates all kinds of images, texts and interactive elements in a scene. When there are more and more elements in the scene, we can use the **Hierarchy** panel to arrange their hierarchy and rendering order to make things organized.
+
+## Hierarchy Panel
+
+When creating and editing nodes, the **Scene** panel can display an intuitive visualization of scene elements. The hierarchical relationships between nodes need to be checked and manipulated using the **Hierarchy** panel. Please refer to the [Hierarchy panel](../../editor/hierarchy/index.md) documentation first to learn how to use it.
+
+## Node Trees
+
+The complete logical relationship between nodes established by the operations of the **Hierarchy** panel or runtime scripts is called a **node tree**.
+
+Using a simple game scenario demonstrates what a node tree is. The following picture includes a background image, a main character (the blob), a title, a springboard, diamonds and a button to start the game.
+
+
+
+Each visual element is a node. Usually all nodes are not laid flat on the scene, but rather, organized into a node tree according to a certain classification and order (e.g.: according to our own preferences). Example:
+
+
+
+The nodes displayed in the upper level are referred to as parent nodes and those displayed in the lower level are referred to as children. In the **Hierarchy** panel, the node tree in the above figure would look like this:
+
+
+
+In Cocos Creator 3.0, UI nodes require any parent node to have at least one **UITransform** component, if it does not comply with the rules, a Canvas node will be automatically added as its parent, the node tree in the above figure puts all UI nodes under the Canvas node. Next, parent nodes are created according to the category and put nodes of the same category under one parent node to build the node tree.
+
+In real game projects, other methods (such as game logic) can be used to organize the node tree as needed.
+
+## Rendering Order of Nodes
+
+The rendering of 3D nodes is related to the Z-coordinate value of the distance between the node and the camera, transparency, etc.
+
+The rendering and occlusion relationship of UI nodes, on the other hand, is influenced by the node tree, which is rendered in order of node arrangement from top to bottom in the **Hierarchy** panel, meaning that nodes displayed above the list are occluded by the nodes below them in the scene. Therefore, the child nodes will always cover the parent nodes. For details, please refer to the [UI rendering ordering rules](../../ui-system/components/engine/priority.md) documentation.
+
+Other rendering-related references can be found in.
+
+- [Graphics Rendering](../../module-map/graphics.md)
+- [Particle Renderer](../../particle-system/renderer.md)
+- [Model Group Rendering](../../engine/renderable/model-component.md#model-group-rendering)
+
+## Performance Considerations
+
+> **Note**: although it is said that the parent node can be used to organize logical relationships or even as a container to host child nodes, the scene loading speed will be affected when there are too many nodes, avoid a large number of meaningless nodes when creating a scene and merge nodes with the same function as much as possible.
diff --git a/versions/4.0/en/concepts/scene/node-tree/game-scene.jpg b/versions/4.0/en/concepts/scene/node-tree/game-scene.jpg
new file mode 100644
index 0000000000..9a5da28d52
Binary files /dev/null and b/versions/4.0/en/concepts/scene/node-tree/game-scene.jpg differ
diff --git a/versions/4.0/en/concepts/scene/node-tree/in_hierarchy.png b/versions/4.0/en/concepts/scene/node-tree/in_hierarchy.png
new file mode 100644
index 0000000000..1e0581e48e
Binary files /dev/null and b/versions/4.0/en/concepts/scene/node-tree/in_hierarchy.png differ
diff --git a/versions/4.0/en/concepts/scene/node-tree/mobility.png b/versions/4.0/en/concepts/scene/node-tree/mobility.png
new file mode 100644
index 0000000000..47081928db
Binary files /dev/null and b/versions/4.0/en/concepts/scene/node-tree/mobility.png differ
diff --git a/versions/4.0/en/concepts/scene/node-tree/node-op.jpg b/versions/4.0/en/concepts/scene/node-tree/node-op.jpg
new file mode 100644
index 0000000000..d790243402
Binary files /dev/null and b/versions/4.0/en/concepts/scene/node-tree/node-op.jpg differ
diff --git a/versions/4.0/en/concepts/scene/node-tree/node-property.png b/versions/4.0/en/concepts/scene/node-tree/node-property.png
new file mode 100644
index 0000000000..97971345c7
Binary files /dev/null and b/versions/4.0/en/concepts/scene/node-tree/node-property.png differ
diff --git a/versions/4.0/en/concepts/scene/node-tree/node-tree.png b/versions/4.0/en/concepts/scene/node-tree/node-tree.png
new file mode 100644
index 0000000000..12671235c6
Binary files /dev/null and b/versions/4.0/en/concepts/scene/node-tree/node-tree.png differ
diff --git a/versions/4.0/en/concepts/scene/node-tree/rolling-ball.png b/versions/4.0/en/concepts/scene/node-tree/rolling-ball.png
new file mode 100644
index 0000000000..6915444476
Binary files /dev/null and b/versions/4.0/en/concepts/scene/node-tree/rolling-ball.png differ
diff --git a/versions/4.0/en/concepts/scene/scene-editing.md b/versions/4.0/en/concepts/scene/scene-editing.md
new file mode 100644
index 0000000000..f768fbe3a0
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/scene-editing.md
@@ -0,0 +1,95 @@
+# Build a Scene Image Using the Scene Panel
+
+This document will introduce the workflow and tips of using [Scene](../../editor/scene/index.md) panel to create and edit scene images.
+
+## Use the "Create Node" Menu to Quickly Add Basic Node Types
+
+When we start adding content to the scene, we typically start with the **Create Node** menu in the **Hierarchy** panel, which is the menu that pops up when you click the **+** button in the upper left corner, and select the base node type we need from several simple node categories and add it to the scene.
+
+When adding nodes, the node selected in **Hierarchy** panel will become the parent of the newly created node. If you select a node that is collapsed and then add a new node through the menu, you need to expand the node you just selected to see the newly added node.
+
+### Empty Node
+
+Select **Create Empty Node** in the **Create Node** menu to create a node that does not contain any components. Empty nodes can be used as containers for organizing other nodes or for mounting logic and control components written by the developer. Also in the following we will describe how to create controls that meet your specific requirements by combining empty nodes and components.
+
+### 3D Objects
+
+Select **Create 3D Object** in the **Create Node** menu to create some of the more basic static model controls that come with the editor, which currently include cub, cylinder, sphere, capsule, cone, torus, plane, and quad. If you need to create other types of models, you can refer to the [MeshRenderer component](../../engine/renderable/model-component.md).
+
+### UI Nodes
+
+UI nodes can be created by selecting **Create UI** from the **Create Node** menu. UI nodes in Creator 3.0 require that any parent node must have at least one **UITransform** component. And every UI node itself will also have a **UITransform** component.
+
+So the Canvas node is the **root node** of UI rendering, and all rendering-related UI nodes are placed under the Canvas, which has the following benefits:
+
+- Canvas can provide multi-resolution adaptive scaling, and using Canvas as the root node can ensure that our scenes will look good on larger or smaller screens, see [Multi-resolution adaptation scheme](../../ui-system/components/engine/multi-resolution.md).
+- Canvas nodes are automatically centered according to the screen size, so UI nodes under Canvas will have the center of the screen as the origin of the coordinate system. In our experience, this simplifies the scene and UI setup (e.g.: having the button element's text appear right in the center of the button node by default), and makes it easier to script the UI node position control.
+
+#### 2D Rendering Nodes
+
+The **Create Node** menu allows you to create node types consisting of nodes and base renderable components like **ParticleSystem**, **Sprite**, **Label**, **Mask**, etc.
+
+The base 2D renderable component here cannot be replaced by a combination of other components. Note that only one renderable component can be added to each node, and repeated additions will result in an error. However, complex interface controls can be implemented by combining different rendering nodes, such as the UI control node below.
+
+#### UI Control Node
+
+Common UI controls including Button, Widget, Layout, ScrollView, EditBox, etc. nodes can be created from the **UI** category in the **Create Node** menu.
+
+UI nodes are mostly a combination of rendered nodes, for example, the **Button** node we created through the menu includes a button background node with a **Button** component + a **Sprite** component, and a label node with a **Label** component:
+
+
+
+Creating nodes of the base type using the menu is the recommended way to quickly add content to the scene, and then we can edit the nodes created using the menu as needed to create the combinations we need.
+
+For more on UI nodes, see [UI Structure Description](../../2d-object/ui-system/index.md).
+
+### Attribution of Logical Nodes
+
+In addition to nodes with specific rendering and other tasks, it is recommended to have some nodes in the root directory of the scene that are only responsible for mounting scripts and executing game logic, without any rendering and other related content. Usually we place these nodes at the root level of the scene, side by side with Canvas nodes, so that other developers can find the game logic and bind relevant data in the first place when collaborating.
+
+## Tips to Improve the Efficiency of Scene Creation
+
+The **Scene** panel includes both 3D and 2D views. The 3D view is used for 3D scene editing, and the 2D view is used mainly for editing 2D elements such as UI nodes. The scene view can be switched via the 3D/2D button in the toolbar at the top left of the editor.
+The following shortcuts work for both views.
+
+- Select a node in the **Hierarchy** panel and double-click or press F to focus the node in the **Scene** panel.
+- Pressing Cmd/Ctrl + D after selecting a node will copy and paste an identical node at the same location as the node, which can be used for efficiency when we need to make multiple similar nodes quickly.
+- In **Scene**/**Hierarchy** panel, hold down the Cmd/Ctrl key and click on the node you want in order to select multiple nodes at the same time. The Shift key allows you to select nodes in succession, without selecting them one by one.
+
+### Align/Evenly Distribute Nodes
+
+When the **Scene** panel is in **2D** view, there is a row of buttons in the upper left corner that can be used to align or evenly distribute multiple nodes when they are selected. The specific rules are as follows:
+
+
+
+Assuming that all three Label nodes are selected, the six alignment buttons from left to right will align these nodes in turn:
+
+- Top-aligned to the nearest upper border (not the upper border of the topmost node)
+- Vertically centered, aligned to the overall horizontal center line
+- Bottom-aligned, aligned to the nearest lower boundary
+- Left-aligned to its closest left border
+- Horizontally centered, aligned to the overall vertical center line
+- Right-aligned, aligned to the nearest right border
+
+The 6 distribution buttons in the second half, from left to right, will align these nodes in turn:
+
+- Top distribution, evenly distributed along the top boundary of the node
+- Vertically centered distribution, evenly distributed along the horizontal midline of the node
+- Bottom distribution, evenly distributed along the lower boundary of the node
+- Left distribution, evenly distributed along the left border of the node
+- Horizontally centered distribution, evenly distributed along the vertical center line of the node
+- Right distribution, evenly distributed along the right boundary of the node
+
+> **Note**: whether the left and right boundaries and the center line are determined at the beginning, or the reference when aligning/evenly distributing each node later, it is the center of the node bounding box or one of the boundaries rather than the position coordinates of the nodes.
+
+For example, in the figure below, when we align the three Label nodes with different widths to the right, we get the alignment of the right boundaries of the three node bounding boxes, not the `x` coordinates of the three node positions becoming the same.
+
+
+
+## Scene Display Effects
+
+There is also support for setting the Skybox, Global Fog, and Shadows in the scene to better enrich the scene and render and display the scene environment. For details, please refer to:
+
+- [Skybox](./skybox.md)
+- [Global Fog](./fog.md)
+- [Shadows](./light/shadow.md)
diff --git a/versions/4.0/en/concepts/scene/scene-editing/align-to-right.png b/versions/4.0/en/concepts/scene/scene-editing/align-to-right.png
new file mode 100644
index 0000000000..d621bdbf76
Binary files /dev/null and b/versions/4.0/en/concepts/scene/scene-editing/align-to-right.png differ
diff --git a/versions/4.0/en/concepts/scene/scene-editing/alignment.png b/versions/4.0/en/concepts/scene/scene-editing/alignment.png
new file mode 100644
index 0000000000..a152de01b1
Binary files /dev/null and b/versions/4.0/en/concepts/scene/scene-editing/alignment.png differ
diff --git a/versions/4.0/en/concepts/scene/scene-editing/button-breakdown.png b/versions/4.0/en/concepts/scene/scene-editing/button-breakdown.png
new file mode 100644
index 0000000000..0b0bb80167
Binary files /dev/null and b/versions/4.0/en/concepts/scene/scene-editing/button-breakdown.png differ
diff --git a/versions/4.0/en/concepts/scene/scene.md b/versions/4.0/en/concepts/scene/scene.md
new file mode 100644
index 0000000000..0453a4852e
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/scene.md
@@ -0,0 +1,12 @@
+# Scene structure
+
+__Cocos Creator__ adds a 3D scene structure to __Creator’s__ __EC (entity component) framework__. The 3D scene is represented by __RenderScene__. The corresponding __Component__ in the __EC structure__ references the *Model*, *Camera*, and *Light* are maintained in `RenderScene`. Other elements are also linked together through __Node__, including the *Transformations* in `RenderScene` is also manipulated through the __Node API__.
+
+> __Note__: the differences between __Scene__ in __EC structure__ and __RenderScene__ in a __3D__ scene structure. __Scene__ in __EC structure__ is
+the logical organization structure of the __Node hierarchy__. __RenderScene__ in __3D__ is the organization structure of scene rendering elements. Elements in __EC scene__'s contain references to the correspond rendering objects in `RenderScene`.
+
+The relationship between __EC structure__ and __3D__ scene structure is shown in the following figure:
+
+
+
+The entire __3D__ scene structure is encapsulated under __Component__, and the organizational relationship is established through __Node__. This is completely transparent relationship between __EC structure__ and a __3D__ scene.
diff --git a/versions/4.0/en/concepts/scene/scene/create.png b/versions/4.0/en/concepts/scene/scene/create.png
new file mode 100644
index 0000000000..f32562b34c
Binary files /dev/null and b/versions/4.0/en/concepts/scene/scene/create.png differ
diff --git a/versions/4.0/en/concepts/scene/scene/directional-light.png b/versions/4.0/en/concepts/scene/scene/directional-light.png
new file mode 100644
index 0000000000..ed82696731
Binary files /dev/null and b/versions/4.0/en/concepts/scene/scene/directional-light.png differ
diff --git a/versions/4.0/en/concepts/scene/scene/ecs-scene.jpg b/versions/4.0/en/concepts/scene/scene/ecs-scene.jpg
new file mode 100644
index 0000000000..895a266640
Binary files /dev/null and b/versions/4.0/en/concepts/scene/scene/ecs-scene.jpg differ
diff --git a/versions/4.0/en/concepts/scene/scene/inspector.png b/versions/4.0/en/concepts/scene/scene/inspector.png
new file mode 100644
index 0000000000..4e70ae296d
Binary files /dev/null and b/versions/4.0/en/concepts/scene/scene/inspector.png differ
diff --git a/versions/4.0/en/concepts/scene/scene/layer-edit.png b/versions/4.0/en/concepts/scene/scene/layer-edit.png
new file mode 100644
index 0000000000..9e5d933ba6
Binary files /dev/null and b/versions/4.0/en/concepts/scene/scene/layer-edit.png differ
diff --git a/versions/4.0/en/concepts/scene/scene/layer-gizmo.png b/versions/4.0/en/concepts/scene/scene/layer-gizmo.png
new file mode 100644
index 0000000000..68e8fae78c
Binary files /dev/null and b/versions/4.0/en/concepts/scene/scene/layer-gizmo.png differ
diff --git a/versions/4.0/en/concepts/scene/scene/node-after.png b/versions/4.0/en/concepts/scene/scene/node-after.png
new file mode 100644
index 0000000000..c8da0ad838
Binary files /dev/null and b/versions/4.0/en/concepts/scene/scene/node-after.png differ
diff --git a/versions/4.0/en/concepts/scene/scene/node-before.png b/versions/4.0/en/concepts/scene/scene/node-before.png
new file mode 100644
index 0000000000..0c59049360
Binary files /dev/null and b/versions/4.0/en/concepts/scene/scene/node-before.png differ
diff --git a/versions/4.0/en/concepts/scene/scene/node-chart.png b/versions/4.0/en/concepts/scene/scene/node-chart.png
new file mode 100644
index 0000000000..5615cd6ada
Binary files /dev/null and b/versions/4.0/en/concepts/scene/scene/node-chart.png differ
diff --git a/versions/4.0/en/concepts/scene/scene/node-layer-edit.png b/versions/4.0/en/concepts/scene/scene/node-layer-edit.png
new file mode 100644
index 0000000000..910a8dba2d
Binary files /dev/null and b/versions/4.0/en/concepts/scene/scene/node-layer-edit.png differ
diff --git a/versions/4.0/en/concepts/scene/scene/node-layer-gizmo.png b/versions/4.0/en/concepts/scene/scene/node-layer-gizmo.png
new file mode 100644
index 0000000000..77226e00f1
Binary files /dev/null and b/versions/4.0/en/concepts/scene/scene/node-layer-gizmo.png differ
diff --git a/versions/4.0/en/concepts/scene/scene/nodes.jpg b/versions/4.0/en/concepts/scene/scene/nodes.jpg
new file mode 100644
index 0000000000..2d998652d5
Binary files /dev/null and b/versions/4.0/en/concepts/scene/scene/nodes.jpg differ
diff --git a/versions/4.0/en/concepts/scene/scene/world01.jpg b/versions/4.0/en/concepts/scene/scene/world01.jpg
new file mode 100644
index 0000000000..3a7f31548e
Binary files /dev/null and b/versions/4.0/en/concepts/scene/scene/world01.jpg differ
diff --git a/versions/4.0/en/concepts/scene/skin.md b/versions/4.0/en/concepts/scene/skin.md
new file mode 100644
index 0000000000..0db847590a
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/skin.md
@@ -0,0 +1,10 @@
+# Global skin material configuration panel
+
+
+
+The intensity of the skin material is set globally. The skin material is turned on by default and cannot be turned off, which will not bring additional performance loss if no skin material is used in the scene.
+
+| Attributes | Descriptions |
+| :---| :--- |
+| **Enabled** | Whether to turn on skin material |
+| **Sss Intensity** | Global skin subcutaneous scattering intensity setting |
diff --git a/versions/4.0/en/concepts/scene/skin/ScenePanel.png b/versions/4.0/en/concepts/scene/skin/ScenePanel.png
new file mode 100644
index 0000000000..1d4d7f5080
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skin/ScenePanel.png differ
diff --git a/versions/4.0/en/concepts/scene/skybox.md b/versions/4.0/en/concepts/scene/skybox.md
new file mode 100644
index 0000000000..7f1a46898a
--- /dev/null
+++ b/versions/4.0/en/concepts/scene/skybox.md
@@ -0,0 +1,156 @@
+# Skybox
+
+The skybox in a video game is a cube that wraps around the entire scene and can render and display the entire scene environment very well. The Skybox can also contribute very important IBL ambient lighting the in PBR-based workflow.
+
+## Enabling Skybox
+
+Check the scene root node in the **Hierarchy** panel, then check the **Enabled** property in the **Skybox** component of the **Inspector** panel to enable the skybox.
+
+ 
+
+The **Skybox** component properties are as follows:
+
+| Property | Description |
+| :---| :--- |
+| **Enabled** | Check this option to enable skybox. |
+| **Env Lighting Type** | Environment lighting type. Please refer to the **Diffuse Illumination** section below for more information. |
+| **UseHDR** | If this option is checked, HDR (High Dynamic Range) will be turned on, if not checked, LDR (Low Dynamic Range) will be used. For details, please refer to the section **Switching HDR/LDR Mode** below. |
+| **Envmap** | Environment map, TextureCube type, see below for details on how to set it. When this property is empty, the skybox uses and displays pixel texture by default. |
+| **Reflection Convolution** | Click the bake button will generates a low resolution environment map and perform convolution calculation on this map, convolution map will be used for environment reflection. |
+| **Reflection Map** | Automatically generated convolutional maps for environmental reflection, currently doesn't support manually editing. Rendering effects, please refer to the section **bake reflection convolution map** below.|
+| **DiffuseMap** | The convolution map for advanced diffuse lighting. It's automatically generated and managed by the engine, currently doesn't support manually editing. This option is only shown when **Env Lighting Type** is **DIFFUSEMAP_WITH_REFLECTION**. |
+| **Reflection Convolution** | Please refer to the **Reflection Convolution** section below for detail |
+| **SkyboxMaterial** | Add custom material for the skybox. Please refer to the **Skybox Material** section below for detail |
+
+## Setting the Environment Map of the Skybox
+
+After enabling the Skybox, it is also necessary to set the environment map, which is used to generate ambient lighting in the scene. Drag and drop the map asset into the **Envmap** property box of the Skybox component, or click the arrow button behind the **Envmap** property box to select the desired map asset. If not set, the Skybox will use and display pixel maps by default.
+
+
+
+The skybox supports the following environment map assets:
+
+1. A single texture of type TextureCube, which can be set in Creator.
+
+ - Cube Cross images
+
+ - PNG or HDR format images
+
+2. CubeMap in the form of image files
+
+3. CubeMap created manually in Creator by combining six texture maps
+
+### By Setting the Texture Assets of TextureCube Type
+
+1. To import a texture asset, drag and drop it directly into the **Assets** panel.
+
+2. Select the imported texture asset, set the **Type** property to **texture cube** in the **Inspector** panel on the right, then click the green checkbox in the upper right corner to save the settings.
+
+ 
+
+3. Check **Scene** in the **Hierarchy** panel, then drag the set texture asset to the **Envmap** property box of the **Skybox** component in the **Inspector** panel.
+
+ 
+
+The setup is done. The developer can directly see the set environment map of the skybox in the **Scene** panel. If the map is not displayed correctly, check if the value of **SkyIllum parameter** is too low, or **modify the Clear Flag** of Camera.
+
+### Use engine builtin resources
+
+In the internal database of the Assets Manager Panel, the engine provides some builtin TextureCube resources that developers can use on demand following the same instructions described above.
+
+
+
+#### SkyIllum Property
+
+The SkyIllum property can be found in the **Ambient** component of the **Inspector** panel by selecting the scene root node in the **Hierarchy** panel, with a default value of 20000.
+
+If the SkyIllum property is set **too low**, the environment map of the skybox may not be displayed correctly in the **Scene** panel. General:
+
+- When the SkyIllum property value is less than 300, the environment map of the Skybox will not be displayed properly.
+
+- When the SkyIllum property is 5000, the effect is equivalent to the light intensity of a moonlit night.
+
+#### Modifying ClearFlags of Camera
+
+If the environment map of the skybox is already displayed correctly in the **Scene** panel but still does not take effect after the project is run, you need to change the **ClearFlags** of the **Camera** component to **SKYBOX**:
+
+
+
+### By Setting the CubeMap
+
+A cube map can be generated manually in Creator from six normal maps by following the steps below:
+
+1. Select all the six prepared texture assets in the **Assets** panel, and then set the **Type** property of these texture assets to **texture** in the **Inspector** panel, and click the green checkbox in the upper right corner.
+
+ 
+
+2. Create a new CubeMap asset. Select the folder where you want to store CubeMap in the **Assets** panel, click the **+** button in the upper left corner, and then select **CubeMap**. Or you can right-click the folder where you want to store the CubeMap, and select **New -> CubeMap**.
+
+ 
+
+3. Drag and drop the six images you just set as texture type into the corresponding property box of the CubeMap, and click the green tick button on the top right then you are done.
+
+ 
+
+ > **Notes**:
+ >
+ > 1. The property boxes in CubeMap that do not have a texture asset yet will be populated using the default asset.
+ > 2. The six property boxes in CubeMap **do not use the same texture**, otherwise they will not be displayed properly for some platforms.
+
+## Diffuse Illumination
+
+Creator supports the following three types of ambient diffuse lighting, which can be select in the pull-down menu of **Env Lighting Type**.
+
+
+
+The types are described as follows:
+
+1. **Hemisphere Diffuse**: when the **Env Lighting Type** options is **HEMISPHERE_DIFFUSE**, hemispheric light diffusion will be used. This method is controlled by the **SkyLightingColor** and **GroundLightingColor** properties in the **Ambient** component, and has higher rendering performance, but less detail and poor lighting directionality. **The properties are manually adjustable, but may become inconsistent with the environment map**.
+
+ 
+
+2. **Hemisphere Diffuse And Environment Reflection**: when the **Env Lighting Type** options is **AUTOGEN_HEMISPHERE_DIFFUSE_WITH_REFLECTION**, diffuse reflection is controlled by the **SkyLightingColor** and **GroundLightingColor** properties in the **Ambient** component. It also reflects the specular reflection generated by the environment map.
+
+ 
+
+3. **Diffuse Convolution Map And Environment Reflection**: when the **Env Lighting Type** options is **DIFFUSEMAP_WITH_REFLECTION**, the convolution map diffuse will be used. This method is advanced diffuse reflection, which can correctly express the diffuse lighting generated by environment map, with better lighting directionality and details. However, the convolution map in the **DiffuseMap** property is automatically generated for diffuse reflection and does not allow manual editing.
+
+ 
+
+The comparison between the **AUTOGEN_HEMISPHERE_DIFFUSE_WITH_REFLECTION** and **DIFFUSEMAP_WITH_REFLECTION** is more obvious from the GIF below,when the **Env Lighting Type** is **DIFFUSEMAP_WITH_REFLECTION** The backlight is dark, highlighting the overall sense of layering, light and shade contrast details are also greatly improved.
+
+
+
+> **NOTICE**: When replacing the environment map in the **Envmap** property, Creator will automatically calculate the corresponding ambient lighting information, as well as the diffuse lighting (only CubeMap in the form of image files is supported, manually created CubeMap is not supported).
+
+## Toggling HDR/LDR mode
+
+The **UseHDR** option in the Skybox component is used to toggle the HDR/LDR mode, which is used when checked.
+
+
+
+- HDR (High Dynamic Range): High dynamic range, with **photometric intensity of the lights** and **exposure parameters of the camera** to achieve a more realistic level of contrast between light and dark. If this mode is used, the intensity of all lights (including parallel light, point light, spot light, etc.) **will become photometric physical units** and ambient light cube map should use **HDR format images** to provide a high dynamic range data source.
+
+- LDR (Low Dynamic Range): Low dynamic range. If this mode is used, the **lights intensity becomes unitless** and no longer has any connection to photometry or camera exposure. This mode is suitable for scenarios where you want the original map color to be reflected without any color tinting. Ambient light cube map can be done using images in formats such as **PNG**.
+
+## Skybox Material
+
+
+
+The default shader used for the skybox material is **Assets -> internal/pipeline/skybox.effect**, if you want to customize the material, you can refer to [New Material](.../.../asset/material.md) to create a new material and select [Custom Shader](.../.../.../shader/write-effect-overview.md).
+
+
+
+## Reflective Convolution
+
+Use GGX BRDF lighting model to generate a pre-filtered reflection result for the environment map, which will take into consideration the effect of roughness and store the final result in Mipmap in order of roughness (roughness from 0 to 1, with Mipmap level 0 for roughness 0).
+
+Since this algorithm takes into consideration the effect of roughness on the environment reflection (i.e., as roughness increases, the environment reflection becomes more blurred), it results in more realistic reflections for the PBR material.
+
+## Bake Reflection Convolution Map
+
+Click the  button in the **Inspector** panel to bake the reflection convolution results. After the bake is complete, you can also choose to click the  to delete it.
+
+The generated environment reflection convolution map will fill to the mipmaps for TextureCube, Sampling mipmap in the shader based on material roughness, thus providing a more realistic IBL effect, You can clearly see the comparison effect by the following GIF image.
+
+
diff --git a/versions/4.0/en/concepts/scene/skybox/autogen-hemisphere.png b/versions/4.0/en/concepts/scene/skybox/autogen-hemisphere.png
new file mode 100644
index 0000000000..490850b5ec
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/autogen-hemisphere.png differ
diff --git a/versions/4.0/en/concepts/scene/skybox/bake.png b/versions/4.0/en/concepts/scene/skybox/bake.png
new file mode 100644
index 0000000000..0508854cc4
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/bake.png differ
diff --git a/versions/4.0/en/concepts/scene/skybox/builtin.png b/versions/4.0/en/concepts/scene/skybox/builtin.png
new file mode 100644
index 0000000000..396f475878
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/builtin.png differ
diff --git a/versions/4.0/en/concepts/scene/skybox/compare.gif b/versions/4.0/en/concepts/scene/skybox/compare.gif
new file mode 100644
index 0000000000..ba7d6b376f
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/compare.gif differ
diff --git a/versions/4.0/en/concepts/scene/skybox/convolution-map.gif b/versions/4.0/en/concepts/scene/skybox/convolution-map.gif
new file mode 100644
index 0000000000..e5fbc2eb30
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/convolution-map.gif differ
diff --git a/versions/4.0/en/concepts/scene/skybox/create-cubemap.png b/versions/4.0/en/concepts/scene/skybox/create-cubemap.png
new file mode 100644
index 0000000000..8d00089d3c
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/create-cubemap.png differ
diff --git a/versions/4.0/en/concepts/scene/skybox/cubemap-properties.png b/versions/4.0/en/concepts/scene/skybox/cubemap-properties.png
new file mode 100644
index 0000000000..9637da61b4
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/cubemap-properties.png differ
diff --git a/versions/4.0/en/concepts/scene/skybox/cubemap-texture-type.png b/versions/4.0/en/concepts/scene/skybox/cubemap-texture-type.png
new file mode 100644
index 0000000000..bfd5145c89
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/cubemap-texture-type.png differ
diff --git a/versions/4.0/en/concepts/scene/skybox/custom-skybox-material.png b/versions/4.0/en/concepts/scene/skybox/custom-skybox-material.png
new file mode 100644
index 0000000000..9f2a26a012
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/custom-skybox-material.png differ
diff --git a/versions/4.0/en/concepts/scene/skybox/diffuse-map-with-reflection.png b/versions/4.0/en/concepts/scene/skybox/diffuse-map-with-reflection.png
new file mode 100644
index 0000000000..e47e4dff14
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/diffuse-map-with-reflection.png differ
diff --git a/versions/4.0/en/concepts/scene/skybox/enable-skybox.jpg b/versions/4.0/en/concepts/scene/skybox/enable-skybox.jpg
new file mode 100644
index 0000000000..92c9b77d5b
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/enable-skybox.jpg differ
diff --git a/versions/4.0/en/concepts/scene/skybox/enable-skybox.png b/versions/4.0/en/concepts/scene/skybox/enable-skybox.png
new file mode 100644
index 0000000000..801f14822c
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/enable-skybox.png differ
diff --git a/versions/4.0/en/concepts/scene/skybox/envmap.png b/versions/4.0/en/concepts/scene/skybox/envmap.png
new file mode 100644
index 0000000000..11f17e8441
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/envmap.png differ
diff --git a/versions/4.0/en/concepts/scene/skybox/generate-rc.png b/versions/4.0/en/concepts/scene/skybox/generate-rc.png
new file mode 100644
index 0000000000..56ec995c34
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/generate-rc.png differ
diff --git a/versions/4.0/en/concepts/scene/skybox/hemisphere.png b/versions/4.0/en/concepts/scene/skybox/hemisphere.png
new file mode 100644
index 0000000000..67025c5d3e
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/hemisphere.png differ
diff --git a/versions/4.0/en/concepts/scene/skybox/material.png b/versions/4.0/en/concepts/scene/skybox/material.png
new file mode 100644
index 0000000000..1f3d48646f
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/material.png differ
diff --git a/versions/4.0/en/concepts/scene/skybox/remove.png b/versions/4.0/en/concepts/scene/skybox/remove.png
new file mode 100644
index 0000000000..75eca35630
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/remove.png differ
diff --git a/versions/4.0/en/concepts/scene/skybox/set-envmap.png b/versions/4.0/en/concepts/scene/skybox/set-envmap.png
new file mode 100644
index 0000000000..08024c5a7a
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/set-envmap.png differ
diff --git a/versions/4.0/en/concepts/scene/skybox/sky-box-type.png b/versions/4.0/en/concepts/scene/skybox/sky-box-type.png
new file mode 100644
index 0000000000..0546441ce4
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/sky-box-type.png differ
diff --git a/versions/4.0/en/concepts/scene/skybox/skybox-camera.png b/versions/4.0/en/concepts/scene/skybox/skybox-camera.png
new file mode 100644
index 0000000000..880b9b1051
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/skybox-camera.png differ
diff --git a/versions/4.0/en/concepts/scene/skybox/texturecube.png b/versions/4.0/en/concepts/scene/skybox/texturecube.png
new file mode 100644
index 0000000000..9912b3b253
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/texturecube.png differ
diff --git a/versions/4.0/en/concepts/scene/skybox/use-hdr.png b/versions/4.0/en/concepts/scene/skybox/use-hdr.png
new file mode 100644
index 0000000000..127fef4c82
Binary files /dev/null and b/versions/4.0/en/concepts/scene/skybox/use-hdr.png differ
diff --git a/versions/4.0/en/editor/assets/extension.md b/versions/4.0/en/editor/assets/extension.md
new file mode 100644
index 0000000000..dbfff20294
--- /dev/null
+++ b/versions/4.0/en/editor/assets/extension.md
@@ -0,0 +1,181 @@
+# Extending the Assets Panel
+
+## Extending the Right-Click Menu
+
+The right-click menu display mechanism is to get the live menu data before it is displayed. The extension pre-registers the `assets` module in its own `package.json` to get the right-click menu display events for the **Assets** panel, and returns the menu data to be displayed via the events, and then displays it uniformly. The registered menu is usually displayed after the existing menu.
+
+Assuming a location (`where`) in the **Assets** panel has a right-click menu event, the currently supported extended locations (`where`) are:
+
+- `createMenu` -- two entry points for creating assets: one is the **+** button in the top left corner of the panel; the other is the **Create** option in the right-click menu.
+- `dbMenu` -- the asset database root node
+- `assetMenu` -- asset general node
+- `panelMenu` -- blank area of the panel
+
+Specific implementation steps:
+
+- Select **Extension** --> **Create Extension** in the menu bar at the top of the editor and create a new extension in the **Global/Projects** directory as needed. The extension package will then be generated in the `extensions` directory of the root/project directory.
+- Open the `package.json` file of the extension package and configure the `contributions.assets.menu` property, where `methods` is introduced into the `assets-menu.js` file. Other properties such as `createMenu` are explicit declarations of `where` above, and the corresponding `onCreateMenu` is the method exported from `assets-menu.js`:
+
+ ```json5
+ // package.json
+ {
+ contributions: {
+ assets: {
+ menu: {
+ methods: '. /assets-menu.js', // This file is in the following demo example
+ createMenu: 'onCreateMenu',
+ assetMenu: 'onAssetMenu',
+ dbMenu: 'onDBMenu',
+ panelMenu: 'onPanelMenu',
+ },
+ },
+ },
+ }
+ ```
+
+- The `assets-menu.js` part of the code example in the **Demo example** at the end of the article is as follows:
+
+ ```javascript
+ // assets-menu.js
+ exports.onCreateMenu = function (assetInfo) {
+ return [
+ {
+ label: 'i18n:extend-assets-demo.menu.createAsset',
+ click() {
+ if (!assetInfo) {
+ console.log('get create command from header menu');
+ } else {
+ console.log('get create command, the detail of diretory asset is:');
+ console.log(assetInfo);
+ }
+ },
+ },
+ ];
+ };
+
+ exports.onAssetMenu = function (assetInfo) {
+ return [
+ {
+ label: 'i18n:extend-assets-demo.menu.assetCommandParent',
+ submenu: [
+ {
+ label: 'i18n:extend-assets-demo.menu.assetCommand1',
+ enabled: assetInfo.isDirectory,
+ click() {
+ console.log('get it');
+ console.log(assetInfo);
+ },
+ },
+ {
+ label: 'i18n:extend-assets-demo.menu.assetCommand2',
+ enabled: !assetInfo.isDirectory,
+ click() {
+ console.log('yes, you clicked');
+ console.log(assetInfo);
+ },
+ },
+ ],
+ },
+ ];
+ };
+ ```
+
+- The `onCreateMenu(assetInfo)` function in `assets-menu.js` and similar functions are described as follows:
+
+ - Parameter `assetInfo` Object
+
+ - `displayName` String - the name of the asset to be displayed
+ - `extends` (optional) String[] - the class to inherit from
+ - `importer` String - the name of the importer
+ - `isDirectory` Boolean - whether it is a folder
+ - `instantiation` (optional) String - will carry this extension name if the virtual asset can be instantiated as an entity
+ - `imported` Boolean - whether the import is complete
+ - `invalid` Boolean - whether the import is failed
+ - `name` String - the name of the asset
+ - `file` String - the absolute path to the disk where the asset file is located
+ - `redirect` Object - jump to the asset
+ - `type` String - the asset type
+ - `uuid` String - the asset ID
+ - `readonly` Boolean - whether to be read-only
+ - `type` String - asset type
+ - `url` String - the address of the asset starting with db://
+ - `uuid` String - asset ID
+
+ - Return Value `MenuItem[]`, `MenuItem` Object
+
+ - `type` (optional) String - optional, normal, separator, submenu, checkbox or radio
+ - `label` (optional) String - the text displayed
+ - `sublabel` (optional) String - the secondary text displayed
+ - `submenu` (optional) MenuItem[] - the submenu
+ - `click` (optional) Function - the click event
+ - `enable` (optional) Boolean - whether it is available, if not it will be grayed out style
+ - `visible` (optional) Boolean - whether to show
+ - `accelerator` (optional) String - Show shortcut keys
+ - `checked` (optional) Boolean - whether checked when type is `checkbox` / `radio`
+
+More properties can be found in the data format of the [electron menu-item](https://www.electronjs.org/docs/api/menu-item) documentation.
+
+The effect of implementing the extension is illustrated as follows:
+
+
+
+## Extending Drag-and-Drop Recognition
+
+Recognizing an acceptable type requires the support of the editor UI component ``, where an important property is `type`, ``. Customize a drag-in type and inject it into the **Assets** panel's scope. If a `` element containing that custom type is subsequently dragged into the **Assets** panel from another editor panel, the **Assets** panel recognizes it and sends a message to the registrant (plugin) of the custom type. The registrant can then perform a custom action, such as creating a new set of assets.
+
+The specific implementation steps are roughly the same as the above **extension right-click menu**, open the extension's `package.json` file to do the corresponding configuration.
+
+```json5
+// package.json
+{
+ contributions: {
+ assets: {
+ drop: [
+ {
+ type: 'my-defined-asset-type-for-drop', // corresponds to the usage of panel.html in the demo example
+ message: 'drop-asset',
+ },
+ menu: ',]
+ menu: '. /assets-menu.js',
+ },
+ },
+ messages: {
+ 'drop-asset': {
+ methods: ['default.dropAsset'], // 'default' is the current extension's default panel
+ },
+ },
+}
+```
+
+- The `panel.js` file in the **Demo example** at the end of the article:
+
+ ```javascript
+ exports.methods = {
+ dropAsset(assetInfo, dragInfo) {
+ console.log(Editor.I18n.t('extend-assets-demo.drop.callback'));
+ console.log(assetInfo);
+ console.log(dragInfo);
+ },
+ };
+ ```
+
+ `assetInfo` parameter description:
+
+ - `uuid` String - The UUID of the asset at the mouse release location when dragging an asset in the **Assets** panel.
+ - `type` String - the asset type
+ - `isDirectory` Boolean - whether the asset is a folder
+
+- The `panel.html` file in the **Demo example** at the end of the article:
+
+ ```html
+
+ Drag me to assets panel, and look conosole log.
+
+ ```
+
+## Demo examples
+
+For executable code for both extensions, please download the workingexamples
diff --git a/versions/4.0/en/editor/assets/img/create.png b/versions/4.0/en/editor/assets/img/create.png
new file mode 100644
index 0000000000..7569f34f79
Binary files /dev/null and b/versions/4.0/en/editor/assets/img/create.png differ
diff --git a/versions/4.0/en/editor/assets/img/drag.png b/versions/4.0/en/editor/assets/img/drag.png
new file mode 100644
index 0000000000..1f70ec2042
Binary files /dev/null and b/versions/4.0/en/editor/assets/img/drag.png differ
diff --git a/versions/4.0/en/editor/assets/img/extend-assets-demo.zip b/versions/4.0/en/editor/assets/img/extend-assets-demo.zip
new file mode 100644
index 0000000000..7dd7e5282b
Binary files /dev/null and b/versions/4.0/en/editor/assets/img/extend-assets-demo.zip differ
diff --git a/versions/4.0/en/editor/assets/img/extend-create-menu.png b/versions/4.0/en/editor/assets/img/extend-create-menu.png
new file mode 100644
index 0000000000..510fcea2b9
Binary files /dev/null and b/versions/4.0/en/editor/assets/img/extend-create-menu.png differ
diff --git a/versions/4.0/en/editor/assets/img/package-asset/exporting.png b/versions/4.0/en/editor/assets/img/package-asset/exporting.png
new file mode 100644
index 0000000000..f67659081d
Binary files /dev/null and b/versions/4.0/en/editor/assets/img/package-asset/exporting.png differ
diff --git a/versions/4.0/en/editor/assets/img/package-asset/importing.png b/versions/4.0/en/editor/assets/img/package-asset/importing.png
new file mode 100644
index 0000000000..0d676eb29f
Binary files /dev/null and b/versions/4.0/en/editor/assets/img/package-asset/importing.png differ
diff --git a/versions/4.0/en/editor/assets/img/preview.png b/versions/4.0/en/editor/assets/img/preview.png
new file mode 100644
index 0000000000..eb1a6cbaa1
Binary files /dev/null and b/versions/4.0/en/editor/assets/img/preview.png differ
diff --git a/versions/4.0/en/editor/assets/img/right-click.png b/versions/4.0/en/editor/assets/img/right-click.png
new file mode 100644
index 0000000000..3a609fe8e7
Binary files /dev/null and b/versions/4.0/en/editor/assets/img/right-click.png differ
diff --git a/versions/4.0/en/editor/assets/img/search-name.png b/versions/4.0/en/editor/assets/img/search-name.png
new file mode 100644
index 0000000000..082b13deae
Binary files /dev/null and b/versions/4.0/en/editor/assets/img/search-name.png differ
diff --git a/versions/4.0/en/editor/assets/img/search-types.png b/versions/4.0/en/editor/assets/img/search-types.png
new file mode 100644
index 0000000000..fb524308d7
Binary files /dev/null and b/versions/4.0/en/editor/assets/img/search-types.png differ
diff --git a/versions/4.0/en/editor/assets/img/search-uuid.png b/versions/4.0/en/editor/assets/img/search-uuid.png
new file mode 100644
index 0000000000..1ae821a2b7
Binary files /dev/null and b/versions/4.0/en/editor/assets/img/search-uuid.png differ
diff --git a/versions/4.0/en/editor/assets/img/thumb.gif b/versions/4.0/en/editor/assets/img/thumb.gif
new file mode 100644
index 0000000000..7d4d273a6b
Binary files /dev/null and b/versions/4.0/en/editor/assets/img/thumb.gif differ
diff --git a/versions/4.0/en/editor/assets/index.md b/versions/4.0/en/editor/assets/index.md
new file mode 100644
index 0000000000..5566d59f3d
--- /dev/null
+++ b/versions/4.0/en/editor/assets/index.md
@@ -0,0 +1,168 @@
+# Assets Panel
+
+The **Assets** panel is an important work area for accessing and managing project assets. When starting a game, **Import Assets** is usually a mandatory step. Use the **HelloWorld** template project when creating a new project, and notice that the **Assets** panel already contains some basic asset types.
+
+
+
+## Panel introduction
+
+The **Assets** panel can be divided into two main sections: **Toolbar** and **Asset List**.
+
+- The functions in **Toolbar** include **New Asset (+)**, **Sort by**, **Search Filter**, **Search Box**, **Collapse/Expand All** and **Refresh**. For details, please refer to the description below.
+
+- The **Asset List** presents the contents of the project's asset folder in a tree structure, which by default includes the **assets** and **internal** base repositories (DBs for short).
+
+ - **assets** is similar to the file manager in the operating system, only assets placed in the `assets` directory of the project folder will be displayed here. For a description of the project folder structure, please refer to the [Project Structure](../../getting-started/project-structure/index.md) documentation.
+ - The **internal** contains the default built-in assets (read-only). Built-in assets can be copied, but cannot be added, deleted, or changed. It can be dragged and dropped into **assets** as an asset template, i.e. a new project asset is created.
+
+- The panel currently supports shortcuts for manipulating assets, including:
+ - **Copy**: Ctrl/Cmd + C
+ - **Paste**: Ctrl/Cmd + V
+ - **Duplicate**: Ctrl/Cmd + D, Ctrl + drag assets
+ - **Delete**: Delete
+ - **Up and down selection**: Up arrow, Down arrow
+ - **Previous hierarchy**: Left arrow
+ - **Next hierarchy**: Right arrow
+ - **Multi-select**: Ctrl/Cmd + Click
+ - **Multi-select continuously**: Shift + Click
+ - **Select All**: Ctrl/Cmd + A
+ - **Rename**: Enter/F2
+ - **Cancel input**: Esc
+
+### Creating assets
+
+There are two ways to create an asset.
+1. Click the **+** button at the top left of the **Assets** panel.
+2. Right-click in the **Assets** panel and select **Create**.
+
+
+
+> **Note**: when creating an asset, an **INPUT BOX** will first appear asking for the name of the new asset, which cannot be empty.
+
+When creating an asset, select the folder where to place the asset in the tree asset list, then the new asset will be created in the currently selected folder directory. If a folder isn't selected, the new asset will be created in the current root directory (`assets`) by default.
+
+For additional information about Assets, please refer to the [Asset](../../asset/index.md) documentation.
+
+### Selecting assets
+
+The following asset selection actions can be used in the asset list:
+
+- Click to select a single asset. The selected asset will be highlighted in **yellow on blue**.
+- Double-click to open an asset, e.g.: scene, script, image; double-click on a folder to collapse/expand it
+- Hold Ctrl/Cmd and select an asset to select multiple assets at once
+- Hold Shift and select an asset to select multiple assets in a row
+
+For selected assets, you can move, delete, etc.
+
+### Moving assets
+
+After selecting an asset (multiple selections are possible), move the asset to another location by holding down the mouse and dragging it. When dragging the asset to be moved to the target folder, notice the folder where the mouse is hovering appears highlighted in yellow and has a blue box around it. Release the mouse at this point and the asset will be moved to the highlighted folder directory.
+
+
+
+Asset movement also includes the following actions:
+
+- Drag and drop assets from **Assets** panel to the **Scene** panel or **Hierarchy** panel to generate nodes, currently supporting dragging and dropping `cc.Prefab`, `cc.Mesh`, `cc.SpriteFrame` assets.
+- Drag and drop files from the **system's file manager** to the **Assets** panel list to import assets.
+- Drag and drop a node from the **Hierarchy** panel to a folder in the **Assets** panel to save the node as a `cc.Prefab` asset. Please review the [Prefab Assets](../../asset/prefab.md) documentation.
+
+### Sorting assets
+
+The **Sort by** in the toolbar includes **Sort by name** and **Sort by type**. The current sorting method is recorded and will be maintained the next time the editor is opened.
+
+### Collapsing assets
+
+Collapses are divided into single collapses or all collapses with subsets:
+
+- The **Collapse/Expand All** button in the **Toolbar** works globally
+- Click on the triangle icon of a parent asset (e.g.: folder) to expand or collapse its subsets. Use the shortcut key **Alt** and click on the triangle icon to expand or collapse all children of the asset
+
+The current collapsed state of the asset will be recorded and will be maintained the next time the editor is opened.
+
+### Searching assets
+
+The search function can limit the search type and specify the search field, both of which can be used to achieve a type filtering effect. Depending on the selected type/field, all the corresponding assets will be displayed in the panel.
+
+
+
+- **Limit search types**: multiple selections are possible. The type is the asset type `assetType`, not the suffix name or importer name.
+
+- **Specify search fields**: the search name is not case sensitive and includes the following search types:
+
+ 1. **search Name or UUID**, support searching for asset file extensions, such as `.png`:
+
+ 
+
+ 2. **Search UUID**
+
+ 3. **Search URL**, starting with the `db://` protocol.
+
+ 4. **Find UUID usage**, used to find out which assets the UUID asset is used by. For example:
+
+ 
+ 5. **Only Show Imported Failed**: show asserts that failed to import.
+ 6. **Search Bundle**: search for bundle assets/
+
+If you want to search only in a parent asset (e.g.: folder), right-click and select **Find in Folder** to narrow the search.
+
+Selecting an asset in the search result list and double-clicking on it is equivalent to the operation in normal mode. After clearing the search content, it will redirect to the selected asset.
+
+### Assets preview
+
+Selecting an asset in the **Assets** panel displays a thumbnail image of the asset in the **Assets Preview** panel. Selecting the folder where the asset is located, displays thumbnails of all assets under the folder for easy viewing.
+
+
+
+## Right-click menu for assets
+
+After selecting a specific asset/folder, right-click on it to perform a series of actions on the asset in the pop-up menu:
+
+
+
+- **Create**: the same function as the **Create** button in the **Assets** panel, it will add the asset to the currently selected folder, if the currently selected is an asset file, it will add the new asset to the same folder as the currently selected asset.
+- **Copy**/**Cut**/**Paste**: copy/cut the selected asset (multiple options available) and paste it under that folder or another folder.
+- **Duplicate**: duplicate the selected asset (can be multi-selected), and the duplicated asset will be in the same hierarchy as the selected asset.
+- **Rename**: modify the asset name, please check the description below for details.
+- **Delete**: delete the asset (can be multi-selected), or you can use the shortcut **Delete**. The asset will remain in the **Recycle Bin** of the system after deletion, and can be restored if necessary.
+- **Select All**: selects all assets in the same hierarchy.
+- **Search in Folder**: when using the search function, only search the assets in that folder.
+- **Find UUID Usages**: find which assets the asset is referenced by by the asset's UUID.
+- **Import New Files/New Folders**: import new files or folder to the project.
+- **Import/Export Asset Package**: please refer to the introduction below for details.
+- **Preview this scene in the browser**: only available for scene assets.
+- **Reveal in Explorer (Windows) or Finder (Mac)**: opens the folder where this asset is located in the operating system's file manager window.
+- **Reimport Asset**: updates the asset to the project's `./library` folder of the project, with multiple selections for bulk import.
+- **Reveal in Library**: opens the asset in the `Library` folder of the project, please read the [Project Structure](../../getting-started/project-structure/index.md) documentation.
+- **UUID/URL/PATH**: copies the UUID/URL/PATH of the asset and outputs it in the **Console** panel.
+
+Also for specific asset types, double-clicking on an asset allows you to enter the edit state of that asset, such as scene assets and script assets.
+
+### Rename asset
+
+Select the asset to rename, then right-click and select **Rename** to change the asset name, or use the shortcut keys **Enter** or **F2**. Click elsewhere in the panel or press the shortcut **Esc** to cancel the renaming.
+
+### Exporting asset package
+
+Select the asset to be exported and right-click on it, then select **Export Asset Package**. The **Export Asset** panel will automatically list the currently selected asset with its dependencies. If you don't need to export related dependent assets, uncheck **Include Dependency** in the lower left corner of the **Export Assets** panel.
+
+After determining the assets to be exported, click the **Export** button, a file storage dialog will pop up, the user needs to specify a folder location and file name, click **Save**, and a **filename.zip** file will be generated, containing all the exported assets.
+
+> **Note**: the extension will automatically break the assets into a zip package, which is only available for use with the **Import Asset Package** extension.
+
+
+
+### Importing asset package
+
+Select and right-click on the folder you want to import assets from, or right-click on the **blank space** in the **Assets** panel, then select **Import Package** and select the zip package exported by **Export Package** in the pop-up file browse dialog. The assets in the zip package will be automatically parsed to the pop-up **Import Asset Package** panel.
+
+During the import process, the user will be asked to confirm the imported assets again, uncheck some assets to remove the ones you don't want to import.
+
+
+
+> **Notes**:
+> 1. Imported zip packages are only supported by Cocos Creator 3.0.0 and above using **Export Asset Package**.
+> 2. Importing scripts with the same class name is not supported.
+
+## Extending the Assets Panel
+
+Currently supported extensions include **right-click menu** and **drop-in recognition**, please refer to the [Extending the Assets Panel](./extension.md) documentation.
diff --git a/versions/4.0/en/editor/components/camera-component.md b/versions/4.0/en/editor/components/camera-component.md
new file mode 100644
index 0000000000..7b36aff32d
--- /dev/null
+++ b/versions/4.0/en/editor/components/camera-component.md
@@ -0,0 +1,77 @@
+# Camera
+
+The __Camera__ in a game is the main tool used to capture __Scenes__. The visible range of the __Camera__ is controlled by adjusting camera-related parameters. The __Camera__ is represented as follows in the __Cocos Creator__ editor:
+
+
+
+The __Camera__'s visual range is composed of __6__ planes forming a __Frustum__, a __Near Plane__, and a __Far Plane__ to control the visible distance and range of near and far distance, at the same time, they also constitute the size of the viewport.
+
+
+
+To use `Camera`, please refer to the [Camera API](%__APIDOC__%/en/class/Camera).
+
+## Camera component
+
+The __Camera Component__ is an important functional component that we use to present a __Scene__.
+
+
+
+| Property | Description |
+|:-------|:---|
+| __Priority__ | Render priority of the camera. High-priority __Camera__'s will be rendered first in the rendering process |
+| __Visibility__ | The `Visibility` of the __Camera__. Used to control the `Visibility` of different models in the same __Camera__. |
+| __ClearFlags__ | Clearing flags of the Camera, spaces which part of the framebuffer will be actually clearedevery frame. Contains: __DONT_CLEAR__: not clear. __DEPTH_ONLY__: only clear the depth. __SLOD_COLOR__: clear the color, depth and template buffer. __SKYBOX__: enable skybox to clear depth only. |
+| __ClearColor__ | Clear the specified color |
+| __ClearDepth__ | Clear the specified depth |
+| __ClearStencil__ | Clear the specified template buffer |
+| __Projection__ | Projection mode. Divided into __perspective projection (PERSPECTIVE)__ and __orthogonal projection (ORTHO)__ |
+| __FovAxis__ | The axis on which the FOV would be fixed regardless of screen aspect changes |
+| __Fov__ | Field of view of the camera |
+| __OrthoHeight__ | Viewport height in orthogonal mode |
+| __Near__ | The near clipping distance of the camera, should be as large as possible within acceptable range |
+| __Far__ | The far clipping distance of the camera, should be as small as possible within acceptable range |
+| __Aperture__ | The camera aperture, which affects the exposure parameters of the camera |
+| __Shutter__ | The camera shutter, which affects the exposure parameters of the camera |
+| __Iso__ | The camera ISO, which affects the exposure parameters of the camera Please refer to __Exposure__ below for more information |
+| __Rect__ | The position and size of the viewport that the camera will eventually render to the screen |
+| __TargetTexture__ | Output render target texture of the camera, which renders directly to the screen. Defaults to null |
+
+## Camera group rendering
+
+The __Camera__'s group rendering function is determined by the `Visibility` property and the [Layer property](../../concepts/scene/node-component.md#set-the-layer-property-of-the-node) of the node. The user can set the __Visibility__ value through code to complete the group rendering. It should be noted that the __Visibility__ value is __bitwise comparison__, and the user can manipulate the __top 20 bits of Visibility__ through __bit operations__ to complete the grouping.
+
+The __Camera__ and models provided by default are all __rendered without grouping__. You do not need to change this value if the game has no special requirements to do so.
+
+### Set the Visibility property
+
+The `Visibility` property is used to set which layers of nodes should be observed by the camera, and multiple Layers can be selected at the same time.
+
+> __Note__: the rendering of 2d elements (such as Sprite) also follows the `Layer` and `Visibility` judgement, adjust the `Layer` and `Visibility` as required.
+
+When you check multiple Layers in the `Visibility` property, the value of the `Visibility` property is calculated by performing a `|` operation on the property values of multiple Layers.
+
+For example, in the following image, the `Visibility` property of the camera has both __UI_3D__ and __DEFAULT__ Layer checked, and by looking up [the value of the Layer property](../../concepts/scene/layer.md), notice the value of the __UI_3D__ property is __1 << 23__ , the value of the __DEFAULT__ property is __1 << 30__, and the value of the `Visibility` property is __1 << 23 | 1 << 30 = 1082130432__.
+
+
+
+For additional information on the implementation of Layer, please refer to the [Layer](../../concepts/scene/layer.md) documentation.
+
+### Visibility calculations for the camera
+
+The `Visibility` property allows multiple Layers to be selected at the same time, while the `Layer` on the Node has its own value, so the `Visibility` property of the camera is an __232__ bit integer. Each visible Layer occupies one bit, using bitwise operations, and supports up to 32 different Layer labels (one bit for each Layer value, that is, represented by __232__). When the camera is culling, the Layer's property value of each node will perform a `&` operation with the camera, and if the `Visibility` property of the camera contains this `Layer`, then the current node will be visible to the camera, and vice versa.
+
+### Exposure
+
+__Aperture__, __Shutter__, __Iso__: These three parameters of __Camera__ will determine the amount of incoming light, which in turn affects the exposure value. Only takes effect if the scene has HDR turned on. The algorithm is usually as follows:
+
+ev = log2 (ApertureValue2 / ShutterValue*k / IsoValue)
+
+`ApertureValue`, `ShutterValue` and `IsoValue` are obtained by looking up the enumeration values of the three attributes __Aperture__, __Shutter__, __Iso__. Where k is a cosntant.
+
+The following images demonstrate the effect of exposure on a scene:
+
+
+
+
+
+To enable scene HDR, please refer to [Skybox - Toggling HDR/LDR mode](../../concepts/scene/skybox.md#Toggling%HDR/LDR%mode).
diff --git a/versions/4.0/en/editor/components/camera/camera-component.png b/versions/4.0/en/editor/components/camera/camera-component.png
new file mode 100644
index 0000000000..f5d33fb4d4
Binary files /dev/null and b/versions/4.0/en/editor/components/camera/camera-component.png differ
diff --git a/versions/4.0/en/editor/components/camera/camera-frustum.jpg b/versions/4.0/en/editor/components/camera/camera-frustum.jpg
new file mode 100644
index 0000000000..cd53fe1768
Binary files /dev/null and b/versions/4.0/en/editor/components/camera/camera-frustum.jpg differ
diff --git a/versions/4.0/en/editor/components/camera/camera-view.gif b/versions/4.0/en/editor/components/camera/camera-view.gif
new file mode 100644
index 0000000000..417e3314d9
Binary files /dev/null and b/versions/4.0/en/editor/components/camera/camera-view.gif differ
diff --git a/versions/4.0/en/editor/components/camera/camera-visibility-gizmo.png b/versions/4.0/en/editor/components/camera/camera-visibility-gizmo.png
new file mode 100644
index 0000000000..e267e40a33
Binary files /dev/null and b/versions/4.0/en/editor/components/camera/camera-visibility-gizmo.png differ
diff --git a/versions/4.0/en/editor/components/camera/camera.png b/versions/4.0/en/editor/components/camera/camera.png
new file mode 100644
index 0000000000..9c196ee77b
Binary files /dev/null and b/versions/4.0/en/editor/components/camera/camera.png differ
diff --git a/versions/4.0/en/editor/components/camera/hdr1.png b/versions/4.0/en/editor/components/camera/hdr1.png
new file mode 100644
index 0000000000..ab580824fc
Binary files /dev/null and b/versions/4.0/en/editor/components/camera/hdr1.png differ
diff --git a/versions/4.0/en/editor/components/camera/hdr2.png b/versions/4.0/en/editor/components/camera/hdr2.png
new file mode 100644
index 0000000000..0f885981d3
Binary files /dev/null and b/versions/4.0/en/editor/components/camera/hdr2.png differ
diff --git a/versions/4.0/en/editor/components/dragonbones.md b/versions/4.0/en/editor/components/dragonbones.md
new file mode 100644
index 0000000000..1ff0390078
--- /dev/null
+++ b/versions/4.0/en/editor/components/dragonbones.md
@@ -0,0 +1,123 @@
+# DragonBones ArmatureDisplay Component References
+
+The ArmatureDisplay component can render and play DragonBones assets.
+
+
+
+In the **Hierarchy** panel, select the node where you want to add the ArmatureDisplay component, and then click the **Add Components -> DragonBones -> ArmatureDisplay** button under the **Inspector** panel to add the ArmatureDisplay component to the node.
+
+- For information on using the ArmatureDisplay component, please refer to the [DragonBones example case](https://github.com/cocos/cocos-test-projects/tree/v3.8/assets/cases/middleware/dragonbones) for details.
+- For DragonBones ArmatureDisplay related scripting interfaces, please refer to the [ArmatureDisplay API](%__APIDOC__%/en/class/dragonBones.ArmatureDisplay) for details.
+
+## DragonBones Properties
+
+| Property | Description
+| :-------- | :---------- |
+| CustomMaterial | Custom materials that can be used to achieve rendering effects such as dissolve, external glow, etc. Please refer to the [Custom Materials](../../ui-system/components/engine/ui-material.md) documentation for details.
+| Color | Set the skeleton animation color.
+| DragonAsset | Skeletal information data that contains skeletal information (bound skeletal actions, slots, render order, attachments, skins, etc.) and animations, but does not hold any state. Multiple ArmatureDisplays can share the same skeletal data. Skeletal assets exported by DragonBones can be dragged and dropped here.
+| DragonAtlasAsset | The Atlas Texture data needed for the skeleton data. Drag and drop DragonBones exported Atlas assets here.
+| Armature | The name of the Armature currently in use
+| Animation | Name of the currently playing animation
+| Animation Cache Mode | Rendering modes, including **REALTIME** (default setting), **SHARED_CACHE** and **PRIVATE_CACHE**. 1. **REALTIME** mode, real-time computing, supports all DragonBones features. 2. **SHARED_CACHE** mode, caches and shares skeletal animations and texture data, equivalent to pre-baked skeletal animations. **SHARED_CACHE** mode has higher performance, but does not support action fusion, action overlay, skeleton nesting, and only supports action start and end events. As for memory, it has a memory advantage when creating N (N>=3) animations with the same skeleton and the same action, the larger the N value, the more obvious the advantage. In summary, **SHARED_CACHE** mode is suitable for scene animations, effects, replica monsters, NPCs, etc., and can greatly improve frame rates and reduce memory consumption. 3. **PRIVATE_CACHE** mode, similar to **SHARED_CACHE** but does not share animation and texture data, so there is no memory advantage, only performance advantage. Use **PRIVATE_CACHE** to take advantage of the high performance of the cache mode and to also implement texture replacement (which cannot share the texture data).
+| TimeScale | The time scale of all animations in the current skeleton. The default value is **1**, which means no scaling.
+| PlayTimes | The number of cycles to play the default animation. **-1** means use the default value from the DragonBones resource file. **0** means infinite loop. **>0** means loop times.
+| PremultipliedAlpha | Whether the image is enabled for texture pre-multiplied, default is True. This item needs to be turned off when the transparent area of the image appears color blocked. Enabled when the translucent areas of the image become black.
+| DebugBones | Whether to show debug information for bone
+| Sockets | Used to attach certain external nodes to the specified skeleton joints. The value of the property indicates the number of attachment points. For details, please refer to the description below.
+| Enable Batch | Whether to enable batching |
+
+> **Notes**:
+> 1. The **Anchor** and **Size** properties on the Node component in the **Inspector** panel are disabled when using the ArmatureDisplay component.
+> 2. The ArmatureDisplay component is a UI renderable component, and the `Canvas` node is the rendering root for UI rendering, so the node with this component must be a child of the `Canvas` node (or a node with a `RenderRoot2D` component) to be displayed properly in the scene.
+
+## DragonBones ReplaceTexture
+
+The following is an example of how DragonBones replaces the texture. Replace the weapon in the left or right hand of the robot below with the weapon in the red box by replacing the slot's display object.
+
+
+
+1. First create a new `Canvas` node in the **Hierarchy** panel, and then create a new empty node and name it to `replaceDBNode` under the `Canvas` node. Select `replaceDBNode` and add the **ArmatureDisplay** component to the **Inspector** panel. Drag and drop the weapon resource in the green box to the property boxes of the **ArmatureDisplay** component, as shown below:
+
+ 
+
+2. Create a new empty node again and name it to `dbNode`. Then add the **ArmatureDisplay** component to the **Inspector** panel and drag the robot's assets to the property boxes of the **ArmatureDisplay** component, as shown below. Change the `Animation` property of the **ArmatureDisplay** component to set the animation you want to play.
+
+ 
+
+3. Create a new TypeScript script and name it `ReplaceSlotDisplay` in the **Assets** panel to write the component script. The script code is as follows:
+
+ ```ts
+ import { _decorator, Component, dragonBones } from 'cc';
+ const { ccclass, property } = _decorator;
+
+ @ccclass('ReplaceSlotDisplay')
+ export class ReplaceSlotDisplay extends Component {
+
+ @property({ type: dragonBones.ArmatureDisplay })
+ armatureDisplay: dragonBones.ArmatureDisplay | null = null
+ @property({ type: dragonBones.ArmatureDisplay })
+ replaceArmatureDisplay: dragonBones.ArmatureDisplay | null = null;
+
+ _leftWeaponIndex = 0;
+ _rightDisplayIndex = 0;
+ _rightDisplayNames:string[] = [];
+ _rightDisplayOffset:{x: number, y: number}[] = [];
+
+ start () {
+ this.replaceArmatureDisplay!.node.active = false;
+ this._leftWeaponIndex = 0;
+ this._rightDisplayIndex = 0;
+ this._rightDisplayNames = ["weapon_1004s_r", "weapon_1004e_r"];
+ this._rightDisplayOffset = [{ x: 0, y: 0 }, { x: -60, y: 100 }];
+ }
+
+ left () {
+ let armature = this.armatureDisplay!.armature();
+ let slot = armature!.getSlot("weapon_hand_l");
+ slot!.displayIndex = slot!.displayIndex == 0 ? 4 : 0;
+ }
+
+ right () {
+ this._rightDisplayIndex++;
+ this._rightDisplayIndex %= this._rightDisplayNames.length;
+ let armature = this.armatureDisplay!.armature();
+ let slot = armature!.getSlot("weapon_hand_r");
+ let replaceArmatureName = this.replaceArmatureDisplay!.armatureName;
+ const displayName = this._rightDisplayNames[this._rightDisplayIndex];
+ let factory = dragonBones.CCFactory.getInstance() as any;
+ factory.replaceSlotDisplay(this.replaceArmatureDisplay!.getArmatureKey(), replaceArmatureName , "weapon_r", displayName, slot);
+
+ let offset = this._rightDisplayOffset[this._rightDisplayIndex];
+ slot!.parent.offset.x = offset.x;
+ slot!.parent.offset.y = offset.y;
+ armature!.invalidUpdate();
+ }
+ }
+ ```
+
+4. Next, attach the script component to the `Canvas` node, i.e. drag and drop the script into the **Inspector** panel of the `Canvas` node. Drag and drop the `dbNode` node and `replaceDBNode` node from the **Hierarchy** panel into the corresponding property boxes of the script component and save the scene.
+
+ 
+
+5. Next, use the Button component's click event to trigger the `left` and `right` callback in the `ReplaceSlotDisplay` script to replace the texture by clicking the button.
+
+ Create two new Button nodes under the `Canvas` node in the **Assets** panel and name them `left` and `right`. Adjust their position, size, text display and other properties as needed.
+
+ Set the click events for the `left` and `right` nodes in the **Inspector** panel, drag the `Canvas` node with the `ReplaceSlotDisplay` script component attached to the `cc.Node` property box of the `ClickEvents` property of the `left` and `right` nodes respectively, specify script component as `ReplaceSlotDisplay`, and set the callback to `left`/`right` (the following figure shows the `right` node as an example).
+
+ 
+
+6. After saving the scene, click the **Preview** button at the top of the editor, and click the **Left**/**Right** button to see that the robot's left/right hand weapons have been replaced. For details, please refer to the [ReplaceSlotDisplay](https://github.com/cocos/cocos-test-projects/tree/v3.8/assets/cases/middleware/dragonbones) example.
+
+ 
+
+ > **Notes**:
+ > 1. After the example is run, the weapon style replaced by the right hand is not consistent with the weapon style prepared in the Scene, which is caused by the resource problem, please refer to the specific code implementation.
+ > 2. If the scene is not displayed when previewing, check that the `Layer` property of each node is consistent with that of the `Camera` node.
+ >
+ > 
+
+## DragonBones Attachment and Collision Detection
+
+DragonBones attachment and collision detection are done in exactly the same way as Spine, please refer to the [Spine Attachment and Collision Detection](./spine.md) documentation.
diff --git a/versions/4.0/en/editor/components/dragonbones/click-events.png b/versions/4.0/en/editor/components/dragonbones/click-events.png
new file mode 100644
index 0000000000..fab4088ec8
Binary files /dev/null and b/versions/4.0/en/editor/components/dragonbones/click-events.png differ
diff --git a/versions/4.0/en/editor/components/dragonbones/cloth.png b/versions/4.0/en/editor/components/dragonbones/cloth.png
new file mode 100644
index 0000000000..39a09e6b5c
Binary files /dev/null and b/versions/4.0/en/editor/components/dragonbones/cloth.png differ
diff --git a/versions/4.0/en/editor/components/dragonbones/cloth2.png b/versions/4.0/en/editor/components/dragonbones/cloth2.png
new file mode 100644
index 0000000000..cec303adc5
Binary files /dev/null and b/versions/4.0/en/editor/components/dragonbones/cloth2.png differ
diff --git a/versions/4.0/en/editor/components/dragonbones/cloth3.png b/versions/4.0/en/editor/components/dragonbones/cloth3.png
new file mode 100644
index 0000000000..8f84946a37
Binary files /dev/null and b/versions/4.0/en/editor/components/dragonbones/cloth3.png differ
diff --git a/versions/4.0/en/editor/components/dragonbones/cloth4.png b/versions/4.0/en/editor/components/dragonbones/cloth4.png
new file mode 100644
index 0000000000..93774e2510
Binary files /dev/null and b/versions/4.0/en/editor/components/dragonbones/cloth4.png differ
diff --git a/versions/4.0/en/editor/components/dragonbones/dragonbone_tscomponent.png b/versions/4.0/en/editor/components/dragonbones/dragonbone_tscomponent.png
new file mode 100644
index 0000000000..15378ac77a
Binary files /dev/null and b/versions/4.0/en/editor/components/dragonbones/dragonbone_tscomponent.png differ
diff --git a/versions/4.0/en/editor/components/dragonbones/layer.png b/versions/4.0/en/editor/components/dragonbones/layer.png
new file mode 100644
index 0000000000..f77f10b251
Binary files /dev/null and b/versions/4.0/en/editor/components/dragonbones/layer.png differ
diff --git a/versions/4.0/en/editor/components/dragonbones/properties.png b/versions/4.0/en/editor/components/dragonbones/properties.png
new file mode 100644
index 0000000000..a0152ad984
Binary files /dev/null and b/versions/4.0/en/editor/components/dragonbones/properties.png differ
diff --git a/versions/4.0/en/editor/components/layer-gizmo.png b/versions/4.0/en/editor/components/layer-gizmo.png
new file mode 100644
index 0000000000..68e8fae78c
Binary files /dev/null and b/versions/4.0/en/editor/components/layer-gizmo.png differ
diff --git a/versions/4.0/en/editor/components/motion-streak.md b/versions/4.0/en/editor/components/motion-streak.md
new file mode 100644
index 0000000000..760561bcd0
--- /dev/null
+++ b/versions/4.0/en/editor/components/motion-streak.md
@@ -0,0 +1,26 @@
+# MotionStreak Component Reference
+
+MotionStreak is used to implement a streak effect on the motion track of a game object.
+
+
+
+Click the **Add Component** button at the bottom of the **Inspector** panel and select **MotionStreak** from **Effects** to add the MotionStreak component to the node.
+
+For details on how to use it, please refer to the [MotionStreak](https://github.com/cocos/cocos-test-projects/tree/v3.8/assets/cases/ui/24.motion-streak) example.
+
+
+
+For script interfaces of MotionStreak, please refer to [MotionStreak API](%__APIDOC__%/en/class/MotionStreak).
+
+## MotionStreak Properties
+
+| Property | Description
+| :-------------- | :----------- |
+| CustomMaterial | Custom Material, please refer to the [Custom Material](./../../ui-system/components/engine/ui-material.md) documentation for usage. |
+| Preview | Whether to enable preview. If this option is enabled, the MotionStreak effect can be previewed in the **Scene** panel. |
+| FadeTime | The fade time in seconds of the segment. |
+| MinSeg | The minimum segment length (the size of the fading segment). |
+| Stroke | The width of the MotionStreak. |
+| Texture | The texture of the MotionStreak. |
+| FastMode | Whether to enable the fast mode. When fast mode is enabled, new vertices will be added faster, but with less precision. |
+| Color | The color of the MotionStreak. |
diff --git a/versions/4.0/en/editor/components/motion-streak/add-motion-streak.png b/versions/4.0/en/editor/components/motion-streak/add-motion-streak.png
new file mode 100644
index 0000000000..1571e733ee
Binary files /dev/null and b/versions/4.0/en/editor/components/motion-streak/add-motion-streak.png differ
diff --git a/versions/4.0/en/editor/components/motion-streak/motionstreak.png b/versions/4.0/en/editor/components/motion-streak/motionstreak.png
new file mode 100644
index 0000000000..eb120c85ed
Binary files /dev/null and b/versions/4.0/en/editor/components/motion-streak/motionstreak.png differ
diff --git a/versions/4.0/en/editor/components/spine.md b/versions/4.0/en/editor/components/spine.md
new file mode 100644
index 0000000000..acb07fe342
--- /dev/null
+++ b/versions/4.0/en/editor/components/spine.md
@@ -0,0 +1,290 @@
+# Spine Skeletal Component References
+
+The Spine Skeleton components support the data format exported by the official Spine tools, and renders and plays Spine assets.
+
+
+
+Select the node and choose **Add Component -> Spine -> Skeleton** on the **Inspector** panel to add the Skeleton component to the node.
+
+- For information on using the Spine Skeleton component, please refer to the [Spine Skeleton example case](https://github.com/cocos/cocos-test-projects/tree/v3.8/assets/cases/middleware/spine) for details.
+- For Spine Skeleton component related scripting interfaces, please refer to the [Spine Skeleton API](%__APIDOC__%/en/class/Skeleton) for details.
+
+## Spine Properties
+
+| Property | Description
+| :-------------------- | :----------------- |
+| CustomMaterial | Custom materials that can be used to achieve rendering effects such as dissolve, external glow, etc. Please refer to the [Custom Materials](../../ui-system/components/engine/ui-material.md) documentation for details.
+| Color | Set the skeleton animation color.
+| SkeletonData | Skeleton information data, drag and drop the skeleton assets exported from Spine. into this property
+| Default Skin | Select the default skin.
+| Animation | The name of the currently playing animation.
+| Animation Cache Mode | Rendering mode, the default is **REALTIME** mode. 1. **REALTIME** mode, real-time computing, supports all Spine features. 2. **SHARED_CACHE** mode, caches, and shares skeletal animations and texture data, equivalent to pre-baked skeletal animations. **SHARED_CACHE** mode has higher performance, but does not support motion fusion, motion overlay, and only supports motion start and end events. As for memory, when creating N (N>=3) animations with the same skeleton and the same action, the memory advantage is obvious. In summary, **SHARED_CACHE** mode is suitable for scene animations, effects, replica monsters, NPCs, etc., and can greatly improve frame rates and reduce memory consumption. 3. **PRIVATE_CACHE** mode, similar to **SHARED_CACHE**, but does not share animation and texture data, and will occupy extra memory, there is only a performance advantage, and it may cause stutter if using this mode a lot to play animation. Use **PRIVATE_CACHE** to take advantage of the high performance of the cache mode and to also implement texture replacement (which cannot share the texture data).
+| Loop | Whether to loop the current animation.
+| Premultiplied Alpha | Whether to enable premultiplied alpha for the image, default is True. This item needs to be disabled when the transparent area of the image appears as a color block, and enabled when the translucent area of the image turns black.
+| Time Scale | The time scale of all animations in the current skeleton.
+| Debug Slots | Whether to show debug information of slots.
+| Debug Bones | Whether to show debug information of skeletons.
+| Debug Mesh | Whether to show debug information of mesh.
+| Use Tint | Whether to turn on the tinting effect, off by default.
+| Sockets | Used to attach certain external nodes to the specified skeleton joints. The value of the property indicates the number of attachment points. For details, please refer to the description below.
+| Enable Batch | Whether to enable Spine batching |
+
+> **Notes**:
+> 1. The `Anchor` and `Size` properties on the Node component in the **Inspector** panel are invalid when using the Skeleton component.
+> 2. The Spine Skeletal component is a UI renderable component, and the `Canvas` node is the rendering root for UI rendering, the node with this component must be a child of the `Canvas` node (or a node with a `RenderRoot2D` component) to be displayed properly in the scene.
+> 3. When using the Spine Skeleton component, since it has the `UseTint` property, its custom material needs to have two color information, otherwise the Spine staining effect may be wrong. Please refer to the [builtin-spine.effect](https://github.com/cocos/cocos-engine/blob/v3.0.0/editor/assets/effects/builtin-spine.effect) example to achieve this.
+
+## Spine ReplaceTexture
+
+Here is an example of how Spine replaces the texture.
+
+
+
+1. First, create a new `Canvas` node in the **Hierarchy** panel, and then create a new empty node and name it to `girl` under the `Canvas` node. Select the `girl` node and add the Skeleton component in the **Inspector** panel, drag and drop the asset into the `SkeletonData` property box of the Skeleton component. The `Animation` property of the Skeleton component can be changed to set the animation that the developer wants to play.
+
+ 
+
+2. Create a new TypeScript script and name it `SpineSkin` in the **Assets** panel to write the component's script. The script code is as follows:
+
+ ```ts
+ import { _decorator, Component, sp } from 'cc';
+ const { ccclass, property } = _decorator;
+
+ @ccclass('SpineSkin')
+ export class SpineSkin extends Component {
+
+
+ @property({ type:sp.Skeleton })
+ spine: sp.Skeleton | null = null;
+
+ skinId: number = 0;
+
+ start () {
+ // Your initialization goes here.
+ sp.Skeleton }
+
+ change() {
+ const skins = ['girl', 'boy', 'girl-blue-cape', 'girl-spring-dress'].map(x=> `full-skins/${x}`);
+ this.skinId = (this.skinId + 1) % skins.length;
+ this.skin!.setSkin(skins[this.skinId]);
+ }
+
+ // update (deltaTime: number) {
+ // // Your update function goes here.
+ // }
+ }
+ ```
+
+3. Next, attach the `SpineSkin` script to the `Canvas` node, i.e. drag and drop the script into the **Inspector** panel of the `Canvas` node. Drag and drop the `girl` node in the **Assets** panel into the property boxes corresponding to the `SpineSkin` script component and save the scene.
+
+ 
+
+4. Next, use the Button component's click event to trigger the `change` callback in the `SpineSkin` script to replace the texture by clicking the button.
+
+ Create a new Button node under the `Canvas` node in the **Assets** panel and name it `change_skin`. Adjust its position, size, text display, and other properties as needed.
+
+ Set the click event of the `change_skin` node in the **Inspector** panel, drag the `Canvas` node attached with the `SpineSkin` script component into the `cc.Node` property box of the `ClickEvents` property, specify script component as `SpineSkin`, and set the callback to `change`.
+
+ 
+
+5. Adjust the scene structure as needed, save the scene and click the **Preview** button at the top of the editor. Click the **change skin** button to see that the character skin has been replaced.
+
+ 
+
+ > **Note**: if the scene is not displayed when previewing, check that the `Layer` property of each node is consistent with that of the `Camera` node.
+ >
+ > 
+
+## Spine Vertex Effect
+
+The vertex effect is only available when Spine's `Animation Cache Mode` is in the **REALTIME** mode. Here is an example of how to set the vertex effect in Spine.
+
+1. First, create a new `Canvas` node in the **Hierarchy** panel, and then create a new empty node under the `Canvas` node. Select the node and add the Skeleton component in the **Inspector** panel, drag and drop the asset to the `SkeletonData` property box of the Skeleton component, and set the Skeleton component properties.
+
+2. Create a new TypeScript script in the **Assets** panel and name it `SpineExample`, write the component script. The script code is as follows:
+
+ ```ts
+ import { _decorator, Component, sp } from 'cc';
+ const { ccclass, property } = _decorator;
+
+ @ccclass('SpineExample')
+ export class SpineExample extends Component {
+
+ @property({ type:sp.Skeleton })
+ skeleton: sp.Skeleton | null = null;
+
+ private _jitterEffect?:sp.VertexEffectDelegate;
+
+ start () {
+ this._jitterEffect = new sp.VertexEffectDelegate();
+ // Set the jitter parameters.
+ this._jitterEffect.initJitter(20, 20);
+ // Call the 'setVertexEffectDelegate' method of the Skeleton component to set the effect.
+ this.skeleton!.setVertexEffectDelegate(this._jitterEffect!);
+ }
+
+ };
+ ```
+
+3. Next, attach the `SpineExample` script to the `Canvas` node, i.e. drag and drop the script into the node's **Inspector** panel. Drag the `Spine` node with the **Skeleton** component attached in the **Hierarchy** panel to the corresponding `Skeleton` property box of the script component, and save the scene.
+
+4. Click the **Preview** button at the top of the editor to see the effect of vertex jitter of the Spine animation. For example, please refer to the [SpineMesh](https://github.com/cocos/cocos-test-projects/tree/v3.8/assets/cases/middleware/spine) example.
+
+## Spine Attachment
+
+When using skeleton animation, nodes are often attached on a certain part of the skeleton animation to achieve the effect of linkage between the nodes and the skeleton animation.
+
+Spine Attachments can be implemented by using both editor and script. Here is an example of how Spine uses an attachment to attach a star to the dragon's tail, and shake it with the dragon's tail.
+
+
+
+### Implementing via the editor
+
+1. First, create a new `Canvas` node in the **Hierarchy** panel, and then create a new empty node and name it to `Spine` under the `Canvas` node. Select `Spine` and add the **Skeleton** component to the **Inspector** panel. Drag and drop the asset into the `SkeletonData` property box of the **Skeleton** component and set the Skeleton component properties.
+
+2. Second, right-click on the Spine node in the **Hierarchy** panel and select **Create -> Empty Node** to add a child node for it and name it `targetNode`. **Create -> 2D Object -> Sprite** to add a sprite component named `star` under `targetNode`. Drag the star asset to the **SpriteFrame** property of the Sprite component in the **Inspector** panel.
+
+ 
+
+3. Select the Spine node in the **Hierarchy** panel, and set the Skeleton component's `Sockets` property to **1** in the **Inspector** panel (the value of the `Sockets` property represents the number of attachments).
+
+ 
+
+4. Next, set the **Path** and **Target** properties of the **Sockets**. The **Path** drop-down box will list all the skeletons, select the target bone you want to attach, here take the dragon's tail as an example, drag the `targetNode` node to the **Target** property box. Notice the star attached on the dragon's tail in the **Scene** panel.
+
+ > **Note**:Do not set the `star` node as **Target** node, because this will make UITransform of `star` invalid. Please create a new empty node as the **Target** node and set components which to be attached as children nodes of **Target ** node.
+
+ 
+
+5. Finally, save the scene and click the **Preview** button on top of the editor to see the star hanging on the dragon's tail and swaying along with it. Please refer to the [SpineAttach](https://github.com/cocos/cocos-test-projects/tree/v3.8/assets/cases/middleware/spine) example for details.
+
+### Implementing via code
+
+1. The first two steps are the same as those implemented via the editor.
+
+2. Create a new TypeScript script in the Explorer panel and name it `SpineAttach`. Write the component script. The script code is as follows:
+
+ ```ts
+ import { _decorator, Component, sp, Label, Node } from 'cc';
+ const { ccclass, property } = _decorator;
+
+ @ccclass('SpineAttach')
+ export class SpineAttach extends Component {
+
+ @property({ type: sp.Skeleton })
+ skeleton: sp.Skeleton = null!;
+
+ @property({ type: Node })
+ attachNode: Node = null!;
+
+ start () {
+ var socket = new sp.SpineSocket("root/hip/tail1/tail2/tail3/tail4/tail5/tail6/tail7/tail8/tail9/tail10", this.attachNode); // The first incoming parameter is the target bone of the attachment, and the second incoming parameter is the node of the attachment.
+ this.skeleton!.sockets.push(socket);
+ this.skeleton!.sockets = this.skeleton!.sockets;
+ }
+
+ }
+ ```
+
+ If the name of the target bone is unknown, set the `Sockets` property in the Skeleton component to **1** and then look for the name of the desired target bone in the `Path` drop-down box. When the search is complete, restore the `Sockets` property to 0.
+
+3. Next, attach the `SpineAttach` script to the `Canvas` node, i.e. drag and drop the script into the node's **Inspector** panel. Drag and drop the `Spine` node with the Skeleton component attached and the `targetNode` node in the **Hierarchy** panel to the **Skeleton** property box and the **AttachNode** property box of the script component, respectively, and save the scene.
+
+4. Click the **Preview** button at the top of the editor to see the star hanging from the dragon's tail and shaking along with the dragon's tail.
+
+ 
+
+## Spine Collision Detection
+
+The Spine attachment function allows for the detection of a collision of a part of the skeleton animation. The following is an example of how Spine implements collision detection, by determining whether the character's feet are in contact with the ground or not to dynamically change the ground color when the character is running.
+
+
+
+1. First, set the **2D Physics System** to **Builtin 2D Physics System** in the **Project -> Project Settings -> Feature Cropping** of the editor menu bar.
+
+ 
+
+2. Create the Spine node and its children (an empty node and named `frontFoot`), as well as the Sprite node as the ground (named `Ground`), and set the position, size, and other properties, as in the first two steps for the Spine attachment.
+
+ 
+
+3. Select the `frontFoot` node in the **Hierarchy** panel, click **Add Component -> Physics2D -> Colliders -> Polygon Collider2D** in the **Inspector** panel to add a collision component, and set the collision component parameters.
+
+ 
+
+ Referring to steps 3 and 4 of the Spine attachment, attach the `frontFoot` node to the target bone ("foot" for example) of the Sprite node. The `frontFoot` node will then move along with the skeletal animation, and thus the collision component's bounding box will be synchronized with the skeletal animation in real time.
+
+ 
+
+4. Select the `Ground` node in the **Hierarchy** panel, click **Add Component -> Physics2D -> Colliders -> BoxCollider2D** in the **Inspector** panel to add a collision component, and set the collision component parameters.
+
+5. Create a new TypeScript script in the **Assets** panel and name it `SpineCollider`. Then attach the script on the `Ground` node. The script code is as follows:
+
+ ```ts
+ import { _decorator, Component, Node, PhysicsSystem2D, Contact2DType, Collider2D, Color, Sprite, ParticleSystem2D, EPhysics2DDrawFlags } from 'cc';
+ const { ccclass } = _decorator;
+
+ @ccclass('SpineCollider')
+ export class SpineCollider extends Component {
+
+ touchingCountMap : Map < Node, number > = new Map;
+
+ private debugDrawFlags : number = 0;
+
+ start () {
+ // Your initialization goes here.
+ PhysicsSystem2D.instance.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
+ PhysicsSystem2D.instance.on(Contact2DType.END_CONTACT, this.onEndContact, this);
+ this.debugDrawFlags = PhysicsSystem2D.instance.debugDrawFlags;
+ }
+
+ onEnable () {
+ PhysicsSystem2D.instance.debugDrawFlags = this.debugDrawFlags | EPhysics2DDrawFlags.Shape;
+ }
+
+ onDisable () {
+ PhysicsSystem2D.instance.debugDrawFlags = this.debugDrawFlags;
+ }
+
+ addContact (c: Collider2D) {
+ let count = this.touchingCountMap.get(c.node) || 0;
+ this.touchingCountMap.set(c.node, ++count);
+
+ let sprite = c.getComponent(Sprite);
+ if (sprite) {
+ sprite.color = Color.RED;
+ }
+ }
+
+ removeContact (c: Collider2D) {
+ let count = this.touchingCountMap.get(c.node) || 0;
+ --count;
+ if (count <= 0) {
+ this.touchingCountMap.delete(c.node);
+
+ let sprite = c.getComponent(Sprite);
+ if (sprite) {
+ sprite.color = Color.WHITE;
+ }
+ } else {
+ this.touchingCountMap.set(c.node, count);
+ }
+ }
+
+ onBeginContact (a: Collider2D, b: Collider2D) {
+ this.addContact(a);
+ this.addContact(b);
+ }
+
+ onEndContact (a: Collider2D, b: Collider2D) {
+ this.removeContact(a);
+ this.removeContact(b);
+ }
+ }
+ ```
+
+6. Click the **Preview** button at the top of the editor to see the effect. For details, please refer to the [SpineCollider](https://github.com/cocos/cocos-test-projects/tree/v3.8/assets/cases/middleware/spine) example.
+
+ > **Note**: the collision detection based on attachment has a delay of one frame due to the implementation mechanism of the attachment.
+
+ 
diff --git a/versions/4.0/en/editor/components/spine/attach-ts.gif b/versions/4.0/en/editor/components/spine/attach-ts.gif
new file mode 100644
index 0000000000..db5f5465d5
Binary files /dev/null and b/versions/4.0/en/editor/components/spine/attach-ts.gif differ
diff --git a/versions/4.0/en/editor/components/spine/attach0.png b/versions/4.0/en/editor/components/spine/attach0.png
new file mode 100644
index 0000000000..8ac5c2e1be
Binary files /dev/null and b/versions/4.0/en/editor/components/spine/attach0.png differ
diff --git a/versions/4.0/en/editor/components/spine/attach1.png b/versions/4.0/en/editor/components/spine/attach1.png
new file mode 100644
index 0000000000..f41869a0eb
Binary files /dev/null and b/versions/4.0/en/editor/components/spine/attach1.png differ
diff --git a/versions/4.0/en/editor/components/spine/attach2.png b/versions/4.0/en/editor/components/spine/attach2.png
new file mode 100644
index 0000000000..39c82fd585
Binary files /dev/null and b/versions/4.0/en/editor/components/spine/attach2.png differ
diff --git a/versions/4.0/en/editor/components/spine/attach3.png b/versions/4.0/en/editor/components/spine/attach3.png
new file mode 100644
index 0000000000..0c3d444319
Binary files /dev/null and b/versions/4.0/en/editor/components/spine/attach3.png differ
diff --git a/versions/4.0/en/editor/components/spine/click_event.png b/versions/4.0/en/editor/components/spine/click_event.png
new file mode 100644
index 0000000000..9033d779e0
Binary files /dev/null and b/versions/4.0/en/editor/components/spine/click_event.png differ
diff --git a/versions/4.0/en/editor/components/spine/cloth0.png b/versions/4.0/en/editor/components/spine/cloth0.png
new file mode 100644
index 0000000000..cee994f916
Binary files /dev/null and b/versions/4.0/en/editor/components/spine/cloth0.png differ
diff --git a/versions/4.0/en/editor/components/spine/cloth1.png b/versions/4.0/en/editor/components/spine/cloth1.png
new file mode 100644
index 0000000000..dd6072b16e
Binary files /dev/null and b/versions/4.0/en/editor/components/spine/cloth1.png differ
diff --git a/versions/4.0/en/editor/components/spine/cloth2.png b/versions/4.0/en/editor/components/spine/cloth2.png
new file mode 100644
index 0000000000..6d763ae0ae
Binary files /dev/null and b/versions/4.0/en/editor/components/spine/cloth2.png differ
diff --git a/versions/4.0/en/editor/components/spine/collider.gif b/versions/4.0/en/editor/components/spine/collider.gif
new file mode 100644
index 0000000000..5e5f1c7781
Binary files /dev/null and b/versions/4.0/en/editor/components/spine/collider.gif differ
diff --git a/versions/4.0/en/editor/components/spine/collider0.png b/versions/4.0/en/editor/components/spine/collider0.png
new file mode 100644
index 0000000000..c97db18065
Binary files /dev/null and b/versions/4.0/en/editor/components/spine/collider0.png differ
diff --git a/versions/4.0/en/editor/components/spine/collider1.png b/versions/4.0/en/editor/components/spine/collider1.png
new file mode 100644
index 0000000000..b6f6d58007
Binary files /dev/null and b/versions/4.0/en/editor/components/spine/collider1.png differ
diff --git a/versions/4.0/en/editor/components/spine/collider2.png b/versions/4.0/en/editor/components/spine/collider2.png
new file mode 100644
index 0000000000..a284c0a2e0
Binary files /dev/null and b/versions/4.0/en/editor/components/spine/collider2.png differ
diff --git a/versions/4.0/en/editor/components/spine/collider3.png b/versions/4.0/en/editor/components/spine/collider3.png
new file mode 100644
index 0000000000..3afbd503c3
Binary files /dev/null and b/versions/4.0/en/editor/components/spine/collider3.png differ
diff --git a/versions/4.0/en/editor/components/spine/collider4.png b/versions/4.0/en/editor/components/spine/collider4.png
new file mode 100644
index 0000000000..5dccdfc5c4
Binary files /dev/null and b/versions/4.0/en/editor/components/spine/collider4.png differ
diff --git a/versions/4.0/en/editor/components/spine/layer.png b/versions/4.0/en/editor/components/spine/layer.png
new file mode 100644
index 0000000000..f77f10b251
Binary files /dev/null and b/versions/4.0/en/editor/components/spine/layer.png differ
diff --git a/versions/4.0/en/editor/components/spine/spine-jscom.png b/versions/4.0/en/editor/components/spine/spine-jscom.png
new file mode 100644
index 0000000000..f8b6f69f89
Binary files /dev/null and b/versions/4.0/en/editor/components/spine/spine-jscom.png differ
diff --git a/versions/4.0/en/editor/components/spine/spine-properties.png b/versions/4.0/en/editor/components/spine/spine-properties.png
new file mode 100644
index 0000000000..b2e914ef6b
Binary files /dev/null and b/versions/4.0/en/editor/components/spine/spine-properties.png differ
diff --git a/versions/4.0/en/editor/components/tiledmap.md b/versions/4.0/en/editor/components/tiledmap.md
new file mode 100644
index 0000000000..71b7d00726
--- /dev/null
+++ b/versions/4.0/en/editor/components/tiledmap.md
@@ -0,0 +1,85 @@
+# TiledMap Component References
+
+TiledMap is used to display a map in TMX format in the game.
+
+
+
+Click the **Add Component -> Components -> TiledMap** button under the **Inspector** panel to add the TiledMap component to the node.
+
+
+
+For the script interface of TiledMap, please refer to the [TiledMap API](%__APIDOC__%/en/class/TiledMap).
+
+## TiledMap Properties
+
+| Property | Description
+| :---------------- | :----------------- |
+| **Tmx Asset** | Specifies a map asset in `.tmx` format (Ensure the `.tmx` and `.tsx` are in the same folder)|
+| **EnableCulling** | Enables culling, which needs to be turned off if the map needs to be rotated or placed in the 3D camera. If the map is not very large, e.g., less than 5000 blocks, then turning off culling reduces the CPU computational load and the GPU renders directly using the cache.
+
+## Detailed Description
+
+- After adding the TiledMap component, drag and drop a map asset in **.tmx** format from the **Assets** panel to the Tmx Asset property to see the map displayed in the scene.
+- When the Tmx Asset property is added to the TiledMap component, nodes corresponding to the Layers in the map are automatically added to the nodes (floor, barrier, and players nodes in the image below). These nodes are added to the TiledLayer component. **Do not delete the TiledLayer component from these Layer nodes**.
+
+ 
+
+- TiledMap component does not support the `mapLoaded` callback. It can be used normally in the `start` function.
+
+## TiledLayer and Node Occlusion
+
+The TiledLayer component converts the node coordinates added to the map layer into map block row coordinates. When rendering a map block in a map layer in row order, if there is a node in the row of the map block, then rendering of the map block will be interrupted in favor of rendering the node. After the nodes in the map block are rendered, the rendering of the map block will continue. In this way, the nodes and map layers are mutually occluded from each other.
+
+> **Note**: this occlusion relationship is only related to the coordinates of the node, not the size of the node.
+
+The following is an example of how the TiledLayer and the node can occlude each other.
+
+1. Create a new node in the scene and add the TiledMap component. After setting the properties of the TiledMap component, the node with the TiledLayer component (i.e. map layer) will be generated automatically.
+
+2. Create [Prefab](../../asset/prefab.md)s to instantiate multiple nodes in the scene.
+
+3. Create a new TypeScript script in **Assets** panel to write component scripts. The script code is as follows:
+
+ ```ts
+ import { _decorator, Component, Node, TiledLayer, loader, Prefab, v2, instantiate, Vec3, EventTouch } from 'cc';
+ const { ccclass, property } = _decorator;
+
+ @ccclass('ShieldNode')
+ export class ShieldNode extends Component {
+
+ @property({ type: TiledLayer })
+ public tiledLayer: TiledLayer | null = null;
+
+ @property({ type: Prefab })
+ public nodePrefab: Prefab | null = null;
+
+ start () {
+ this.initScene(this.nodePrefab!);
+ }
+
+ initScene (prefab: Prefab) {
+ const posArr = [v2(-249, 96), v2(-150, 76), v2(-60, 54), v2(-248, -144), v2(-89, -34)];
+ const tmpP = new Vec3();
+ for (let i = 0; i < posArr.length; i++) {
+ const shieldNode = instantiate(prefab);
+ shieldNode.setPosition(posArr[i].x, posArr[i].y);
+ this.tiledLayer!.addUserNode(shieldNode);
+ shieldNode.on(Node.EventType.TOUCH_MOVE, (event:EventTouch) => {
+ const deltaMove = event.getDelta();
+ shieldNode.getPosition(tmpP);
+ tmpP.x += deltaMove.x;
+ tmpP.y += deltaMove.y;
+ shieldNode.setPosition(tmpP);
+ });
+ }
+ }
+ }
+ ```
+
+4. Attach the script component to the Canvas node, i.e. drag and drop the script into the **Inspector** panel of the Canvas node. Then drag and drop the automatically generated node with TiledLayer component from **Hierarchy** panel and the Prefabs from **Assets** panel to the corresponding property box of the script component, and then save the scene.
+
+5. Click the Preview button at the top of the editor to see the effect of the nodes and map layers occluding each other. For the code, please refer to the [ShieldNode](https://github.com/cocos/cocos-test-projects/tree/v3.8/assets/cases/middleware/tiled-map) example.
+
+ 
+
+To remove a node from a map layer, call the `removeUserNode` method of TiledLayer.
diff --git a/versions/4.0/en/editor/components/tiledmap/add_tiledmap.png b/versions/4.0/en/editor/components/tiledmap/add_tiledmap.png
new file mode 100644
index 0000000000..89b32df536
Binary files /dev/null and b/versions/4.0/en/editor/components/tiledmap/add_tiledmap.png differ
diff --git a/versions/4.0/en/editor/components/tiledmap/shieldNode.png b/versions/4.0/en/editor/components/tiledmap/shieldNode.png
new file mode 100644
index 0000000000..9ed5de9157
Binary files /dev/null and b/versions/4.0/en/editor/components/tiledmap/shieldNode.png differ
diff --git a/versions/4.0/en/editor/components/tiledmap/tiledlayer.png b/versions/4.0/en/editor/components/tiledmap/tiledlayer.png
new file mode 100644
index 0000000000..293588271c
Binary files /dev/null and b/versions/4.0/en/editor/components/tiledmap/tiledlayer.png differ
diff --git a/versions/4.0/en/editor/components/tiledmap/tiledmap-component.png b/versions/4.0/en/editor/components/tiledmap/tiledmap-component.png
new file mode 100644
index 0000000000..2539041575
Binary files /dev/null and b/versions/4.0/en/editor/components/tiledmap/tiledmap-component.png differ
diff --git a/versions/4.0/en/editor/components/tiledtile.md b/versions/4.0/en/editor/components/tiledtile.md
new file mode 100644
index 0000000000..6ab931e2a4
--- /dev/null
+++ b/versions/4.0/en/editor/components/tiledtile.md
@@ -0,0 +1,62 @@
+# TiledTile Component References
+
+The TiledTile component can operate on a particular map block individually.
+
+
+
+## Creation Method
+
+### Create via Editor
+
+Create an empty node under the Layer node **automatically generated** during the creation of the [TiledMap component](tiledmap.md). Then select the empty node and click **Add component -> TiledMap -> TiledTile** under the **Inspector** panel to add the TiledTile component to the node. Then you can manipulate the map block by setting the properties on the TiledTile component.
+
+
+
+For related TiledTile script interface, please refer to the [TiledTile API](%__APIDOC__%/en/class/TiledTile).
+
+### Create by Code
+
+There are two ways to set up a map block in code. When setting the TiledTile in a Layer node, the TiledTile at the original location of that Layer node will be replaced.
+
+#### Create by adding a TiledTile Ccmponent to a node
+
+```ts
+// Create a new node
+const node = new Node();
+// then set the node's parent to any layer node
+node.parent = this.layer.node;
+// Finally add the TiledTile component to the node and return the TiledTile object, which allows you to perform a series of operations on the TiledTile object
+const tiledTile = node.addComponent(TiledTile);
+```
+
+#### Get TiledTile by getTiledTileAt
+
+```ts
+// Get the TiledTile object on the layer with horizontal coordinates of 0 and vertical coordinates of 0. You can then perform a series of operations on the TiledTile object
+const tiledTile = this.layer.getTiledTileAt(0, 0);
+```
+
+For the Layer script interface, please refer to the [TiledLayer API](%__APIDOC__%/en/class/TiledLayer).
+
+## TiledTile Properties
+
+| Property | Description
+| :-----| :---------- |
+| **X** | Specifies the horizontal coordinates of the TiledTile, in map blocks
+| **Y** | Specifies the vertical coordinates of the TiledTile, in map blocks
+| **Gid** | Specifies the gid value of the TiledTile to toggle the style of the TiledTile
+
+TiledTile can control the specified map block and apply the displacement, rotation and scaling of nodes to the map block. The user can change the map block style by changing the gid property of the TiledTile.
+
+> **Note**: the gid can only be used with an existing map block in the map to toggle the style of the map block, it is not possible to toggle the style of the map block by customizing the Sprite Frame.
+
+## Node properties that can be applied to TiledTile
+
+| Property | Description
+| :-----| :---------- |
+| **Position** | Change the **Position** of the specified TiledTile
+| **Rotation** | **Rotate** the specified TiledTile
+| **Scale** | **Scale** the specified TiledTile
+| **Color** | Change the **Color** of the specified TiledTile
+| **Opacity** | Adjust the **Opacity** of the specified TiledTile
+| **Skew** | Adjust the **Skew** of the specified TiledTile
diff --git a/versions/4.0/en/editor/components/tiledtile/add_tiledtile.png b/versions/4.0/en/editor/components/tiledtile/add_tiledtile.png
new file mode 100644
index 0000000000..c90a45a63e
Binary files /dev/null and b/versions/4.0/en/editor/components/tiledtile/add_tiledtile.png differ
diff --git a/versions/4.0/en/editor/components/tiledtile/tiledtile-component.png b/versions/4.0/en/editor/components/tiledtile/tiledtile-component.png
new file mode 100644
index 0000000000..bab5fc2276
Binary files /dev/null and b/versions/4.0/en/editor/components/tiledtile/tiledtile-component.png differ
diff --git a/versions/4.0/en/editor/console/index.md b/versions/4.0/en/editor/console/index.md
new file mode 100644
index 0000000000..181bba73d1
--- /dev/null
+++ b/versions/4.0/en/editor/console/index.md
@@ -0,0 +1,84 @@
+# Console
+
+
+
+**Console** outputs editor or engine messages, including **log**, **warn**, and **error**. Different types of messages are displayed in different colors.
+
+- `console.log()`: outputs log, gray text, usually used to show what action is in progress.
+
+ 
+
+- `console.warn()`: outputs warnings, yellow text, used to indicate exceptions that the developer would be wise to handle, but which will not affect operation if left unhandled.
+
+ 
+
+- `console.error()`: outputs error, red text, indicating a serious error that must be resolved before proceeding to the next step or running the game.
+
+ 
+
+## Panel operations
+
+The top toolbar functions, in order, are:
+
+- Clear all logs in the current console
+- Enter text for fuzzy search
+- Whether to convert the input text to regular for searching
+- Select the type of logs to be displayed
+- Open the log file backed up on disk, which will be reset each time the editor is started.
+
+ 
+
+## Parameter settings
+
+Some parameters of the console can be configured in **Preferences -> Console**, including whether to display the date and adjust the text size.
+
+
+
+## Custom output messages
+
+To make it easier to locate files, nodes or assets, or to provide links to jump to help documentation, etc., Cocos Creator supports custom output to the **console** log in **Developer -> Developer Tools** in the editor's main menu, which currently supports output of the following:
+
+- Jump to links by URL
+- Show images by URL
+- Locate assets by URL or UUID
+- Locate nodes by UUID
+- Locate script files by disk file path
+- Output the text in the corresponding language
+
+### Data format
+
+Depending on the output content, the input data formats include the following two:
+
+- `{type[text](url)}`
+- `{type(text | url | uuid | path)}`
+
+The data formats are described as follows:
+
+- Matches the characters in `{}` as a whole.
+- `[text]`: Text of the jump link, optional.
+- `type`: The type of information to be output, including the following. The filling is case-insensitive, and if not fill in, the input is directly output without format.
+
+ - `link`: external jump link
+ - `image`: display image
+ - `asset`: locate to a asset
+ - `node`: locate to a node
+ - `i18n`: multilingual translation
+
+### Example
+
+Open **Developer -> Developer Tools** in the editor's main menu, then type:
+
+```sh
+console.log('Open {link[the help doc url](https://docs.cocos.com/creator/manual/en/editor/console/)}');
+console.log('Locate {link[ the file in library](D:/cocos-creator/a/library/36/36b55a90-1547-4695-8105-abd89f8a0e5f.js)}');
+console.log('Locate Node UUID {node(f6zHdGKiZDhqbDizUsp8mK)}');
+console.warn('Locate Asset UUID {asset(17185449-5194-4d6c-83dc-1e785375acdb)}');
+console.error('Locate Asset URL {asset(db://assets/animation.anim)}');
+console.log('The URL is {asset[{asset(db://assets/animation.anim)}](db://assets/animation.anim)}');
+console.log('Show image {image(https://forum.cocos.org/images/logo.png)}');
+console.log('Translate: {i18n(console.description)}');
+```
+
+The output log can be seen in the **Console** panel as follows:
+
+
diff --git a/versions/4.0/en/editor/console/index/content.png b/versions/4.0/en/editor/console/index/content.png
new file mode 100644
index 0000000000..49e97861a2
Binary files /dev/null and b/versions/4.0/en/editor/console/index/content.png differ
diff --git a/versions/4.0/en/editor/console/index/error.png b/versions/4.0/en/editor/console/index/error.png
new file mode 100644
index 0000000000..b6db81ad83
Binary files /dev/null and b/versions/4.0/en/editor/console/index/error.png differ
diff --git a/versions/4.0/en/editor/console/index/index.png b/versions/4.0/en/editor/console/index/index.png
new file mode 100644
index 0000000000..2a81b90704
Binary files /dev/null and b/versions/4.0/en/editor/console/index/index.png differ
diff --git a/versions/4.0/en/editor/console/index/log.png b/versions/4.0/en/editor/console/index/log.png
new file mode 100644
index 0000000000..20dd9ffa23
Binary files /dev/null and b/versions/4.0/en/editor/console/index/log.png differ
diff --git a/versions/4.0/en/editor/console/index/open-log-file.png b/versions/4.0/en/editor/console/index/open-log-file.png
new file mode 100644
index 0000000000..60f2516aa4
Binary files /dev/null and b/versions/4.0/en/editor/console/index/open-log-file.png differ
diff --git a/versions/4.0/en/editor/console/index/preferences.png b/versions/4.0/en/editor/console/index/preferences.png
new file mode 100644
index 0000000000..63b0b12cab
Binary files /dev/null and b/versions/4.0/en/editor/console/index/preferences.png differ
diff --git a/versions/4.0/en/editor/console/index/warn.png b/versions/4.0/en/editor/console/index/warn.png
new file mode 100644
index 0000000000..e2d938337b
Binary files /dev/null and b/versions/4.0/en/editor/console/index/warn.png differ
diff --git a/versions/4.0/en/editor/editor-layout/index.md b/versions/4.0/en/editor/editor-layout/index.md
new file mode 100644
index 0000000000..b9dabf5ef0
--- /dev/null
+++ b/versions/4.0/en/editor/editor-layout/index.md
@@ -0,0 +1,40 @@
+# Editor Layout
+
+Editor layout is the position, size and stacking of each panel in Cocos Creator.
+
+Select the **Cocos Creator/File -> Layout** menu in the main menu, currently only **Default Layout** is supported. Based on the default layout, it is allowed to continue to adjust the position and size of each panel. Changes to the layout are automatically saved in the global directory at:
+
+- **Windows**: `%USERPROFILE%\.CocosCreator\editor\window.json`
+- **macOS**: `$HOME/.CocosCreator/editor/window.json`
+
+## Resizing panel
+
+Hover the mouse over the boundary line between the two panels and see the mouse pointer become , then press the mouse, the boundary line will turn yellow, then drag the mouse to change the size of the two adjacent panels.
+
+
+
+> **Note**: some panels are set to the minimum size, when dragging to the minimum size limit, shrinking the panel cannot continue.
+
+## Moving panel
+
+A panel can be moved to any position in the editor window by clicking the tab bar of the panel and dragging it. The red box in the following figure indicates the area of the tab bar that can be dragged and dropped, and the arrow indicates the dragging direction:
+
+
+
+The blue translucent box during moving the panel indicates the position where the moved panel will be placed after releasing the mouse.
+
+## Stacking Panel
+
+In addition to moving the panel position, it is allowed to move the mouse to the tab bar area of another panel when dragging and dropping the panel tab bar:
+
+
+
+Releasing the mouse when the red vertical line appears in the tab bar of the target panel allows stacking two panels together, while only one panel is displayed:
+
+
+
+Stacking panel is useful when the screen resolution is insufficient, or when laying out less-used panels. Panels in the stack can be dragged out at any time to restore displaying at the top level.
+
+Panels also support pop-up standalone panels or close panel operations by clicking the button at the top right of the panel. However, note that the **Scene** panel does not support pop-up/close.
+
+
diff --git a/versions/4.0/en/editor/editor-layout/index/drag_tab.png b/versions/4.0/en/editor/editor-layout/index/drag_tab.png
new file mode 100644
index 0000000000..17d7800e77
Binary files /dev/null and b/versions/4.0/en/editor/editor-layout/index/drag_tab.png differ
diff --git a/versions/4.0/en/editor/editor-layout/index/mouse-cursor.jpg b/versions/4.0/en/editor/editor-layout/index/mouse-cursor.jpg
new file mode 100644
index 0000000000..df66301fc4
Binary files /dev/null and b/versions/4.0/en/editor/editor-layout/index/mouse-cursor.jpg differ
diff --git a/versions/4.0/en/editor/editor-layout/index/popup.png b/versions/4.0/en/editor/editor-layout/index/popup.png
new file mode 100644
index 0000000000..de83312559
Binary files /dev/null and b/versions/4.0/en/editor/editor-layout/index/popup.png differ
diff --git a/versions/4.0/en/editor/editor-layout/index/resize.png b/versions/4.0/en/editor/editor-layout/index/resize.png
new file mode 100644
index 0000000000..c8a7d9f1f4
Binary files /dev/null and b/versions/4.0/en/editor/editor-layout/index/resize.png differ
diff --git a/versions/4.0/en/editor/editor-layout/index/stack_after.png b/versions/4.0/en/editor/editor-layout/index/stack_after.png
new file mode 100644
index 0000000000..c631652c96
Binary files /dev/null and b/versions/4.0/en/editor/editor-layout/index/stack_after.png differ
diff --git a/versions/4.0/en/editor/editor-layout/index/stack_before.png b/versions/4.0/en/editor/editor-layout/index/stack_before.png
new file mode 100644
index 0000000000..de3d8e49d8
Binary files /dev/null and b/versions/4.0/en/editor/editor-layout/index/stack_before.png differ
diff --git a/versions/4.0/en/editor/extension/basic.md b/versions/4.0/en/editor/extension/basic.md
new file mode 100644
index 0000000000..f2ab9c42db
--- /dev/null
+++ b/versions/4.0/en/editor/extension/basic.md
@@ -0,0 +1,11 @@
+# Basic
+
+Many functions are provided within the editor, here are some of the most commonly used features.
+
+- [Extension Infrastructure](./package.md)
+- [Definition of Extension](./define.md)
+- [Message System](./messages.md)
+- [Multilingual System (i18n)](./i18n.md)
+- [Configuration System](./profile.md)
+- [Extension Panel](./panel.md)
+- [UI Components](./ui.md)
diff --git a/versions/4.0/en/editor/extension/contributions-database.md b/versions/4.0/en/editor/extension/contributions-database.md
new file mode 100644
index 0000000000..871ddc9229
--- /dev/null
+++ b/versions/4.0/en/editor/extension/contributions-database.md
@@ -0,0 +1,86 @@
+# Extending the Database (DB)
+
+All asset files in the project are managed through the asset database, where the `assets` directory in the project stores the assets of the current project, and the `editor/assets` in the engine repository stores the built-in assets of the engine (e.g., common images, scripts, etc.).
+
+When we use the assets in the extension, we need to register the asset folder in the extension to the asset database, and publish the assets with the extension when it is released.
+
+Through this article we will learn how to register a asset folder and use the assets in scripts.
+
+## Registration Database Configuration
+
+Asset registration needs to be configured in `contributions` using the `asset-db` field, as follows.
+
+```json5
+{
+ "name": "test-package",
+ "contributions": {
+ "asset-db": {
+ "mount": {
+ "path": "./assets",
+ "readonly": true
+ }
+ }
+ }
+}
+```
+
+In the above example, we have registered the `assets` folder in the root directory of the extension `test-package` to the asset database.
+
+## Writing Script Resources in Extensions
+
+Create a script `foo.ts` in the `test-package/assets/` directory, with the following content:
+
+```typescript
+/// foo.ts
+import { _decorator, Component, Node } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass('Foo')
+export class Foo extends Component {
+ start () {
+ console.log('foo');
+ }
+}
+```
+
+In order to use the `cc` definitions, we need to copy the definition files from `{project directory}\temp\declarations` to the extension root directory.
+
+Since `foo.ts` is only used as a asset and is not part of the extension source code, we need to exclude it by adding `exclude` configuration to `tsconfig.json`, otherwise we will get a compilation error.
+
+```json5
+{
+ "compilerOptions": {
+ ...
+ },
+ "exclude": ["./assets"]
+}
+```
+
+> **Note**: The script assets in the extension can be written and tested in the Cocos Creator project and then copied to the extension's `assets` directory.
+
+## Other Assets
+
+Assets such as images, text, fonts, etc. can be placed directly in the `assets` directory.
+
+## Using Assets in Extensions
+
+Refresh the extension and you will see a new `test-package` assets package in the **Assets Manager** panel of the Cocos Creator editor, as shown below:s
+
+
+
+## Drag-and-drop Assets
+
+To reference an asset within a package as a drag-and-drop component, use it in the same way as the assets in `assets` and `internal`.
+
+## Import Script
+
+You can simply reference a script file from the AssetDatabase as follows:
+
+```typescript
+/// bar.ts
+import { Foo } from 'db://test-package/foo';
+```
+
+You don't need to pay attention to whether a class comes from an extension package, the TypeScript development environment's auto-completion feature will prompt the **import** directory, no need to worry.
+
+> **Note**: The class name in the extension package should be kept globally unique, otherwise it will cause conflicts, try to add a suitable prefix in the actual development (e.g. `test-package` can be shortened to `TP`, and all classes in the package are unified with the `TP` prefix to become `TPFoo`).
diff --git a/versions/4.0/en/editor/extension/contributions-menu.md b/versions/4.0/en/editor/extension/contributions-menu.md
new file mode 100644
index 0000000000..1c1fe883b1
--- /dev/null
+++ b/versions/4.0/en/editor/extension/contributions-menu.md
@@ -0,0 +1,70 @@
+# Customize the Main Menu
+
+There is a main menu bar at the top of the editor, and it is easy to add your own menu in this menu bar within the extension.
+
+## Registering menus
+
+When an extension needs to add a menu, just fill in the `contributions.menu` object. For example, if we add a menu item to the "Extensions" menu, we can modify `package.json` with the following code example:
+
+```json5
+{
+ // package.json
+ "name": "hello-world",
+ "contributions": {
+ "messages": {
+ "open-panel": {
+ "methods": ["openPanel"]
+ }
+ },
+ "menu": [
+ {
+ "path": "i18n:menu.extension",
+ "label": "Open Hello World",
+ "icon": "./static/icon.png",
+ "message": "open-panel"
+ }
+ ]
+ }
+}
+```
+
+The above configuration information will add a new "Open Hello World" menu in the "Extensions" menu of the editor. Clicking this menu will send an `open-panel` message to the current extension according to the message configuration, which will be triggered if the current extension is configured to listen to this message and the corresponding `openPanel` handler.
+
+For the definition of messages, please refer to the documentation [Customized Messages](./contributions-messages.md).
+
+Let's look at the meaning of the fields in the `menu` object.
+
+### path
+
+type {string} required
+
+The format is: [top existing menu path][/path1][/path2], and the following is reasonable.
+- `i18n:menu.extension` - with the extension menu as the parent menu
+- `i18n:menu.extension/Hello World` - adds a `Hello World` menu item to the extension menu as a parent menu
+- `MyMenu` - Adds a `MyMenu` menu to the top menu bar as a parent menu
+- `MyMenu/Hello World` - adds a `MyMenu` to the top menu bar and adds a `Hello World` menu item as a parent
+
+In the top menu bar, the pre-defined menus are
+- i18n:menu.project - the "Project" menu
+- i18n:menu.node - the "Node" menu
+- i18n:menu.panel - "Panel" menu
+- i18n:menu.extension - "Extensions" menu
+- i18n:menu.develop - "Developers" menu
+
+### label
+
+Type {string} Required
+
+The name of the menu item, supports i18n:key syntax.
+
+### icon
+
+Type {string} Optional
+
+Relative path to the icon of the menu, the material used by the extension is usually placed under a folder named `static`, if it doesn't exist, create a new one.
+
+### message
+
+Type {string} Optional
+
+The message that will be triggered when the menu is clicked, this message needs to be defined in `contributions.messsages` first.
diff --git a/versions/4.0/en/editor/extension/contributions-messages.md b/versions/4.0/en/editor/extension/contributions-messages.md
new file mode 100644
index 0000000000..dc8f1d8c41
--- /dev/null
+++ b/versions/4.0/en/editor/extension/contributions-messages.md
@@ -0,0 +1,83 @@
+# Customized Messages
+
+In the Cocos Creator editor architecture, all interactions are implemented through message communication, and this article will explain how to customize a message.
+
+## View the Public Message List
+
+Find **Developer** -> **Message Manager** in the top menu bar of the editor to open the message management panel, which shows the public messages of each system of the editor and their descriptions.
+
+
+
+
+
+## Define a message
+
+Only messages defined in the `contributions.messages` field of the `package.json` file can be used. The messages are defined as follows.
+
+```json
+{
+ "name": "hello-world",
+ "contributions": {
+ "messages": {
+ "test-messasge": {
+ "public": false,
+ "description": "",
+ "doc": "",
+ "methods": []
+ }
+ }
+ }
+}
+```
+
+`test-messasge` is the name of the message, and we will explain the meaning of each property one by one.
+
+### public
+
+Type `{string}` Optional
+
+Whether to display this message externally, if true, the basic information of this message will be displayed on the message list interface.
+
+### description
+
+Type `{string}` Optional
+
+If public is true, some simple descriptions will be displayed in the message list, supporting `i18n: key` syntax.
+
+### doc
+
+Type `{string}` Optional
+
+If public is true, some documents of this message will be displayed, supporting i18n:key syntax.
+
+This document is written and rendered in markdown format.
+
+### methods
+
+Type `{string[]}` Optional
+
+The method queue triggered by the message.
+
+This is an array of strings. The strings are methods on the extension or panel.
+
+If it is a method on the extension, directly define `methodName`, if you want to trigger a method on the panel, you must fill in `panelName.methodName`. For example, the `ready` method of the scene manager is `scene:ready`.
+
+## Define broadcast message
+
+When developing an extension, you need to send some notifications to other extension after completing an action. If these notifications also need to be displayed on the **Developer -> Message List** panel, you can define the message like this:
+
+```json
+{
+ "name": "hello-world",
+ "contributions": {
+ "messages": {
+ "hello-world:ready": {
+ "public": true,
+ "description": "hello-world ready notification"
+ }
+ }
+ }
+}
+```
+
+For more information, please refer to the document [Message System](./messages.md).
diff --git a/versions/4.0/en/editor/extension/contributions-preferences.md b/versions/4.0/en/editor/extension/contributions-preferences.md
new file mode 100644
index 0000000000..aaf0703323
--- /dev/null
+++ b/versions/4.0/en/editor/extension/contributions-preferences.md
@@ -0,0 +1,128 @@
+# Extending the Preferences Panel
+
+## Preferences Panel Introduction
+
+The **Cocos Creator/File -> Preferences** menu can be found in the top menu bar, as shown in the following image:
+
+
+
+Clicking on it opens the Preferences panel, as shown below.
+
+
+
+The Preferences panel is divided into left and right sides.
+
+- The left side shows the names of the feature extensions that provide configuration items.
+- On the right side is the operation panel rendered according to the configuration.
+
+Changes on the panel are immediately modified to the corresponding configuration items. For more information about the **Preferences** panel, please refer to the document [Preferences](../../editor/preferences/index.md).
+
+## Customization panel
+
+Cocos Creator allows each extension to register its own editor configuration, which is then displayed within the Preferences panel.
+
+The preferences control editor-related configurations and will act on all projects. If you want to add only project-specific configurations, please refer to the documentation [Custom Project Settings Panel](./contributions-project.md).
+
+### Two ways of preference setting
+
+Preference settings allow to display the configuration in two ways.
+
+1. general configuration
+2. Lab configuration
+
+Generic settings are displayed directly as tabs, while lab switches are displayed centrally in a separate tab.
+
+- When the functionality provided by the plug-in is more stable it is recommended to place the configuration data within the generic functionality.
+- When the functions provided by the plug-in are in the development stage it is recommended that the switch configuration data of the function be placed in the lab configuration.
+
+### Preferences definition
+
+Extending preferences depend on data configuration and need to be defined in `contributions.profile.editor` first.
+
+> **Note**: The configuration data in the preferences should be stored in the `profile.editor` field.
+
+Once the data fields are defined, you also need to define the data to be displayed and the UI components to be used to display it in the `contributions.preferences` field. This is shown below.
+
+```JSON5
+{
+ //`package.json`
+ "name": "first-panel",
+ "contributions": {
+ "profile": {
+ "editor": {
+ "foo": {
+ "default": 1,
+ "label":"foo"
+ },
+ "foo1": {
+ "default": 1,
+ "label":"foo1"
+ },
+ "foo2": {
+ "default": false,
+ "label":"foo2"
+ },
+ "foo3": {
+ "default": 0,
+ "label":"foo3"
+ }
+ }
+ },
+ "preferences": {
+ "properties": {
+ "foo1": {
+ "ui": "ui-slider",
+ "attributes": {
+ "min": 0,
+ "max": 1,
+ "step": 0.1
+ }
+ },
+ "foo2": {
+ "ui": "ui-checkbox"
+ },
+ "foo3": {
+ "ui": "ui-select",
+ "items": [
+ {
+ "value": 0,
+ "label": "ITEM 0"
+ },
+ {
+ "value": 1,
+ "label": "ITEM 1"
+ },
+ {
+ "value": 2,
+ "label": "ITEM 2"
+ }
+ ]
+ }
+ },
+ "laboratory": ["foo"]
+ }
+ }
+}
+```
+
+In the above example, 4 data items are defined in the `contributions.profile.project` field: `foo`, `foo1`, `foo2`, `foo3`.
+
+For more information on how to define `profile` related configuration, please refer to [Configuration System](./profile.md).
+
+In the `contributions.preferences` field, we define `properties` and `laboratory`.
+
+### General configuration (properties)
+
+The fields defined in `properties` will be displayed independently in a new tab with the same name as the extension in the preferences panel, as follows:
+
+
+
+### Laboratory configuration (laboratory)
+
+The fields defined in `laboratory` will be displayed in the **Laboratory** tab in the preferences panel, as follows:
+
+
+
+## UI Component Configuration
+
+This example shows the usage of 4 common UI components in customizing the preferences panel, in theory all UI components with `value` attribute can be used in the preferences panel, please refer to the document [UI Components](./ui.md).
diff --git a/versions/4.0/en/editor/extension/contributions-project.md b/versions/4.0/en/editor/extension/contributions-project.md
new file mode 100644
index 0000000000..e4388f2040
--- /dev/null
+++ b/versions/4.0/en/editor/extension/contributions-project.md
@@ -0,0 +1,142 @@
+# Extending Project Settings Panel
+
+## Panel Introduction
+
+**Project Settings** holds the configuration related to the project operation, which is stored in the `settings` folder under the project directory and needs to be included in the version management, so that multiple people can share the configuration, otherwise it may lead to inconsistent operation on different machines.
+
+The **Projects** -> **Projects Settings** menu can be found in the top menu bar, as shown below:
+
+
+
+Click on it to open the settings panel, as shown in the following figure:s
+
+
+
+On the left side of the project settings panel is the function module tab, and on the right side is the configuration modification interface for the corresponding function.
+
+We can add custom configurations to the project by customizing the display data in this panel, and visualize and manage the project configuration with the help of the project settings panel.
+
+If you want to take effect for all projects, you need to customize the editor-related configuration, please refer to the document [Extending the Preferences Panel](./contributions-preferences.md).
+
+The **Custom Item Settings** function allows a we to register multiple tabs, so there will be a small line on the left tab indicating which function the tab belongs to.
+
+## Data Configuration and Display
+
+Custom project settings need to rely on data configuration, you need to define the relevant data fields in `contributions.profile.project` first.
+
+> **Note**: The configuration data in the project settings should be stored in the `profile.project` field.
+
+Once the data fields are defined, you also need to define the data to be displayed and the UI components to be used to display it in the `contributions.project` field. This is shown below.
+
+```json5
+// package.json
+{
+ "name": "project-test",
+ "contributions": {
+ "profile": {
+ "project": {
+ "foo": {
+ "default": 1
+ },
+ "foo1": {
+ "default": 0.4
+ },
+ "foo2": {
+ "default": false
+ },
+ "foo3": {
+ "default": 0
+ },
+ "foo4": {
+ "default": "label"
+ }
+ }
+ },
+ "project": {
+ "tab1": {
+ "label": "test",
+ "content": {
+ "foo": {
+ "ui": "ui-num-input"
+ },
+ "foo1": {
+ "ui": "ui-slider",
+ "attributes": {
+ "min": 0,
+ "max": 1,
+ "step": 0.1
+ }
+ },
+ "foo2": {
+ "ui": "ui-checkbox"
+ },
+ "foo3": {
+ "ui": "ui-select",
+ "items": [
+ {
+ "value": 0,
+ "label": "ITEM 0"
+ },
+ {
+ "value": 1,
+ "label": "ITEM 1"
+ },
+ {
+ "value": 2,
+ "label": "ITEM 2"
+ }
+ ]
+ }
+ }
+ },
+ "tab2": {
+ "label": "test2",
+ "content": {
+ "foo4": {
+ "ui": "ui-input"
+ }
+ },
+ "foo2": {
+ "ui": "ui-checkbox"
+ },
+ "foo3": {
+ "ui": "ui-select",
+ "items": [
+ {
+ "value": 0,
+ "label": "ITEM 0"
+ },
+ {
+ "value": 1,
+ "label": "ITEM 1"
+ },
+ {
+ "value": 2,
+ "label": "ITEM 2"
+ }
+ ]
+ }
+ },
+ "tab1": {
+ "label": "test"
+ }
+ }
+ }
+}
+```
+
+In the above example, 4 data items are defined in the `contributions.profile.project` field: `foo`, `foo1`, `foo2`, `foo3`.
+
+For more information on how to define `profile` related configuration, please refer to [Configuration System](./profile.md).
+
+There are 2 tabs defined in the `contributions.project` field: `test`, `tes2`.
+
+In the `test` tab, each of the 4 data items is configured, see [UI Component Configuration](##UI%20Component%20Configuration) later for the specific configuration properties.
+
+After refreshing the extension in the Extension Manager list, open the **Project Settings Panel** again via the **Project -> Project Settings** menu to see the following screen.
+
+
+
+## UI Component Configuration
+
+This example shows the usage of 4 common UI components in customizing the project settings panel, in theory all UI components with `value` attribute can be used in customizing the project settings panel, please refer to the documentation [UI Components](./ui.md).
diff --git a/versions/4.0/en/editor/extension/contributions-shortcuts.md b/versions/4.0/en/editor/extension/contributions-shortcuts.md
new file mode 100644
index 0000000000..c321e0ca22
--- /dev/null
+++ b/versions/4.0/en/editor/extension/contributions-shortcuts.md
@@ -0,0 +1,71 @@
+# Extending Shortcut
+
+Shortcut keys within the editor are managed by the "Shortcut Key Manager". Each shortcut key can be bound to a message, and when the shortcut key is pressed, the bound message will be triggered.
+
+## Defining Shortcut
+
+Defining the shortcuts needs to be done in the `contributions.shortcuts` field of `package.json`, as follows:
+
+```json5
+// package.json
+{
+ "name": "hello-world",
+ "panels": {
+ "default": {
+ "main": "./panel.js"
+ }
+ },
+ "contributions": {
+ "messages": {
+ "undo": {
+ "title": "i18n:hello.messages.undo.title",
+ "methods": ["say-undo"]
+ }
+ },
+ "shortcuts": [
+ {
+ "message": "undo",
+ "when": "panelName === 'hello-world'",
+ "win": "ctrl+z",
+ "mac": "cmd+z",
+ }
+ ]
+ }
+}
+```
+
+In this example, we define a shortcut key for the **undo** operation, which is `CTRL + Z` on Windows and `CMD + Z` on macOS.
+
+When the corresponding shortcut key is pressed, the `undo` message is sent.
+
+> **Note**: This message needs to be defined in `contributions.messages`, please refer to the documentation [Customized Messages](./contributions-messages.md).
+
+## Parameter descriptions
+
+Below we will see the details of each parameter of `contributions.shortcuts`.
+
+### message
+
+Type {string} Required
+
+Shortcut-bound message that will be sent when this shortcut is triggered. Shortcut pressed messages can only be sent to the current extension.
+
+### when
+
+Type {string} Optional
+
+The shortcut will be triggered only under certain conditions.
+
+`"when": "PanelName === 'hello-world'"` means that the `message` message will be sent when the shortcut key is pressed when the panel name that gets focus is `hello-world`.
+
+### win
+
+type {string} required
+
+On Windows platform, the keystroke to listen to.
+
+### mac
+
+Type {string} Required
+
+On macOS, the keystroke to listen to.
diff --git a/versions/4.0/en/editor/extension/contributions.md b/versions/4.0/en/editor/extension/contributions.md
new file mode 100644
index 0000000000..c6d31c07ca
--- /dev/null
+++ b/versions/4.0/en/editor/extension/contributions.md
@@ -0,0 +1,53 @@
+# Extend Existing Functionality
+
+**Cocos Creator** supports contributions between extensions.
+
+When writing an extension, it is possible to query whether the existing functions in the editor provide the ability of receiving `contributions` externally.
+
+If there are functions that provide the ability of receiving `contributions` externally, use these functions when writing extensions.
+
+## Contributions Data Definition
+
+The `contributions` function, uniformly defined in the `contributions` field in `package.json`, is as follows.
+
+```JSON5
+{
+ "name": "hello-world",
+ "contributions": {
+ "builder":{ ... },
+ "assets":{ ... },
+ "profile": { ... },
+ "scene": { ... },
+ "menu": [ ... ],
+ "inspector":{ ... },
+ "messages": { ... },
+ "shortcuts": { ... },
+ "preferences": { ... },
+ "project": { ... }
+ },
+}
+```
+
+## Field Descriptions
+
+`contributions` provides the ability to interact with the editor's various functional systems, the main functions involved are as follows:
+
+- `builder` - custom build process, please refer to the documentation [Extending Build Process](../publish/custom-build-plugin.md) for details.
+
+- `assets` - Enhanced Explorer panel, please refer to the documentation for more details [Extending the Assets Panel](../assets/extension.md).
+
+- `profile` - defines the configuration needed for the extension, see the documentation [Configuration System](./profile.md).
+
+- `scene` - Write scripts in the extension that need to interact with the engine and project scripts, see the documentation [Calling the Engine API and Project Script](./scene-script.md).
+
+- `inspector` - custom **Inspector** panel, see the documentation [Custom Property Inspector Panel](./inspector.md).
+
+- `menu` - defines the menu information that the extension needs to add, see the documentation [Customize the Main Menu](./contributions-menu.md).
+
+- `messages` - defines the list of messages that the extension needs to use, please refer to the documentation [Custom Messages](./contributions-messages.md).
+
+- `shortcuts` - defines the shortcuts required by the extension, see the documentation [Extending Shortcut](./contributions-shortcuts.md).
+
+- `preferences` - customize the preferences, see the documentation [Extending the Preferences Panel](./contributions-preferences.md).
+
+- `project` - Custom project settings, see the documentation [Extending Project Settings Panel](./contributions-project.md).
diff --git a/versions/4.0/en/editor/extension/create-extension.md b/versions/4.0/en/editor/extension/create-extension.md
new file mode 100644
index 0000000000..b2f0911c7a
--- /dev/null
+++ b/versions/4.0/en/editor/extension/create-extension.md
@@ -0,0 +1,59 @@
+# Extension Templates and Compile Builds
+
+This article will explain in detail how to create an extension with a panel and use it with the extension template provided by Creator.
+
+Select the **Extension -> Create Extension** menu on the main editor menu to open the New Panel.
+
+
+
+
+
+## Template Types
+
+Cocos Creator provides 4 types of extension templates for quickly creating a new extension project.
+- **Blank**: empty extension.
+- **HTML Panel**: HTML-based extension template with a popup panel.
+- **Vue2.x Panel**: Vue2.x based extension template with a popup panel.
+- **Vue3.x Panel**: Vue3.x based extension template with a popup panel.
+
+The extensions created in the above 4 ways differ only in workload and technical selection, and there is no difference in the achievable capabilities of the extensions, so developers can choose according to their needs and technical background.
+
+> **Note**: Please refer to the `README.md` file in the corresponding extension package directory after creation.
+
+## Option Description
+
+| Options | Description |
+| :--- | :----- |
+| **Extension's name** | The extension name created must not start with `_` or `.`, and cannot contain capital letters. Because extensions become part of the URL, they also cannot contain illegal characters from the URL, `.`, `'` and `,`. |
+| **Author** | Author of extension |
+| **Editor dependency version** | The Cocos Creator version required by the runtime of the created extension. |
+| **Show in the manager** | If this item is checked, **Extension Manager** will automatically open and show the created extensions when the extension creation is finished. If this is unchecked, you can click **Extensions -> Extension Manager** in the menu bar at the top of the editor to view the extensions when they are created.|
+| **Show in folder** | If this item is checked, the extension will be automatically opened in the system file manager when the extension is created. |
+| **Extension's location** | The directory where the extension package was created. Since v3.7, extension can only be created with the **Project** option. |
+
+## Extension's Location
+
+### Project
+
+Apply the extension package to the specified Cocos Creator project, **Project** with the path:
+
+`${your project address}/extensions`
+
+## Dependency Installation and Compilation Build
+
+Once created, open the directory where the extension package is located and execute the following command:
+
+```bash
+## Install the dependency module
+npm install
+# Build
+npm run build
+```
+
+The extension depends on **Node.js** third-party libraries, so you need to run `npm install` in the extension directory before enabling the extension to compile properly.
+
+TypeScript can be written with full code hints and is more engineering friendly, so Cocos Creator recommends using a TypeScript-based workflow.
+
+The extension templates provided by default are also based on TypeScript and need to be compiled with `npm run build` to run.
+
+> **Note**: The extension `tsconfig.json` configuration file has `resolveJsonModule` enabled to get the extension name from the imported extension's `package.json`, so TypeScript requires **v4.3** and above, otherwise, importing `json` outside the root directory, otherwise the compilation result will be wrong path.
diff --git a/versions/4.0/en/editor/extension/define.md b/versions/4.0/en/editor/extension/define.md
new file mode 100644
index 0000000000..0a8b317158
--- /dev/null
+++ b/versions/4.0/en/editor/extension/define.md
@@ -0,0 +1,91 @@
+# Definition of Extension
+
+The extension package needs to have all the features and some basic information predefined in the `package.json` file, as follows.
+
+```JSON5
+{
+ "package_version": 2,
+ "version": "1.0.0",
+ "name": "first-panel",
+ "tilte": "i18n:first-panel.title",
+ "description": "i18n:first-panel.description",
+ "author": "Cocos Creator",
+ "editor": ">=3.4.2",
+ "main": "./dist/main.js",
+ "dependencies": { ... },
+ "devDependencies": { ... },
+ "panels": { ... },
+ "contributions": {
+ },
+ "scripts": {
+ "build": "tsc -b",
+ "watch": "tsc -w"
+ }
+}
+```
+
+## package_version
+
+Type {number} Required
+
+The version number of the extension, which is used to submit the version verification of the extension, as well as some upgrades of the extension itself, and data migration as a basis for comparison.
+
+## version
+
+Type {string} Required
+
+The version number of the extension, mainly used for display, if you want to make logical judgments, `package_version` is recommended.
+
+## name
+
+Type {string} Required
+
+The name of the extension, this name should correspond to the extension folder.
+
+## title
+
+Type {string} Optional
+
+The title of the extension, when `title` is configured, `title` will be used when the extension needs to be displayed, supports [Multilingual System (i18n)](./i18n.md) configuration.
+
+## description
+
+Type {string} Optional
+
+The description of the extension, a brief overview of the extension's functionality. Supports [Multilingual System (i18n)](./i18n.md) for multilingual syntax.
+
+## author
+
+type {string} optional
+
+The name of the author of the extension, which will be shown in the "Extension Manager".
+
+## editor
+
+type {string} Optional
+
+Description of the editor version supported by the extension, conforming to the [`semver` semantic version control specification](https://semver.org/).
+
+## main
+
+type {string} Optional
+
+A relative path to a js file that defines the function entry file. When the extension starts, the js file pointed to by the `main` field will be executed and the corresponding method will be triggered or executed according to the flow.
+
+## panels
+
+Type {[name: string]: PanelInfo} Optional
+
+The panel information defined within the extension. You can use `Editor.Panel.open('hello-world.list');` to open the defined panel. For details, please refer to [Extension Panel](./panel.md).
+
+## contributions
+
+type {[name: string]: any} optional
+
+`contributions` provides the ability to interact with the editor's feature system, see the documentation [Extend existing functionality](./contributions.md).
+
+## scripts
+
+type {[name: string]: any} required
+
+Extends the executable command line.
diff --git a/versions/4.0/en/editor/extension/extension-change-name.md b/versions/4.0/en/editor/extension/extension-change-name.md
new file mode 100644
index 0000000000..80c40d950b
--- /dev/null
+++ b/versions/4.0/en/editor/extension/extension-change-name.md
@@ -0,0 +1,25 @@
+# Change the Name of a Extension
+
+## Change the Display Name
+
+If you want to rename the extension, just change the `name` field in the `package.json` file. The code example is as follows:
+
+```JSON5
+// "name": "simple-1649426645745"
+"name": "hello-world"
+```
+
+Change the `name` field to "hello-world" as above and refresh the extension in the extension manager panel to see the name of the extension changed to **hello-world**.
+
+
+
+## Change the Extension Folder Name
+
+If you want to change the folder name along with it, you need to restart Cocos Creator after the folder change in order to make the extension with the modified folder name take effect again.
+
+If you modify the folder name, **i18n** the path to the multilanguage related string needs to be modified as well, as follows.
+
+```json5
+// "description": "i18n:simple-1649426645745.description",
+"description": "i18n:hello-world.description",
+```
diff --git a/versions/4.0/en/editor/extension/extension-manager.md b/versions/4.0/en/editor/extension/extension-manager.md
new file mode 100644
index 0000000000..d7701ef557
--- /dev/null
+++ b/versions/4.0/en/editor/extension/extension-manager.md
@@ -0,0 +1,37 @@
+# Extension Manager Panel
+
+The **Extension Manager** is used to manage extensions within the editor. Click **Extension -> Extension Manager** in the main menu bar of Cocos Creator to open.
+
+
+
+The Extension Manager panel is as follows.
+
+
+
+## Functions
+
+Its relevant functions are described as follows.
+
+1. Extension type, divided into **Cocos Official** and **Builtin**, selected by drop-down menu.
+2. Installed, click it to show the currently installed extensions.
+3. From left to right, **Search Extensions**, **Import Extension** and **Refresh Extension List**
+ - **Search Extensions**: When clicked, you can find the extensions within the current project by keywords in the input box shown below.
+ 
+ - **Import Extension**: Click to import a new extension via zip file
+ - **Refresh Exntesion List**: Refresh the current status of all extensions
+4. Extension list.
+
+ 
+
+ For each extension, the extension name, icon, version number and description are displayed on the left side.
+ The buttons on the right side are.
+ - **Open extension directory**
+ - **Delete** the extension
+ - **Enable/Disable** the extension
+ The built-in and official extensions cannot be deleted or disabled, some of the buttons need to be visible by moving the mouse over the entry.
+5. Details of extensions
+
+## Import Methods
+
+- **Import Extension Folder**: If you choose this import method, you need to copy the extension to the "extensions" directory of the project.
+- **Developer Import**: After choosing this import method, the extension will be referenced in the form of a soft link and doesn't need to be copied to the "extensions" directory, which facilitates developers in project management.
diff --git a/versions/4.0/en/editor/extension/first-communication.md b/versions/4.0/en/editor/extension/first-communication.md
new file mode 100644
index 0000000000..3139c741d4
--- /dev/null
+++ b/versions/4.0/en/editor/extension/first-communication.md
@@ -0,0 +1,157 @@
+# Getting Started Example - First Data Interaction
+
+In the previous two documents [Getting Started Example - Menu](./first.md) and [Getting Started Example - Panel](./first-panel.md), we introduced:
+- How to create extensions
+- How to define menus in extensions
+- how to define messages in an extension
+- How to define a panel in an extension
+
+This article demonstrates how two extensions can communicate with each other and will cover three topics:
+- How to open a panel of another extension
+- How to send a message to another extension
+- How to send and listen to broadcast messages
+
+## Open Another Extension's Panel
+
+Sometimes we need to open another extension in an extension we wrote, so next we'll try to modify the extension example in **Getting Started Example - Menu** so that it opens the panel defined in **Getting Started Example - Panel**.
+
+The modified `package.json` looks like this:
+
+```JSON5
+{
+ "package_version": 2,
+ "version": "1.0.0",
+ "name": "hello-world",
+ ...
+ "contributions": {
+ "menu": [
+ {
+ "path": "Develop/HelloWorld",
+ "label": "test",
+ "message": "log"
+ },
+ {
+ "path": "Develop/HelloWorld",
+ "label": "open other",
+ "message": "open-other"
+ }
+ ],
+ "messages": {
+ "log": {
+ "methods": [
+ "log"
+ ]
+ },
+ "open-other": {
+ "methods": [
+ "openOther"
+ ]
+ }
+ }
+ }
+}
+```
+
+We modified `contributions.menu`, added `open other` menu item, and put all the menus of this extension under Develop/HelloWorld. After refreshing the extension, you can find the menu items in the top menu bar as shown below.
+
+
+
+In `contributions.messages`, we add an `open-other` message and let the `openOther` function in `main.ts` handle this message.
+
+The extension in **Getting Started Example - Panel** is `first-panel`, so we use `Editor.Panel.open('extension')` to open its default panel, as follows:
+
+```typescript
+openOther(){
+ Editor.Panel.open('first-panel');
+}
+```
+
+After executing the `npm run build` command at the root of `hello-world`, go to **Extension Manager** to refresh the `hello-world` extension.
+
+Click on the **Develop** -> **HelloWorld** -> **open other** menu item and you will see the example panel open.
+
+## Communication with other extensions
+
+### Directional communication
+
+In the above example, we open the `first-panel` panel in `hello-world` with `Editor.Panel.open('extension')`. But if we are trying to do something else, this solution won't work.
+
+When an extension wants to call the function of another extension, this can be done by sending a message to one of the extensions with the following function:
+
+```typescript
+Editor.Message.send(extensionName:string,messasge:string,...args:any[])
+```
+
+The messages defined in `contributions.messages` of each extension are available to the public by default. In `first-panel` we find the `open-panel` message, which is used to open its own default panel. For simplicity, we replace the `openOther` function in `main.ts` in `hello-world` with the following:
+
+```typescript
+openOther(){
+ Editor.Message.send('first-panel','open-panel');
+}
+```
+
+After recompiling the `hello-world` extension and refreshing it, click **Develop** -> **HelloWorld** -> **open other** menu item again, you can see the default panel of `first-panel` is opened.
+
+### Broadcast communication
+
+When an extension wants to notify all extensions across the system of the completion of an event, it can do so by broadcasting a message with the following function.
+
+```typescript
+Editor.Message.broadcast(message:string, ...args:any[])`
+```
+
+Next, we define a broadcast message called `first-panel:open`, which is broadcast by the `first-panel` extension and listened to by the `hello-world` extension.
+
+In `hello-world`, we add a new message listener and specify the handler function, with the following modified `contributions.messages`:
+
+```json5
+{
+ "messages": {
+ "log": {
+ "methods": [
+ "log"
+ ]
+ },
+ "open-other": {
+ "methods": [
+ "openOther"
+ ]
+ },
+ "first-panel:open":{
+ "methods": [
+ "onFirstPanelOpen"
+ ]
+ }
+ }
+}
+```
+
+Then add the following handler function to `main.ts` of `hello-world`:
+
+```typescript
+onFirstPanelOpen(){
+ console.log("hello-world knows first-panel is open");
+}
+```
+
+The transformation as a listener is done, next we modify the broadcast side `first-panel`.
+
+Add the following broadcast message code to the ``src/panels/default/index.ts :ready`` function in the ``first-panel` project.
+
+```typescript
+Editor.Message.broadcast("first-panel:open");
+```
+
+The `ready` function will be called when the default panel of `first-panel` is opened, at which point the `first-panel:open` message will be broadcast.
+
+> **Note**: Broadcasters can also listen for their own broadcast messages in messages, but this is usually not necessary.
+
+Compile and refresh the two extensions separately, click again on the **Develop** -> **HelloWorld** -> **open other** menu item, and you will see the sample panel opened, in addition to the following print in the Cocos Creator console window.
+
+```
+hello-world knows first-panel is open
+```
+
+This means that the ``hello-world`` extension has received a broadcast message from the ``first-panel`` extension.
+
+For more message-related details, please refer to the documentation [Message System](./messages.md).
diff --git a/versions/4.0/en/editor/extension/first-panel.md b/versions/4.0/en/editor/extension/first-panel.md
new file mode 100644
index 0000000000..02dd1cd687
--- /dev/null
+++ b/versions/4.0/en/editor/extension/first-panel.md
@@ -0,0 +1,148 @@
+# Getting Started Example - Panel
+
+In the document [Getting Started Example - Menus](./first.md) explains how to create a minimal extension, next we look at how to create a panel and communicate with it.
+
+## Creating via templates
+
+The quickest way to create a panel in Cocos Creator is through the **Extension template with a panel**, as shown in the following image:
+
+
+
+After clicking the **Create** button, you can find the extensions/first-panel extension in the project root directory.
+
+### Compile, Install
+
+In the command line tool, locate the extensions/first-panel directory and execute the following statement:
+
+```bash
+npm install
+npm run build
+```
+
+After the command is executed, go back to the **Extension Manager**, find the first-panel extension, enable it and refresh it, as shown in the following image:
+
+
+
+### View Panel
+
+After enabling and refreshing the extension, you can find the menu items in the **Panel** menu as shown in the following figure.
+
+
+
+Click on the **Default panel** menu item to bring up the panel shown below.
+
+
+
+This example also defines another menu item for communication in the **Developer** menu, as shown in the following image.
+
+
+
+After clicking the **Send message to Default Panel** button shown in the red box in the above image, you can see that the content displayed on the panel will change.
+
+> **Note**: If this menu is not displayed, please open the **Extension Manager** panel and make sure the extension is enabled.
+>
+> 
+
+## Panel Explanation
+
+In the following, we'll explain the panel directory structure, definition and communication mechanism one by one.
+
+### Panel Directory Structure
+
+In the project directory, find `./extensions/first-panel` folder, which is the directory where the entire extension can be viewed.
+
+
+
+As shown above, there are more `static` and `panels` directories than hello-world.
+
+`static` - used to store panel layout files, such as css\html, etc.
+
+`panels` - used to store panel-related source code, each panel has an `index.ts` entry source file.
+
+`index.ts`, `style`, `template` Please refer to the documentation [Write a Custom Panel](./panel-boot.md)
+
+### Description File package.json
+
+Before we understand the panel, let's look at the panel-related definitions in `package.json`, as follows:
+
+```json
+{
+ "package_version": 2,
+ "version": "1.0.0",
+ "name": "first-panel",
+ "description": "i18n:first-panel.description",
+ "main": "./dist/main.js",
+ "dependencies": {
+ "fs-extra": "^10.0.0"
+ },
+ "devDependencies": {
+ "@types/node": "^16.0.1",
+ "@types/fs-extra": "^9.0.5",
+ "typescript": "^4.3.4"
+ },
+ "panels": {
+ "default": {
+ "title": "first-panel Default Panel",
+ "type": "dockable",
+ "main": "dist/panels/default",
+ "size": {
+ "min-width": 400,
+ "min-height": 300,
+ "width": 1024,
+ "height": 600
+ }
+ }
+ },
+ "contributions": {
+ "menu": [
+ {
+ "path": "i18n:menu.panel/first-panel",
+ "label": "i18n:first-panel.open_panel",
+ "message": "open-panel"
+ },
+ {
+ "path": "i18n:menu.develop/first-panel",
+ "label": "i18n:first-panel.send_to_panel",
+ "message": "send-to-panel"
+ }
+ ],
+ "messages": {
+ "open-panel": {
+ "methods": [
+ "openPanel"
+ ]
+ },
+ "send-to-panel": {
+ "methods": [
+ "default.hello"
+ ]
+ }
+ }
+ },
+ "author": "Cocos Creator",
+ "editor": ">=3.4.2",
+ "scripts": {
+ "build": "tsc -b",
+ "watch": "tsc -w"
+ }
+}
+```
+
+`panels`: {} - The panels defined in this extension
+- default: String - defines a panel named default
+ - title: String - the title of the panel
+ - type: String - the type of the panel
+ - main: String - the panel source directory
+ - size: {} - size information
+ - min-width: Number - the minimum width
+ - min-height: Number - the minimum height
+ - width: Number - the default width of the panel
+ - height: Number - the default height of the panel
+
+## Additional Reading
+
+`panel` For a detailed explanation of panels, please refer to the documentation [Extension Panel](./panel.md).
+
+`i18n` for multi-language configuration, please refer to the documentation [Multilingual System (i18n)](./i18n.md).
+
+`messages` For the complete message definition mechanism, please refer to the documentation [Customized Messages](./contributions-messages.md).
diff --git a/versions/4.0/en/editor/extension/first.md b/versions/4.0/en/editor/extension/first.md
new file mode 100644
index 0000000000..809e281036
--- /dev/null
+++ b/versions/4.0/en/editor/extension/first.md
@@ -0,0 +1,200 @@
+# Getting Started Example - Menu
+
+This article will demonstrate how to create a Cocos Creator extension, and it will cover the following points.
+- Creating an extension
+- Adding a menu
+- Menu Messages
+
+## Create and Install Extensions
+
+Find the **Extension -> Create** menu in the editor's menu bar, as shown below:
+
+
+
+After clicking **Create**, the creation panel will pop up as shown below:
+
+
+
+Cocos Creator provides 4 extension templates as shown above for quickly creating a new extension project.
+
+To demonstrate the template creation process more simply, let's select the **Blank** template and click the **Create Extension** button at the bottom right of the panel to build an extension package.
+
+For more template creation related content, please refer to the document [Extension Templates and Compile Builds - Template Types](./create-extension.md).
+
+## Extension Manager
+
+After the extension is successfully created, click **Extensions-> Extension Manager -> Project/Global** in the top menu bar, you can see the extension you just created. The newly created extension is not enabled by default, click the Enable button to enable this extension.
+
+
+
+For more information about extension management, please refer to the documentation [Extension Manager - Extension List](./extension-manager.md#Extensions%20list).
+
+## Extended Directory
+
+Click the  button to open the directory where the extensions are located. Take the **Blank** template as an example, the directory structure is as follows:
+
+
+
+The function of each subfile (folder) is as follows.
+- `@types` - TypeScript definition file.
+- `dist` - TypeScript-generated javascript code.
+- `i18n` - Multilanguage configuration.
+- `src` - TypeScript source code.
+- `package.json` - The extension description file.
+- `README-CN/EN.md` - Chinese/English description file.
+- `tsconfig.json` - TypeScript configuration file.
+
+## Extension Definition File `package.json`
+
+Each extension needs a `package.json` file to describe the purpose of the extension.
+
+Only after the complete definition of the description file `package.json`, the editor will be able to know the specific functionality, loading entry and other information defined in the extension.
+
+> **Note**: Although many of the fields in `package.json` are defined similarly to `package.json` of the `node.js` npm module, the npm module downloaded from the npm community cannot be used directly as a Cocos Creator extension. You can call the npm module from within the Cocos Creator extension to make the extension capable of doing so.
+
+Open the `package.json` file and you will see the following:
+
+```json
+{
+ "package_version": 2,
+ "version": "1.0.0",
+ "name": "simple-1649426645745",
+ "description": "i18n:simple-1649426645745.description",
+ "main": "./dist/main.js",
+ "devDependencies": {
+ "@types/node": "^16.0.1",
+ "typescript": "^4.3.4"
+ },
+ "author": "Cocos Creator",
+ "editor": ">=3.4.2",
+ "scripts": {
+ "build": "tsc -b",
+ "watch": "tsc -w"
+ }
+}
+
+```
+
+The description of each field is as follows.
+- `package_version`: Number - the value of the version number.
+- `version`: String - The version number string, it is recommended to use [semver](http://semver.org/) format to manage your package version.
+- `name`: String - defines the name of the package, the package name is globally unique. Please refer to [option description] for naming rules (. /create-extension.md).
+- `description`: Stirng - Extension description, used to briefly introduce the key features, usage and other information of the extension, supports **i18n** multi-language settings.
+- `main`: String - The entry program file.
+- `devDependencies`: {} - Extension dependencies. In this example, the extension depends on NodeJS version 16.0.1 and TypeScript version 4.3.4.
+- `author`: String - Author information.
+- `editor`: String - the supported Cocos Creator editor version.
+- `scripts`: {} - Script compilation related commands.
+
+## Define Menus and Messages
+
+Replace `package.json` with the following:
+
+```json
+{
+ "package_version": 2,
+ "version": "1.0.0",
+ "name": "simple-1649426645745",
+ "description": "i18n:simple-1649426645745.description",
+ "main": "./dist/main.js",
+ "devDependencies": {
+ "@types/node": "^16.0.1",
+ "typescript": "^4.3.4"
+ },
+ "author": "Cocos Creator",
+ "editor": ">=3.4.2",
+ "scripts": {
+ "build": "tsc -b",
+ "watch": "tsc -w"
+ },
+ //------------------------------
+ "contributions": {
+ "menu": [{
+ "path": "Develop",
+ "label": "test",
+ "message": "log"
+ }],
+ "messages": {
+ "log": {
+ "methods": ["log"]
+ }
+ }
+ }
+}
+```
+
+The description of the new fields is as follows.
+- `contributions`: Object (optional) - configuration related to the extension of the editor's existing functionality
+ - `menu`: [], register the menu and bind the message. For details, please refer to [Customize the Main Menu](./contributions-menu.md).
+ - `messages`:[] - Register editor messages, which can be bound to one or more methods defined within the extension. See [Customized Messages](./contributions-messages.md) for more definition data.
+
+For more definitions of the `package.json` format, please refer to [Definition of Extension](./define.md).
+
+## Installing Dependencies and Compiling
+
+After the extension is created, open the directory where the extension package is located and execute the following command.
+
+```bash
+# install dependencies
+npm install
+# build
+npm run build
+```
+
+For more information on building extensions, see the documentation [Extension Templates and Compile Builds](./create-extension.md).
+
+## Run Extensions
+
+Go back to the editor and click **Extension -> Extension Manager -> Project/Global** in the top menu bar and find the extension you created earlier. Click on the  button on the right side of the extension to make the above changes take effect.
+
+If the extension has taken effect, a **Develop** menu will appear in the top menu bar area of Cocos Creator with a **test** menu item, as shown below.
+
+
+
+If you click on the **test** menu item, you will see that there is no response, because we have not yet written the code for the menu information.
+
+Next, we will see how to make the menu communicate with the extension.
+
+## Entry Program `main.ts`
+
+Each extension has a unique entry program `main.ts`, which is generated by default as follows:
+
+```typescript
+/**
+ * @en Registration method for the main process of Extension
+ * @zh 为扩展的主进程的注册方法
+ */
+export const methods: { [key: string]: (...any: any) => any } = { };
+
+/**
+ * @en Hooks triggered after extension loading is complete
+ * @zh 扩展加载完成后触发的钩子
+ */
+export const load = function() { };
+
+/**
+ * @en Hooks triggered after extension uninstallation is complete
+ * @zh 扩展卸载完成后触发的钩子
+ */
+export const unload = function() { };
+```
+
+The methods defined in `export const methods` will be used as interfaces for operations that will be called across extensions via the [Message System](./messages.md) to be called across extensions or to communicate with panels.
+
+The entry program is the main process of the extension and will be loaded during the startup of Cocos Creator.
+
+## Menu Message Handling
+
+We modify the entry program slightly by adding a handler function that receives ``log`` messages, as follows.
+
+```typescript
+export const methods: { [key: string]: (.. . any: any) => any } = {
+ log(){console.log('Hello World')},
+};
+```
+
+Execute the `npm run build` command to compile the extension.
+
+Click on the  button on the right side of the extension to make the above changes take effect.
+
+Click the `Develop/test` menu item again and you will see that "Hello World" is printed out in the Cocos Creator **console**.
diff --git a/versions/4.0/en/editor/extension/first/delete.png b/versions/4.0/en/editor/extension/first/delete.png
new file mode 100644
index 0000000000..a0bd4163e6
Binary files /dev/null and b/versions/4.0/en/editor/extension/first/delete.png differ
diff --git a/versions/4.0/en/editor/extension/first/enable-or-not.png b/versions/4.0/en/editor/extension/first/enable-or-not.png
new file mode 100644
index 0000000000..d0c512bbd0
Binary files /dev/null and b/versions/4.0/en/editor/extension/first/enable-or-not.png differ
diff --git a/versions/4.0/en/editor/extension/first/enable.png b/versions/4.0/en/editor/extension/first/enable.png
new file mode 100644
index 0000000000..c49a0d4eb5
Binary files /dev/null and b/versions/4.0/en/editor/extension/first/enable.png differ
diff --git a/versions/4.0/en/editor/extension/first/extension-first-panel-create.png b/versions/4.0/en/editor/extension/first/extension-first-panel-create.png
new file mode 100644
index 0000000000..a789d5eebd
Binary files /dev/null and b/versions/4.0/en/editor/extension/first/extension-first-panel-create.png differ
diff --git a/versions/4.0/en/editor/extension/first/extension-first-panel-enable.png b/versions/4.0/en/editor/extension/first/extension-first-panel-enable.png
new file mode 100644
index 0000000000..b151b115be
Binary files /dev/null and b/versions/4.0/en/editor/extension/first/extension-first-panel-enable.png differ
diff --git a/versions/4.0/en/editor/extension/first/extension-first-panel-folder-origin.png b/versions/4.0/en/editor/extension/first/extension-first-panel-folder-origin.png
new file mode 100644
index 0000000000..6ee820b818
Binary files /dev/null and b/versions/4.0/en/editor/extension/first/extension-first-panel-folder-origin.png differ
diff --git a/versions/4.0/en/editor/extension/first/extension-first-panel-folder.png b/versions/4.0/en/editor/extension/first/extension-first-panel-folder.png
new file mode 100644
index 0000000000..fa9c130698
Binary files /dev/null and b/versions/4.0/en/editor/extension/first/extension-first-panel-folder.png differ
diff --git a/versions/4.0/en/editor/extension/first/extension-first-panel-install.png b/versions/4.0/en/editor/extension/first/extension-first-panel-install.png
new file mode 100644
index 0000000000..fc95c5c9ae
Binary files /dev/null and b/versions/4.0/en/editor/extension/first/extension-first-panel-install.png differ
diff --git a/versions/4.0/en/editor/extension/first/extension-first-panel-menu.png b/versions/4.0/en/editor/extension/first/extension-first-panel-menu.png
new file mode 100644
index 0000000000..44e76671a5
Binary files /dev/null and b/versions/4.0/en/editor/extension/first/extension-first-panel-menu.png differ
diff --git a/versions/4.0/en/editor/extension/first/extension-first-panel-sendmsg.png b/versions/4.0/en/editor/extension/first/extension-first-panel-sendmsg.png
new file mode 100644
index 0000000000..1a35f1ac38
Binary files /dev/null and b/versions/4.0/en/editor/extension/first/extension-first-panel-sendmsg.png differ
diff --git a/versions/4.0/en/editor/extension/first/extension-first-panel.png b/versions/4.0/en/editor/extension/first/extension-first-panel.png
new file mode 100644
index 0000000000..32985244cf
Binary files /dev/null and b/versions/4.0/en/editor/extension/first/extension-first-panel.png differ
diff --git a/versions/4.0/en/editor/extension/first/extension-hello-world.png b/versions/4.0/en/editor/extension/first/extension-hello-world.png
new file mode 100644
index 0000000000..efb558bf9a
Binary files /dev/null and b/versions/4.0/en/editor/extension/first/extension-hello-world.png differ
diff --git a/versions/4.0/en/editor/extension/first/extension-menu-hw.png b/versions/4.0/en/editor/extension/first/extension-menu-hw.png
new file mode 100644
index 0000000000..847403389c
Binary files /dev/null and b/versions/4.0/en/editor/extension/first/extension-menu-hw.png differ
diff --git a/versions/4.0/en/editor/extension/first/extension-menu-test.png b/versions/4.0/en/editor/extension/first/extension-menu-test.png
new file mode 100644
index 0000000000..9205042cb1
Binary files /dev/null and b/versions/4.0/en/editor/extension/first/extension-menu-test.png differ
diff --git a/versions/4.0/en/editor/extension/first/extension-package.png b/versions/4.0/en/editor/extension/first/extension-package.png
new file mode 100644
index 0000000000..8977bf3054
Binary files /dev/null and b/versions/4.0/en/editor/extension/first/extension-package.png differ
diff --git a/versions/4.0/en/editor/extension/first/extension.png b/versions/4.0/en/editor/extension/first/extension.png
new file mode 100644
index 0000000000..bc23d8c182
Binary files /dev/null and b/versions/4.0/en/editor/extension/first/extension.png differ
diff --git a/versions/4.0/en/editor/extension/first/folder.png b/versions/4.0/en/editor/extension/first/folder.png
new file mode 100644
index 0000000000..ae8f1ec9f6
Binary files /dev/null and b/versions/4.0/en/editor/extension/first/folder.png differ
diff --git a/versions/4.0/en/editor/extension/first/refresh.png b/versions/4.0/en/editor/extension/first/refresh.png
new file mode 100644
index 0000000000..b719f388b2
Binary files /dev/null and b/versions/4.0/en/editor/extension/first/refresh.png differ
diff --git a/versions/4.0/en/editor/extension/i18n.md b/versions/4.0/en/editor/extension/i18n.md
new file mode 100644
index 0000000000..1a31b0d171
--- /dev/null
+++ b/versions/4.0/en/editor/extension/i18n.md
@@ -0,0 +1,106 @@
+# Multilingual System (i18n)
+
+## What is i18n
+
+**i18n** (derived from the first and last characters i and n of the English word internationalization, with 18 being the number of characters in between) is short for "internationalization".
+
+In the field of information, i18n refers to the ability to adapt products (publications, software, hardware, etc.) to the needs of different languages and regions without much change.
+
+In the field of application development, i18n refers to the ability to display localized content for different languages and regions without modifying the internal code.
+
+The built-in i18n in the Cocos Creator extension system allows extensions to configure **key-value mapping** for multiple languages and use strings from different languages in the extension according to the editor's current language settings.
+
+## i18n Folder
+
+To enable the i18n, you need to create a new folder named i18n in the extension directory and add a corresponding `JavaScript` file for each language as key-value mapping data.
+
+The data file name should be consistent with the language code, e.g. `en.js` corresponds to English mapping data, `zh.js` corresponds to Chinese mapping data. As shown in the following figure.
+
+
+
+The mapping takes the key of the `JavaScript` object as the key value and is exported with the module information as follows:
+
+- `en.js`
+
+ ```javascript
+ "use strict";
+ module.exports = {
+ open_panel:"Default Panel",
+ send_to_panel:"Send message to Default Panel",
+ description:"Extension with a panel"
+ };
+ ```
+
+- `zh.js`
+
+ ```javascript
+ module.exports = {
+ open_panel:"默认面板",
+ send_to_panel:"发送消息给面板",
+ description:"含有一个面板的扩展"
+ };
+ ```
+
+Take `open_panel` as an example, suppose the registered extension name is `first-panel`, then the corresponding text translation key is `first-panel.open_panel`.
+
+## Using in Scripts
+
+In TypeScript or JavaScript scripts, the translated text for the current language can be obtained through the ``Editor.I18n.t`'' interface.
+
+```typescript
+let str = Editor.I18n.t('first-panel.open_panel');
+```
+
+## Use in HTML Templates
+
+You can use the ui-label element for translation in HTML templates if you need to translate.
+
+```html
+
+```
+
+> **Note**: `ui-label` is a normal in-line element, similar to span.
+
+### Use in json Files
+
+For example, when registering a menu path in the `package.json` of an extension package, the path can be translated into multiple languages using the form `i18n:${key}`, as long as the field supports i18n formatted paths.
+
+Example 1: Extension description
+
+```json5
+// "package_version": 2,
+// "version": "1.0.0",
+// "name": "first-panel",
+"description": "i18n:first-panel.description",
+// "main": "./dist/main.js",
+```
+
+Example 2: Panel Title
+
+```json5
+"panels": {
+ "default": {
+ "title": "first-panel Default Panel",
+ // "type": "dockable",
+ // "main": "dist/panels/default",
+ // "size": {...}
+ }
+},
+```
+
+Example 3: Menu path and display content
+
+```json
+"menu":[
+ {
+ "path": "i18n:menu.panel/first-panel",
+ "label": "i18n:first-panel.open_panel",
+ "message": "open-panel"
+ },
+ {
+ "path": "i18n:menu.develop/first-panel",
+ "label": "i18n:first-panel.send_to_panel",
+ "message": "send-to-panel"
+ }
+]
+```
diff --git a/versions/4.0/en/editor/extension/image/category.png b/versions/4.0/en/editor/extension/image/category.png
new file mode 100644
index 0000000000..f23a305b36
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/category.png differ
diff --git a/versions/4.0/en/editor/extension/image/create-extension-menu.png b/versions/4.0/en/editor/extension/image/create-extension-menu.png
new file mode 100644
index 0000000000..3c05598adb
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/create-extension-menu.png differ
diff --git a/versions/4.0/en/editor/extension/image/create-extension-panel.png b/versions/4.0/en/editor/extension/image/create-extension-panel.png
new file mode 100644
index 0000000000..6dbc663601
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/create-extension-panel.png differ
diff --git a/versions/4.0/en/editor/extension/image/create.png b/versions/4.0/en/editor/extension/image/create.png
new file mode 100644
index 0000000000..2c2970a8d3
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/create.png differ
diff --git a/versions/4.0/en/editor/extension/image/dashboard-store.png b/versions/4.0/en/editor/extension/image/dashboard-store.png
new file mode 100644
index 0000000000..aa2e597c21
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/dashboard-store.png differ
diff --git a/versions/4.0/en/editor/extension/image/default-extension-panel.png b/versions/4.0/en/editor/extension/image/default-extension-panel.png
new file mode 100644
index 0000000000..1d45b29cf4
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/default-extension-panel.png differ
diff --git a/versions/4.0/en/editor/extension/image/electron-process.png b/versions/4.0/en/editor/extension/image/electron-process.png
new file mode 100644
index 0000000000..642b4117a3
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/electron-process.png differ
diff --git a/versions/4.0/en/editor/extension/image/enable-extension.png b/versions/4.0/en/editor/extension/image/enable-extension.png
new file mode 100644
index 0000000000..b67e838923
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/enable-extension.png differ
diff --git a/versions/4.0/en/editor/extension/image/enable-first-panel.png b/versions/4.0/en/editor/extension/image/enable-first-panel.png
new file mode 100644
index 0000000000..38bf951ae6
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/enable-first-panel.png differ
diff --git a/versions/4.0/en/editor/extension/image/ext-detail.png b/versions/4.0/en/editor/extension/image/ext-detail.png
new file mode 100644
index 0000000000..95ae974526
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/ext-detail.png differ
diff --git a/versions/4.0/en/editor/extension/image/extension-database.png b/versions/4.0/en/editor/extension/image/extension-database.png
new file mode 100644
index 0000000000..492c2585bf
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/extension-database.png differ
diff --git a/versions/4.0/en/editor/extension/image/extension-folder-blank.png b/versions/4.0/en/editor/extension/image/extension-folder-blank.png
new file mode 100644
index 0000000000..2701aad028
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/extension-folder-blank.png differ
diff --git a/versions/4.0/en/editor/extension/image/extension-global.png b/versions/4.0/en/editor/extension/image/extension-global.png
new file mode 100644
index 0000000000..384280592b
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/extension-global.png differ
diff --git a/versions/4.0/en/editor/extension/image/extension-internal.png b/versions/4.0/en/editor/extension/image/extension-internal.png
new file mode 100644
index 0000000000..9e1d1f90a7
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/extension-internal.png differ
diff --git a/versions/4.0/en/editor/extension/image/extension-list.png b/versions/4.0/en/editor/extension/image/extension-list.png
new file mode 100644
index 0000000000..52d06c7ab5
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/extension-list.png differ
diff --git a/versions/4.0/en/editor/extension/image/extension-manager-menu.png b/versions/4.0/en/editor/extension/image/extension-manager-menu.png
new file mode 100644
index 0000000000..863e70870e
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/extension-manager-menu.png differ
diff --git a/versions/4.0/en/editor/extension/image/extension-manager.png b/versions/4.0/en/editor/extension/image/extension-manager.png
new file mode 100644
index 0000000000..98c9ea92c0
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/extension-manager.png differ
diff --git a/versions/4.0/en/editor/extension/image/extension-message-mgr-menu.png b/versions/4.0/en/editor/extension/image/extension-message-mgr-menu.png
new file mode 100644
index 0000000000..0b13c7222c
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/extension-message-mgr-menu.png differ
diff --git a/versions/4.0/en/editor/extension/image/extension-message-mgr-panel.png b/versions/4.0/en/editor/extension/image/extension-message-mgr-panel.png
new file mode 100644
index 0000000000..2357044169
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/extension-message-mgr-panel.png differ
diff --git a/versions/4.0/en/editor/extension/image/extension-project.png b/versions/4.0/en/editor/extension/image/extension-project.png
new file mode 100644
index 0000000000..2f66e88892
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/extension-project.png differ
diff --git a/versions/4.0/en/editor/extension/image/i18n-folder.png b/versions/4.0/en/editor/extension/image/i18n-folder.png
new file mode 100644
index 0000000000..b82d28db85
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/i18n-folder.png differ
diff --git a/versions/4.0/en/editor/extension/image/introduction.png b/versions/4.0/en/editor/extension/image/introduction.png
new file mode 100644
index 0000000000..3c6c37ec04
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/introduction.png differ
diff --git a/versions/4.0/en/editor/extension/image/output.png b/versions/4.0/en/editor/extension/image/output.png
new file mode 100644
index 0000000000..0dafdb8e8a
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/output.png differ
diff --git a/versions/4.0/en/editor/extension/image/preferences-menu.png b/versions/4.0/en/editor/extension/image/preferences-menu.png
new file mode 100644
index 0000000000..d2ebf81094
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/preferences-menu.png differ
diff --git a/versions/4.0/en/editor/extension/image/preferences-tool-custom-laboratory.png b/versions/4.0/en/editor/extension/image/preferences-tool-custom-laboratory.png
new file mode 100644
index 0000000000..76d3405fc2
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/preferences-tool-custom-laboratory.png differ
diff --git a/versions/4.0/en/editor/extension/image/preferences-tool-custom.png b/versions/4.0/en/editor/extension/image/preferences-tool-custom.png
new file mode 100644
index 0000000000..0daceecf34
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/preferences-tool-custom.png differ
diff --git a/versions/4.0/en/editor/extension/image/preferences-tool.png b/versions/4.0/en/editor/extension/image/preferences-tool.png
new file mode 100644
index 0000000000..55b0c1eee3
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/preferences-tool.png differ
diff --git a/versions/4.0/en/editor/extension/image/pricing.png b/versions/4.0/en/editor/extension/image/pricing.png
new file mode 100644
index 0000000000..fb469f478d
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/pricing.png differ
diff --git a/versions/4.0/en/editor/extension/image/project-settings-menu.png b/versions/4.0/en/editor/extension/image/project-settings-menu.png
new file mode 100644
index 0000000000..1826d6e213
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/project-settings-menu.png differ
diff --git a/versions/4.0/en/editor/extension/image/project-settings-panel-custom.png b/versions/4.0/en/editor/extension/image/project-settings-panel-custom.png
new file mode 100644
index 0000000000..71e531437b
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/project-settings-panel-custom.png differ
diff --git a/versions/4.0/en/editor/extension/image/project-settings-panel.png b/versions/4.0/en/editor/extension/image/project-settings-panel.png
new file mode 100644
index 0000000000..1a08df4740
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/project-settings-panel.png differ
diff --git a/versions/4.0/en/editor/extension/image/search.png b/versions/4.0/en/editor/extension/image/search.png
new file mode 100644
index 0000000000..e24a3964db
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/search.png differ
diff --git a/versions/4.0/en/editor/extension/image/store.png b/versions/4.0/en/editor/extension/image/store.png
new file mode 100644
index 0000000000..ec7b3db78b
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/store.png differ
diff --git a/versions/4.0/en/editor/extension/image/submit-for-review.png b/versions/4.0/en/editor/extension/image/submit-for-review.png
new file mode 100644
index 0000000000..139a8992f6
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/submit-for-review.png differ
diff --git a/versions/4.0/en/editor/extension/image/ui-component-menu.png b/versions/4.0/en/editor/extension/image/ui-component-menu.png
new file mode 100644
index 0000000000..d301482e8b
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/ui-component-menu.png differ
diff --git a/versions/4.0/en/editor/extension/image/ui-component.png b/versions/4.0/en/editor/extension/image/ui-component.png
new file mode 100644
index 0000000000..88a46280ab
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/ui-component.png differ
diff --git a/versions/4.0/en/editor/extension/image/upload-store.png b/versions/4.0/en/editor/extension/image/upload-store.png
new file mode 100644
index 0000000000..9f8bcfd8b6
Binary files /dev/null and b/versions/4.0/en/editor/extension/image/upload-store.png differ
diff --git a/versions/4.0/en/editor/extension/inspector.md b/versions/4.0/en/editor/extension/inspector.md
new file mode 100644
index 0000000000..c2738d7ffb
--- /dev/null
+++ b/versions/4.0/en/editor/extension/inspector.md
@@ -0,0 +1,255 @@
+# Custom Inspector Panel
+
+Developers with custom inspector needs are advised to first refer to the documentation [Decorator](../../scripting/decorator.md), and if that document meets the requirements, it is recommended that the methods in that document be used first.
+
+The **Inspector** panel, the module in Cocos Creator that displays the currently selected state, provides some basic extension capabilities.
+
+In **Inspector** panel, two levels of data are defined:
+
+1. the main type of the selected object
+2. the sub-data types contained in the content when rendering the content of the main type
+
+When a **node** or an **asset** is selected in the **Hierarchy**/**Assets Panel**, Cocos Creator broadcasts the message that the object is selected. When the **Inspector** panel receives the message, it checks the type of the selected object, e.g. if the selected object is a node, then the type is `node`.
+
+For both types, two types of renderers are allowed to be registered.
+1. the main type renderer
+2. When the main type renderer receives data to start rendering, it allows subtype renderers to be attached
+
+The selected object in the example is `node`, and `node` carries multiple `component`s, so the main type is `node` and the subtype is `component`.
+
+After the **Inspector** receives the broadcast message for the selected object, it first determines the type, and then the **Inspector** takes the received data (the uuid of the object) and passes it to the `node` renderer, handing over the rendering privileges completely.
+
+And in the `node` renderer, the rendering privileges for that region are handed over to the `subtype renderer` when rendering to each `component`, according to its own implementation. For the most part, we don't need to be concerned about this. Let's take a look at a few common ways to customize it.
+
+## Customizing Component Rendering
+
+The default component renderer sometimes doesn't meet our needs, so we need to customize a component's rendering method.
+
+First, create a new script component `CustomLabelComponent.ts` in the project and add a string property with the following content:
+
+```typescript
+
+import { _decorator, Component, Node } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass('CustomLabelComponent')
+export class CustomLabelComponent extends Component {
+ @property
+ label = '';
+
+ start () {
+
+ }
+}
+
+```
+
+Drag the component to the node and you will see an input box on the component.
+
+Create a new extension and register the following `contributions.inspector` information in the extension's `package.json`:
+
+```json
+{
+ "contributions": {
+ "inspector": {
+ "section": {
+ "node": {
+ "CustomLabelComponent": "./dist/contributions/inspector/comp-label.js"
+ }
+ }
+ }
+ }
+}
+```
+
+### Automatic Rendering
+
+Write a `src/contributions/inspector/comp-label.ts` file with the following contents:
+
+```typescript
+'use strict';
+
+import { methods } from "../../main";
+
+type Selector<$> = { $: Record }
+
+export const template = `
+
+`;
+
+export const $ = {
+ test: '.test',
+};
+
+export function update(this: Selector, dump: any) {
+ // Use ui-prop to auto-render, set the type of prop to dump
+ // render pass in a dump data to be able to automatically render the corresponding interface
+ // Auto-rendered interface can automatically commit data after modification
+ this.$.test.render(dump.value.label);
+}
+export function ready(this: Selector) {}
+```
+
+After compiling and refreshing the extension, we can see that the rendering of the `CustomLabelComponent` component has been taken over.
+
+> **Note**: Each `ui-prop` corresponds to one property, to display multiple properties you need to define multiple `ui-props`.
+
+### Manual Rendering
+
+In the above auto-rendering example, we used a special `ui-prop` of type `dump` for rendering data submission, which allows us to quickly take over the rendering of the component, but if we face some extreme cases but it is difficult to handle some details, we can switch to manual rendering mode, the code is as follows:
+
+```typescript
+'use strict';
+
+type Selector<$> = { $: Record }
+
+export const template = `
+
+
+
+
+
+`;
+
+export const $ = {
+ label:'.label',
+ test: '.test',
+ testInput: '.test-input',
+};
+
+type PanelThis = Selector & { dump: any };
+
+export function update(this: PanelThis, dump: any) {
+ // Cache 'dump' data, please hang on 'this', otherwise there may be problems when multiple opening
+ this.dump = dump;
+ // Pass the 'dump' data to the prop element that helped submit the data
+ this.$.test.dump = dump.value.label;
+ // Update the data on the input element responsible for 'input' and display
+ this.$.testInput.value = dump.value.label.value;
+ this.$.label.value = dump.value.label.name;
+}
+export function ready(this: PanelThis) {
+ // Listen for commit events on the input, update the dump data when the input commits data, and use prop to send change-dump events
+ this.$.testInput.addEventListener('confirm', () => {
+ this.dump.value.label.value = this.$.testInput.value;
+ this.$.test.dispatch('change-dump');
+ });
+}
+```
+
+Manual rendering mode still requires data to be submitted via a `ui-prop` element of type `dump`. However, the `html` layout in the `template` is a completely free-handed content that can be displayed in very complex ways depending on the requirements.
+> **Note 1**: If you do not modify `this.$.test.dump = dump.value.label`, `this.$.test.dispatch('change-dump')` won't actually do anything.
+> **Note 2**: If you wish to modify a more complex field, such as a `cc.JsonAsset`, yoiu need to do `this.$.testJsonInput.value = dump.value.testJson.value.uuid`. Since the value from the acutal asset won't fit the controller there.
+
+
+## Customizing Asset rendering
+
+When a file is selected in the **Assets** panel, the **Inspector** panel will display the important properties of the currently selected file, or we can customize the rendering if the default display does not meet the requirements.
+
+Add the `contributions.section.asset` field to `package.json` and define a custom rendering script for the corresponding asset type as follows:
+
+```json
+{
+ "contributions": {
+ "inspector": {
+ "section": {
+ "asset": {
+ "effect": "./dist/contributions/inspector/asset-effect.js"
+ }
+ }
+ }
+ }
+}
+```
+
+`effect` indicates that we want to customize the rendering of the asset inspector panel for the Cocos Effect (*.effect) file type. Common asset file types are as follows.
+- `scene` - Scene files
+- `typescript` - TypeScript script files
+- `prefab` - prefab files
+- `fbx` - FBX files
+- `material` - material files
+- `directory` - folder
+- `image` - image files
+
+> **Note**: Currently, you can't add new assets. Those listed above are the only extensible assets for this time.
+
+You can get the type definition of the file by looking at the `importer` field in the `*.meta` corresponding to the file.
+
+Next, create a new `src/contributions/inspector/asset-effect.ts` script file in the extension directory and write the following code:
+
+```typescript
+'use strict';
+
+interface Asset {
+ displayName: string;
+ file: string;
+ imported: boolean;
+ importer: string;
+ invalid: boolean;
+ isDirectory: boolean;
+ library: {
+ [extname: string]: string;
+ };
+ name: string;
+ url: string;
+ uuid: string;
+ visible: boolean;
+ subAssets: {
+ [id: string]: Asset;
+ };
+}
+
+interface Meta {
+ files: string[];
+ imported: boolean;
+ importer: string;
+ subMetas: {
+ [id: string]: Meta;
+ };
+ userData: {
+ [key: string]: any;
+ };
+ uuid: string;
+ ver: string;
+}
+
+type Selector<$> = { $: Record } & { dispatch(str: string): void, assetList: Asset[], metaList: Meta[] };
+
+export const $ = {
+ 'test': '.test',
+};
+
+export const template = `
+
+ Test
+
+
+`;
+
+type PanelThis = Selector;
+
+export function update(this: PanelThis, assetList: Asset[], metaList: Meta[]) {
+ this.assetList = assetList;
+ this.metaList = metaList;
+ this.$.test.value = metaList[0].userData.test || false;
+};
+
+export function ready(this: PanelThis) {
+ this.$.test.addEventListener('confirm', () => {
+ this.metaList.forEach((meta: any) => {
+ // Modify the data in the corresponding meta
+ meta.userData.test = !!this.$.test.value;
+ });
+ // The Assets panel is modifying the meta file of the asset, not the dump data, so the event sent is not the same as the component property modification
+ this.dispatch('change');
+ });
+};
+
+export function close(his: PanelThis, ) {
+ // TODO something
+};
+```
+
+After compiling and refreshing the extension, go back to the Cocos Creator editor interface, select one of the `Cocos Effect` files, and you can find an additional **Test checkbox** at the bottom of the **Inspector** panel.
+
+> **Note**: Multiple extensions register data side by side. If a **Component**/**Asset** already has a custom renderer, any custom renderers registered again will be appended to it. If a **Component**/**Asset** does not have a custom renderer built-in and uses the default renderer, then when the extension registers a custom renderer, it takes over the rendered content completely.
diff --git a/versions/4.0/en/editor/extension/install.md b/versions/4.0/en/editor/extension/install.md
new file mode 100644
index 0000000000..389a318090
--- /dev/null
+++ b/versions/4.0/en/editor/extension/install.md
@@ -0,0 +1,82 @@
+# Install and Share
+
+## Install Location
+
+Cocos Creator will search and load extensions under **Global** and **Project** paths during project startup.
+
+### Global
+
+If you need to apply an extension to all Cocos Creator projects, you can choose to place the extension package in the **Global** extension package path at
+
+- **Windows**: `%USERPROFILE%\.CocosCreator\extensions`
+- **macOS**: `$HOME/.CocosCreator/extensions`
+
+### Project
+
+If you only wish to apply the extension to the specified project, you can choose to place the extension package in the **Project** extension package path at.
+
+- `${your project address}/extensions`
+
+## Installing extensions
+
+Extensions can be obtained in three ways.
+- Other developers packaged and shared, see [Packaged Extensions](#Package%20extensions) below.
+
+- Download from **Dashboard -> Store**.
+
+ 
+
+- Downloaded from the [Cocos Store](http://store.cocos.com) page.
+
+After getting the extension zip file, click **Extension -> Extension Manager** in the top menu bar of the editor.
+
+
+
+Clicking on it opens the **Extension Manager** panel as shown below.
+
+
+
+In the **Extension Manager**, select the **Projects**/**Global** (1 above) tab and click the **+** (3 above) button.
+
+In the file selection box that pops up, select the extension zip you want to import and click the **Open** button to import it.
+
+The imported extension zip will be extracted and placed in the specified [installation location](#Install%20Location).
+
+Finally, find the extension in the **Project**/**Global** tab of the corresponding **Extension Manager** and click the **Enable** button on the right side, the extension you just imported will run normally. As shown in the figure below.
+
+
+
+## Uninstall installed extensions
+
+Find the extension you want to delete in **Extension Manager** and click the **Delete button**  to do so, and the folder where the extension is located will also be deleted. If you only need to disable it, you can just select "Close".
+
+## Reload extensions
+
+If the content of the extension has been modified, it will not be updated automatically, so you need to reload the extension once manually inside the editor.
+
+Find the corresponding extension in the **Extension Manager** and click the **Reload button** , then the extension will be re-run with the latest code and files in the editor.
+
+## Package extensions
+
+After writing an extension, if you want to share it with other users, you need to package the extension as a zip archive.
+
+Let's take the `first-panel` extension as an example, its directory structure is as follows.
+
+
+
+Go to the extension root directory, select the appropriate files and zip all files as follows (screenshot for macOS, same for all other platforms)
+
+
+
+The files (folders) selected in the above diagram are mandatory, none of them are required, and they serve the following purposes.
+- `dist` - Generated javascript code.
+- `i18n` - Multilanguage configuration.
+- `node_modules` - dependent Node.js modules.
+- `package.json` - Extension description file.
+- `static` - Static resource files.
+
+Name the zip package `first-panel.zip` (same name as the extensions folder is recommended) and share it with others or upload it to the Cocos Store to finish sharing.
+
+> **Note**: You have to do the file selection operation in the directory of the extension, otherwise it may lead to incorrect directory structure.
+
+If you want to upload the extension to the [Cocos Store](https://store.cocos.com), please refer to the document [Submitting Resources to Cocos Store](./store/upload-store.md).
diff --git a/versions/4.0/en/editor/extension/messages.md b/versions/4.0/en/editor/extension/messages.md
new file mode 100644
index 0000000000..e4da2d3d1c
--- /dev/null
+++ b/versions/4.0/en/editor/extension/messages.md
@@ -0,0 +1,141 @@
+# Message System
+
+There are many independent processes running in Cocos Creator, and they are isolated from each other. When you need to interact with other functions within the editor, you need to do so through the "messaging mechanism".
+
+The "Message System" in the editor is a functional extension of the IPC (Inter-Process Communication) wrapper. This system carries the burden of communication and interaction within the editor.
+
+For more information about multi-process architecture and cross-process communication, please refer to the document [Extension Infrastructure](./package.md).
+
+## Message Types
+
+There are two types of messages within the Cocos Creator system.
+
+1. Normal message: a message is sent to a function (extension) on its own initiative
+2. Broadcast messages: a function (extension) sends a notification to everyone that an operation has been completed
+
+### Normal messages
+
+It can be understood as an external interface, for example the engine's **Scene Editor** module has defined a `query-node` message for querying nodes, as follows:
+
+```json
+{
+ "name": "scene",
+ "contributions": {
+ "messages": {
+ "query-node": {
+ "methods": ["queryNode"]
+ }
+ }
+ }
+}
+```
+
+For more information on how to customize messages and the meaning of the message fields, please refer to the document [Customized Messages](./contributions-messages.md).
+
+When we want to query a scene node in an extension we have written, we can use this message to do so, as follows:
+
+```typescript
+const info = await Editor.Message.request('scene', 'query-node', uuid);
+```
+
+This message is similar to a remote process call (RPC), where the `info` object is part of the data on the actual node being queried.
+
+> **Note**: Since this is a remote call, `request` will not return immediately, so you need to use `await` to convert asynchronous to synchronous.
+
+#### Naming Convention for Normal Messages
+
+Please use **lowercase** words, and no special characters, with **-** concatenated between words. For example, `open-panel`, `text-changed`.
+
+### Broadcast Messages
+
+A broadcast message is a notification to the outside world after the completion of an operation within a function.
+
+#### Receive Broadcast Messages
+
+For example, if the **Scene Editor** needs to notify everyone that a scene has been started after it has been started, the **Scene Editor** sends a broadcast message using the following code.
+
+```typescript
+Editor.Message.broadcast('scene:ready', sceneUUID);
+```
+
+If an extension wants to receive `scene:ready` messages, they need to be defined first in `package.json`, as follows:
+
+```json
+{
+ "name": "hello-world",
+ "contributions": {
+ "messages": {
+ "scene:ready": {
+ "methods": ["initData"]
+ }
+ }
+ }
+}
+```
+
+The broadcast `scene:ready` message triggers the `initData` method in the "hello-world" extension whenever the scene is ready.
+
+#### Sending Broadcast Messages
+
+If an extension wants to send a broadcast message, it also needs to be defined in `package.json` first.
+
+For example, "hello-world" will broadcast a message to other extensions when it is ready for data. As shown below:
+
+```json
+{
+ "name": "hello-world",
+ "contributions": {
+ "messages": {
+ "scene:ready": {
+ "methods": ["initData"]
+ },
+ "hello-world:ready": {
+ "public": true,
+ "description": "hello-world ready notification."
+ }
+ }
+ }
+}
+```
+
+At the appropriate time, the following code is called within the "hello-world" extension to broadcast to everyone.
+
+```typescript
+Editor.Message.broadcast('hello-world:ready');
+```
+
+> **Note**: Broadcast messages can have no `methods`, which means they don't listen. As shown in the definition above, it means that "hello-world" does not need to listen for its own initialization completion message.
+
+#### Naming Convention for Broadcast Messages
+
+The format is `packageName:actionName`, and the following naming is legal.
+- scene:ready
+- scene:query-node
+- hello-world:ready
+- hello-world:data-loaded
+
+Adding `packageName` prevents naming conflicts and makes it more intuitive to see which extension is listening to which broadcast message (action) when defining messages in `package.json`.
+
+## View the List of Messages
+
+The list of messages that are available to the editor and extensions can be viewed in the **Developer -> Message Manager** panel. For detailed definition rules, please refer to the documentation [Custom Messages](./contributions-messages.md).
+
+## Sending Messages in Code
+
+The `send` method only sends the message and does not wait for a return. Use this method if you don't need to return data and don't care if execution completes.
+
+```typescript
+Editor.Message.send(pkgName, message, . .args);
+```
+
+The `request` method returns a promise object that receives the data returned after the message has been processed.
+
+```typescript
+await Editor.Message.request(pkgName, message, . . args);
+```
+
+The `broadcast` method only sends, and sends to all function extensions that listen for the corresponding message.
+
+```typescript
+Editor.Message.broadcast(`${pkgName}:${actionName}`, . .args);
+```
diff --git a/versions/4.0/en/editor/extension/package.md b/versions/4.0/en/editor/extension/package.md
new file mode 100644
index 0000000000..bf9ab4e2a1
--- /dev/null
+++ b/versions/4.0/en/editor/extension/package.md
@@ -0,0 +1,41 @@
+# Extension Infrastructure
+
+Before writing an extension, we first need to understand the infrastructure of extensions within Cocos Creator.
+
+## Electron
+
+The Cocos Creator editor is based on the [Electron](https://github.com/atom/electron) kernel from GitHub.
+
+Electron is a cross-platform development framework that integrates with [Node.js](https://nodejs.org/) and [Google Chromium](https://github.com/chromium/chromium).
+
+## Multi-process Mechanism
+
+In Electron's architecture, an application consists of a main process and a rendering process, with the main process managing platform-related scheduling, such as window opening and closing, menu options, basic dialogs, and so on. Each newly opened window is a separate rendering process. Each process has its own JavaScript content and is not directly accessible to each other. When data needs to be passed between processes, the Inter-Process Communication (IPC) mechanism is used.
+
+You can read [Electron's introduction document](https://github.com/atom/electron/blob/master/docs/tutorial/quick-start.md) for a more in-depth understanding of the features The relationship between the main process and the rendering process in Electron.
+
+To put it simply, the main process in Electron is equivalent to a Node.js server application, while each window (rendering process) is equivalent to a client-side web application.
+
+The Cocos Creator editor follows the structure of Electron's main process and rendering process. So when the extension is started and run inside the editor, the main defined by the extension is actually started in the main process, while the panels defined by the panels are started in the rendering process. The process structure is briefly summarized as follows.
+
+
+
+## Inter-process Communication
+
+Inter-process communication is actually the process of sending a message in one process and listening to it in another process.
+
+Electron provides modules `ipcMain` and `ipcRenderer` for inter-process communication to help us with this task.
+
+Since these two modules only perform very basic communication functions and do not satisfy the communication needs between the editor, extension panel and the main process, Cocos Creator wraps this and extends the method of sending and receiving messages between processes to make it easier for extension developers and editor developers to create more complex scenarios. For more details, please see the documentation [Message System](./messages.md).
+
+## Capabilities of extensions
+
+With a full Node.js environment inside the extension, it is easy to use the large number of tools available on the npm marketplace for the functionality you want.
+
+If you need to interact with other features, you need to open up the corresponding operation messages for the corresponding features, and we do this within our own extension, via [Message System](./messages.md) to trigger, query and process functions or data in the editor.
+
+The list of opened messages can be viewed in the top menu **Developer -> Message Manager** panel, as shown below.
+
+
+
+
diff --git a/versions/4.0/en/editor/extension/panel-boot.md b/versions/4.0/en/editor/extension/panel-boot.md
new file mode 100644
index 0000000000..fc1cc75c1c
--- /dev/null
+++ b/versions/4.0/en/editor/extension/panel-boot.md
@@ -0,0 +1,326 @@
+# Creating a Custom Panel
+
+We have already written the panel definition in [package.json](./panel.md), it's time to implement the panel's logical functionality.
+
+It is time to identify the main entry file in the panel definition and fill it with the following content.
+
+Javascript
+
+```javascript
+'use strict';
+
+// html text
+exports.template ='';
+// style text
+exports.style ='';
+// html selector after rendering
+exports.$ = {};
+// method on the panel
+exports.methods = {};
+// event triggered on the panel
+exports.listeners = {};
+
+// Triggered when the panel is rendered successfully
+exports.ready = async function() {};
+// Triggered when trying to close the panel
+exports.beforeClose = async function() {};
+// Triggered when the panel is actually closed
+exports.close = async function() {};
+```
+
+Typescript
+
+```typescript
+'use strict';
+
+// html text
+export const template = '';
+// style text
+export const style = '';
+// html selector after rendering
+export const $ = {};
+// method on the panel
+export const methods = {};
+// event triggered on the panel
+export const listeners = {};
+
+// Triggered when the panel is rendered successfully
+export async function ready() {};
+// Triggered when trying to close the panel
+export async function beforeClose() {};
+// Triggered when the panel is actually closed
+export async function close() {};
+```
+
+If we are using Typescript, when this is not correctly identified within functions such as ready, we can add the definition of this:
+
+```typescript
+'use strict';
+
+type Selector<$> = { $: Record }
+
+export const $ = {
+ test: '.test',
+};
+
+export const methods = {
+ update() {},
+};
+
+export async function ready(this: Selector & typeof methods) {
+ this.update();
+};
+```
+
+You can also use Editor.Pabel.define for common panel objects.
+
+```typescript
+module.exports = Editor.Panel.define({
+ methods: {
+ update() {},
+ },
+ ready() {
+ this.update();
+ },
+});
+```
+
+`Editor.Panel.define` is a new interface added in v3.3.
+
+## template
+
+html text, e.g.
+
+Javascript
+
+```javascript
+exports.template = `
+
+ Header
+
+
+ Section
+
+`;
+```
+
+Typescript
+
+```typescript
+export const template = `
+
+ Header
+
+
+ Section
+
+`;
+```
+
+It is also possible to read an HTML file directly.
+
+Javascript
+
+```javascript
+const { readFileSync } = require('fs');
+const { join } = require('path');
+exports.template = readFileSync(join(__dirname, '../static/default.html'), 'utf8');
+```
+
+Typescript
+
+```typescript
+import { readFileSync } from 'fs';
+import { join } from 'path';
+export const template = readFileSync(join(__dirname, '../static/default.html'), 'utf8');
+```
+
+When the `template` is defined and the panel is opened, the content of the template will be automatically rendered to the interface.
+
+In addition, the editor also provides some custom elements, which can be used in the [UI components](./ui.md).
+
+## style
+
+With HTML, you need to customize some styles and use style, which is a string like template.
+
+Javascript
+
+```javascript
+exports.style = `
+header { padding: 10px; }
+`;
+```
+
+Typescript
+
+```typescript
+export const style = `
+header { padding: 10px; }
+`;
+```
+
+Of course, it is also possible to read a css file:
+
+Javascript
+
+```javascript
+const { readFileSync } = require('fs');
+const { join } = require('path');
+exports.style = readFileSync(join(__dirname, '../static/default.css'), 'utf8');
+```
+
+Typescript
+
+```typescript
+import { readFileSync } from 'fs';
+import { join } from 'path';
+export const style = readFileSync(join(__dirname, '../static/default.css'), 'utf8');
+```
+
+## $
+
+This is an HTML element selector that is used as a shortcut after calling `querySelector` directly to find the specified element.
+
+Javascript
+
+```javascript
+exports.$ = {
+ header: 'header',
+ test: '.test',
+};
+```
+
+Typescript
+
+```typescript
+export const $ = {
+ header: 'header',
+ test: '.test',
+};
+```
+
+First define the selector and the editor will automatically call `document.querySelector` after the template is rendered to find the corresponding element and hang it on `this.$`.
+
+Javascript
+
+```javascript
+exports.ready = function() {
+ console.log(this.$.header); //
+ console.log(this.$.test); //
+}
+```
+
+Typescript
+
+```typescript
+export function ready() {
+ console.log(this.$.header); //
+ console.log(this.$.test); //
+}
+```
+
+## methods
+
+Methods defined on the panel. The external functions of the panel need to be encapsulated as methods and made available to the public as functions. Messages can also trigger methods on the panel directly, see [custom messages](./contributions-messages.md).
+
+This object is full of functions, please don't mount other types of objects to it.
+
+Javascript
+
+```javascript
+const packageJSON = require('./package.json');
+exports.methods = {
+ open() {
+ Editor.Panel.open(packageJSON.name);
+ },
+};
+```
+
+Typescript
+
+```typescript
+import { name } from './package.json';
+export const methods = {
+ open() {
+ Editor.Panel.open(packageJSON.name);
+ },
+};
+```
+
+## listeners
+
+After the basic layout is completed, we sometimes need to update the state on some panels according to some circumstances, and this time we need to use the listeners function.
+
+Javascript
+
+```javascript
+exports.listeners = {
+ /**
+ * Triggered when the panel is hidden
+ */
+ hide() {
+ console.log(`hide: ${this.hidden}`);
+ },
+ /**
+ * Triggered when the panel is displayed
+ */
+ show() {
+ console.log(`hide: ${this.hidden}`);
+ },
+ /**
+ * Triggered when the panel size is changed
+ */
+ resize() {
+ console.log(`height: ${this.clientHeight}`);
+ console.log(`width: ${this.clientWidth}`);
+ },
+};
+```
+
+Typescript
+
+```typescript
+interface PanelInfo {
+ hidden: boolean;
+ clientHeight: number;
+ clientWidth: number;
+}
+
+export const listeners = {
+ /**
+ * Triggered when the panel is hidden
+ */
+ hide(this: PanelInfo) {
+ console.log(`hide: ${this.hidden}`);
+ },
+ /**
+ * Triggered when the panel is displayed
+ */
+ show(this: PanelInfo) {
+ console.log(`hide: ${this.hidden}`);
+ },
+ /**
+ * Triggered when the panel size is changed
+ */
+ resize(this: PanelInfo) {
+ console.log(`height: ${this.clientHeight}`);
+ console.log(`width: ${this.clientWidth}`);
+ },
+};
+```
+
+## ready
+
+This life cycle function will be triggered when the panel is ready.
+
+## beforeClose
+
+This function will be triggered when the panel tries to be closed. beforeClose can be an async function, which can make asynchronous judgments, and if return false, it will terminate the current close operation.
+
+Please don't execute the actual destruction and close related logic code in this function, this step is just to ask, please put the actual destruction in the close function.
+
+**Please use with caution** If you make a mistake, the editor or panel window may not close properly.
+
+## close
+
+When all panels in the window are allowed to close, it will trigger the close of the panel. Once the close is triggered, the window will be forcibly closed after the end, so please save the data in the close, and if there is an abnormal close, please make a backup of the data so that the data can be restored as much as possible when restarting.
diff --git a/versions/4.0/en/editor/extension/panel-messages.md b/versions/4.0/en/editor/extension/panel-messages.md
new file mode 100644
index 0000000000..dde917d135
--- /dev/null
+++ b/versions/4.0/en/editor/extension/panel-messages.md
@@ -0,0 +1,159 @@
+# Panel and Extension Communication
+
+> **NOTE**: After v3.5, we updated the plugin documentation, so this documentation is deprecated, please move to [Message System](./messages.md) or [Customized Messages](./contributions-messages.md) for more information. If you see this document online, please post an issue on [github](https://github.com/cocos/cocos-docs/issues/new) and let the official staff know how to handle it.
+
+Some useful tools or simple functions can be written directly on the panel, but the panel is not a reliable data storage location. The window may be closed at any time, and the panel will also be closed.
+
+The most common example is that a panel is dragged and docked to the main window. At this time, the panel will be closed first and then reopened in the main window. If the data in the memory used on the panel is not stored and backed up, it will be lost with restart.
+
+At this time, a certain degree of data interaction is required with the extended main body.
+
+Before reading this chapter, please review the [Message System](./messages.md) documentation.
+
+## Define the method of extending the top and panel
+
+**First**, define a `package.json`:
+
+```json
+{
+ "name": "hello-world",
+ "main": "./browser.js",
+ "panels": {
+ "default": {
+ "title": "hw",
+ "main": "./panel.js"
+ }
+ },
+ "contributions": {
+ "messages": {
+ "upload": {
+ "methods": ["saveData"]
+ },
+ "query": {
+ "methods": ["queryData"]
+ }
+ }
+ }
+}
+```
+
+**Second**, define the extended main file `browser.js`:
+
+```javascript
+exports.methods = {
+ saveData(path, data) {
+ // Cache it after receiving the data
+ this.cache[path] = data;
+ },
+ queryData(path) {
+ const result = this.cache[path];
+ delete this.cache[path];
+ return result;
+ },
+};
+
+exports.load = function() {};
+exports.unload = function() {};
+```
+
+Typescript
+
+```typescript
+interface PackagelItem {
+ cache: {
+ [path: string]: any;
+ }
+}
+export const methods = {
+ saveData(this: PackagelItem, path: string, data: any) {
+ // 收到数据后缓存起来
+ this.cache[path] = data;
+ },
+ queryData(this: PackagelItem, path: string) {
+ const result = this.cache[path];
+ delete this.cache[path];
+ return result;
+ },
+};
+
+export function load() {};
+export function unloal() {};
+```
+
+**Last**, define the main file of the panel:
+
+```javascript
+const packageJSON = require('./package.json');
+exports.ready = async () => {
+ const tab = await Editor.Message.request(packageJSON.name, 'query', 'tab');
+ const subTab = await Editor.Message.request(packageJSON.name, 'query', 'subTab');
+
+ // Print the queried data
+ console.log(tab, subTab):
+ // TODO uses these two data to initialize
+};
+exports.close() {
+ // Upload the data to the extension process after receiving the data
+ Editor.Message.send(packageJSON.name, 'upload', 'tab', 1);
+ Editor.Message.send(packageJSON.name, 'upload', 'subTab', 0);
+};
+```
+
+Typescript
+
+```typescript
+import { name } from './package.json';
+exports.ready = async () => {
+ const tab = await Editor.Message.request(name, 'query', 'tab');
+ const subTab = await Editor.Message.request(name, 'query', 'subTab');
+ // 打印查询到的数据
+ console.log(tab, subTab):
+ // TODO 使用这两个数据初始化
+};
+exports.close() {
+ // 收到数据后上传到扩展进程
+ Editor.Message.send(name, 'upload', 'tab', 1);
+ Editor.Message.send(name, 'upload', 'subTab', 0);
+};
+```
+
+## Send a message
+
+After defining the extension and the panels in the extension, we can try to trigger these messages.
+
+Press **ctrl(cmd) + shift + i** to open the console. Open the panel in the console:
+
+```javascript
+// Default can be omitted, if the panel name is not default, you need to fill in'hello-world.xxx'
+Editor.Panel.open('hello-world');
+```
+
+After opening the panel, the console will print out a sentence:
+
+```sh
+undefined, undefined
+```
+
+This is because the data has not yet been submitted. Now, close this panel and open it again. At this time, the console prints out the data:
+
+```sh
+1, 0
+```
+
+Because when the panel is closed, two messages are sent:
+
+```javascript
+Editor.Message.send(packageJSON.name, 'upload', 'tab', 1);
+Editor.Message.send(packageJSON.name, 'upload', 'subTab', 0);
+```
+
+Through these two messages, the Message system first saves the data to the extension process according to the upload definition in messages `"methods": ["saveData"]`.
+
+When opening the panel again, use the following code to query for the data you just saved, initialize the interface, and print to the console.
+
+```javascript
+const tab = await Editor.Message.send(packageJSON.name, 'query', 'tab');
+const subTab = await Editor.Message.send(packageJSON.name, 'query', 'subTab');
+```
+
+At this point, we have completed an interaction between the panel and the extension process.
diff --git a/versions/4.0/en/editor/extension/panel.md b/versions/4.0/en/editor/extension/panel.md
new file mode 100644
index 0000000000..2255ebc8db
--- /dev/null
+++ b/versions/4.0/en/editor/extension/panel.md
@@ -0,0 +1,194 @@
+# Extension Panel
+
+By default, extensions do not have an interface to display. If an extension needs to implement interface interaction, it needs to use the panel system related functions.
+
+## Panel Definition
+
+One or more panels can be defined in `package.json` in the `panels` field, as follows:
+
+```json
+{
+ "name": "hello-world",
+ "panels": {
+ "default": {
+ "title": "world panel",
+ "type": "dockable",
+ "main": "./dist/panels/default",
+ "icon": "./static/default.png"
+ },
+ "list": {
+ "title": "world list",
+ "type": "simple",
+ "main": "./dist/panels/list",
+ "icon": "./static/list.png",
+
+ "flags": {},
+ "size": {}
+ }
+ }
+}
+```
+
+We define two panels: `defualt` and `list`. `default` is the default panel, which is used as the default action object when no specific panel is named.
+
+The meaning of the fields in the panel is as follows.
+- `title`: string - the title of the panel, supports i18n:key, required
+- `main`: string - the relative directory of the panel source code, required
+- `icon`: string - panel icon relative to directory, required
+- `type`: string - Panel type (dockable | simple), optional
+- `flags`: {} - flags, optional
+ - resizable - if or not the size can be changed, default true, optional
+ - save - if or not the panel needs to be saved, default false, optional
+ - alwaysOnTop - if or not to keep the top level displayed, default flase, optional
+- `size`: {} - size information, optional
+ - min-width: Number - the minimum width, optional
+ - min-height: Number - the minimum height, optional
+ - width: Number - the default width of the panel, optional
+ - height: Number - the default height of the panel, optional
+
+## Writing Panels
+
+Create two files `src/panels/default/index.ts` and `src/panels/list/index.ts` in the extension root directory, and paste the following minimal panel template code into each of the two `index.ts` files.
+
+```typescript
+
+module.exports = Editor.Panel.define({
+ listeners: {
+ show() { console.log('show'); },
+ hide() { console.log('hide'); },
+ },
+ template: '
Hello
',
+ style: 'div { color: yellow; }',
+ $: {
+ elem: 'div',
+ },
+ methods: {
+
+ },
+ ready() {
+
+ },
+ beforeClose() { },
+ close() { },
+});
+```
+
+`listeners` - some event listeners for the panel
+`template` - the panel's HTML layout file
+`style` - the panel's css file
+`$` - global selector for quick access to some elements
+`methods` - the external method interface for this panel
+`ready` - called when the panel is opened
+`beforeClose` - called before the panel is closed
+`close` - called after the panel is closed
+
+## Displaying panels
+
+You can use the `Editor.Panel.open` method to open any panel (this extension's own panels and other extensions' panels).
+
+Assuming the extension is `hello-world`, the default panel can be opened in either of the following ways:
+
+```typescript
+// Editor.Panel.open('hello-world.defualt');
+Editor.Panel.open('hello-world');
+```
+
+Open other panels by:
+
+```typescript
+// Editor.Panel.open('{extension-name}.panelName');
+Editor.Panel.open('hello-world.list');
+```
+
+## Communication Interaction
+
+The Cocos Creator extension system is built based on Electron's multi-process approach. Each extension is a separate process, and each panel in the extension, is also a separate process. Therefore, the interaction between extensions and panels and between panels and panels can only be achieved through Inter-Process Communication (IPC). For details, please refer to the document [Message System](./messages.md).
+
+### Panels send outgoing messages
+
+Since the process also exits when the panel is closed, we usually use the extension as a carrier for in-memory data. The data and logical interfaces that are needed in the panel will usually be fetched from the extension's main process.
+
+If you want to **query** and **set** the data located in the main process of the extension, assuming the extension defines two messages ``queryData` and `saveData`, we can use them as follows
+
+```typescript
+const data = await Editor.Message.request(packageName, 'queryData', dataName);
+await Editor.Message.request(packageName, 'saveData', dataName,dataValue);
+```
+
+If you want to broadcast notifications to the entire extension system, you can do so using the **broadcast message** mechanism, see the documentation [Messaging System](./messages.md).
+
+### Panel Receives Messages
+
+```json5
+// package.json
+{
+"contributions": {
+ "messages": {
+ "log": {
+ "methods": ["log"]
+ }
+ }
+ }
+}
+```
+
+The above message defines a log message, which is handled by the log method in the extended master process. Next we make a slight modification so that the recipient of the message is a panel:
+
+```json5
+// package.json
+{
+"contributions": {
+ "messages": {
+ "log": {
+ "methods": ["default.log"]
+ }
+ }
+ }
+}
+```
+
+`default.log` makes the message recipient a `default` panel, just implement a `log` method in the panel and you can handle this message smoothly.
+
+## A better way to organize panel resources
+
+In the minimalist panel template above, we have two lines of panel display-related code:
+
+```typescript
+module.exports = Editor.Panel.define({
+ ...
+ template: '
Hello
',
+ style: 'div { color: yellow; }',
+ ...
+});
+```
+
+In most cases, panel layouts cannot be this simple. If you continue to write complex HTML layouts and css styles here, the code will become unmaintainable. You can refer to the project created in the document [Getting Started Example - Panel](./first-panel.md), we can separate the `html` and `css` code into separate files and put them in the `static` folder.
+
+The resulting panel template code is shown below:
+
+```typescript
+import { readFileSync } from 'fs-extra';
+import { join } from 'path';
+
+module.exports = Editor.Panel.define({
+ listeners: {
+ show() { console.log('show'); },
+ hide() { console.log('hide'); },
+ },
+ template: readFileSync(join(__dirname, '../../../static/template/default/index.html'), 'utf-8'),
+ style: readFileSync(join(__dirname, '../../../static/style/default/index.css'), 'utf-8'),
+ $: {
+ app: '#app',
+ },
+ methods: {
+
+ },
+ ready() {
+
+ },
+ beforeClose() { },
+ close() { },
+});
+```
+
+For more details on the panel utility, please refer to [Getting Started Example - Panel](./first-panel.md).
diff --git a/versions/4.0/en/editor/extension/profile.md b/versions/4.0/en/editor/extension/profile.md
new file mode 100644
index 0000000000..cfc67c21b7
--- /dev/null
+++ b/versions/4.0/en/editor/extension/profile.md
@@ -0,0 +1,149 @@
+# Configuration System
+
+The Cocos Creator extension provides a configuration management mechanism for saving user settings and data in the extension.
+
+## Configuration Types
+
+There are two types of configuration types.
+1. editor configuration (editor)
+2. project configuration (project)
+
+### Editor Configuration
+
+The editor configuration is used to store some editor-related user settings and data, and is divided into three priority levels, from high to low, as follows.
+
+```
+local -> global -> default
+```
+
+If there is no corresponding configuration in `local`, the configuration in `global` will be used, and if no corresponding configuration in `global` is found, the default `default` configuration will be used.
+
+### Project Configuration
+
+The project configuration is used to store some project-related user settings and data, and is divided into two priority levels, from highest to lowest.
+
+```
+local -> default
+```
+
+Similar to the rules of **Editor Configuration**, when fetching configuration data, the configuration item in `local` will be used first, and if there is no corresponding configuration item in `local`, the default `default` configuration will be used.
+
+## Registering Configuration
+
+To use the configuration system, you need to define the `profile` information in the `contributions` field of the extension definition file `package.json`, as follows.
+
+```json
+{
+ "name": "hello-world",
+ "contributions": {
+ "profile": {
+ "editor": {
+ "test.a": {
+ "default": 0,
+ "message": "editorTestAChanged",
+ "label": "Test Editor configuration"
+ }
+ },
+ "project": {
+ "test.a": {
+ "default": 1,
+ "message": "projectTestAChanged",
+ "label": "Test Project Configuration"
+ }
+ }
+ }
+ },
+}
+```
+
+**contributions.profile** The related fields are interpreted as follows.
+- `editor`:{} - editor configuration
+- `project`:{} - project configuration
+- `test.a`:{} - key for the configuration of test.a
+- `default`:any - the default value of this configuration item, optional parameter
+- `message`:string - the message that will be triggered when this configuration item is modified, optional
+- `label`:string - where the configuration can be displayed, this description may be displayed. Supports i18n:key format, optional parameters
+
+The TypeScript interface associated with `profile` is defined as follows.
+
+```typescript
+interface ProfileInfo {
+ editor: { [ key: string ]: ProfileItem };
+ project: { [ key: string ]: ProfileItem };
+}
+
+interface ProfileItem {
+ // Default data for configuration
+ default: any;
+ // This message is automatically sent for notification of configuration changes
+ message: string;
+ // A simple description of the role of configuration information, supporting the i18n:key syntax
+ label: string;
+}
+```
+
+## Read and Modify Configuration
+
+### Importing Extension Definitions
+
+```typescript
+import packageJSON from '../package.json';
+```
+
+If the last parameter of `Editor.Profile.getConfig` is empty, a [priority](#Editor%20Configuration) match will be performed.
+
+If the fetch location (one of `local`, `global`, `default`) is specified, the corresponding value will be returned. As shown below, `local` and `global` are `undefined` because they are not set.
+
+```typescript
+await Editor.Profile.getConfig(packageJSON.name, 'test.a'); // 0
+await Editor.Profile.getConfig(packageJSON.name, 'test.a', 'local'); // undefined
+await Editor.Profile.getConfig(packageJSON.name, 'test.a', 'global'); // undefined
+```
+
+### Modify the Editor Configuration
+
+Call `getConfig` after modifying the configuration with the following code to see the corresponding changes.
+
+```typescript
+await Editor.Profile.setConfig(packageJSON.name, 'test.a', 1);
+await Editor.Profile.setConfig(packageJSON.name, 'test.a', 'local', 2);
+await Editor.Profile.setConfig(packageJSON.name, 'test.a', 'global', 3);
+```
+
+### Read Project Configuration
+
+If the last parameter of `Editor.Profile.getProject` is empty, a [priority](#Project%20Configuration) match will be performed.
+
+If the fetch location (either `local`, `default`) is specified, the corresponding value will be returned. As shown below, the `local` is `undefined` because it is not set.
+
+```typescript
+await Editor.Profile.getProject(packageJSON.name, 'test.a'); // 1
+await Editor.Profile.getProject(packageJSON.name, 'test.a', 'local'); // undefined
+```
+
+### Modify the Project Configuration
+
+Call `getProject` after modifying the configuration with the following code to see the corresponding changes.
+
+```typescript
+await Editor.Profile.setProject(packageJSON.name, 'test.a', 1);
+await Editor.Profile.setProject(packageJSON.name, 'test.a', 'local', 2);
+```
+
+## Storage Paths
+
+### Editor Configuration Storage Path
+
+| Hierarchy | Path |
+| ------- | ------------------------------------------------------------ |
+| local | `{projectPath}/profiles/v2/extensions/{extensionName}.json` |
+| global(mac) | `Users/{name}/.CocosCreator/profiles/v2/extensions/{extensionName}.json` |
+| global(window) | `c/Users/{name}/.CocosCreator/profiles/v2/extensions/{extensionName}.json` |
+| default | `{extensionPath}/package.json` |
+
+### Project Configuration Storage Path
+
+| Hierarchy | Path |
+| ------- | ----------------------------------------------------------- |
+| local | `{projectPath}/settings/v2/extensions/{extensionName}.json` |
+| default | `{extensionPath}/package.json` |
diff --git a/versions/4.0/en/editor/extension/readme.md b/versions/4.0/en/editor/extension/readme.md
new file mode 100644
index 0000000000..ca3b1d9e21
--- /dev/null
+++ b/versions/4.0/en/editor/extension/readme.md
@@ -0,0 +1,13 @@
+# Editor Extension
+
+This section focuses on extending the editor, including the following:
+
+- [Extension Manager](./extension-manager.md)
+- [The First Extension](./first.md)
+- [First Panel](./first-panel.md)
+- [First Data Interaction](./first-communication.md)
+- [Change the Name of a Extension](./extension-change-name.md)
+- [Install and Share](./install.md)
+- [Extended Panel](./panel.md)
+- [Contributions](./contributions.md)
+- [Basic](./basic.md)
diff --git a/versions/4.0/en/editor/extension/scene-script.md b/versions/4.0/en/editor/extension/scene-script.md
new file mode 100644
index 0000000000..205e96a9a9
--- /dev/null
+++ b/versions/4.0/en/editor/extension/scene-script.md
@@ -0,0 +1,89 @@
+# Calling the Engine API and Project Script
+
+In the extension you can define a special **scene script** file, which will be in the same runtime as the scripts in the `assets\` directory of the project, with the same runtime environment.
+
+In the **Scene Script** you can call the engine `API` and other project scripts, and with this feature we can
+
+- Query and traverse the nodes in the scene to get or modify node data
+- Call functions related to the engine components on the node to finish the job
+
+## Register Scene Script
+
+First, add a `scene` field to the `contributions` property of `package.json`, the value of which is the path to a script file, relative to the extension package directory. Example:
+
+```json
+{
+ "contributions": {
+ "scene": {
+ "script": "./dist/scene.js"
+ }
+ }
+}
+```
+
+## Scene Script Template
+
+Create a new `scene.ts` in the `src` directory and write the following code.
+
+```typescript
+export function load() {};
+export function unload() {};
+export const methods = { };
+```
+
+`load` - the function that fires when the module is loaded
+
+`unload` - the function that fires when the module is unloaded
+
+`methods` - methods defined inside the module that can be used to respond to external messages
+
+## Calling the Engine API
+
+Next, we will demonstrate how the scene script calls the engine API by rotating the main camera.
+
+In order to call the engine API, we need to add the search path of the engine script at the beginning of `scene.ts` and write the corresponding code, which ends up looking like this
+
+```typescript
+import { join } from 'path';
+module.paths.push(join(Editor.App.path, 'node_modules'));
+
+export function load() {};
+
+export function unload() {};
+
+export const methods = {
+ rotateCamera() {
+ const { director } = require('cc');
+ let mainCamera = director.getScene().getChildByName("Main Camera");
+ if(mainCamera){
+ let euler = new Vec3();
+ euler.set(mainCamera.eulerAngles.x, mainCamera.eulerAngles.y + num, mainCamera.eulerAngles.z);
+ mainCamera.setRotationFromEuler(euler);
+ return true;
+ }
+ return false;
+ },
+};
+```
+
+In the above code, we have defined a `rotateCamera` method that rotates the main camera `10` degrees around the `Y` axis every time it is executed.
+
+In other extension scripts, we can call the `rotateCamera` function with the following code.
+
+```typescript
+const options: ExecuteSceneScriptMethodOptions = {
+ name: packageJSON.name,
+ method: 'rotateCamera',
+ args: []
+};
+
+// result: {}
+const result = await Editor.Message.request('scene', 'execute-scene-script', options);
+```
+
+The properties of `ExecuteSceneScriptMethodOptions` are defined as follows:
+- name - the package name of the extension where `scene.ts` is located, you can use `packageJSON.name` if it is in this extension
+- method: the method defined in `scene.ts`
+- args: arguments, optional
+
+As the communication between extensions is based on Electron's underlying cross-process IPC mechanism, the transferred data will be serialized as JSON. so the transferred data must not contain native objects, otherwise it may lead to process crashes or memory spikes. It is recommended to transfer only pure `JSON` objects, such as the `options.args` parameter in the above code and the return value of the scenario script method.
diff --git a/versions/4.0/en/editor/extension/store/upload-store.md b/versions/4.0/en/editor/extension/store/upload-store.md
new file mode 100644
index 0000000000..21a6917c09
--- /dev/null
+++ b/versions/4.0/en/editor/extension/store/upload-store.md
@@ -0,0 +1,77 @@
+# Submitting Resources to Cocos Store
+
+Cocos Creator has a built-in **Extension Store** for users to browse, download and automatically install official or third-party extensions and resources. Users can also submit their own extensions, art materials, music and sound effects to the extension store for sharing or selling. Here is an example of submitting an extension.
+
+
+
+## Packaging the Extension
+
+Suppose the developer completes a extension package with the following directory structure:
+
+```
+foobar
+ |--panel
+ |--index.js
+ |--package.json
+ |--main.js
+```
+
+Developers need to package the `foobar` folder into a `foobar.zip` file and submit it to the Cocos Developer Center.
+
+For additional information on extension packages, please review the [Creating Extension Packages](../first.md) documentation.
+
+### Third-party Libraries
+
+There is currently no workflow for installing an included management system such as NPM in the extension package installation system, extension packages that use third-party libraries should be packaged in a zip package with folders such as `node_modules`.
+
+## Submitting the Extension
+
+Visit the [Cocos Developer Center](https://auth.cocos.com/#/) and login. Next, visit the [Store](https://store-my.cocos.com/#/seller/resources/) section and click **Create New Resource** on the top right.
+
+
+
+- First, go to the **Category** page, fill in the **Name** and **Category**, and check the agreement checkbox.
+
+ 
+
+ - **Name**: the name of the extension to be displayed in the extension store. Please note that the name cannot be changed once it is confirmed, please fill it in carefully.
+ - **Category**: the category of the resource to be submitted, choose **Creator Extension -> Plugins** here.
+
+ Click **Next** after the settings are done to enter the **Introduction** page.
+
+- Second, fill in the relevant information on the **Introduction** page.
+
+ 
+
+ - **Keyword**: facilitate users to search for your extension faster, support multiple keywords
+ - **Supported Platforms**: including Android, iOS, HTML5
+ - **Icon**: icon size of **256 * 256**, size no more than **500KB**, **PNG** format.
+ - **Screenshots**: upload a maximum of **5** screenshots in **jpg**/**png** format. The size of each screenshot is limited to a minimum of **640px** and a maximum of **2048px**, and the size should not exceed **1000KB**.
+ - **Description**: fill in the basic functions and usage of the extension. It includes **Chinese** and **English** languages, and will only be displayed in the extension store of the corresponding language version after filling it in. The Extension Store has certain formatting requirements for the descriptions of plugins, please refer to the [plugin description template [cn]](https://store.cocos.com/document/zh/cocos-store-template-extension.html) documentation for details.
+
+ Click **Next** to enter the **Pricing** page after filling out the form.
+
+- Third, in the **Pricing** page, set the price of the extension, including **CNY** and **USD**, if it is free, please fill in **0**.
+
+ 
+
+ Click **Next** to enter the **Upload** page after completing the form.
+
+- Fourth, on the **Upload** page, upload the extensions and fill in the relevant information.
+
+ 
+
+ - **Package**: zip format, max 100MB.
+ - **Extension Name**: the name of the extension package, defined in the `package.json` file of the extension package.
+ - **Version Number**: extension version number, defined in the `package.json` file of the extension package. Please follow the [semver specification](https://semver.org/) for the writing specification.
+ - **Creator Minimum Version Requirement**: the extension's requirement for Creator version.
+
+ > **Note**: since Creator 2.x and 3.x extensions are not compatible with each other, if there is no corresponding version of the supported extension package, the work will not be displayed in the corresponding version of the extension store of Creator.
+
+ Click **Next** to go to the **Submit for Review** page after completing the form.
+
+- Fifth, on the **Submit for Review** page, click the **Submit Review** button, or click the **View** button to re-edit the extension resource.
+
+ 
+
+- Lastly, after submitting for review, the extension store management will review the extension content and information within **3** business days.
diff --git a/versions/4.0/en/editor/extension/to-panel-messages.md b/versions/4.0/en/editor/extension/to-panel-messages.md
new file mode 100644
index 0000000000..a47fd0cda7
--- /dev/null
+++ b/versions/4.0/en/editor/extension/to-panel-messages.md
@@ -0,0 +1,90 @@
+# Communicate with the Panel
+
+> **NOTE**: After v3.5, we updated the extension documentation, so this documentation is deprecated, please move to [Message System](./messages.md) or [Customized Messages](./contributions-messages.md) for more information. If you see this document online, please post an issue on [github](https://github.com/cocos/cocos-docs/issues/new) and let the official staff know how to handle it.
+
+In general, the interaction model is dominated by **extension process** and **panel** for data presentation. Similarly to the traditional Web, the **plug-in** function is the server side, and the __panel__ function is the browser on the client's computer.
+
+In this case, there is usually no direct data sent to the panel, the majority is some state synchronization, just using **broadcast** to broadcast.
+
+But for simple extensions, or extensions to the browser environment, the actual functionality may be on the panel, and a request needs to be sent to the panel.
+
+Some level of understanding of the [Message System](./messages.md) is required before reading this section.
+
+## Define methods on extensions and panels
+
+First we define the file: `package.json`
+
+```json
+{
+ "name": "hello-world",
+ "panels": {
+ "default": {
+ "title": "hw",
+ "main": "./panel.js"
+ }
+ },
+ "contributions": {
+ "messages": {
+ "console": {
+ "methods": ["default.console"]
+ }
+ }
+ }
+}
+```
+
+The method name defined by methods in `messages.console` is `default.console`. Represents a console method issued to the `default` panel.
+(to send to the plug-in process, fill in `methdName` directly)
+
+Then define the `panel.js` file of the panel:
+
+```javascript
+exports.template = '';
+exports.style = '';
+
+exports.methods = {
+ console(str) {
+ console.log(str);
+ },
+};
+
+exports.ready = async function() {};
+
+exports.close = function() {};
+```
+
+Typescript
+
+```typescript
+export const template = '';
+export const style = '';
+
+export const methods = {
+ console(str: string) {
+ console.log(`console: ${str}`);
+ },
+};
+
+export async function ready() {};
+
+export function close() {};
+```
+
+## Send a message
+
+Once we have defined the extension and the panels within the extension, we can try to trigger these messages.
+
+Press **CTRL (CMD) + Shift + I** to open the console. Open the panel in the console:
+
+ ```javascript
+ // default can be omitted, if the panel name is non-default, then you need to fill in 'hello-world.xxx'
+ Editor.Panel.open('hello-world');
+ // Send a console message to the hello-world plugin
+ Editor.Message.send('hello-world', 'console', 'log');
+ ```
+
+When the **Hello World** plug-in receives a message, it passes it to the `methods.console` in `panel.js` for processing.
+
+The result is printing a string to the **log** on the console.
+
+At this point, we have completed one interaction with the panel.
diff --git a/versions/4.0/en/editor/extension/ui.md b/versions/4.0/en/editor/extension/ui.md
new file mode 100644
index 0000000000..c90f0624e2
--- /dev/null
+++ b/versions/4.0/en/editor/extension/ui.md
@@ -0,0 +1,50 @@
+# UI Components
+
+## UI Components Panel
+
+To facilitate the layout, many pre-defined UI components are provided within the editor.
+
+1. Find **Developer -> UI Components** in the main menu at the top of the editor to view them.
+
+
+
+2. Click it to open the following panel.
+
+! [ui component](image/ui-component.png)
+
+The panel consists of two parts, the left column lists the UI types currently supported by the engine, and the right column provides some examples that developers can use as needed.
+
+## Using in HTML
+
+Using UI components in HTML is very easy, just copy the corresponding code into your HTML file and you are ready to use.
+
+## Using in Extension Panel
+
+When extending the editor panel, it can be configured using json. In theory, all UI components with `value` attribute can be used to extend the editor panel, here are some common ones.
+
+### input-box
+
+- Component: `ui-num-input`
+- No additional properties
+
+### ui-slider
+
+- Component: `ui-slider`
+- `attributes` component attributes
+ - `min` minimum
+ - `max` maximum value
+ - `step` step length
+
+### ui-checkbox
+
+- Component: `ui-checkbox`
+- No additional properties
+
+### ui-select
+
+- Component `ui-select`
+- `items` list element
+ - `value` value
+ - `label` display label
+
+For usage examples, please refer to the documentation [Extending the Preferences Panel](./contributions-preferences.md) and [Extending Project Settings Panel](./contributions-project.md).
diff --git a/versions/4.0/en/editor/hierarchy/img/after.png b/versions/4.0/en/editor/hierarchy/img/after.png
new file mode 100644
index 0000000000..66204497b1
Binary files /dev/null and b/versions/4.0/en/editor/hierarchy/img/after.png differ
diff --git a/versions/4.0/en/editor/hierarchy/img/context-menu.png b/versions/4.0/en/editor/hierarchy/img/context-menu.png
new file mode 100644
index 0000000000..eda312e7cb
Binary files /dev/null and b/versions/4.0/en/editor/hierarchy/img/context-menu.png differ
diff --git a/versions/4.0/en/editor/hierarchy/img/create.png b/versions/4.0/en/editor/hierarchy/img/create.png
new file mode 100644
index 0000000000..92ad456f25
Binary files /dev/null and b/versions/4.0/en/editor/hierarchy/img/create.png differ
diff --git a/versions/4.0/en/editor/hierarchy/img/drop.png b/versions/4.0/en/editor/hierarchy/img/drop.png
new file mode 100644
index 0000000000..969cfaeaea
Binary files /dev/null and b/versions/4.0/en/editor/hierarchy/img/drop.png differ
diff --git a/versions/4.0/en/editor/hierarchy/img/drop1.png b/versions/4.0/en/editor/hierarchy/img/drop1.png
new file mode 100644
index 0000000000..dea4ec5af9
Binary files /dev/null and b/versions/4.0/en/editor/hierarchy/img/drop1.png differ
diff --git a/versions/4.0/en/editor/hierarchy/img/drop2.png b/versions/4.0/en/editor/hierarchy/img/drop2.png
new file mode 100644
index 0000000000..642a3372b2
Binary files /dev/null and b/versions/4.0/en/editor/hierarchy/img/drop2.png differ
diff --git a/versions/4.0/en/editor/hierarchy/img/hierarchy.png b/versions/4.0/en/editor/hierarchy/img/hierarchy.png
new file mode 100644
index 0000000000..e88acee20c
Binary files /dev/null and b/versions/4.0/en/editor/hierarchy/img/hierarchy.png differ
diff --git a/versions/4.0/en/editor/hierarchy/img/node-name.png b/versions/4.0/en/editor/hierarchy/img/node-name.png
new file mode 100644
index 0000000000..6590dca28f
Binary files /dev/null and b/versions/4.0/en/editor/hierarchy/img/node-name.png differ
diff --git a/versions/4.0/en/editor/hierarchy/img/rename.png b/versions/4.0/en/editor/hierarchy/img/rename.png
new file mode 100644
index 0000000000..9ba5d01e2a
Binary files /dev/null and b/versions/4.0/en/editor/hierarchy/img/rename.png differ
diff --git a/versions/4.0/en/editor/hierarchy/img/search-type.png b/versions/4.0/en/editor/hierarchy/img/search-type.png
new file mode 100644
index 0000000000..ae80a102c6
Binary files /dev/null and b/versions/4.0/en/editor/hierarchy/img/search-type.png differ
diff --git a/versions/4.0/en/editor/hierarchy/img/search.png b/versions/4.0/en/editor/hierarchy/img/search.png
new file mode 100644
index 0000000000..bcf4f9573d
Binary files /dev/null and b/versions/4.0/en/editor/hierarchy/img/search.png differ
diff --git a/versions/4.0/en/editor/hierarchy/img/thumb.gif b/versions/4.0/en/editor/hierarchy/img/thumb.gif
new file mode 100644
index 0000000000..cb2dce658c
Binary files /dev/null and b/versions/4.0/en/editor/hierarchy/img/thumb.gif differ
diff --git a/versions/4.0/en/editor/hierarchy/index.md b/versions/4.0/en/editor/hierarchy/index.md
new file mode 100644
index 0000000000..29c849c742
--- /dev/null
+++ b/versions/4.0/en/editor/hierarchy/index.md
@@ -0,0 +1,102 @@
+# Hierarchy Panel
+
+The **Hierarchy** panel consists of two main sections, the **Toolbar** and the **Node List**, which are used to show the relationships between the nodes that are editable in the current scene. There are still some private nodes in the scene that are not visible and will not be displayed here.
+
+You can single-select, multi-select, create, copy, move, delete and rename nodes. Any node can create a child node, whose coordinates are relative to the parent node and follow it.
+
+
+
+- When a node is selected, it is highlighted on a blue background and its detailed properties are displayed in the **Inspector** panel. Click on the blank area of the panel to **unselect** it.
+- Functions in the **Toolbar** include: **New Node(+)**, **Search Type**, **Search Box**, and **All Collapse**.
+- The **Node list** mainly reflects the hierarchical relationship of nodes, the root node is **Scene**. When editing the Prefab file, its own node is used as the root node. Add or delete nodes is done here with the right-click menu or a drag-and-drop operation.
+- The panel supports the following keyboard shortcuts:
+ - **Copy**: Ctrl/Cmd + C
+ - **Paste**: Ctrl/Cmd + V
+ - **Clone**: Ctrl/Cmd + D, Ctrl + drag nodes
+ - **Delete**: Delete
+ - **Select up and down**: Up and Down arrows
+ - **Collapse nodes**: Left arrow
+ - **Expand nodes**: Right arrow
+ - **Multi-select**: Ctrl or Cmd + click
+ - **Multi-select Continuously**: Shift + click
+ - **Rename**: Enter/F2
+ - **Cancel input**: Esc
+
+## New Node
+
+Click the **New Node (+)** button in the upper left corner of the panel or right-click directly in the panel to create a node.
+
+
+
+When creating a node, an **Input box** will appear asking for the name of the node, which is allowed to be empty and will be named by the default node name if it is empty.
+
+> The menus are a little different when you create a project through the Project(2D) template in the Cocos Dashboard.
+> - Only 2D objects can be created.
+> - All 3D objects, terrain, particle systems and lights are invalid.
+
+
+
+- If there isn't a node selected in the tree list, the new node will be created under the current root node by default (`Scene`).
+- If there are multiple nodes selected, the new node will be created under the first selected node.
+
+### UI nodes
+
+For a UI node to display properly, any of its parent nodes must have at least one **UITransform** component. When creating a UI node, if it does not meet the rules, a **Canvas** node will be automatically created as the root of the UI node, as described in the [UI Structure Description](../../2d-object/ui-system/index.md) documentation.
+
+### Prefab nodes
+
+For a Prefab node, drag a **Prefab** asset from the **Assets** panel directly into the **Hierarchy** panel to generate a Prefab node. Also, dragging a **Prefab** node from the **Hierarchy** panel into the **Assets** panel to generate a Prefab asset.
+
+## Search Nodes
+
+Search types include: **Search Name or UUID**, **Search UUID**, **Search Path**, **Search Component Name**, **Search Asset UUID**, and **Only Nodes With Missing Asset**.
+
+
+
+**Search Component Name** will search out all nodes in the node list containing the specified component, which can be viewed in the **Inspector** panel, such as **MeshRenderer**.
+
+The **Search box** will update the search results instantly based on the input content. When a node is selected in the search results and the search is cleared, the selected node will still be located in the asset list.
+
+
+
+## Change the display order of nodes
+
+The order of nodes in the list can be changed by dragging them up and down. Moving nodes are divided into **moved nodes** and **target placement nodes**.
+
+- Drag the **moved node** on top of the **target placement node**, both are **level**.
+
+ As shown below, select the Cube node and drag it above the Sphere node. The Sphere node will be highlighted in yellow and have a blue line above it indicating where the Cube node will be inserted.
+
+ 
+
+- Drag the **moved node** onto the **target placement node**, and the **moved node** will be at the end as a child of the **target placement node**.
+
+ In the following figure, select the Cube node and drag it to the Sphere node. The Sphere node will be highlighted in yellow on a light blue background, indicating that the Cube node will become a child of the Sphere.
+
+ 
+
+- Drag the **moved node** below the **target placement node**, both are **level**.
+
+ As shown below, select the Sphere node and drag it below the Cube node. The Cube node will appear highlighted in yellow and have a blue line below it indicating where the Sphere node will be inserted.
+
+ 
+
+## Rename Nodes
+
+Select a node, then right click and select **Rename** to change the node name, or just use the shortcut keys **Enter** or **F2**. Click elsewhere in the panel or press the shortcut **Esc** to cancel the renaming.
+
+Different nodes can have the same name.
+
+
+
+## Other Operations
+
+The menu that pops up when right-clicking on a node also includes the following actions.
+
+- **Copy/Paste**: Copy the node to the clipboard, then you can paste it to another location, or open another scene to paste the node that was just copied.
+- **Duplicate**: Generate a copy of the node that is exactly the same as the selected node, with the generated node and the selected node in the same hierarchy.
+- **Select All**: Select all nodes in the same hierarchy.
+- **Copy and print UUID/PATH**: In complex scenarios, we sometimes need to get the UUID or full hierarchy path of a node in order to access it when the script is running. Click this option to see the UUID of the currently selected node and the node's hierarchical path in the **Console** panel.
+- **Lock Node**: Mouse over the node and there will be a lock button on the left side, the node cannot be selected in the **Scene** panel once it is locked.
+
+ Starting from v3.1.1, batch locking of nodes and their children is supported. Select any node, hold down the Alt and click the lock button, and the node and its children will all be locked.
diff --git a/versions/4.0/en/editor/index.md b/versions/4.0/en/editor/index.md
new file mode 100644
index 0000000000..a808a3b5ee
--- /dev/null
+++ b/versions/4.0/en/editor/index.md
@@ -0,0 +1,40 @@
+# Editor Interface Introduction
+
+This chapter will introduce the editor interface and familiarize you with the panels, menus, and function buttons that make up the editor, which consists of multiple panels that can be freely moved and combined to suit the needs of different projects and developers. Taking the default editor layout as an example, notice the names and roles of each panel:
+
+
+
+- (**A**) [Hierarchy](./hierarchy/index.md): show all the nodes in the scene and their hierarchy in the form of a tree list, all the contents seen in the **Scene** panel can find the corresponding node entries in the **Hierarchy** panel, the contents of these two panels will be displayed simultaneously when editing the scene, and we usually use both panels to build scenes.
+- (**B**) [Assets](./assets/index.md): shows all assets in the project assets folder (`assets`). Here the folders are displayed in a tree structure and automatically synchronized with changes made to the project asset folder contents in the operating system. Drag and drop files directly from outside the project, or import assets using the menu.
+- (**C**) [Scene](./scene/index.md): workspace for displaying and editing the visual content of the scene. Building the scene in the **Scene** panel allows to get a WYSIWYG preview of the scene.
+- (**D**) [Animation](./animation/index.md): used to edit and store animation data.
+- (**E**) [Inspector](./inspector/index.md): used to view and edit the working area of the currently selected node and component properties. This panel displays the property data from the script definition in the most appropriate form and allows the user to edit them.
+- (**F**) [Preview](./preview/index.md): after the scene is built, preview the game in action on the Web or native platform.
+
+Other important editor-based interfaces include:
+
+- **Console**
+
+ 
+
+ The **Console** displays error reports, warnings, or other editor- and engine-generated log messages. For details, please review the [Console](console/index.md) documentation.
+
+- **Preferences**
+
+ 
+
+ **Preferences** provides various editor-specific global settings, including global settings for native development environment, game preview, other extensions, etc. For details, please read the section [Preferences](preferences/index.md).
+
+- **Project Settings**
+
+ 
+
+ **Project Settings** provides various project-specific personalization settings, including group management, feature cropping, project preview, custom engine, etc. For details, please review the [Project Settings](project/index.md) documentation.
+
+- **Service**
+
+ 
+
+ Cocos Service is a **Service** panel integrated within Cocos Creator. We select high-quality technology solution providers to provide cost-effective service access, and are committed to giving users a one-click access experience and providing corresponding technical support. At the same time, we will also rely on the Cocos developer community to get a more favorable price for developers.
+
+ For details, please refer to the [Cocos Service Introduction](https://service.cocos.com/document/en/) documentation.
diff --git a/versions/4.0/en/editor/index/animation.png b/versions/4.0/en/editor/index/animation.png
new file mode 100644
index 0000000000..9d4391514f
Binary files /dev/null and b/versions/4.0/en/editor/index/animation.png differ
diff --git a/versions/4.0/en/editor/index/assets.png b/versions/4.0/en/editor/index/assets.png
new file mode 100644
index 0000000000..f29251e5aa
Binary files /dev/null and b/versions/4.0/en/editor/index/assets.png differ
diff --git a/versions/4.0/en/editor/index/console.png b/versions/4.0/en/editor/index/console.png
new file mode 100644
index 0000000000..2d17e7da73
Binary files /dev/null and b/versions/4.0/en/editor/index/console.png differ
diff --git a/versions/4.0/en/editor/index/editor.png b/versions/4.0/en/editor/index/editor.png
new file mode 100644
index 0000000000..9bd13f27dc
Binary files /dev/null and b/versions/4.0/en/editor/index/editor.png differ
diff --git a/versions/4.0/en/editor/index/hierarchy.png b/versions/4.0/en/editor/index/hierarchy.png
new file mode 100644
index 0000000000..e88acee20c
Binary files /dev/null and b/versions/4.0/en/editor/index/hierarchy.png differ
diff --git a/versions/4.0/en/editor/index/inspector.png b/versions/4.0/en/editor/index/inspector.png
new file mode 100644
index 0000000000..afd9af3969
Binary files /dev/null and b/versions/4.0/en/editor/index/inspector.png differ
diff --git a/versions/4.0/en/editor/index/main.jpg b/versions/4.0/en/editor/index/main.jpg
new file mode 100644
index 0000000000..f31dd09e05
Binary files /dev/null and b/versions/4.0/en/editor/index/main.jpg differ
diff --git a/versions/4.0/en/editor/index/preferences.png b/versions/4.0/en/editor/index/preferences.png
new file mode 100644
index 0000000000..cc67b46004
Binary files /dev/null and b/versions/4.0/en/editor/index/preferences.png differ
diff --git a/versions/4.0/en/editor/index/scene.png b/versions/4.0/en/editor/index/scene.png
new file mode 100644
index 0000000000..fbb94090a3
Binary files /dev/null and b/versions/4.0/en/editor/index/scene.png differ
diff --git a/versions/4.0/en/editor/index/service.png b/versions/4.0/en/editor/index/service.png
new file mode 100644
index 0000000000..15561df35e
Binary files /dev/null and b/versions/4.0/en/editor/index/service.png differ
diff --git a/versions/4.0/en/editor/index/settings.png b/versions/4.0/en/editor/index/settings.png
new file mode 100644
index 0000000000..65b71c64a0
Binary files /dev/null and b/versions/4.0/en/editor/index/settings.png differ
diff --git a/versions/4.0/en/editor/inspector/index.md b/versions/4.0/en/editor/inspector/index.md
new file mode 100644
index 0000000000..0b3e38b778
--- /dev/null
+++ b/versions/4.0/en/editor/inspector/index.md
@@ -0,0 +1,118 @@
+# Inspector Panel
+
+The **Inspector** panel is the work area for viewing and editing the currently selected nodes, node components, and assets. Properties can be displayed and edited in the **Inspector** panel by selecting a node in the **Scene** panel or **Hierarchy** panel, or by selecting an asset in the **Assets** panel.
+
+
+
+## Panel overview
+
+
+
+The **Inspector** panel can be divided into two parts: **Toolbar** and **Property Settings**.
+
+## Toolbar
+
+The **two arrows** in the top left corner are the edit history, click on them to advance/reverse the selected nodes/assets.
+The **lock** button in the upper right corner can lock the panel, fixing the currently edited object and not allowing the panel to change with new selections.
+
+
+
+## Property Settings
+
+The **Property Settings** area allows setting node properties, component properties, asset properties, etc.
+
+### Node name and activation switch
+
+Node name, consistent with the node name displayed in **Hierarchy** panel.
+
+The Node checkbox indicates the node's enabled/disabled status. When unchecked, the node is disabled and rendering of the node will be suspended, and the node's children will be hidden (grayed out).
+
+### Node properties
+
+Click `Node` below the node name to collapse or expand the node's properties. To the right of `Node` are the **Help Documentations** and **Node Settings** buttons.
+
+- The Help button jumps to the official documentation about the node.
+
+- Click the Node Settings button to perform the following operations on the node:
+
+ 1. Reset the node properties.
+ 2. Copy/paste the node values.
+ 3. Copy/paste world transform of the node, including `worldPosition`/`worldRotation`/`worldScale` properties.
+ 4. Reset the `Position`/`Rotation`/`Scale` properties of the node respectively.
+
+ 
+
+The transformation properties of nodes include **Position**, **Rotation** and **Scale**. Modifying the properties of a node will usually result in immediate changes in the appearance or position of the node in the **Scene** panel. For details, please review the [Coordinate Systems and Transformations](../../concepts/scene/coord.md#transformation-properties) documentation.
+
+To modify node properties in a batch, press Shift in the **Hierarchy** panel to select multiple nodes and then set them in batch in the **Inspector** panel. The batch setting of node properties is similar to that of assets, please refer to the Batch Setting of Assets Multiple Selection section at the end of this article for details.
+
+### Component property settings
+
+The Component checkbox indicates the enabled/disabled state of the component. When unchecked, the component is disabled and will not participate in rendering.
+
+Below the node properties, all the components attached on the node and the component properties are listed. As with the node properties, clicking on a component's name toggles the collapsed/expanded state of that component's properties. In the case of many components attached on the node, collapse infrequently modified component properties to get a larger working area.
+
+To the right of the component name are buttons for **Help Documentations** and **Component Settings**.
+- The Help Documentations button jumps to the official documentation page for the component.
+- The Component Settings button allows resetting, deleting, moving up, moving down, copying the component, paste the component's value, paste it as a new component, etc. for the component.
+
+The properties and settings of each component are different, please refer to the corresponding component description documentation for details.
+
+## Adding components
+
+Clicking the **Add Component** button brings up a list of components, including system-provided components and custom script components. The list of added components has a search box that supports toggling with the up and down keys and confirming the selection with **Enter**.
+
+
+
+Developers' script in the **Assets** panel can be dragged and dropped directly into the **Inspector** panel to generate a script component, or added via **Add Component -> Custom Script**. The properties of a script component are declared by the script. Different types of properties have different control appearance and editing in the **Inspector** panel. We will add the properties in [Declare Properties](../../scripting/decorator.md) section for details on how properties are defined.
+
+## Property types
+
+**Property** is a publicly available variable declared in the component script that can be serialized and stored in the scene and animation data. The **Inspector** panel allows quickly modifying property settings for the purpose of adjusting game data and game play without modifying the script.
+
+**Property** can usually be divided into two categories, **value type** and **reference type**, depending on where the variable uses memory.
+
+### Value type properties
+
+**Value Types** include simple variable types that take up very little memory, such as numbers, strings, booleans, enumerations, etc.
+
+- `Number`: can be entered directly using the keyboard or incremented or decremented by pressing the up and down arrows next to the input box.
+- `Vec2`: the control of a vector is a combination of two numeric inputs, and the input box is marked with x and y to identify the sub-property name corresponding to each value.
+- `String`: entered directly into the text box using the keyboard.
+- `Boolean`: edited in the form of a checkbox, the selected state means the property value is true, the non-selected state means false.
+- `Enum`: edited in the form of a drop-down menu. Click the enumeration menu, and then select an item from the pop-up menu list to finish modifying the enumeration value.
+- `Color`: click on the color property preview box, the **Color Picker** window will pop up, in this window use the mouse to directly click on the desired color, or directly enter the specified color in the RGBA color input box below. Clicking anywhere outside the **Color Picker** window will close the window and use the last selected color as the property value. For example, the color picker component.
+
+ 
+
+### Reference type properties
+
+**Reference Types** include `object` objects, such as nodes, components, or assets. They can be selected and assigned by **dragging the node or asset into the property bar** or by **popping up the asset panel**.
+
+
+
+## Batch operations
+
+When needing to set asset properties of the **same type** in a batch, press Shift in the **Assets** panel and select multiple assets, the **Inspector** panel will show the number of assets selected and the editable asset properties. Click the **Apply** button at the top right when done.
+
+
+
+Batch modification of node properties is the same. However, if an property in the **Inspector** panel displays one of the following states, it means that the property has inconsistent property values across the multiple assets selected, and choose whether to continue to batch modify the property as needed:
+
+- The check box displays **Grey**.
+- The input box displays **-**.
+- The selection box displays **blank**.
+
+> **Notes**:
+> 1. Batch setting operations are not currently supported for Material assets.
+> 2. Assets of **different types** can be selected at the same time, but they do not support setting properties in batch.
+
+## Edit Prefab node properties
+
+The Prefab node functions in the top toolbar of the **Inspector** panel include: disassociate, locate asset, restore from asset, and update to asset. For details, please refer to the [Prefab](../../asset/prefab.md) documentation.
+
+
+
+> **Note**: when editing the asset, please remember to save it by clicking the **green tick** button in the upper right corner.
+>
+> 
diff --git a/versions/4.0/en/editor/inspector/index/add-component.png b/versions/4.0/en/editor/inspector/index/add-component.png
new file mode 100644
index 0000000000..20cb0408e4
Binary files /dev/null and b/versions/4.0/en/editor/inspector/index/add-component.png differ
diff --git a/versions/4.0/en/editor/inspector/index/assets-panel.png b/versions/4.0/en/editor/inspector/index/assets-panel.png
new file mode 100644
index 0000000000..26d8208e44
Binary files /dev/null and b/versions/4.0/en/editor/inspector/index/assets-panel.png differ
diff --git a/versions/4.0/en/editor/inspector/index/component-menu.png b/versions/4.0/en/editor/inspector/index/component-menu.png
new file mode 100644
index 0000000000..8d9ca875e2
Binary files /dev/null and b/versions/4.0/en/editor/inspector/index/component-menu.png differ
diff --git a/versions/4.0/en/editor/inspector/index/drag-assets.png b/versions/4.0/en/editor/inspector/index/drag-assets.png
new file mode 100644
index 0000000000..c055e45481
Binary files /dev/null and b/versions/4.0/en/editor/inspector/index/drag-assets.png differ
diff --git a/versions/4.0/en/editor/inspector/index/edit-assets.png b/versions/4.0/en/editor/inspector/index/edit-assets.png
new file mode 100644
index 0000000000..c10f9afb87
Binary files /dev/null and b/versions/4.0/en/editor/inspector/index/edit-assets.png differ
diff --git a/versions/4.0/en/editor/inspector/index/header.png b/versions/4.0/en/editor/inspector/index/header.png
new file mode 100644
index 0000000000..5a0b1d9a20
Binary files /dev/null and b/versions/4.0/en/editor/inspector/index/header.png differ
diff --git a/versions/4.0/en/editor/inspector/index/inspector-panel.png b/versions/4.0/en/editor/inspector/index/inspector-panel.png
new file mode 100644
index 0000000000..7bd27ae8bd
Binary files /dev/null and b/versions/4.0/en/editor/inspector/index/inspector-panel.png differ
diff --git a/versions/4.0/en/editor/inspector/index/introduce.gif b/versions/4.0/en/editor/inspector/index/introduce.gif
new file mode 100644
index 0000000000..76aa5e7cd5
Binary files /dev/null and b/versions/4.0/en/editor/inspector/index/introduce.gif differ
diff --git a/versions/4.0/en/editor/inspector/index/material-in-node.png b/versions/4.0/en/editor/inspector/index/material-in-node.png
new file mode 100644
index 0000000000..23d4f19d05
Binary files /dev/null and b/versions/4.0/en/editor/inspector/index/material-in-node.png differ
diff --git a/versions/4.0/en/editor/inspector/index/multiple-edit.png b/versions/4.0/en/editor/inspector/index/multiple-edit.png
new file mode 100644
index 0000000000..74feed07d1
Binary files /dev/null and b/versions/4.0/en/editor/inspector/index/multiple-edit.png differ
diff --git a/versions/4.0/en/editor/inspector/index/multiple-edit1.png b/versions/4.0/en/editor/inspector/index/multiple-edit1.png
new file mode 100644
index 0000000000..ff0c25147e
Binary files /dev/null and b/versions/4.0/en/editor/inspector/index/multiple-edit1.png differ
diff --git a/versions/4.0/en/editor/inspector/index/node-attrs.png b/versions/4.0/en/editor/inspector/index/node-attrs.png
new file mode 100644
index 0000000000..542cf06f8d
Binary files /dev/null and b/versions/4.0/en/editor/inspector/index/node-attrs.png differ
diff --git a/versions/4.0/en/editor/inspector/index/node-menu.png b/versions/4.0/en/editor/inspector/index/node-menu.png
new file mode 100644
index 0000000000..cb7ccd21c0
Binary files /dev/null and b/versions/4.0/en/editor/inspector/index/node-menu.png differ
diff --git a/versions/4.0/en/editor/inspector/index/prefab-edit-menu.png b/versions/4.0/en/editor/inspector/index/prefab-edit-menu.png
new file mode 100644
index 0000000000..c436178d80
Binary files /dev/null and b/versions/4.0/en/editor/inspector/index/prefab-edit-menu.png differ
diff --git a/versions/4.0/en/editor/inspector/index/prefab-menu.png b/versions/4.0/en/editor/inspector/index/prefab-menu.png
new file mode 100644
index 0000000000..2182571bcd
Binary files /dev/null and b/versions/4.0/en/editor/inspector/index/prefab-menu.png differ
diff --git a/versions/4.0/en/editor/inspector/index/ui-color.png b/versions/4.0/en/editor/inspector/index/ui-color.png
new file mode 100644
index 0000000000..95b0ee9294
Binary files /dev/null and b/versions/4.0/en/editor/inspector/index/ui-color.png differ
diff --git a/versions/4.0/en/editor/l10n/collect-and-count.md b/versions/4.0/en/editor/l10n/collect-and-count.md
new file mode 100644
index 0000000000..98e813a9ea
--- /dev/null
+++ b/versions/4.0/en/editor/l10n/collect-and-count.md
@@ -0,0 +1,27 @@
+# Collect and Count
+
+The Collect and Count feature collects files such as text, Typescript scripts, scene resources, Prefab, videos and images from within the project and allows developers to localize and configure them.
+
+
+
+## Properties and Descriptions
+
+- **Local development language**: The local development language, the language used by the developer during development. The language selected here will be used as the source language and provided to the translation service provider for translation. Developers can select it according to their current preferences via the drop-down menu at.
+
+ 
+
+ This option is required.
+
+- **Collecting from resource files**: The localization editor feature allows you to collect text information from different resource directories for the desired translation, as well as the option to filter or exclude certain files/folders.
+
+ 
+
+ - **Collection groups**: Multiple can be added, different collection groups can be added by the **+** button, for the added items, **delete** button will be displayed when mouse slide over.
+
+ 
+
+ - **Search directory**: You can specify a specific directory within the current resource database for collecting resources to be translated, with a minimum of 1 i.e. `db://assets`. To reduce the collection time, we recommend developers to store the resources to be translated in a separate directory. Then sort them by this option.
+ - **Extension name**: Specify to collect by a specific file extension, or if none, collect all files.
+ - **Excluded path**: excluded paths will not be collected.
+
+Once the directory to be collected is configured, the data is recorded by clicking the **Collect and Count** button and can be compiled and organized by [Compile Language](compile-language.md).
diff --git a/versions/4.0/en/editor/l10n/collect/add-remove.png b/versions/4.0/en/editor/l10n/collect/add-remove.png
new file mode 100644
index 0000000000..5132d27015
Binary files /dev/null and b/versions/4.0/en/editor/l10n/collect/add-remove.png differ
diff --git a/versions/4.0/en/editor/l10n/collect/diff-language.png b/versions/4.0/en/editor/l10n/collect/diff-language.png
new file mode 100644
index 0000000000..bc9156621d
Binary files /dev/null and b/versions/4.0/en/editor/l10n/collect/diff-language.png differ
diff --git a/versions/4.0/en/editor/l10n/collect/group.png b/versions/4.0/en/editor/l10n/collect/group.png
new file mode 100644
index 0000000000..808c8f8348
Binary files /dev/null and b/versions/4.0/en/editor/l10n/collect/group.png differ
diff --git a/versions/4.0/en/editor/l10n/collect/overview.png b/versions/4.0/en/editor/l10n/collect/overview.png
new file mode 100644
index 0000000000..30d1f8e706
Binary files /dev/null and b/versions/4.0/en/editor/l10n/collect/overview.png differ
diff --git a/versions/4.0/en/editor/l10n/compile-language.md b/versions/4.0/en/editor/l10n/compile-language.md
new file mode 100644
index 0000000000..6bbede5d28
--- /dev/null
+++ b/versions/4.0/en/editor/l10n/compile-language.md
@@ -0,0 +1,187 @@
+# Compile Language
+
+
+
+Once the local development language is selected in the [Collect and Count](collect-and-count.md) view, the compilation process can be configured. This will include features such as **automatic translation**, **manual translation**, **variants**, etc.
+
+## Language
+
+Developers can choose to add a new language here.
+
+
+
+The language in the first row is **Local Development Language**, which records the local language used in the current development process, and can usually be chosen as a language familiar to the developer. Under this language, **Operation** column appears **Complete** function, which is used to record the original text of the Label component and should be used with [L10nLabel](l10n-label.md). Please refer to the following for details.
+
+Starting from the second line, the language used in the target country/region, developers need to select at least one language of the target country/region for the translation option to appear.
+
+## Languages recognized by translation service providers
+
+
+
+The above chart is used to select the input/output language type of the translation service provider at the time of automatic translation.
+
+- For native development languages, the input language type is selected.
+
+- For the translation language, the selection is for the output language type.
+
+For example, in the above figure, the local development language is English (en), then the drop-down menu needs to select **English**.
+
+And the translation language is **Simplified Chinese (zh-Hans-CN)**, then in the drop-down menu, please select **zh-CHS**.
+
+> **Note**: If the drop-down menu is not available, please check if [AppKey/AppSecret](translation-service.md) is configured correctly.
+
+## Translation Progress
+
+
+
+Shows current translation progress.
+
+## Operations
+
+The actions field provides **Complement** functionality for native development languages and **Translation** functionality for target translation languages. Common functions for both include **Preview**, **Export** and **Delete**.
+
+### Complement
+
+**Complement** for only taking effect when the current language is set to **Local Development Language**. The purpose of the complement feature is to record the original text of the content to be translated in the current development language. All the original text data obtained by the **Collect and Count** function will be displayed here. When you click on it, you can view all the results.
+
+
+
+When adding a key via the [L10nLabel](l10n-label.md) component within a prefab or scene:
+
+
+
+You can find the corresponding key in the **Complement** panel, enter the value of the key in the Original field, and click the **Save** button to save the original text, which will be automatically filled if the Label's String property has a value.
+
+
+
+Non-text resources such as images and audio are also complemented, see the **Non-Text Resources** section below for details.
+
+### Variants
+
+The variant function is specially used to solve the plural problem encountered in translation. The system will automatically adjust the translation content according to the rules of variants, and users can also freely set the rules of variants.
+
+In the **Complement** panel, click the **Variant** button to enter a new variant.
+
+
+
+After the **Complement** is done, remember that you need to click the **Save** button above to save it.
+
+The number of variants is language dependent and is one of the international rules, which interested users can check by moving to [https://cldr.unicode.org/](https://cldr.unicode.org/).
+
+For more information, see [L10nLabel Variant Count](l10n-label.md).
+
+### Translation
+
+Once the key value and the original text have been added to the **Complement** function, you can use the translation service provider's translation service to translate by clicking on the **Translat** button to bring up the translation interface.
+
+
+
+Click on the **Translate** button at the top right to translate.
+
+
+
+Once the translation is complete, the results can be viewed in the **Translation** sub-page.
+
+
+
+For translated text, different translations can also be added by clicking on **Variant**:.
+
+
+
+> **Note**: This feature only works if the **Translation Service Provider** is properly configured.
+
+### Preview
+
+Click Preview to get a quick preview of how the nodes/image resources etc. of the [L10nLabel](l10n-label.md) component are displayed in that language for the current scene:
+
+
+
+Before translation:
+
+
+
+After translation:
+
+
+
+### Export
+
+Click the **Export** button to export the original/translated content to a PO file.
+
+> PO file is a common text-based object file in software development, usually used to record the result of interface translation.
+
+
+
+The following are some supplementary translation tools, which developers can choose according to their needs.
+
+- Manipulating PO Files
+- [https://poedit.net/](https://poedit.net/)
+- [https://github.com/translate/translate](https://github.com/translate/translate)
+- [OmegaT - The Free Translation Memory Tool - OmegaT 3](https://omegat.org/)
+
+### Delete
+
+
+
+Delete the translated progress of the current language. The result will not be saved after confirmation, so please operate with caution. Local development languages cannot be deleted.
+
+## Non-text resources
+
+Localization may also be required when there is text drawn on images, video and audio dubbed in different languages in the project. In this case, the translation interface will provide the **Import** button, and here is an example of how to configure localization using images.
+
+
+
+When **Collection and Count** is complete, the detected resources will be in the form of paths as key values.
+
+
+
+Import the images required for the target language by clicking on the **Import** button to.
+
+
+
+> **Note**.
+> 1. When importing, you can only import the files in the project.
+> 2. Since auto-atlas will modify the uuid of the resource, it will cause the redirection failure, so the images that need to be translated cannot be checked for auto-atlas function.
+
+### Intelligent Matching
+
+The Intelligent Matching button will bring up a secondary confirmation menu, clicking on it will enable intelligent matching. Intelligent matching will be modified by the file name and match the corresponding language. Example.
+
+The source file is: assets/aassb/cn-abc001.jpg and needs to be translated into English, its translation file is: assets/aassb/en-abc001.jpg, we will automatically replace cn in assets/aassb/cn-abc001.jpg with en.
+
+Operation steps.
+
+- For example, when our local development language is Chinese (zh) and the language to be translated is English (en), the following resources may be prepared as shown in the figure below:
+
+ 
+
+- After clicking **Intelligent Matching**, select Confirm in the secondary menu that pops up:
+
+ 
+
+- Developers do not need to import them manually, and role.jpg in different languages will be automatically matched with:
+
+ 
+
+## Import Files
+
+The **Import File** button allows you to import external data files, supporting PO, CSV and XLSX formats.
+
+The format requirements for CSV and XLSX are as follows.
+
+
+
+The file should be in UTF-8 encoding format.
+
+
+
+After importing, if you need to translate manually, the process is the same as the above document.
+
+### Conflict resolution
+
+If you import the same external file repeatedly, a conflict will occur, and you will need to resolve the conflict manually at this point:
+
+
+
+- **Skip**: skip the conflicting key value, no additional processing.
+- **Cover**: Overwrite the existing key value, the old data will be discarded.
diff --git a/versions/4.0/en/editor/l10n/compile/add-lang.png b/versions/4.0/en/editor/l10n/compile/add-lang.png
new file mode 100644
index 0000000000..c9c5097972
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/add-lang.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/asset.png b/versions/4.0/en/editor/l10n/compile/asset.png
new file mode 100644
index 0000000000..a56e032116
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/asset.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/before-matching.png b/versions/4.0/en/editor/l10n/compile/before-matching.png
new file mode 100644
index 0000000000..4516fd69e7
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/before-matching.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/complement.png b/versions/4.0/en/editor/l10n/compile/complement.png
new file mode 100644
index 0000000000..bc2a350f5e
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/complement.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/conflict.png b/versions/4.0/en/editor/l10n/compile/conflict.png
new file mode 100644
index 0000000000..8c15ee19f1
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/conflict.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/delete.png b/versions/4.0/en/editor/l10n/compile/delete.png
new file mode 100644
index 0000000000..e70db7a858
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/delete.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/export.png b/versions/4.0/en/editor/l10n/compile/export.png
new file mode 100644
index 0000000000..4e9ae19bb8
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/export.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/import-csv.png b/versions/4.0/en/editor/l10n/compile/import-csv.png
new file mode 100644
index 0000000000..f5c8caa606
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/import-csv.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/import-image.png b/versions/4.0/en/editor/l10n/compile/import-image.png
new file mode 100644
index 0000000000..c632692494
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/import-image.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/import-other-lang-jpg.png b/versions/4.0/en/editor/l10n/compile/import-other-lang-jpg.png
new file mode 100644
index 0000000000..4b1cce3969
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/import-other-lang-jpg.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/lang-provider.png b/versions/4.0/en/editor/l10n/compile/lang-provider.png
new file mode 100644
index 0000000000..df244c0ced
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/lang-provider.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/matching-result.png b/versions/4.0/en/editor/l10n/compile/matching-result.png
new file mode 100644
index 0000000000..fcd78aa1eb
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/matching-result.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/new-key.png b/versions/4.0/en/editor/l10n/compile/new-key.png
new file mode 100644
index 0000000000..270eedd9b0
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/new-key.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/original-preview.png b/versions/4.0/en/editor/l10n/compile/original-preview.png
new file mode 100644
index 0000000000..06549fee47
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/original-preview.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/other.png b/versions/4.0/en/editor/l10n/compile/other.png
new file mode 100644
index 0000000000..c26eb121d5
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/other.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/overview.png b/versions/4.0/en/editor/l10n/compile/overview.png
new file mode 100644
index 0000000000..8236703abc
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/overview.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/preview-overview.png b/versions/4.0/en/editor/l10n/compile/preview-overview.png
new file mode 100644
index 0000000000..6df220616c
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/preview-overview.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/progress.png b/versions/4.0/en/editor/l10n/compile/progress.png
new file mode 100644
index 0000000000..292484eba4
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/progress.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/source-matching.png b/versions/4.0/en/editor/l10n/compile/source-matching.png
new file mode 100644
index 0000000000..d8f1ceb130
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/source-matching.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/translate-complete.png b/versions/4.0/en/editor/l10n/compile/translate-complete.png
new file mode 100644
index 0000000000..6c828a5515
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/translate-complete.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/translate-overview.png b/versions/4.0/en/editor/l10n/compile/translate-overview.png
new file mode 100644
index 0000000000..7a0ab9b0af
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/translate-overview.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/translate-preview.png b/versions/4.0/en/editor/l10n/compile/translate-preview.png
new file mode 100644
index 0000000000..33c899b304
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/translate-preview.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/translate.png b/versions/4.0/en/editor/l10n/compile/translate.png
new file mode 100644
index 0000000000..ebcd99dc18
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/translate.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/translated-variant.png b/versions/4.0/en/editor/l10n/compile/translated-variant.png
new file mode 100644
index 0000000000..aeb1673331
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/translated-variant.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/unfilled.png b/versions/4.0/en/editor/l10n/compile/unfilled.png
new file mode 100644
index 0000000000..d50cb44eb8
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/unfilled.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/variant.png b/versions/4.0/en/editor/l10n/compile/variant.png
new file mode 100644
index 0000000000..fccfe7f465
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/variant.png differ
diff --git a/versions/4.0/en/editor/l10n/compile/xlsx.png b/versions/4.0/en/editor/l10n/compile/xlsx.png
new file mode 100644
index 0000000000..ff0e68e1c4
Binary files /dev/null and b/versions/4.0/en/editor/l10n/compile/xlsx.png differ
diff --git a/versions/4.0/en/editor/l10n/l10n-label.md b/versions/4.0/en/editor/l10n/l10n-label.md
new file mode 100644
index 0000000000..6a8afc97bd
--- /dev/null
+++ b/versions/4.0/en/editor/l10n/l10n-label.md
@@ -0,0 +1,84 @@
+# L10nLabel
+
+L10nLabel is a component that can be customized to translate content. Used in conjunction with a text component, the content of the text component can be translated.
+
+
+
+## Adding Components
+
+Users can click **Add Component** on the **Inspector** panel and select L10nLabel to add.
+
+
+
+> **Note**: L10nLabel must be paired with a Label component to work, if there is no Label component on the node, one will be created automatically.
+
+## Properties and descriptions
+
+| Properties | Description |
+| :-- | :-- |
+| **String** | Text within Label component not editable|
+| **Count** | Number of variants See below for details |
+| **Key** | Localized key |
+
+### Count
+
+By entering a different number, the localization will switch between different variants.
+
+In some languages, different formats are used to represent singular and plural, for example, in English, one apple is expressed as one apple, while two apples is used in the plural form of apples: two apples.
+
+In order to be able to use the correct format after translation, we can fill in **Count** exactly how many objects are specified in the current sentence.
+
+As a rule, the number of variants in different languages is related to the local language, and developers can consult with native speakers.
+
+For example, English has a singular/plural distinction, so there are two variants in configuration `one` and `other`. Some languages like Arabic have 5 variants while Russian has 3 variants. The engine generates the number of variants by adapting international rules, which can be found at the following URL if you wish to know them.
+
+- ECMAScript Internationalization API:[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules)
+- Unicode CLDR Project:[https://cldr.unicode.org/](https://cldr.unicode.org/)
+
+We'll walk through a detailed example below, for those unfamiliar with the **Localized Edit** panel, you can start by referring to [Localization](./overview.md).
+
+- First enable **localization editing** and select Chinese as the development language:.
+
+ 
+
+- Add a node with a Label component within the scene.
+
+ 
+
+- Add a L10nLabel component to this node and change the Key to: apple-key:
+
+ 
+
+- Add the language to be translated to English:
+
+ 
+
+- Adding variants within the **translation** panel:
+
+ 
+
+- The translated result can be previewed by clicking on the **Preview** action in the **Localization Editor** panel, and different variants will be displayed when switching between singular/plural in the Count property.
+
+ 
+
+### Key
+
+Globally unique keys, localization will get the result of that key in localization depending on the key. Developers can enter their own custom keys. New keys can also be added by the **reset** button.
+
+
+
+#### Reset Key
+
+
+
+If you need new keys you can click on the reset button shown, at which point the L10N will generate new keys, which can then also be edited in the **Localization Editor** in the panel opened by the **Compile** operation:
+
+
+
+For details, please refer to [Compile Language](compile-language.md)
+
+#### Select Key
+
+The drop-down menu shown allows you to select existing keys:
+
+
diff --git a/versions/4.0/en/editor/l10n/l10nlabel/add.png b/versions/4.0/en/editor/l10n/l10nlabel/add.png
new file mode 100644
index 0000000000..034490af48
Binary files /dev/null and b/versions/4.0/en/editor/l10n/l10nlabel/add.png differ
diff --git a/versions/4.0/en/editor/l10n/l10nlabel/apple-key.png b/versions/4.0/en/editor/l10n/l10nlabel/apple-key.png
new file mode 100644
index 0000000000..c20d5600bb
Binary files /dev/null and b/versions/4.0/en/editor/l10n/l10nlabel/apple-key.png differ
diff --git a/versions/4.0/en/editor/l10n/l10nlabel/apple-variant.png b/versions/4.0/en/editor/l10n/l10nlabel/apple-variant.png
new file mode 100644
index 0000000000..51637e7a23
Binary files /dev/null and b/versions/4.0/en/editor/l10n/l10nlabel/apple-variant.png differ
diff --git a/versions/4.0/en/editor/l10n/l10nlabel/compile.png b/versions/4.0/en/editor/l10n/l10nlabel/compile.png
new file mode 100644
index 0000000000..cb30c40949
Binary files /dev/null and b/versions/4.0/en/editor/l10n/l10nlabel/compile.png differ
diff --git a/versions/4.0/en/editor/l10n/l10nlabel/dev-lang.png b/versions/4.0/en/editor/l10n/l10nlabel/dev-lang.png
new file mode 100644
index 0000000000..51d364a6fd
Binary files /dev/null and b/versions/4.0/en/editor/l10n/l10nlabel/dev-lang.png differ
diff --git a/versions/4.0/en/editor/l10n/l10nlabel/english.png b/versions/4.0/en/editor/l10n/l10nlabel/english.png
new file mode 100644
index 0000000000..bff0b02d2d
Binary files /dev/null and b/versions/4.0/en/editor/l10n/l10nlabel/english.png differ
diff --git a/versions/4.0/en/editor/l10n/l10nlabel/key-prop.png b/versions/4.0/en/editor/l10n/l10nlabel/key-prop.png
new file mode 100644
index 0000000000..94960dd963
Binary files /dev/null and b/versions/4.0/en/editor/l10n/l10nlabel/key-prop.png differ
diff --git a/versions/4.0/en/editor/l10n/l10nlabel/overview.png b/versions/4.0/en/editor/l10n/l10nlabel/overview.png
new file mode 100644
index 0000000000..d62fcb2cff
Binary files /dev/null and b/versions/4.0/en/editor/l10n/l10nlabel/overview.png differ
diff --git a/versions/4.0/en/editor/l10n/l10nlabel/pingguo.png b/versions/4.0/en/editor/l10n/l10nlabel/pingguo.png
new file mode 100644
index 0000000000..2b0c0bf78a
Binary files /dev/null and b/versions/4.0/en/editor/l10n/l10nlabel/pingguo.png differ
diff --git a/versions/4.0/en/editor/l10n/l10nlabel/reset-key.png b/versions/4.0/en/editor/l10n/l10nlabel/reset-key.png
new file mode 100644
index 0000000000..8a509c3f43
Binary files /dev/null and b/versions/4.0/en/editor/l10n/l10nlabel/reset-key.png differ
diff --git a/versions/4.0/en/editor/l10n/l10nlabel/select-key.png b/versions/4.0/en/editor/l10n/l10nlabel/select-key.png
new file mode 100644
index 0000000000..ebeda568be
Binary files /dev/null and b/versions/4.0/en/editor/l10n/l10nlabel/select-key.png differ
diff --git a/versions/4.0/en/editor/l10n/l10nlabel/variant-result.gif b/versions/4.0/en/editor/l10n/l10nlabel/variant-result.gif
new file mode 100644
index 0000000000..b320f60b32
Binary files /dev/null and b/versions/4.0/en/editor/l10n/l10nlabel/variant-result.gif differ
diff --git a/versions/4.0/en/editor/l10n/overview.md b/versions/4.0/en/editor/l10n/overview.md
new file mode 100644
index 0000000000..b2090494c5
--- /dev/null
+++ b/versions/4.0/en/editor/l10n/overview.md
@@ -0,0 +1,68 @@
+# Localization
+
+Localization (hereinafter referred to as L10N) is a feature introduced in Cocos Creator 3.6 that integrates translation services from third-party translation service providers, while running the localization of text, audio and image resources into the engine and supporting one-click publishing to different languages.
+
+> L10N is the abbreviation of the first and last letter of the word Localization, 10 means Localization with 10 letters in the middle.
+
+## L10N OverView
+
+The Localization Editor panel can be opened by selecting **Panel** -> **Localization Editor** in the top menu of the engine.
+
+At first start-up, the user has to manually enable the L10N function.
+
+
+
+You can edit it after starting it.
+
+
+
+In the upper right corner of the panel, the L10N provides two functions **Turn Off L10N** and **Unload Data**.
+
+
+
+- **Turn Off L10N**: Disable the L10N function. After selecting Confirm in the secondary menu that pops up, the data is still retained and the developer can enable the function again:
+
+ 
+
+- **Unload data**: After selecting Confirm in the popup secondary menu, the L10N data will be cleared and the associated components in the scene will be deleted:
+
+ 
+
+ > **Note**: The uninstalled data cannot be recovered, please operate with caution.
+
+## Translation Service Provider
+
+
+
+The engine integrates the translation services of several translation service providers, and developers can choose different translation service providers to provide more complete and diversified services. For details, please refer to [Translation Service Provider](translation-service.md).
+
+## Collect and Count
+
+
+
+Collect and count collects resources that may need to be translated in a project to facilitate translation, and developers can also filter them by specifying specific files, directories, or through configuration. For details, please refer to [Collect and Count](collect-and-count.md)
+
+## Compile Language
+
+
+
+Language translation allows you to view the currently configured and translated languages and view their progress or delete actions. Manual processing of certain non-text resources is also provided. For more details, please refer to [Compile Language](compile-language.md)
+
+## Programming Guide
+
+Please refer to [Sample](script-using.md) for an example of programmatic use of L10N.
+
+## Publish
+
+Once the translation has been completed according to the above steps, it can be published with one click on the build panel at
+
+
+
+- **Language used**: This will contain all the languages set in the **Localization Editor**, and developers can select them as needed depending on the version
+- **Default language**: the language used when the project is started after the release
+- **Alternate language**: the alternate language to be used if there is a problem with the default language
+
+## Q & A
+
+- Q: Is there a solution if I accidentally modify the data file and the data file becomes corrupted and I cannot open L10N?
+ A: You can modify it by searching the corresponding file in "{project directory}\localization-editor\translate-data".
diff --git a/versions/4.0/en/editor/l10n/overview/close-alert.png b/versions/4.0/en/editor/l10n/overview/close-alert.png
new file mode 100644
index 0000000000..870e0b2724
Binary files /dev/null and b/versions/4.0/en/editor/l10n/overview/close-alert.png differ
diff --git a/versions/4.0/en/editor/l10n/overview/enable.png b/versions/4.0/en/editor/l10n/overview/enable.png
new file mode 100644
index 0000000000..bb5db137f0
Binary files /dev/null and b/versions/4.0/en/editor/l10n/overview/enable.png differ
diff --git a/versions/4.0/en/editor/l10n/overview/menu.png b/versions/4.0/en/editor/l10n/overview/menu.png
new file mode 100644
index 0000000000..0febbf8ec2
Binary files /dev/null and b/versions/4.0/en/editor/l10n/overview/menu.png differ
diff --git a/versions/4.0/en/editor/l10n/overview/overview.png b/versions/4.0/en/editor/l10n/overview/overview.png
new file mode 100644
index 0000000000..470de1cae3
Binary files /dev/null and b/versions/4.0/en/editor/l10n/overview/overview.png differ
diff --git a/versions/4.0/en/editor/l10n/overview/publish.png b/versions/4.0/en/editor/l10n/overview/publish.png
new file mode 100644
index 0000000000..22fc414a15
Binary files /dev/null and b/versions/4.0/en/editor/l10n/overview/publish.png differ
diff --git a/versions/4.0/en/editor/l10n/overview/uninstal-alert.png b/versions/4.0/en/editor/l10n/overview/uninstal-alert.png
new file mode 100644
index 0000000000..58d8dcd293
Binary files /dev/null and b/versions/4.0/en/editor/l10n/overview/uninstal-alert.png differ
diff --git a/versions/4.0/en/editor/l10n/script-using.md b/versions/4.0/en/editor/l10n/script-using.md
new file mode 100644
index 0000000000..2a69b13bec
--- /dev/null
+++ b/versions/4.0/en/editor/l10n/script-using.md
@@ -0,0 +1,73 @@
+# Sample
+
+## Import
+
+The code example is as follows:
+
+```ts
+import l10n from 'db://localization-editor/core/L10nManager'
+```
+
+- Description: l10n provides the ability to translate text in code as an api
+
+## Switch Language at Runtime
+
+The code example is as follows:
+
+```ts
+l10n.changeLanguage('zh-Hans-CN')
+```
+
+For more information, please refer to [BCP47 Language Tag](https://www.techonthenet.com/js/language_tags.php).
+
+> **Note**: After calling this method, the game will be restarted automatically, so please make sure to do the data persistence.
+
+- Interface definination: `t(key: L10nKey, options?: StandardOption): L10nValue`
+
+## Get the value of L10N according to the key
+
+```ts
+console.log(l10n.t('this_is_apple'))
+// This is an apple
+```
+
+Here you can get the value of the current language with `this_is_apple` as the key.
+
+## Query
+
+The code example is as follows:
+
+```ts
+console.log(l10n.exists('test_key'))
+```
+
+### Get the current language
+
+The code example is as follows:
+
+```ts
+console.log(l10n.currentLanguage)
+// 'zh-Hans-CN'
+```
+
+Returns the current language's [BCP47 Language Tag](https://www.techonthenet.com/js/language_tags.php)。
+
+### Get all available languages
+
+The code example is as follows:
+
+```ts
+console.log(l10n.languages)
+// ['zh-Hans-CN', 'en-US']
+```
+
+Returns all available language's [BCP47 Language Tag](https://www.techonthenet.com/js/language_tags.php) as an array.
+
+## Get directions to the language
+
+Most languages follow a left-to-right reading convention, with the exception of some languages such as Arabic, where this method learns the `TextInfoDirection` of the incoming language
+
+```ts
+console.log(l10n.direction('ar'))
+// 'rtl'
+```
diff --git a/versions/4.0/en/editor/l10n/translation-service.md b/versions/4.0/en/editor/l10n/translation-service.md
new file mode 100644
index 0000000000..8c2a6d6a72
--- /dev/null
+++ b/versions/4.0/en/editor/l10n/translation-service.md
@@ -0,0 +1,22 @@
+# Translation Service Provider
+
+Translation service providers are third-party software vendors that the engine integrates with by smoothing out the differences in APIs between them. Usually the developer needs to register the service provider's account and enable the corresponding API in order to start the automatic translation function.
+
+Don't worry if you don't have a corresponding developer account, L10N supports manual translation.
+
+
+
+- **Translation Service Provider**: This drop-down menu allows developers to select a different translation service provider. If **None** is selected, the automatic translation function is not available, and the manual translation function is not affected:
+
+ 
+
+ The URL of the currently supported service providers are as follows:
+
+ - [有道智云平台](https://ai.youdao.com/gw.s#/)
+ - [Google Cloud](https://cloud.google.com)
+
+- **AppKey**/**AppSecret**: After selecting different service providers, developers need to enter AppKey and AppSecret to continue the subsequent operation. Usually these information need to be obtained on the website of the translation service provider:
+
+ 
+
+ Once you have finished entering, just click the **Save** button.
diff --git a/versions/4.0/en/editor/l10n/translation-service/overview.png b/versions/4.0/en/editor/l10n/translation-service/overview.png
new file mode 100644
index 0000000000..8cedb5221d
Binary files /dev/null and b/versions/4.0/en/editor/l10n/translation-service/overview.png differ
diff --git a/versions/4.0/en/editor/l10n/translation-service/select.png b/versions/4.0/en/editor/l10n/translation-service/select.png
new file mode 100644
index 0000000000..7c323a7e46
Binary files /dev/null and b/versions/4.0/en/editor/l10n/translation-service/select.png differ
diff --git a/versions/4.0/en/editor/l10n/translation-service/youdao.png b/versions/4.0/en/editor/l10n/translation-service/youdao.png
new file mode 100644
index 0000000000..2ff5c9c549
Binary files /dev/null and b/versions/4.0/en/editor/l10n/translation-service/youdao.png differ
diff --git a/versions/4.0/en/editor/mainMenu/img/cocos.png b/versions/4.0/en/editor/mainMenu/img/cocos.png
new file mode 100644
index 0000000000..9b38b3a004
Binary files /dev/null and b/versions/4.0/en/editor/mainMenu/img/cocos.png differ
diff --git a/versions/4.0/en/editor/mainMenu/img/developer.png b/versions/4.0/en/editor/mainMenu/img/developer.png
new file mode 100644
index 0000000000..75b9a2fe31
Binary files /dev/null and b/versions/4.0/en/editor/mainMenu/img/developer.png differ
diff --git a/versions/4.0/en/editor/mainMenu/img/edit.png b/versions/4.0/en/editor/mainMenu/img/edit.png
new file mode 100644
index 0000000000..e40f0b2007
Binary files /dev/null and b/versions/4.0/en/editor/mainMenu/img/edit.png differ
diff --git a/versions/4.0/en/editor/mainMenu/img/extension.png b/versions/4.0/en/editor/mainMenu/img/extension.png
new file mode 100644
index 0000000000..7bf30d8d8e
Binary files /dev/null and b/versions/4.0/en/editor/mainMenu/img/extension.png differ
diff --git a/versions/4.0/en/editor/mainMenu/img/file.png b/versions/4.0/en/editor/mainMenu/img/file.png
new file mode 100644
index 0000000000..a027dd0b00
Binary files /dev/null and b/versions/4.0/en/editor/mainMenu/img/file.png differ
diff --git a/versions/4.0/en/editor/mainMenu/img/help.png b/versions/4.0/en/editor/mainMenu/img/help.png
new file mode 100644
index 0000000000..6eba952977
Binary files /dev/null and b/versions/4.0/en/editor/mainMenu/img/help.png differ
diff --git a/versions/4.0/en/editor/mainMenu/img/menu.png b/versions/4.0/en/editor/mainMenu/img/menu.png
new file mode 100644
index 0000000000..8c3c60f9dd
Binary files /dev/null and b/versions/4.0/en/editor/mainMenu/img/menu.png differ
diff --git a/versions/4.0/en/editor/mainMenu/img/node.png b/versions/4.0/en/editor/mainMenu/img/node.png
new file mode 100644
index 0000000000..e643f686f9
Binary files /dev/null and b/versions/4.0/en/editor/mainMenu/img/node.png differ
diff --git a/versions/4.0/en/editor/mainMenu/img/panel.png b/versions/4.0/en/editor/mainMenu/img/panel.png
new file mode 100644
index 0000000000..e96537b2b6
Binary files /dev/null and b/versions/4.0/en/editor/mainMenu/img/panel.png differ
diff --git a/versions/4.0/en/editor/mainMenu/img/project.png b/versions/4.0/en/editor/mainMenu/img/project.png
new file mode 100644
index 0000000000..1e5450af68
Binary files /dev/null and b/versions/4.0/en/editor/mainMenu/img/project.png differ
diff --git a/versions/4.0/en/editor/mainMenu/index.md b/versions/4.0/en/editor/mainMenu/index.md
new file mode 100644
index 0000000000..8e37e3c82c
--- /dev/null
+++ b/versions/4.0/en/editor/mainMenu/index.md
@@ -0,0 +1,150 @@
+# Main Menu
+
+The main menu bar at the top of Cocos Creator contains 9 menu options, **Cocos Creator**, **File**, **Edit**, **Node**, **Project**, **Panel**, **Extension**, **Developer** and **Help**, which integrate most of Cocos Creator's functionalities.
+
+
+
+## File
+
+This option is mainly used to create, open, and save a project or scene, as well as import Cocos Creator 2.x projects.
+
+
+
+| Option | Description |
+| :--- | :-- |
+| New Project | Opens Dashboard's [Project](../../getting-started/dashboard/index.md#project) tab of Dashboard to create a new project. If you are using Dashboard v1.0.19, you will open Dashboard's [New Project](../../getting-started/dashboard/index.md#new-project) tab. |
+| Open Project | Open Dashboard's [Project](../../getting-started/dashboard/index.md#project) tab. |
+| New Scene (Ctrl/Cmd + N) | Closes the current scene and create a new scene, the newly created scene needs to be saved manually before it will be added to the project directory. |
+| Save Scene (Ctrl/Cmd + S) | Save the scene you are currently editing. If the scene is created using **File -> New Scene**, a dialog box will pop up when you save it for the first time, you need to choose the location to save the scene file and fill in the file name, then click **Save** to save it. Scene files have `.scene` as extension. |
+| Save As (Ctrl/Cmd +Shift+ S) | Generates a copy of the current scene file and save it in the project. |
+| Layout | Sets the editor interface layout. Custom layout can be saved and re-uesed |
+| Preferences | Opens [Preferences](../preferences/index.md) panel to customize the editor.
+| Shortcuts | Opens the Shortcuts panel to view the default shortcuts used by each panel or function module of the editor, support customization. |
+| Import Cocos Creator 2.x Project | V2.x asset import tool, supporting the perfect import of old project assets, as well as the assisted migration of code. Please refer to [v3.0 Upgrade Guide](../../release-notes/upgrade-guide-v3.0.md) for details. |
+| Close Window (Ctrl/Cmd + W) | Closes current window. |
+| Exit | Closes the current editor and automatically opens Dashboard. |
+
+## Edit
+
+This option mainly includes common editing functions such as undo, redo, copy and paste.
+
+
+
+| Option | Description | Default Shortcut |
+| :--- | :-- | :--|
+| Undo | Undoes the last change to the scene. | Ctrl/Cmd + Z
+| Redo | Redoes the undo action from the previous step. | Ctrl/Cmd + Shift + Z
+| Cut | Cuts the currently selected node or character to the clipboard. | Ctrl/Cmd + X
+| Copy | Copies the currently selected node or character to the clipboard. | Ctrl/Cmd + C
+| Paste | Paste the contents of the clipboard into the appropriate location. | Ctrl/Cmd + V
+| Select All | Selects all nodes in the same hierarchy if the focus is within the **Hierarchy** panel, or all assets in the same hierarchy if the focus is in the **Assets** panel. | Ctrl/Cmd + A
+
+> **Note**: **Copy**, **Cut** and **Paste** of nodes should be done using shortcut keys.
+
+## Nodes
+
+This option contains functions to adjust the view, disconnect prefabricated nodes and create nodes.
+
+
+
+| Option | Description |
+| :--- | :-- |
+| Align With View (Ctrl/Cmd + Shift + F) | Moves the currently selected node to the center of the view of the **Scene** panel. |
+| Align View With Node | Sets the view in the **Scene** panel to be centered on the currently selected node.
+| Disconnect Node With Prefab Asset | For converting the selected prefab node to a normal node, please refer to [Prefab](../../asset/prefab.md) for details. |
+| Disconnect Node With Prefab Asset Recursively | Recursively convert prefab nodes containing nested nodes in the scene to normal nodes, see [Prefab](../../asset/prefab.md) for details.
+| Empty Node | Creates an empty node in the scene. If the node is already selected in the scene before the command is executed, the newly created node will become a child of the selected node. |
+| 3D Objects | Creator provides some relatively basic static model controls for use, currently including **Cube**, **Cylinder**, **Sphere**, **Capsule**, **Cone**, **Torus**, **Flat** and **Quad**. To create other types of models, refer to the [MeshRenderer component](../../engine/renderable/model-component.md) documentation. |
+| 2D Objects | Create Creator's pre-defined 2D nodes in the scene containing the base renderable components, which currently include **Graphics**, **Label**, **Mask**, **ParticleSystem2D**, **Sprite**, **SpriteSplash** (monochrome) and **TiledMap** (map), for details please refer to the [Introduction to 2D Renderable Components](../../ui-system/components/editor/render-component.md) documentation. |
+| UI Components | Create Creator's pre-defined nodes containing basic UI components in the scene, which currently include Common UI controls such as **Button**, **Widget**, **Layout**, **ScrollView**, **EditBox** nodes, etc. For more UI components, please refer to the [UI Basic Components](../../ui-system/components/editor/base-component.md) documentation. |
+| Lighting | Create Creator preset nodes in the scene containing base light components, currently including **Parallel Light**, **Spherical Light** and **Spot Light**, please refer to the [Lighting](../../concepts/scene/light.md) documentation. |
+| Effects | Create a Creator preset in the scene containing [Particle System](../../particle-system/overview.md) component in the scene. More effects components can be added in the **Property Inspector** panel by clicking **Add Component -> Special Effects**. |
+| Camera | Creates a node in the scene with the Camera component pre-defined by Creator. For details on how to use it, please refer to the [Camera component](../components/camera-component.md) documentation. |
+| Terrain | Creates a node containing the terrain component pre-defined by Creator in the scene. Please refer to the [Terrain System](../terrain/index.md) documentation for more details on how to use it. |
+
+## Project
+
+This option is mainly used to perform preview run build projects, project configuration and custom builds, etc.
+
+
+
+| Option | Description |
+| :--- | :--- |
+| Project Settings | Opens [Project Settings](../project/index.md) panel to set the relevant configuration options for a specific project. |
+| Play on Device (Ctrl/Cmd + P) | Click on this option to preview the project in the selected browser/simulator window, for details please refer to the [Project Preview & Debugging](../preview/index.md) documentation. |
+| Refresh Device (Ctrl/Cmd + Shift + P) | Refreshes the opened browser preview window. |
+| Create Preview Template | This option is used to customize the desired preview effect, please refer to the [Web Preview Customization Workflow](../preview/browser.md) documentation for details. |
+| Build (Ctrl/Cmd + Shift + B) | Opens the [Build](../publish/index.md) panel to package the game to the target platform. |
+| Create Build Template | This option is used to customize the Build panel of the project, please refer to the [Custom Project Build Process](../publish/custom-project-build-template.md) documentation for details. |
+| Generate Build Extension | This option is used to extend the build process, please refer to the [Extending Build Process](../publish/custom-build-plugin.md) documentation for details. |
+
+## Panel
+
+This option is mainly used to open various panels in the editor.
+
+
+
+| Option | Description | Default Shortcut |
+| :--- | :-- |:-- |
+| Console | Opens [Console](../console/index.md). For viewing the output log messages. |Ctrl/Cmd + 0
+| Scene | Opens the [Scene](../scene/index.md) panel. For selecting and placing various game elements such as scene images, characters, effects, UI, etc. |Ctrl/Cmd + 1
+| Assets | Opens **Assets**/**Assets Preview** panel. For accessing/managing/viewing project assets, please refer to the [Assets](../assets/index.md) documentation for details. | The shortcut for the **Assets** panel is Ctrl/Cmd + 2
+| Inspector | Opens the [Inspector](../inspector/index.md) panel. For viewing and editing the working area of the currently selected node, node components and assets. |Ctrl/Cmd + 3
+| Hierarchy | Opens the [Hierarchy](../hierarchy/index.md) panel, which shows the hierarchical relationship between all nodes in the scene in the form of a tree-like list. |Ctrl/Cmd + 4
+| Animation | Opens the [Animation](../../animation/index.md) panel or [Joint Texture Layout](../../animation/joint-texture-layout.md) panel. For editing and viewing frame animation or skeleton animation, etc. |The shortcut for the **Animation** panel is Ctrl/Cmd + 6
+| Animation Graph | Opens the [Animation Graph](../../animation/marionette/index.md) panel. Animated Graphics and Program Animation is a visual animation editing panel. | The shortcut for the **Animation** panel is Ctrl/Cmd + 5
+| Light Baking | Opens the [Lightmapping](../../concepts/scene/light/lightmap.md) panel to configure the baking properties for generating light maps. |
+| Node Library | Open the Node Prefab Library panel. This panel is a very simple and straightforward visual control repository, where developers can drag and drop the controls listed here into the **Scene** or the **Hierarchy** panel to quickly create pre-configured controls. |Ctrl/Cmd + 7
+| Service | Opens the [Service](https://service.cocos.com/document/en) panel, which provides a number of quality official and third-party services that allow developers to access more extensions beyond the engine and make game development easier. |Ctrl/Cmd + 8
+| Reference Image | Opens the [reference image](../../editor/scene/index.md#reference-image) panel when creating UI in the scene |Ctrl/Cmd + 8
+| Service | Opens the [Service](https://service.cocos.com/document/en) panel, which provides a number of quality official and third-party services that allow developers to access more extensions beyond the engine and make game development easier. |Ctrl/Cmd + 9
+| Localization Editor | Opens the [L10N](../l10n/overview.md) panel. |
+
+## Extension
+
+This option mainly includes Extension Manager, Store and Create Extension, please refer to the [Extending the Editor](../extension/readme.md) chapter.
+
+
+
+| Option | Description |
+| :--- | :--- |
+| Extension Manager | Opens the **Extension Manager** panel, which includes editor built-in extensions, extensions installed in project directory and global directory, please refer to the [Extending the Editor](../extension/readme.md) chapter for details. |
+| Store | The [Cocos Store](https://store.cocos.com/app/) is built into Cocos Creator and allows users to browse, download and automatically install official or third-party extensions and assets. You can also submit your own extensions, art materials, music and sound effects to the extension store for sharing or selling. For more information, please refer to the [Submitting Resources to Store](../extension/store/upload-store.md) documentation.
+| Create Extension | This option is used to generate an [extension package](../extension/first.md) in the project/global directory to extend the editor with features. |
+
+## Developer
+
+This option contains mainly development-related menu functions such as scripts, engine and DevTools.
+
+
+
+| Option | Description |
+| :--- | :--- |
+| Compile Engine (Ctrl/Cmd + F7) | Compile custom engine, please refer to the [Engine Customization Workflow](../../advanced-topics/engine-customization.md) documentation. |
+| Rebuild Native Engine | Compile the custom native engine simulator, please refer to [Customizing the Native Engine Simulator](../../advanced-topics/engine-customization.md#modifying-native-engine-simulator). |
+| Message DevTools | Opens the Message DevTool for debugging IPC interactions at runtime inside the editor. |
+| Tester | The editor's built-in extended testing tool, not yet fully functional |
+|Toggle Graphics Tool | Toggles the Graphics tool panel for debugging scene rendering. |
+| Message Manager | Opens the [Message Manager](../extension/contributions-messages.md) panel to display public messages and their descriptions for each feature defined by the editor. |
+| Export.d.ts | Exports editor-related APIs. |
+| Reload (Ctrl/Cmd + R) | Reload the editor interface. |
+| UI Components | Opens the UI Components panel, which lists how to use the pre-defined UI components provided within the editor, please refer to [UI Components](../extension/ui.md). |
+| Cache | The **clear code cache** in this option is used to clear the cache generated when compiling scripts. |
+| VS Code Workflow | The working environment-related features of the VS Code editor, currently supporting **Add Chrome Debug Setting** and **Add Compile Task**. Please refer to the [Coding Environment Setup](../../scripting/coding-setup.md) documentation for details. |
+| Toggle DevTools (Ctrl/Cmd + Shift + I) | Opens DevTools window for editor interface extension development. It is also possible to customize the log output to **Console**, please refer to [Custom output messages](../console/index.md#custom-output-messages). |
+| Open Assets DevTools | Opens the Assets DevTool panel for viewing log messages during modifications to the asset-db process. |
+| Open Scene DevTools | Opens the Scene DevTool panel to view log messages during modifications to the scene. |
+| Open Build DevTools | Opens the Build DevTool to view all log messages generated during the build process including the call stack. |
+
+## Help
+
+
+
+| Option | Description |
+| :--- |:--------------------------------------------------------------------------------------------------------------|
+| User Manual | Open [User Manual](../../index.md) in default browser. |
+| API Reference | Open [API Reference Documentation](%__APIDOC__%/en/) in default browser. |
+| Forum | Open [Cocos Creator Forum](https://discuss.cocos2d-x.org/c/33) in default browser. |
+| Release Notes | Open the [release notes](https://www.cocos.com/creator-download) for each version of Cocos Creator in default browser. |
+| Engine Repository | Open [TypeScript Engine Repository](https://github.com/cocos/cocos4/) in default browser. |
+| About Cocos Creator | Shows Cocos Creator-related version number and copyright information. |
diff --git a/versions/4.0/en/editor/preferences/index.md b/versions/4.0/en/editor/preferences/index.md
new file mode 100644
index 0000000000..e10dab26f4
--- /dev/null
+++ b/versions/4.0/en/editor/preferences/index.md
@@ -0,0 +1,230 @@
+# Preferences
+
+The **Preferences** panel provides personalized settings for the editor, which can be opened by clicking **Cocos Creator/File -> Preferences** in the editor's main menu bar.
+
+**Preferences** consists of several different tabs, including **General**, **External Program**, **Device Manager**, **Engine Manager**, **AssetDB**, **Console**, **Inspector**, **Preview**, **Build** and **Laboratory**. The **Preferences** panel will automatically save the changes after you modify them.
+
+## General
+
+
+
+The **General** tab is mainly for configuring some basic information related to the editor, including:
+
+**Language**: choose Chinese or English, the editor will automatically switch the language after modifying the language setting, if some texts are not switched, refresh the editor.
+
+- **Number Step**: used to set the step size when adjusting the numeric properties by step button in the **Inspector** panel. The default step size is 0.001. The step buttons in the **Inspector** panel include the following two types:
+
+ - When the mouse is moved to the right of the numeric property input box, a set of up and down arrows will appear, which can continuously increase or decrease the value by a certain step magnitude.
+
+ 
+
+ - When the mouse is hovered near the name of a numeric property, the cursor will change to , and then drag the mouse left and right to increase or decrease the value continuously in a certain step.
+
+## External Program
+
+The **External Program** tab is used to set up the development environment required to build for publishing to the native platform, as well as to configure some third-party programs. When the mouse is moved over a specific configuration item, a gray circular question mark icon is displayed on the left side. Clicking on this icon allows setting the configuration item to be applied to the current project or to all projects globally. When set to apply to the current project, the gray icon will turn yellow.
+
+
+
+- **WeChat DevTools**: used to configure the Developer tools of WeChat Mini Game, please refer to the [Publishing to WeChat Mini Game](../publish/publish-wechatgame.md) documentation.
+
+- **Android NDK**: used to set up the Android NDK path, please refer to the [Setup Native Development Environment](../publish/setup-native-development.md) documentation.
+
+- **Android SDK**: used to set the Android SDK path, please refer to the [Setup Native Development Environment](../publish/setup-native-development.md) documentation.
+
+- **HarmonyOS NDK**: used to set the HarmonyOS NDK path, please refer to the [Publish for the Huawei HarmonyOS](../publish/publish-huawei-ohos.md) documentation.
+
+- **HarmonyOS SDK**: used to set the HarmonyOS SDK path, please refer to the [Publish for the Huawei HarmonyOS](../publish/publish-huawei-ohos.md) documentation.
+
+- **Default Script Editor**: choose any executable file from an external text editing tool (e.g.: [VS Code](../../scripting/coding-setup.md)) as the way to open the script file when you double-click it in the **Assets** panel. The executable file of the preferred text editor can be selected by clicking the **Search** button after the input box. The folder icon is used to open the path to the text editor that has been set up.
+
+- **Default Browser**: used to select the browser to be used when previewing the editor. A browser path can be specified by clicking the **Search icon** button behind the input box.
+
+## Device Manager
+
+The **Device Manager** tab is used to manage the device resolution when using the simulator or browser preview, and supports adding/modifying/deleting custom device resolutions manually on the right side of the panel. The editor's default device resolution does not support modification/deletion.
+
+
+
+## Engine Manager
+
+The **Engine Manager** tab is used to configure the engine path when customizing the engine.
+
+
+
+- **Use built-in TypeScript engine**: whether to use the engine path that comes with the Cocos Creator installation path as the TypeScript engine path. This engine is used for scene rendering in the scene editor, declaration of built-in components and other engine modules in the web environment.
+
+- **Custom TypeScript engine path**: in addition to using your own engine, an engine can also be cloned from the [engine repository](https://github.com/cocos/cocos4/) or forked to any local location for customization, uncheck **Use built-in TypeScript engine** and specify **Custom TypeScript engine path** as the customized engine path, then it's ready to use.
+
+- **Use built-in native engine**: whether to use the `engine-naive` path that comes with the Cocos Creator installation path as the native engine path. This engine is used to build and compile projects for all native platforms (iOS, Android, Mac, Windows) when building.
+
+- **Custom native engine path**: after unselecting the previous item **Use built-in native engine**, the native engine path can be specified manually.
+
+> **Note**: the native engine used here must be from [engine-native](https://github.com/cocos/cocos4/) or the fork of that repository.
+
+For details on customizing the engine, please review the [Engine customization workflow](../../advanced-topics/engine-customization.md) documentation.
+
+## Asset Database
+
+The **Asset database** tab is used to set the [Assets](../assets/index.md) panel with information about the asset database, including **Log Levels**, **Ignore (regular)** and **Default Meta**.
+
+
+
+- **Log Level**: used to set the type of information output to the **console** from the asset database in the **Assets** panel. This currently includes **Error Only**, **Error and Warning Only**, **Error, Warning, and Log**, and **Output All Information**.
+- **Ignore Files (Glob)**: Use Glob patterns to match files that should be ignored. The `!` prefix in Glob patterns means to exclude matching resources from search results, and the editor will not import these resources. Editor restart is required after modification.
+ - Example: `!**/*.txt` ignores all `.txt` files.
+ - Example: `!test` ignores all files in the relative path assets/test folder.
+ - Example: `!**/Node.*` ignores all files named Node.
+- **Update resources automatically**: automatically refresh resources when returning to the editor from outside. See below for details.
+- **Automatically overwrite metadata on import**: when importing assets to replace existing assets, if the imported assets come with Meta, use this option to set whether to overwrite the Meta of the existing assets.
+- **Default Meta**: used to set the default configuration when importing assets within a project. Please refer to the description below for details.
+
+### Update resources automatically
+
+If this option is enabled, all resources will be automatically checked when returning to Creator, regardless of whether resources have been manipulated outside of Creator. Then when the number of files in the project is too high, or the random read and write speed of the hard disk is too low, it will cause the resource system response lag. For example, if a resource is selected in **Assets** panel, the **Inspector** panel will take a while to show the resource-related properties.
+
+At this point, please disable the automatic refresh feature of Creator. After disabling this feature, if resources are manipulated, then manually click the **Refresh** button at the top right of the **Assets** panel to refresh the resources.
+
+> **Note**: it is not recommended to turn this option off if not experiencing resource system response problems.
+
+### Default Meta
+
+This option is used to set the default configuration when importing assets into the project. For example, if want the imported image to be `sprite-frame` by default, then click on the **Edit** button to the right of this option and fill in the following in the `json` file that opens:
+
+```json5
+{
+ // 'image' indicates that the type of the asset is an image.
+ "image": {
+ "type": "sprite-frame"
+ }
+}
+```
+
+After editing and saving, return to the editor and click the **Apply** button to take effect.
+
+The asset type is `key`, and the key value `value` needs to be an **object**, which is the default configuration used when the asset is imported.
+For example, in the above sample code, the `key` is `image`, the `value` is the content configured in `image`, and the configuration information of the asset database will be refreshed after clicking the **Apply** button, and the content in `image` will be configured into the `userData` field of the asset `meta` file one by one. For example, if `image.type` is set to `sprite-frame`, the default `userData.type` will be set to `sprite-frame` when importing image assets. So the default import configuration of various assets can be set dynamically according to project needs.
+
+If want to get the asset type, just right-click on the asset in **Assets** panel, select **Reveal in Explorer**, then find the meta file corresponding to the asset in the opened folder and open it, the asset type will be marked in the `importer` field.
+
+For example, the meta file for a material asset is as follows, and the `material` in the `importer` field is the asset type.
+
+```json
+{
+ "ver": "1.0.9",
+ "importer": "material",
+ "imported": true,
+ "uuid": "482a5162-dad9-446c-b548-8486c7598ee1",
+ "files": [
+ ".json"
+ ],
+ "subMetas": {},
+ "userData": {}
+}
+```
+
+## Console
+
+The **Console** tab is used to set the [Console](../console/index.md) panel output log, including **Display date** and **Font size**.
+
+
+
+- **Display date**: whether to display the date in front of the log output from the **Console** panel.
+- **Font size**: used to set the text size of the log output from the **Console** panel.
+
+## Inspector
+
+The **Auto-save when leaving edit** option in the **Inspector** tab is used to set the [Inspector](../inspector/index.md) panel to automatically save changes after the property edit is complete.
+
+
+
+## Preview
+
+The **Preview** tab is mainly used for the various options that can be set when using the [Preview](../preview/index.md) button on the top of the editor, but is only available for the current project.
+
+
+
+- **Auto refresh preview when saving scene**: if this option is checked, the opened preview page will be automatically refreshed when saving the scene in the editor. Currently the preview using the simulator is not supported for now.
+- **Auto clear cache when using simulator**: if this option is checked, the cache will be automatically cleared when using the simulator preview.
+- **Open simulator debugger**: if this option is checked, the debugger will be opened automatically when previewing the project with the simulator.
+- **Simulator wait for debugger to connect**: this option will take effect when **Open the simulator debugger** is checked, and it is used to pause the simulator startup process until the debugger is connected, which is used for debugging the loading process.
+- **Preview server port number**: Port for the preview server, Cocos Creator will create a http/https server to preview game when you click the preview button.
+- **Enable HTTPS**:Whether to enable HTTPS for debugging
+- **HTTPS port**: Server port of HTTPS
+- **Private key**: Path of the private key
+- **Public cert**: Path of the public cert
+- **CSR file for certificate singing**: The path of CSR file.
+
+## Animation
+
+**Animation** Paging is used to set up the [animation system](../../animation/index.md) some parameters and configurations during editing.
+
+
+
+- **Enable animation instant cache function**: when enabled, the animation in the editor will be automatically cached according to the **Caching interval time**
+- **Cache interval time**: the time between caches, in milliseconds.
+- **Maximum number of cached files**: the maximum number of animations that can be cached
+
+> **Note**: Currently the cached animation files are not automatically restored, if you want to restore the cached files, please refer to [Animation System](../../animation/index.md).
+
+## Build
+
+The **Build** tab is used to set up the execution of the [Build](../publish/build-panel.md), including **Log file opening method** and **Cache Serialized JSON of Assets**.
+
+
+
+- **Log file opening method**: This option is used to set whether to open the build log file directly or to open the directory where the log file is located, when clicking the **Open Log** button at the bottom left of the [platform build task](../publish/build-panel.md). The default is to open the log file directly.
+
+- **Cache Serialized JSON of Assets**: in order to speed up the build and reduce the repeated deserialization of unmodified assets, the serialized JSON of assets will be cached during the asset build process, which will be placed in the `temp/asset-db/assets/uuid/build` directory of the project and divided into `debug.json` and `release.json` according to **debug** and **release** mode.
+
+ 
+
+ When a cached asset exists the build will take it directly, and this part of the cached asset will be re-updated after each asset import. This option is checked by default, but if some special requirements are encountered and want to build without storing this serialized build cache asset, just uncheck it.
+
+- **Cache Build Engine**: Cache the compiled engine, this cache will take effect in the global directory. Developers can print this cache address by using the `Editor.App.temp` command in **Developer -> Switch Developer Tools**:
+
+ 
+
+ With this feature, it is possible to speed up the build. This feature can also be viewed in the log at:
+
+ 
+
+- **Cache Compressed Texture**: Cache the compressed texture assets, if the texture parameters are modified, the cache will be invalidated, the cache directory is: `temp/builder/CompressTexture`.
+- **Cache Auto Atlas**:The cache of the auto-atlas can be cleared at build time, for details please refer to the [Build Tasks](../publish/build-panel.md#Build%20Tasks)
+- **Keep UUID in the Node Component**:By default, component UUIDs are not serialized into Prefabs/Assets, but are automatically generated by the engine at runtime. When enabled, the component's UUID is serialized into the corresponding Prefab/Assets at build time and remains the same at runtime and editor time.
+
+## Laboratory
+
+The **Laboratory** tab will occasionally provide some new technical solutions or experimental features that can be selected via a switch option to be used or not, and in most cases are turned on by default. Currently these include **Scene Real-time Cache** and **Enable baking feature**.
+
+
+
+- **Enable Deferred Rendering Pipeline**: enables or disables the deferred rendering pipeline. By default, deferred rendering pipelines are disabled. For details, see [Deferred Render Pipeline](../../render-pipeline/builtin-pipeline.md#%E5%BB%B6%E8%BF%9F%E6%B8%B2%E6%9F%93%E7%AE%A1%E7%BA%BF).
+
+- **Automatically update script's import path after relocation**: when enabled, the import part of the script will be automatically modified and relocated to the new location when you move the script in the editor.
+
+- **Optimized scheduling strategy**: This policy will try to merge resources when importing them multiple times repeatedly to reduce the number of scheduling times.
+
+- **Scene real-time cache**: this item is enabled by default, it is mainly used to cache scene files to `temp/scene/[SCENE_UUID]/[TIME].json` file in project directory every once in a while during scene editing (the current time interval is 5s). In case of unexpected situation, such as scene crash, process crash, etc., when you open the editor again, a popup window will prompt you whether to apply the latest scene file in the cache.
+
+ > **Note**: In daily use, as long as the scene is opened normally, all scene files cached before the current scene is opened will be cleared. If you have a special need to view the cache files of a specific scene, please close the corresponding scene in the editor first.
+
+- **Keep scene main loop running**: whether or not to allow the scene to be rendered in the same way as in the preview with a constant rendering loop.
+- **Enable native engine loading scene editor**: when enabled, the rendering module inside the editor will use the native engine.
+- **Debug native engine for scene editor**: whether or not the native engine scene can be enabled. When this option is enabled, it will prevent the native engine from starting and a dialog box will pop up, click to confirm before it will continue to start. It is mainly used for debugging the logic inside the scene after the native engine has been activated.
+
+- **Animation Embedded Player**: This feature supports the user to synchronize with other particles and animations while editing the animation
+- **Animation Auxiliary Curve**: If or not the animation auxiliary curve function is enabled, please check [Auxiliary Curve Edit View](../../animation/animation-auxiliary-curve.md) for details.
+
+- **Enable Pose-Express Function**: If or not enable the animation gesture map function, please check [Programmatic Animation](../../animation/animation-auxiliary-curve.md) for more details.
+- **Enable baking feature**: Use to enable the baking function, please refer to [Light Mapping](../../concepts/scene/light/lightmap.md)
+
+### Caution
+
+In future releases, these features in **Laboratory** may be merged, but there is also a chance that compatibility-breaking changes may occur, or may even be removed. If needing to use these features in a development environment, please be sure to test them rigorously and keep an eye out for update announcements for new releases.
+
+We welcome users to turn on the trial of these features and provide valuable feedback in our [Forum](https://discuss.cocos2d-x.org/c/33) to make these features more suitable for their own usage scenarios and provide more powerful help for projects.
+
+## Extending the Preferences Panel
+
+Creator supports adding custom functional pages on the right side of **Preferences**, please refer to the [Extended Preferences](../../editor/extension/contributions-preferences.md) documentation for details.
diff --git a/versions/4.0/en/editor/preferences/index/add-component.png b/versions/4.0/en/editor/preferences/index/add-component.png
new file mode 100644
index 0000000000..e4873386ac
Binary files /dev/null and b/versions/4.0/en/editor/preferences/index/add-component.png differ
diff --git a/versions/4.0/en/editor/preferences/index/animation.png b/versions/4.0/en/editor/preferences/index/animation.png
new file mode 100644
index 0000000000..06d918598d
Binary files /dev/null and b/versions/4.0/en/editor/preferences/index/animation.png differ
diff --git a/versions/4.0/en/editor/preferences/index/asset-db.png b/versions/4.0/en/editor/preferences/index/asset-db.png
new file mode 100644
index 0000000000..05c82ae66f
Binary files /dev/null and b/versions/4.0/en/editor/preferences/index/asset-db.png differ
diff --git a/versions/4.0/en/editor/preferences/index/build-log-cached-engine.png b/versions/4.0/en/editor/preferences/index/build-log-cached-engine.png
new file mode 100644
index 0000000000..79664a0d29
Binary files /dev/null and b/versions/4.0/en/editor/preferences/index/build-log-cached-engine.png differ
diff --git a/versions/4.0/en/editor/preferences/index/build-temp.png b/versions/4.0/en/editor/preferences/index/build-temp.png
new file mode 100644
index 0000000000..7de1fe5306
Binary files /dev/null and b/versions/4.0/en/editor/preferences/index/build-temp.png differ
diff --git a/versions/4.0/en/editor/preferences/index/build.png b/versions/4.0/en/editor/preferences/index/build.png
new file mode 100644
index 0000000000..89fbe3d5e9
Binary files /dev/null and b/versions/4.0/en/editor/preferences/index/build.png differ
diff --git a/versions/4.0/en/editor/preferences/index/console.png b/versions/4.0/en/editor/preferences/index/console.png
new file mode 100644
index 0000000000..a9c921f224
Binary files /dev/null and b/versions/4.0/en/editor/preferences/index/console.png differ
diff --git a/versions/4.0/en/editor/preferences/index/device-manager.png b/versions/4.0/en/editor/preferences/index/device-manager.png
new file mode 100644
index 0000000000..66a0e9ebba
Binary files /dev/null and b/versions/4.0/en/editor/preferences/index/device-manager.png differ
diff --git a/versions/4.0/en/editor/preferences/index/engine-manager.png b/versions/4.0/en/editor/preferences/index/engine-manager.png
new file mode 100644
index 0000000000..92bf8c1376
Binary files /dev/null and b/versions/4.0/en/editor/preferences/index/engine-manager.png differ
diff --git a/versions/4.0/en/editor/preferences/index/external-program.png b/versions/4.0/en/editor/preferences/index/external-program.png
new file mode 100644
index 0000000000..4d19ca130d
Binary files /dev/null and b/versions/4.0/en/editor/preferences/index/external-program.png differ
diff --git a/versions/4.0/en/editor/preferences/index/general.png b/versions/4.0/en/editor/preferences/index/general.png
new file mode 100644
index 0000000000..a7d901c7b4
Binary files /dev/null and b/versions/4.0/en/editor/preferences/index/general.png differ
diff --git a/versions/4.0/en/editor/preferences/index/inspector.png b/versions/4.0/en/editor/preferences/index/inspector.png
new file mode 100644
index 0000000000..eb093a66e5
Binary files /dev/null and b/versions/4.0/en/editor/preferences/index/inspector.png differ
diff --git a/versions/4.0/en/editor/preferences/index/json.png b/versions/4.0/en/editor/preferences/index/json.png
new file mode 100644
index 0000000000..cbd3490d40
Binary files /dev/null and b/versions/4.0/en/editor/preferences/index/json.png differ
diff --git a/versions/4.0/en/editor/preferences/index/laboratory.png b/versions/4.0/en/editor/preferences/index/laboratory.png
new file mode 100644
index 0000000000..e4fd48bc9b
Binary files /dev/null and b/versions/4.0/en/editor/preferences/index/laboratory.png differ
diff --git a/versions/4.0/en/editor/preferences/index/mouse-cursor.jpg b/versions/4.0/en/editor/preferences/index/mouse-cursor.jpg
new file mode 100644
index 0000000000..df66301fc4
Binary files /dev/null and b/versions/4.0/en/editor/preferences/index/mouse-cursor.jpg differ
diff --git a/versions/4.0/en/editor/preferences/index/preview.png b/versions/4.0/en/editor/preferences/index/preview.png
new file mode 100644
index 0000000000..1ffbc09f63
Binary files /dev/null and b/versions/4.0/en/editor/preferences/index/preview.png differ
diff --git a/versions/4.0/en/editor/preferences/index/step.png b/versions/4.0/en/editor/preferences/index/step.png
new file mode 100644
index 0000000000..71626d43fe
Binary files /dev/null and b/versions/4.0/en/editor/preferences/index/step.png differ
diff --git a/versions/4.0/en/editor/preview/browser.md b/versions/4.0/en/editor/preview/browser.md
new file mode 100644
index 0000000000..f660733db4
--- /dev/null
+++ b/versions/4.0/en/editor/preview/browser.md
@@ -0,0 +1,48 @@
+# Web Preview Customization Workflow
+
+## Custom Preview Templates
+
+Preview supports custom templates for users to customize the preview effect they need, and the custom preview template can be placed in the `preview-template` folder in the project directory. Or click **Project -> Create Preview Template** in the editor main menu to create an updated preview template in the project directory. The preview in the editor also uses the template to inject the latest project data, the preview will look for the index file in the directory and if it exists it will be used as the template for the preview.
+
+The `preview-template` folder has a structure similar to
+
+```js
+project-folder
+ |--assets
+ |--build
+ |--preview-template
+ // Required entry file
+ |--index.ejs
+ // Other files can be added according to the preview effect you want to achieve
+```
+
+To start customizing the page preview, it should be noted that there are some preview menu items and preview debugging tools in the preview template. Be careful when adding or deleting some template syntax. Random changes may cause the preview template to be unavailable. It is recommended to keep all the content injected with ejs and then add the required content on top of it. Also, if `index.html` and `index.ejs` are coexisting, **`index.html` will replace `index.ejs`** as the preview page content.
+
+## Usage examples
+
+1. Click **Project -> Create Preview Template** in the editor main menu, the **Console** will output the message "Preview Template generated successfully" and show the path of the generated preview template.
+
+2. Add scripts like `test.js`, where `<%- include(cocosTemplate, {}) %>` contains the default start game logic, and the added scripts can be stored before/after the game logic is started as needed. The following `test.js` is loaded after the game is launched.
+
+ - Open `index.ejs` and modify it as follows:
+
+ ```html
+
+ ...
+
+ ...
+ <%- include(cocosTemplate, {}) %> // Game launch processing logic
+ // Add a new script
+
+
+ ```
+
+ - `test.js` is placed in the relative path of the logo within the page (only in the `preview-template` folder)
+
+ ```
+ |--preview-template
+ |--index.ejs
+ |--test.js
+ ```
+
+For more details, please refer to the example [Preview Template](https://github.com/cocos/cocos-test-projects/tree/v3.8/preview-template).
diff --git a/versions/4.0/en/editor/preview/index.md b/versions/4.0/en/editor/preview/index.md
new file mode 100644
index 0000000000..a267bd4f60
--- /dev/null
+++ b/versions/4.0/en/editor/preview/index.md
@@ -0,0 +1,143 @@
+# Project Preview & Debugging
+
+After using the main editor panel to import assets, build scenes, configure components, and adjust properties, we can now preview and build to see how the game will look when running on the Web or Native platform.
+
+## Selecting the preview platform in the editor
+
+At any time during game development we can click the **Preview** button at the top of the editor window to see the game in action.
+
+
+
+- The left drop-down menu allows selecting the platform for previewing, currently **Browser**, **Preview in Editor** and **Simulator** are supported.
+- : preview button, click it to run the preview
+- On the right side of the **Preview** button you can select the scene to preview, the dropdown box will list all the scenes in the project, by default **Current scene** is used.
+
+ 
+
+- : refresh button, click this button to refresh all opened preview pages. To refresh the preview page automatically after the save scene operation, select **Cocos Creator/File -> Preferences -> Preview** in the editor main menu, and then check **Refresh preview page when saving scene**.
+
+> **Note**: double-click is needed to open the scene to preview the game content. If there are not any scenes open, or if an empty scene is created, no content will show.
+
+### Browser
+
+After selecting **Browser** to preview, click the **Preview** button next to it to run the web version of the game directly in the default desktop browser. It is recommended to use Google Chrome as the browser for previewing and debugging during development, as Google Chrome has the most comprehensive and powerful DevTools.
+
+At the top of the browser preview screen there are a series of controls to control the preview effect:
+
+- The leftmost menu is used to select the scale size of the preview window to simulate the display effect on different mobile devices, and the device resolution can be added manually in **Cocos Creator/File -> Preferences -> Device Manager**.
+- **Rotate**: decide whether to display landscape or portrait screen
+- **Debug Mode**: choose which levels of log in the script will be output to the browser console
+- **Show FPS**: allows choosing whether to display debug information such as frames per second and number of drawcalls in the bottom left corner
+- **FPS**: allows limiting the maximum number of frames per second
+- **Pause**: pause the game
+
+
+
+Creator supports the feature of web preview customization, please refer to the [web preview customization workflow](browser.md) documentation for details.
+
+#### Browser compatibility
+
+The desktop browsers tested during Cocos Creator development include: **Chrome**, **Firefox** and **QQ Browser**, other browsers can be used normally as long as the kernel version is high enough.
+
+Browsers tested on mobile devices include: **Safari (iOS)**, **Chrome (Android)**, **QQ Browser (Android)** and **UC Browser (Android)**.
+
+#### Debugging with browser DevTools
+
+Taking Google Chrome as an example, click **Developer -> Toggle DevTools** in the main menu of the editor to open the DevTools interface. DevTools, allow viewing the runtime log, using breakpoints to debug, viewing the value of each variable at each step in the call stack, and even performing asset loading and performance analysis.
+
+To learn how to use DevTools for debugging, read the [Chrome DevTools User Guide](https://developers.google.com/web/tools/chrome-devtools), or the DevTools help for other browsers.
+
+
+
+### Preview In Editor
+
+
+
+To preview within the editor, select **Preview in Editor** (mark 1 below) from the drop-down menu and then click on the **Run Preview** (mark 2 at the bottom) button to preview.
+
+
+
+Click  to pause the current preview, and after pause you can also single step by clicking  to run a single step.
+
+When you don't want to continue the preview, you can click  button to stop.
+
+When selecting the editor preview, the preview output can also be configured via the menu at the top of the preview window.
+
+-  Click to select whether to display the following state
+ within the view.
+
+ 
+
+-  Maximum frame rate for previews, or you can enter a custom frame rate.
+
+ 
+
+-  Resolution at preview, the drop-down menu allows you to select a different resolution, or if the current engine's built-in resolution cannot be met, you can pull the drop-down box to the bottom and select **Edit**.
+
+ 
+
+ You can also add/modify/remove resolutions in [Device Manager](../preferences/index.md#Device%20Manager) in **Preferences** in the top menu bar to add/modify/remove resolutions.
+
+ 
+
+-  Toggle landscape/portrait preview
+-  Zoom view
+-  Adapting the game view to fit the current view
+
+The properties of the component can also be modified for debugging within the **Inspector** panel during preview, but note that the data entered at runtime is not saved. If you wish to save the adjusted component, you can click on the **Component Menu** on the right and select **Copy Component** in the drop-down list, then select **Paste Component Value** after the preview exited.
+
+
+
+### Simulator
+
+When you select **Simulator** preview, the current game scene will be run using Cocos Simulator (desktop simulator). When running the game with the simulator, log messages (printed with `cc.log`) and error messages from the script are displayed in the **Console** panel.
+
+
+
+When using **Simulator** preview, it supports automatically opening debug window for debugging, which can be set in **Cocos Creator/File -> Preferences -> Preview**, please refer to [Preferences - Preview](../preferences/index.md).
+
+To add support for the iOS simulator on Apple M1 (Silicon) architecture devices, click the **App** button in the upper right corner of the Creator, open the `CMakeLists.txt` file in the `resources\3d\engine\native\external` directory of the Editor, and uncomment the code related to the iOS simulator and comment the code related to the iOS physical device, as shown below:
+
+
+
+## Mobile preview
+
+There are the following ways to debug the preview effect on mobile phone:
+
+- Use **Mobile Preview mode of Browser DevTools**
+
+- **Scan the preview QR code**
+
+ Move the mouse over the IP preview address on the left side of the editor toolbar, a preview QR code will be displayed, just scan it with your phone.
+
+ 
+
+- Directly **Enter the preview address in your cell phone browser**
+
+> **Note**: the phone needs to be on the **same network segment** as the computer. Since there may be more than one network for the computer, if the IP address of the editor preview URL is not selected correctly, change it in the main menu bar in **Cocos Creator/File -> Preferences -> General -> Preview IP**.
+
+## Build
+
+After previewing and debugging, if you are satisfied with your game, you can open the **Build** panel via **Project -> Build** in the main menu to package and publish the game to the target platforms, including Web, iOS, Android, various "mini-games", PC clients and other platforms. For the detailed build and publish process, please refer to the [Cross-Platform Game Publishing](../publish/index.md) documentation.
+
+> **Note**: the effect of running the game with **Simulator** and the final release to the native platform may be somewhat different, for any important game features, please do the final test with the version after build and release.
+
+## Other references
+
+- [Introduction to the Preview Process and Common Error Handling](preview-guid.md)
diff --git a/versions/4.0/en/editor/preview/index/FPS.png b/versions/4.0/en/editor/preview/index/FPS.png
new file mode 100644
index 0000000000..e3d9429e13
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/FPS.png differ
diff --git a/versions/4.0/en/editor/preview/index/browser.png b/versions/4.0/en/editor/preview/index/browser.png
new file mode 100644
index 0000000000..5aa0d58d78
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/browser.png differ
diff --git a/versions/4.0/en/editor/preview/index/copy-component.png b/versions/4.0/en/editor/preview/index/copy-component.png
new file mode 100644
index 0000000000..745b270be6
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/copy-component.png differ
diff --git a/versions/4.0/en/editor/preview/index/custom.png b/versions/4.0/en/editor/preview/index/custom.png
new file mode 100644
index 0000000000..b761bbea4a
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/custom.png differ
diff --git a/versions/4.0/en/editor/preview/index/device-manager.png b/versions/4.0/en/editor/preview/index/device-manager.png
new file mode 100644
index 0000000000..50c86d166e
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/device-manager.png differ
diff --git a/versions/4.0/en/editor/preview/index/edit-bar.png b/versions/4.0/en/editor/preview/index/edit-bar.png
new file mode 100644
index 0000000000..7a9cc87757
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/edit-bar.png differ
diff --git a/versions/4.0/en/editor/preview/index/edit.png b/versions/4.0/en/editor/preview/index/edit.png
new file mode 100644
index 0000000000..1887a24d10
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/edit.png differ
diff --git a/versions/4.0/en/editor/preview/index/editor-preview-props.png b/versions/4.0/en/editor/preview/index/editor-preview-props.png
new file mode 100644
index 0000000000..97cc7fc077
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/editor-preview-props.png differ
diff --git a/versions/4.0/en/editor/preview/index/fit.png b/versions/4.0/en/editor/preview/index/fit.png
new file mode 100644
index 0000000000..d374e4d18d
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/fit.png differ
diff --git a/versions/4.0/en/editor/preview/index/gameview.png b/versions/4.0/en/editor/preview/index/gameview.png
new file mode 100644
index 0000000000..33c1603959
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/gameview.png differ
diff --git a/versions/4.0/en/editor/preview/index/ios-simulator-m1.png b/versions/4.0/en/editor/preview/index/ios-simulator-m1.png
new file mode 100644
index 0000000000..a249cccc66
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/ios-simulator-m1.png differ
diff --git a/versions/4.0/en/editor/preview/index/max-fps.png b/versions/4.0/en/editor/preview/index/max-fps.png
new file mode 100644
index 0000000000..828a6be9b0
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/max-fps.png differ
diff --git a/versions/4.0/en/editor/preview/index/pause.png b/versions/4.0/en/editor/preview/index/pause.png
new file mode 100644
index 0000000000..3da2bf5106
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/pause.png differ
diff --git a/versions/4.0/en/editor/preview/index/play.png b/versions/4.0/en/editor/preview/index/play.png
new file mode 100644
index 0000000000..884367029b
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/play.png differ
diff --git a/versions/4.0/en/editor/preview/index/preferences.png b/versions/4.0/en/editor/preview/index/preferences.png
new file mode 100644
index 0000000000..ce93c7606b
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/preferences.png differ
diff --git a/versions/4.0/en/editor/preview/index/preview-type-drop-down.png b/versions/4.0/en/editor/preview/index/preview-type-drop-down.png
new file mode 100644
index 0000000000..2974d3682b
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/preview-type-drop-down.png differ
diff --git a/versions/4.0/en/editor/preview/index/preview-url.png b/versions/4.0/en/editor/preview/index/preview-url.png
new file mode 100644
index 0000000000..8157c9de21
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/preview-url.png differ
diff --git a/versions/4.0/en/editor/preview/index/refresh.png b/versions/4.0/en/editor/preview/index/refresh.png
new file mode 100644
index 0000000000..159322e6c6
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/refresh.png differ
diff --git a/versions/4.0/en/editor/preview/index/resolution.png b/versions/4.0/en/editor/preview/index/resolution.png
new file mode 100644
index 0000000000..d4b6c5cc49
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/resolution.png differ
diff --git a/versions/4.0/en/editor/preview/index/rotate-view.png b/versions/4.0/en/editor/preview/index/rotate-view.png
new file mode 100644
index 0000000000..ae3e19045f
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/rotate-view.png differ
diff --git a/versions/4.0/en/editor/preview/index/scale-game-view.png b/versions/4.0/en/editor/preview/index/scale-game-view.png
new file mode 100644
index 0000000000..e98e8562c4
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/scale-game-view.png differ
diff --git a/versions/4.0/en/editor/preview/index/select-platform.png b/versions/4.0/en/editor/preview/index/select-platform.png
new file mode 100644
index 0000000000..e3beced184
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/select-platform.png differ
diff --git a/versions/4.0/en/editor/preview/index/select-preview-type.png b/versions/4.0/en/editor/preview/index/select-preview-type.png
new file mode 100644
index 0000000000..c1568919a6
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/select-preview-type.png differ
diff --git a/versions/4.0/en/editor/preview/index/select-scene.png b/versions/4.0/en/editor/preview/index/select-scene.png
new file mode 100644
index 0000000000..06255ae8e2
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/select-scene.png differ
diff --git a/versions/4.0/en/editor/preview/index/simulator.png b/versions/4.0/en/editor/preview/index/simulator.png
new file mode 100644
index 0000000000..0a8ff618a9
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/simulator.png differ
diff --git a/versions/4.0/en/editor/preview/index/state-info.png b/versions/4.0/en/editor/preview/index/state-info.png
new file mode 100644
index 0000000000..539b3b85dd
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/state-info.png differ
diff --git a/versions/4.0/en/editor/preview/index/state.png b/versions/4.0/en/editor/preview/index/state.png
new file mode 100644
index 0000000000..affad83f9b
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/state.png differ
diff --git a/versions/4.0/en/editor/preview/index/step.png b/versions/4.0/en/editor/preview/index/step.png
new file mode 100644
index 0000000000..be0ac0f620
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/step.png differ
diff --git a/versions/4.0/en/editor/preview/index/stop.png b/versions/4.0/en/editor/preview/index/stop.png
new file mode 100644
index 0000000000..bf3441191e
Binary files /dev/null and b/versions/4.0/en/editor/preview/index/stop.png differ
diff --git a/versions/4.0/en/editor/preview/preview-guid.md b/versions/4.0/en/editor/preview/preview-guid.md
new file mode 100644
index 0000000000..1a8fd96e03
--- /dev/null
+++ b/versions/4.0/en/editor/preview/preview-guid.md
@@ -0,0 +1,23 @@
+# Introduction to the Preview Process and Common Error Handling
+
+This section introduces the browser preview process.
+
+## Process Introduction
+
+The browser preview is essentially the editor opening an express server that opens the user's default browser to access the preview URL when the "Preview" button is clicked. the preview template has some simple logic written in it for loading the engine and initializing the scene, while the loading of user assets relies heavily on the generation of `settings.json`, as `settings.json` contains the The current project's assets, scripts, and project settings are documented in `settings.json`. The preview `settings.json` is generated by calling the interface of the build extension, so if `settings.json` is not generated properly, select **Developers -> Open Build DevTools** to see it.
+
+## Common Error Handling
+
+When encountering a preview that does not display properly, first, open NetWork in DevTools to see if there are assets or scripts that failed to load at this time.
+
+### `settings.json` failed to load
+
+Before looking for the cause of this issue, make sure there are no error messages in the editor before previewing.
+
+Under normal circumstances, `settings.json` load failure means `settings.json` generation fails, there will be error messages in console. Most common is a script error, because when generating `settings.json`, all scripts in the project are loaded in the build process. If any script contains illegal writing, an unexpected error will be thrown during the loading process and `settings.json` will fail to be generated. For specific error message information, you can refer to the hint in the error message. Usually the error content here is the UUID of the asset. The corresponding **UUID** can be copied to the __Assets__ panel to search and locate the script.
+
+For more information about the specific generation process of `settings.json`, please refer to the [Introduction to the Build process and FAQ](../publish/build-guide.md) documentation. The preview `settings.json` generation rules are basically the same as the generation rules with only debug mode checked, the difference is that the preview only sorts out asset information and does not package the assets.
+
+### Asset loading 404
+
+Usually, this is caused by asset loss or import failure. Please **use the missing asset UUID to search in the editor's assets panel**. If no assets are found, usually the asset is lost. You need to modify the scene or other assets that use this lost asset. If assets are found, you can try to re-import.
diff --git a/versions/4.0/en/editor/project/index.md b/versions/4.0/en/editor/project/index.md
new file mode 100644
index 0000000000..d91cea5bcc
--- /dev/null
+++ b/versions/4.0/en/editor/project/index.md
@@ -0,0 +1,403 @@
+# Project Settings
+
+The **Project Settings** panel can be opened by clicking on **Project -> Project Settings** in the editor's main menu bar and is mainly used to set project-specific configuration items. These settings are stored in the project's `settings/packages` folder. To synchronize project settings between developers, please add the `settings` directory to version control.
+
+**Project Settings** consists of several different sub-pages, including **Project Data**, **Layers**, **Physics**, **Scripting**, **Macro Config**, **Feature Cropping** and **Texture Compression**. The **Project Settings** panel will automatically save the changes after modifying the settings.
+
+## Project Data
+
+The **Project Data** tab is mainly used to set the default Canvas, render pipeline, etc. and only works for the current project.
+
+
+
+### Default Canvas Settings
+
+The default Canvas settings include **Design Resolution** and **Fit Screen Width/Height**, which specify the default design resolution values in Canvas when a new scene or Canvas component is created, as well as `Fit Height` and `Fit Width`. For more details, please refer to the [Multi-Resolution Adaptation Solution](../../ui-system/components/engine/multi-resolution.md) documentation.
+
+### High Quality
+
+When using Cocos Dashboard to create projects with the default template 3D HQ, shadows and lighting settings are turned on by default to achieve higher quality rendering, eliminating the need to manually turn on multiple shadows and lighting settings for scenes, objects, lights, etc.
+This high quality mode is the toggle switch for the template function. It mainly affects the lighting effect of 3D projects, and has no effect on the game quality.
+
+### Render Pipeline
+
+The render pipeline is used to control the rendering process of the scene, currently supports **builtin-forward** (Forward Render Pipeline) and **builtin-deferred** (Deferred Render Pipeline), developers can also customize the render pipeline. Please refer to the [Render Pipeline Overview](../../render-pipeline/overview.md) documentations for details.
+
+## Layers
+
+
+
+- Layers allow the camera to render parts of the scene and lights to illuminate parts of the scene.
+- Layers can be customized from 0 to 19, and clearing the input box removes the original settings.
+- The last 12 Layers are built-in to the engine and cannot be modified.
+- The locations where Layers are currently used include:
+
+ 1. The `Layer` property of the node `Node` in the **Inspector** panel, For more details, please refer to the [Node Component](../../concepts/scene/node-component.md#setting-the-visibility-of-nodes) documentation.
+
+ 
+
+ 2. The `Visibility` property of the Camera node in the **Inspector** panel, the `Layer` property of the node matches the `Visibility` property of the Camera. A node can only be seen by the Camera if the `Layer` property set by the node is checked in the `Visibility` of the Camera. For more details, please refer to the [Camera Component](./../components/camera-component.md#camera-component) documentation.
+
+ 
+
+
+
+## Sorting Layers
+
+
+
+Customize the rendering order for both 2D UI and 3D objects.
+
+* Operation Instructions
+ - Click the delete button on the right to remove the corresponding layer.
+ - Except for the `default` layer which cannot be edited, all other layers can have their names manually edited.
+ - Click the plus button to add different layers.
+ - Drag and drop the gray striped button on the left side of layers to manually rearrange them.
+
+ 
+
+* **(2D UI Rendering Order)** After adding render layers, attach the [Sorting2D](../../engine/rendering/sorting-2d.md) component to any 2D render component node and configure the sorting layer and in-layer order to customize the 2D UI rendering sequence.
+
+
+* **(3D Object Rendering Order)** After adding render layers, attach the [Sorting](../../engine/rendering/sorting.md) component to any node with MeshRenderer or SpriteRenderer components and configure the sorting layer and in-layer order to customize the 3D object rendering sequence.
+
+
+## Physics
+
+
+
+Used to configure various parameters of physics, please refer to the [Physics Config](physics-configs.md) documentation for details.
+
+## Scripting
+
+
+
+- **Conforming class fields**: if enabled, class fields are implemented using `Define` semantics; otherwise, class fields are implemented using `Set` semantics.
+
+- **Allows declaration of class fields**: if enabled, the `declare` keyword may be used to declare class fields in TypeScript scripts. In such case, class fields without explicit initializer would be initialized to `undefined`, according to the specification.
+
+- **Enable loose mode**: if enabled, the script will be compiled in non-strict mode.
+
+- **Import Map**: used to control the import behavior of TypeScript/JavaScript, see the [Import Map](../../scripting/modules/import-map.md) documentation for details.
+
+- **Browser list used for preview**: sets the browser list config file for TypeScript/JavaScript compilation at preview time.
+ > **Example:**
+ > For instance, when previewing, async/await uses polyfill by default. If we don't want to use polyfill,
+ > we can create a previewbrowserlist.txt file in the project root directory with the content chrome 80.
+ > Then go to Project Settings -> Scripts -> Browser List for Preview -> select the previewbrowserlist.txt file.
+ > Restart the editor or restart the script compilation process. The polyfill for async/await will no longer be applied.
+
+- **Exports Conditions**: specify the parsing conditions for conditionalized export modules, see [Conditional exports](../../scripting/modules/spec.md) for details.
+
+### Sorting Plugin Scripts
+
+A partial introduction to plugin scripts can be found in the document [Plugin Scripts](../.../scripting/external-scripts.md).
+
+
+
+When some of the plugin scripts have a certain prioritized loading order between them, you can add the sorting here. (Just add the plugin scripts that have a prioritized order)
+
+**How to operate**:
+
+- Click the `+` button to add plug-in scripts that are recognized but not added to the project.
+- Click the `-` button to delete the selected plugin scripts.
+- Click the `┇` button to expand the menu and select `Add All Plugin Scripts` or `Edit as JSON`.
+
+ 
+ Editing in JSON is for those who want to edit the data directly, this is only a simple conversion, please check the data and format by yourself, illegal JSON format will not be submitted and saved.
+
+ 
+
+## Model
+
+- **Start Material Conversion**: Please refer to [FBX Smart Material Conversion
+](../../importer/materials/fbx-materials.md) for more details.
+
+## Joint Texture Layout
+
+
+
+Configure the joint texture layout within the project. Please refer to [Joint Texture Layout Settings](../../animation/joint-texture-layout.md)。
+
+## Macro Config
+
+**Macro Config** provides a shortcut to modify the macro configuration. The configured macros will take effect on preview and build, and will also follow the custom engine configuration to update the default values of the current macro configuration.
+
+
+
+- **ENABLE_TILEDMAP_CULLING**: whether or not to enable TiledMap auto-culling. It's enabled by default. Note that if `skew` and `rotation` are set in the TiledMap, it's necessary to turn it off manually, otherwise it will cause rendering errors.
+
+- **TOUCH_TIMEOUT**: the duration of the delay used to screen a contact object to see if it has failed and can be removed. This value can be modified to get the desired effect, the default value is 5000 ms. Please refer to the API [TOUCH_TIMEOUT](%__APIDOC__%/en/interface/Macro?id=TOUCH_TIMEOUT) for details.
+
+- **ENABLE_TRANSPARENT_CANVAS**: used to set whether the Canvas background supports alpha channels.
+
+ - If enabled, the Canvas background will be transparent and show the other DOM elements behind it.
+ - If disabled, it will result in higher performance.
+
+- **ENABLE_WEBGL_ANTIALIAS**: whether to activate WebGL antialias setting in the engine, it's enabled by default. This setting only affects WebGL graphics back-end, it indicates whether to turn on the anti-aliasing option when creating WebGL Context (for forward pipeline only).
+
+- **ENABLE_ANTIALIAS_FXAA**: used to enable FXAA anti-aliasing (for deferred pipeline only).
+
+- **ENABLE_BLOOM**: used to enable the BLOOM post-processing.
+
+- **CLEANUP_IMAGE_CACHE**: whether to clear the image cache after uploading a texture to GPU. If the cache is cleared, [Dynamic Atlas](../../advanced-topics/dynamic-atlas.md) will not be supported. It's disabled by default.
+
+- **ENABLE_MULTI_TOUCH**: whether to enable multi-touch.
+
+- **MAX_LABEL_CANVAS_POOL_SIZE**: set the maximum number of Canvas object pools used by the Label, and adjust it according to the number of Labels in the same scene of the project.
+
+- **ENABLE_WEBGL_HIGHP_STRUCT_VALUES** (new in v3.4.1): on the Android platform with WebGL backend, the internal variables of the structures defined in the fragment shader use **mediump** precision, which may lead to incorrect results for some data that requires high precision (such as position information). To avoid this problem, check this option and enable WebGL to calculate variables with **highp** precision.
+
+ - If this option is enabled, use the `HIGHP_VALUE_STRUCT_DEFINE` macro in the fragment shader code to define structural variables, and use `HIGHP_VALUE_TO_STRUCT_DEFINED` and `HIGHP_VALUE_FROM_STRUCT_DEFINED` to assign values between structural and non-structural variables.
+
+ - For specific information and code on the above macro calls, please refer to [packing.chunk](https://github.com/cocos/cocos4/blob/v4.0.0/editor/assets/chunks/common/data/packing.chunk#L40) for details.
+
+- **BATCHER2D_MEM_INCREMENT** (new in v3.4.1): this option affects the maximum number of vertices in each MeshBuffer, the default value is 144KB, please refer to the [MeshBuffer Batch Description](../../ui-system/components/engine/ui-batch.md) documentation for the conversion relationship between the number and the value.
+
+- **Custom Macro**: used to customize macro configurations, providing a macro tagging feature for current project scripts for easy visual configuration. Click the **+** button below to add a new macro configuration, hover over the added macro configuration and the **Delete** and **Modify** buttons will be displayed on the left side for deleting/renaming the current macro configuration respectively.
+
+ 
+
+For more specific information and code about the engine macro module, please refer to the [Engine Macro source](https://github.com/cocos/cocos4/blob/3d/cocos/core/platform/macro.ts#L824).
+
+## Feature Cropping
+
+The **Feature Cropping** tab is mainly for modules used in the engine when releasing the game, to achieve the effect of reducing the package size of the released version of the engine. The unchecked modules in the list will be cropped out when packaging and previewing. It is recommended to do a complete test after packaging to avoid scenes and scripts that use modules that have been cropped out.
+
+
+
+## Texture Compression
+
+
+
+The preset configuration of texture compression is moved to **Project Settings**, and developers can select how the image asset is preset in the **Inspector** panel. The editor will automatically scan all the texture compression configurations in the project and sort out a few presets. Since it is automatically scanned, the preset names may not match the project and can be modified here by developers.
+
+### Compress Presets
+
+This panel is mainly used to add presets for texture compression. Each texture compression configuration allows to tailor the configuration for different platforms. Once added, developers can quickly add a texture compression preset in the **Inspector** panel by selecting the image asset in the **Hierarchy** panel. It is also possible to modify the preset directly in this panel to achieve the need to update the compression texture configuration in bulk.
+
+The following platforms are currently supported for configuring texture compressions:
+
+1. Web: both Web-Mobile and Web-Desktop platforms
+2. iOS
+3. Mini Game: including all mini game platforms currently supported by Creator, such as WeChat Mini Game, Huawei Quick Game, etc.
+4. Android
+
+Please refer to the [Texture Compression](../../asset/compress-texture.md) documentation for details of texture compression on each platform.
+
+### Properties
+
+- **Mipmaps for compressed textures**: Pre-generated Mipmap for compressed mapping, options: **Allow Pre-generation (default)**; **Disabled** Disabled
+ - If the project is upgraded from a version before v3.7, this option is disabled by default
+ - Generate multiple images when turned on, it will affect the package size, please choose according to your needs
+ - If the user is using texture with generate mip maps checked, and needs to generate mipmaps with texture compression checked and some formats that need to be compressed by third-party tools such as pvr etc, you need to turn this option on in the project settings. Once enabled, the build will generate compressed mipmaps of the corresponding format for use at runtime
+
+#### Adding/Removing Texture Compression Presets
+
+Enter a texture compression preset name in the upper input box and click Enter or the "+" button on the right to add a preset. The other two buttons are for importing/exporting texture compression presets, please refer to the description below for details.
+
+
+
+After adding a compressed texture, it can be deleted by hovering over the preset name and clicking the delete button on the right.
+
+
+
+> **Note**: the two presets **default** and **transparent** built into the panel cannot be modified/deleted.
+
+#### Adding/Deleting Texture Compression Format
+
+Select the platform, then click the **Add Format** button, select the desired texture format, and then configure the corresponding quality level. Currently the same type of image format can only be added once.
+
+
+
+To delete, move the mouse over the texture format and click the red delete button on the right.
+
+
+
+#### Modifying the Texture Compression Preset Name
+
+The name of the texture compression preset is for display purposes only. When a texture compression preset is added, a random UUID is generated as the ID of the preset, so changing the preset name directly does not affect the reference to the preset at the image asset.
+
+
+
+#### Exporting/Importing Texture Compression Presets
+
+The texture compression configuration page allows importing/exporting texture compression presets for better cross-project reuse of the configuration, or edit the texture compression presets externally and import them to the editor.
+
+To write a custom texture compression configuration, please refer to the following interface definitions and examples:
+
+**The interface is defined as follows**:
+
+```ts
+type IConfigGroups = Record;
+type ITextureCompressPlatform = 'miniGame' | 'web' | 'ios' | 'android' | 'pc';
+type ITextureCompressType =
+ | 'jpg'
+ | 'png'
+ | 'webp'
+ | 'pvrtc_4bits_rgb'
+ | 'pvrtc_4bits_rgba'
+ | 'pvrtc_4bits_rgb_a'
+ | 'pvrtc_2bits_rgb'
+ | 'pvrtc_2bits_rgba'
+ | 'pvrtc_2bits_rgb_a'
+ | 'etc1_rgb'
+ | 'etc1_rgb_a'
+ | 'etc2_rgb'
+ | 'etc2_rgba'
+ | 'astc_4x4'
+ | 'astc_5x5'
+ | 'astc_6x6'
+ | 'astc_8x8'
+ | 'astc_10x5'
+ | 'astc_10x10'
+ | 'astc_12x12';
+type IConfigGroupsInfo = Record
+interface ICompressPresetItem {
+ name: string;
+ options: IConfigGroups;
+}
+```
+
+**Examples**:
+
+```json
+{
+ "default": {
+ "name": "default",
+ "options": {
+ "miniGame": {
+ "etc1_rgb": "fast",
+ "pvrtc_4bits_rgb": "fast"
+ },
+ "android": {
+ "astc_8x8": "-medium",
+ "etc1_rgb": "fast"
+ },
+ "ios": {
+ "astc_8x8": "-medium",
+ "pvrtc_4bits_rgb": "fast"
+ },
+ "web": {
+ "astc_8x8": "-medium",
+ "etc1_rgb": "fast",
+ "pvrtc_4bits_rgb": "fast"
+ },
+ }
+ },
+ "transparent": {
+ "name": "transparent",
+ "options": {
+ "miniGame": {
+ "etc1_rgb_a": "fast",
+ "pvrtc_4bits_rgb_a": "fast"
+ },
+ "android": {
+ "astc_8x8": "-medium",
+ "etc1_rgb_a": "fast"
+ },
+ "ios": {
+ "astc_8x8": "-medium",
+ "pvrtc_4bits_rgb_a": "fast"
+ },
+ "web": {
+ "astc_8x8": "-medium",
+ "etc1_rgb_a": "fast",
+ "pvrtc_4bits_rgb_a": "fast"
+ },
+ }
+ }
+}
+```
+
+### Custom Compress Format
+
+Since v3.5.0, custom texture compression pages have been supported in order to make it easy for users to customize the texture compression tool and some custom parameters, encryption, etc. Interface interaction is similar to texture compression presets.
+
+
+
+### Configuration
+
+- **Compress format**: Config the processing format. After selecting a different format, quality options will keep the same type. If the customized compression mode fails, the system will automatically revert to the original compression scheme of the editor.
+
+ 
+
+- **Overwrite original format**: If this option is selected, the original compression format in the existing texture compression preset will be automatically overwritten. The name of the custom compression mode will appear next to the original configuration name. One format can only be overwritten by one custom compression mode.
+
+ 
+
+- **Compression tool**:
+ - **program**: compress tool path.
+ - **Command line parameters**: Sets the parameters to be passed by the calling program. The names of the parameters to be passed by default to build texture compression can be added quickly through the control on the right of the parameter input box. Currently, the 'src, dest, quality' fields are passed by default.
+
+#### Custom Compress Format In Build
+
+After the custom texture format is configured, the word `custom-compress` and the command line parameter information will be printed to console when build the project.
+
+
+
+## Splash Setting
+
+The splash screen setting is a feature that displays the engine logo or a developer-defined logo at the start of the game.
+
+The splash screen will only be shown after the release, not during the preview.
+
+
+
+- **TotalTime**:Total duration of splash screen(ms)
+- **Image Size Multiplier**: The size multiplier of the splash image
+- **Preview**: If you want to change the Splash Image, Hover the mouse on the preview window, then click the '+' button, then select a new image path.
+
+If you want to disable the splash screen, please refer to [Build Options](../publish/build-options.md) for details.
+
+> **Notes**.
+> 1. After selecting different build platforms in the build options, adjust the splash screen rules again to achieve the diversity of splash screen on different platforms
+> 2. the splash screen will only take effect after packaging, not when previewing
+> 3. some countries and regions are not open for full splash screen, we apologize for any inconvenience caused to you.
+
+## Bundle Config
+
+
+
+Bundle Config allows users can config different configurations for various platforms. For example, to distinguish normal textures and high-resolution textures, or for different shops, etc. For more, please refer to [Asset Bundle](../../asset/bundle.md).
+
+Currently, three main types of platforms are supported by Cocos Creator including the native platform, web, and mini-games.
+
+You can select the target platform by clicking on the platform buttons.
+
+
+
+Use the menus on the top right of the panel to create a new, import, or export config.
+
+
+
+- **New Config**: Create a new config.
+
+ 
+
+ After a config is created, you can select it by clicking on the drop-down box beside **Platform Settings** on the **Inspector** panel when a bundle is selected.
+
+ > Different bundles can use different configs.
+
+- **Import Config**:To import a JSON file as the bundle config.
+- **Export Config**:Export the config to reuse it in other projects.
+
+For the created config, you can **Copy Config**, **Copy ID**, **Rename** or **Delete** the config by clicking the menu button.
+
+
+
+### Platform Override
+
+Currently, Cocos Creator supports multiple platforms for publishing. When publishing on each platform, you can choose the option to add a new configuration to override the currently configured platform.
+
+Click the "+" sign on the right side of **Platform Override** to select the target platform.
+
+
+
+After selecting new platforms as needed, the configuration of these new platforms will override the previous generic configuration.
+
+This operation allows developers to optimize for certain platforms.
+
+## Extending the Project Settings Panel
+
+Creator supports adding custom feature pages on the right side of **Project Settings**, please refer to the [Extending the Project Settings Panel](../../editor/extension/contributions-project.md) documentation.
diff --git a/versions/4.0/en/editor/project/index/bundle-change-type.png b/versions/4.0/en/editor/project/index/bundle-change-type.png
new file mode 100644
index 0000000000..af0a09072e
Binary files /dev/null and b/versions/4.0/en/editor/project/index/bundle-change-type.png differ
diff --git a/versions/4.0/en/editor/project/index/bundle-config.png b/versions/4.0/en/editor/project/index/bundle-config.png
new file mode 100644
index 0000000000..7e2d9e0377
Binary files /dev/null and b/versions/4.0/en/editor/project/index/bundle-config.png differ
diff --git a/versions/4.0/en/editor/project/index/bundle-copy.png b/versions/4.0/en/editor/project/index/bundle-copy.png
new file mode 100644
index 0000000000..5ae6af4067
Binary files /dev/null and b/versions/4.0/en/editor/project/index/bundle-copy.png differ
diff --git a/versions/4.0/en/editor/project/index/bundle-menus.png b/versions/4.0/en/editor/project/index/bundle-menus.png
new file mode 100644
index 0000000000..c357c129b3
Binary files /dev/null and b/versions/4.0/en/editor/project/index/bundle-menus.png differ
diff --git a/versions/4.0/en/editor/project/index/bundle-override.png b/versions/4.0/en/editor/project/index/bundle-override.png
new file mode 100644
index 0000000000..b43a417de7
Binary files /dev/null and b/versions/4.0/en/editor/project/index/bundle-override.png differ
diff --git a/versions/4.0/en/editor/project/index/bundle-platforms.png b/versions/4.0/en/editor/project/index/bundle-platforms.png
new file mode 100644
index 0000000000..e1b9baad94
Binary files /dev/null and b/versions/4.0/en/editor/project/index/bundle-platforms.png differ
diff --git a/versions/4.0/en/editor/project/index/custom-macro.png b/versions/4.0/en/editor/project/index/custom-macro.png
new file mode 100644
index 0000000000..fc70d145a4
Binary files /dev/null and b/versions/4.0/en/editor/project/index/custom-macro.png differ
diff --git a/versions/4.0/en/editor/project/index/drag-to-sort.gif b/versions/4.0/en/editor/project/index/drag-to-sort.gif
new file mode 100644
index 0000000000..2171cac39c
Binary files /dev/null and b/versions/4.0/en/editor/project/index/drag-to-sort.gif differ
diff --git a/versions/4.0/en/editor/project/index/feature-crop.png b/versions/4.0/en/editor/project/index/feature-crop.png
new file mode 100644
index 0000000000..2e10729f25
Binary files /dev/null and b/versions/4.0/en/editor/project/index/feature-crop.png differ
diff --git a/versions/4.0/en/editor/project/index/joint-texture-layout.png b/versions/4.0/en/editor/project/index/joint-texture-layout.png
new file mode 100644
index 0000000000..14487d243a
Binary files /dev/null and b/versions/4.0/en/editor/project/index/joint-texture-layout.png differ
diff --git a/versions/4.0/en/editor/project/index/json-editor.png b/versions/4.0/en/editor/project/index/json-editor.png
new file mode 100644
index 0000000000..fe55c435bc
Binary files /dev/null and b/versions/4.0/en/editor/project/index/json-editor.png differ
diff --git a/versions/4.0/en/editor/project/index/layers-camera.png b/versions/4.0/en/editor/project/index/layers-camera.png
new file mode 100644
index 0000000000..53b43216c6
Binary files /dev/null and b/versions/4.0/en/editor/project/index/layers-camera.png differ
diff --git a/versions/4.0/en/editor/project/index/layers-node.png b/versions/4.0/en/editor/project/index/layers-node.png
new file mode 100644
index 0000000000..f74809a8b4
Binary files /dev/null and b/versions/4.0/en/editor/project/index/layers-node.png differ
diff --git a/versions/4.0/en/editor/project/index/layers.png b/versions/4.0/en/editor/project/index/layers.png
new file mode 100644
index 0000000000..0f2791b44d
Binary files /dev/null and b/versions/4.0/en/editor/project/index/layers.png differ
diff --git a/versions/4.0/en/editor/project/index/macro.png b/versions/4.0/en/editor/project/index/macro.png
new file mode 100644
index 0000000000..38d7e70b55
Binary files /dev/null and b/versions/4.0/en/editor/project/index/macro.png differ
diff --git a/versions/4.0/en/editor/project/index/model.png b/versions/4.0/en/editor/project/index/model.png
new file mode 100644
index 0000000000..2d81a07a4b
Binary files /dev/null and b/versions/4.0/en/editor/project/index/model.png differ
diff --git a/versions/4.0/en/editor/project/index/path-protocol.png b/versions/4.0/en/editor/project/index/path-protocol.png
new file mode 100644
index 0000000000..f8b36d4e78
Binary files /dev/null and b/versions/4.0/en/editor/project/index/path-protocol.png differ
diff --git a/versions/4.0/en/editor/project/index/physics-collision-demo.png b/versions/4.0/en/editor/project/index/physics-collision-demo.png
new file mode 100644
index 0000000000..c8c9e93945
Binary files /dev/null and b/versions/4.0/en/editor/project/index/physics-collision-demo.png differ
diff --git a/versions/4.0/en/editor/project/index/physics-collision.png b/versions/4.0/en/editor/project/index/physics-collision.png
new file mode 100644
index 0000000000..8a8e7896ec
Binary files /dev/null and b/versions/4.0/en/editor/project/index/physics-collision.png differ
diff --git a/versions/4.0/en/editor/project/index/physics-in-engine.png b/versions/4.0/en/editor/project/index/physics-in-engine.png
new file mode 100644
index 0000000000..cb9ff8c3a3
Binary files /dev/null and b/versions/4.0/en/editor/project/index/physics-in-engine.png differ
diff --git a/versions/4.0/en/editor/project/index/physics-index.png b/versions/4.0/en/editor/project/index/physics-index.png
new file mode 100644
index 0000000000..e895e92815
Binary files /dev/null and b/versions/4.0/en/editor/project/index/physics-index.png differ
diff --git a/versions/4.0/en/editor/project/index/physics.png b/versions/4.0/en/editor/project/index/physics.png
new file mode 100644
index 0000000000..c1219e2a71
Binary files /dev/null and b/versions/4.0/en/editor/project/index/physics.png differ
diff --git a/versions/4.0/en/editor/project/index/plugin-script-menu.png b/versions/4.0/en/editor/project/index/plugin-script-menu.png
new file mode 100644
index 0000000000..c7fcfce9d5
Binary files /dev/null and b/versions/4.0/en/editor/project/index/plugin-script-menu.png differ
diff --git a/versions/4.0/en/editor/project/index/project-data.png b/versions/4.0/en/editor/project/index/project-data.png
new file mode 100644
index 0000000000..c6f0ef3415
Binary files /dev/null and b/versions/4.0/en/editor/project/index/project-data.png differ
diff --git a/versions/4.0/en/editor/project/index/rigidbody-group.jpg b/versions/4.0/en/editor/project/index/rigidbody-group.jpg
new file mode 100644
index 0000000000..9601623a75
Binary files /dev/null and b/versions/4.0/en/editor/project/index/rigidbody-group.jpg differ
diff --git a/versions/4.0/en/editor/project/index/scripting.png b/versions/4.0/en/editor/project/index/scripting.png
new file mode 100644
index 0000000000..3c49b05416
Binary files /dev/null and b/versions/4.0/en/editor/project/index/scripting.png differ
diff --git a/versions/4.0/en/editor/project/index/sorting-layer.png b/versions/4.0/en/editor/project/index/sorting-layer.png
new file mode 100644
index 0000000000..3dc77c949d
Binary files /dev/null and b/versions/4.0/en/editor/project/index/sorting-layer.png differ
diff --git a/versions/4.0/en/editor/project/index/sorting-plugin-script.png b/versions/4.0/en/editor/project/index/sorting-plugin-script.png
new file mode 100644
index 0000000000..24fc1b265e
Binary files /dev/null and b/versions/4.0/en/editor/project/index/sorting-plugin-script.png differ
diff --git a/versions/4.0/en/editor/project/index/sorting.png b/versions/4.0/en/editor/project/index/sorting.png
new file mode 100644
index 0000000000..82e81660c9
Binary files /dev/null and b/versions/4.0/en/editor/project/index/sorting.png differ
diff --git a/versions/4.0/en/editor/project/index/splash.png b/versions/4.0/en/editor/project/index/splash.png
new file mode 100644
index 0000000000..6f1f560e3f
Binary files /dev/null and b/versions/4.0/en/editor/project/index/splash.png differ
diff --git a/versions/4.0/en/editor/project/physics-configs.md b/versions/4.0/en/editor/project/physics-configs.md
new file mode 100644
index 0000000000..de57247cba
--- /dev/null
+++ b/versions/4.0/en/editor/project/physics-configs.md
@@ -0,0 +1,59 @@
+# Physics Configs
+
+Physical configuration is used to configure various commonly used properties.
+
+## Property description
+
+
+
+- `gravity` Gravity direction vector, the sign means the positive or negative direction on the axis. **Default**: `{ x: 0, y: -10, z: 0 }`.
+- `allowSleep` Whether to allow rigid bodies to enter sleep state. **Default**: `true`.
+- `sleepThreshold` The maximum speed threshold for entering sleep. **Default**: `0.1`. **Min**: `0`.
+- `autoSimulation` Whether to enable automatic simulation.
+- `fixedTimeStep` Fixed time step between each simulation. **Default**: `1/60`. **Min**: `0`.
+- `maxSubSteps` Maximum number of substeps per simulation step. **Default**: `1`. **Min**: `0`.
+- `friction` Coefficient of friction. **Default**: `0.5`.
+- `rollingFriction` Rolling friction coefficient. **Default**: `0.1`.
+- `spinningFriction` Spin friction coefficient. **Default**: `0.1`.
+- `restitution` Coefficient of elasticity. **Default**: `0.1`.
+- `collisionMatrix` The collision matrix, used only for initialization.
+
+
+## Collision Matrix
+
+The collision matrix is used to initialize groups and masks of physical elements.
+
+
+
+### Grouping concept
+
+In the editor, the grouping format of the collision matrix is __{index, name}__, __index__ is the number of bits from __0__ to __31__, and __name__ is the name of the group. The new project will have a default grouping: __{index: 0, name: 'DEFAULT'}__.
+
+By clicking the __+__ button you can add a new group.
+
+> **Note**: both __index__ and __name__ cannot be empty and cannot be repeated with existing items; after adding, the group cannot be deleted, only the name of the group can be modified.
+
+### How to configure
+
+Take a new __water__ group as an example:
+
+
+
+This table lists all the groups, and you can check it to determine which two groups will do the collision detection.
+
+**As shown in the figure above, whether `DEFAULT` and `water` will perform collision detection will be determined by whether the corresponding check box is checked**.
+
+According to the above rules, the collision pairs generated in this table are:
+
+- DEFAULT - water
+- DEFAULT - DEFAULT
+
+And the grouping pairs that do not perform collision detection include:
+
+- water - water
+
+### Configure groups of physical components
+
+In addition, the __Group__ property on the __RigidBody__ component needs to be configured into the corresponding physical element:
+
+
diff --git a/versions/4.0/en/editor/project/texture-compress/add-format.png b/versions/4.0/en/editor/project/texture-compress/add-format.png
new file mode 100644
index 0000000000..7595797eff
Binary files /dev/null and b/versions/4.0/en/editor/project/texture-compress/add-format.png differ
diff --git a/versions/4.0/en/editor/project/texture-compress/add.png b/versions/4.0/en/editor/project/texture-compress/add.png
new file mode 100644
index 0000000000..aa1ecf7ef2
Binary files /dev/null and b/versions/4.0/en/editor/project/texture-compress/add.png differ
diff --git a/versions/4.0/en/editor/project/texture-compress/compress-presets.png b/versions/4.0/en/editor/project/texture-compress/compress-presets.png
new file mode 100644
index 0000000000..76880dbcec
Binary files /dev/null and b/versions/4.0/en/editor/project/texture-compress/compress-presets.png differ
diff --git a/versions/4.0/en/editor/project/texture-compress/compress-texture.png b/versions/4.0/en/editor/project/texture-compress/compress-texture.png
new file mode 100644
index 0000000000..ba2d602dfb
Binary files /dev/null and b/versions/4.0/en/editor/project/texture-compress/compress-texture.png differ
diff --git a/versions/4.0/en/editor/project/texture-compress/custom-compress-log.png b/versions/4.0/en/editor/project/texture-compress/custom-compress-log.png
new file mode 100644
index 0000000000..c78a629c6a
Binary files /dev/null and b/versions/4.0/en/editor/project/texture-compress/custom-compress-log.png differ
diff --git a/versions/4.0/en/editor/project/texture-compress/custom-compress-options.png b/versions/4.0/en/editor/project/texture-compress/custom-compress-options.png
new file mode 100644
index 0000000000..aa02fe0dfe
Binary files /dev/null and b/versions/4.0/en/editor/project/texture-compress/custom-compress-options.png differ
diff --git a/versions/4.0/en/editor/project/texture-compress/custom-compress.png b/versions/4.0/en/editor/project/texture-compress/custom-compress.png
new file mode 100644
index 0000000000..c1752bb5e2
Binary files /dev/null and b/versions/4.0/en/editor/project/texture-compress/custom-compress.png differ
diff --git a/versions/4.0/en/editor/project/texture-compress/custom-format.png b/versions/4.0/en/editor/project/texture-compress/custom-format.png
new file mode 100644
index 0000000000..27343e7289
Binary files /dev/null and b/versions/4.0/en/editor/project/texture-compress/custom-format.png differ
diff --git a/versions/4.0/en/editor/project/texture-compress/delete-format.png b/versions/4.0/en/editor/project/texture-compress/delete-format.png
new file mode 100644
index 0000000000..fb2874a840
Binary files /dev/null and b/versions/4.0/en/editor/project/texture-compress/delete-format.png differ
diff --git a/versions/4.0/en/editor/project/texture-compress/delete.png b/versions/4.0/en/editor/project/texture-compress/delete.png
new file mode 100644
index 0000000000..debfc3a9f3
Binary files /dev/null and b/versions/4.0/en/editor/project/texture-compress/delete.png differ
diff --git a/versions/4.0/en/editor/project/texture-compress/edit.png b/versions/4.0/en/editor/project/texture-compress/edit.png
new file mode 100644
index 0000000000..cf1ad8e67f
Binary files /dev/null and b/versions/4.0/en/editor/project/texture-compress/edit.png differ
diff --git a/versions/4.0/en/editor/project/texture-compress/overwrite-format.png b/versions/4.0/en/editor/project/texture-compress/overwrite-format.png
new file mode 100644
index 0000000000..315e823aca
Binary files /dev/null and b/versions/4.0/en/editor/project/texture-compress/overwrite-format.png differ
diff --git a/versions/4.0/en/editor/publish/android/build-example-android.md b/versions/4.0/en/editor/publish/android/build-example-android.md
new file mode 100644
index 0000000000..afdc103041
--- /dev/null
+++ b/versions/4.0/en/editor/publish/android/build-example-android.md
@@ -0,0 +1,168 @@
+# Android Publish Example
+
+In this section, we will introduce how to build Cocos Creator project with Android Studio.
+
+Please prepare a Cocos Creator project with at least one scene.
+
+
+
+## Set Android Development Environment
+
+To publish an Android native application, you need to install the Android Studio development environment, as well as specific versions of JDK (or OpenSDK), Android SDK, NDK, and more. For more details, please refer to the [Android Native Development Environment Setup](../setup-native-development.md).
+
+## Publish Process
+
+The next step is to create a new build task and publish an Android APK on the **Build** panel in Cocos Creator.
+
+### Create Build Task
+
+1. By clicking the **Project** -> **Build** menu to open **Build** panel.
+
+ 
+
+2. At the top of **Build** panel, click on the **New Build Task** button
+
+ P
+
+3. To select **Android** as the build target platform, click on the drop-down menu
+
+ 
+
+4. Make sure to have at least one scene designated as the Start Scene. If you have only one scene, it will be added by default
+
+ 
+
+5. Please refer to [Publishing to Native Platforms - Render BackEnd](../native-options.md#Render%20BackEnd) to select an appropriate render backend
+
+ 
+
+6. Enter the Game Package Name
+
+ 
+
+ > Please refer to [Bundle Identifier](../native-options.md#Bundle%20Identifier) for guidance your app's bundle identifier
+
+7. Select Target API Level
+
+ 
+
+ > In case no dropdown content, please check the SDK and NDK configuration in Cocos Creator
+
+Other build options please refer to [Publishing to Native Platforms](../native-options.md)
+
+### Build and Publish
+
+1. To begin a build process, click on the **Build** button for the selected build task.
+
+ 
+
+2. Please wait until the build process finished
+
+ 
+
+3. Click on the button below to open the folder containing the exported Android Project
+
+ 
+
+4. Locate the corresponding directory
+
+ 
+
+5. Click on the open menu on android studio
+
+ 
+
+6. Navigate to the project path in the `{Your project}/build` directory, which is named 'android' by default, and open it using Android Studio.
+
+ 
+
+7. Generate APK in Android Studio
+
+ After the preparation has been completed by Android Studio, you can start building an Android APK. However, the sync process may take a long time to complete. If this happens, you can stop any ongoing background tasks by following the steps below:
+
+ Click on the background task on the status bar:
+ 
+
+ Close all background tasks by clicking on the close button
+ 
+
+8. Click on **Build Bundle(s) / APK(s)** in the **Build** menu
+
+ 
+
+9. The debug APK could be found in the `{proj/build}` directory
+
+ 
+
+## Keystore Generation and Usage
+
+For the release of the final version, the debug key cannot be used. You need to create your own key.
+
+### Creating a Key
+
+You can generate a key using Android Studio:
+
+1. In Android Studio, click on the "Build" menu and select "Generate Signed Bundle / APK":
+
+
+2. In the pop-up window, select "APK" and click "Next":
+
+
+3. In the guided window, click on "Create new":
+
+
+4. Fill in the required information in the pop-up window:
+
+
+> It is recommended to use different keys for different projects. You can store each project's key in the project's root directory.
+
+### Using the Key
+
+After successfully creating the key, a key file will be generated in the selected directory. You can fill in the key information in the Android build panel. This way, both the debug and release versions will use the key you created.
+
+As shown in the following image, uncheck the "Use debug keystore" option and select your custom key file from the "Keystore Path" below. Fill in the relevant information:
+
+
+### Considerations
+
+1. It is recommended to create a dedicated key for each project from the first release.
+2. Some SDK services require APK key signature verification. Using the default debug key may result in service call failures.
+
+## Advanced
+
+### Java and TypeScript Communication
+
+The engine provides various methods to solve the communication issues between TypeScript and the native layer.
+
+When integrating common SDKs, we often need to perform login operations through the SDK's login interface, and then pass the results to the TypeScript layer for further processing in the game.
+
+The engine provides three methods for communication between TypeScript and Android native layer.
+
+- [JavaScript and Java Communication using JsbBridge](../../../advanced-topics/js-java-bridge.md): This method is very convenient for integrating SDKs and handling actions such as registration, login, and displaying ads. It can quickly solve these types of problems.
+
+- [Tutorial: JSB 2.0](../../../advanced-topics/JSB2.0-learning.md): This method is recommended for frequent C++ API calls or batch exporting of C++ APIs..
+
+- [JavaScript and Android Communication with Reflection](../../../advanced-topics/java-reflection.md): This method is highly effective for non-frequent calls.
+
+### Importing Third-Party Libraries
+
+To publish your application to the app market, you usually need to integrate certain third-party SDKs. These SDKs are typically provided in JAR or AAR format. You can refer to [Using Your Library in Other Projects](https://developer.android.com/studio/projects/android-library?hl=zh-cn#psd-add-library-dependency) to import the local library into your project.
+
+### Extending Build Process
+
+Please refer to [Extending Build Process](../custom-build-plugin.md) to extend the publishing mechanism by the extension system.
+
+## Q&A
+
+- Q: How to debug publishing errors
+ - A: You can debug publishing errors by opening the log.txt file using the log button
+
+ 
+
+- Q: Missing LIB_EGL
+ - A: Change your NDK to the version mentioned above.
+
+- Q: Asset name mechanism
+ - A: Since Android is based on Linux, some file specifications of Linux still apply in Android, such as
+ - 1. Android is case-sensitive, make sure the path is case-sensitive, otherwise, it will not load correctly
+ - 2. Do not include spaces in the folder or file name
diff --git a/versions/4.0/en/editor/publish/android/build-options-android.md b/versions/4.0/en/editor/publish/android/build-options-android.md
new file mode 100644
index 0000000000..7186eb9d21
--- /dev/null
+++ b/versions/4.0/en/editor/publish/android/build-options-android.md
@@ -0,0 +1,125 @@
+# Build Options - Android
+
+The build options for the Android platform are as follows:
+
+
+
+## Enable Swappy
+
+**Enable Swappy** is used to decide whether to enable the integrated Swappy feature in the engine. Currently supported for GLES and Vulkan.
+
+This option actively adjusts the rendering time to match the screen refresh rate, achieving stable frame rates and reducing unnecessary rendering. The build parameter is `swappy`.
+
+For more information, refer to the official documentation on [Frame Pacing Library Overview](https://source.android.com/devices/graphics/frame-pacing).
+
+## Render Backend
+
+Currently supported options are as follows:
+
+- [VULKAN](https://www.vulkan.org/)
+- [GLES3](https://www.khronos.org/registry/OpenGL-Refpages/es3/)
+- [GLES2](https://www.khronos.org/registry/OpenGL-Refpages/es2.0/)
+
+At least one option must be selected, with **GLES3** being the default.
+
+If GLES 2/3 is selected, GLES3 must be checked by default and it is not allowed to select GLES2 alone.
+
+When multiple options are selected, the runtime will choose the rendering backend based on the device's actual support.
+
+## Game Package Name
+
+The Game Package Name usually follows the reverse order of the product's website URL, such as `com.mycompany.myproduct`.
+
+> **Note**: The package name can only contain numbers, letters, and underscores. Additionally, the last part of the package name must start with a letter and cannot start with an underscore or a number.
+
+## Target API Level
+
+Set the Target API Level required for Android platform compilation. Clicking the Set Android SDK button next to it will quickly navigate to the configuration page. For specific configuration rules, refer to [Android Development Environment Setup](../setup-native-development.md).
+
+## APP ABI
+
+Set the CPU types that your Android app needs to support. You can choose one or more options, including `armeabi-v7a`, `arm64-v8a`, `x86`, and `x86_64`.
+
+**Notes**:
+
+1. When you select one ABI and build it without cleaning, both ABIs' shared objects (so) will be packaged into the APK. This is the default behavior of Android Studio. If you import the project into Android Studio, after building one ABI, perform **Build -> Clean Project** before building another ABI. This way, only the latter ABI will be packaged into the APK.
+
+2. After importing the project into Android Studio, it exists independently and is not dependent on the build and release panel. If you need to modify the ABI, directly modify the **PROP_APP_ABI** property in the `gradle.properties` file.
+
+
+## Use Debug Keystore
+
+Android requires that all APKs be digitally signed with a certificate before they can be installed. Cocos Creator provides a default keystore, and checking **Use Debug Keystore** means using the default keystore. If developers need a custom keystore, uncheck **Use Debug Keystore**. For more details, refer to the [Android Developer - App Signing](https://developer.android.google.cn/studio/publish/app-signing).
+
+## Orientation
+
+The screen orientation currently includes three options: **Portrait**, **Landscape Left**, and **Landscape Right**.
+
+- **Portrait**: The screen is in an upright position with the Home button at the bottom.
+- **Landscape Left**: The screen is in a landscape position with the Home button on the left side of the screen.
+- **Landscape Right**: The screen is in a landscape position with the Home button on the right side of the screen.
+
+## Google Play Instant
+
+Checking this option allows you to package and publish your game to Google Play Instant. Google Play Instant is dependent on Google Play and is not a separate distribution channel but rather a game streaming solution. It enables players to try, share, and engage with your game instantly without the need to install it.
+
+**Note the following points when using Google Play Instant:**
+
+1. Android Studio version should be 4.0 or above.
+2. Android phones running Android 6.0 or above. Devices with Android SDK versions between 6.0 and 7.0 require the installation of Google Play Services Framework, while devices with SDK versions 8.0 or above do not require it and can use the services directly.
+3. For the first build, you need to open the built project with Android Studio to download the Google Play Instant Development SDK (Windows) or Instant Apps Development SDK (Mac) support package. If the download fails, it is recommended to set up an HTTP proxy for Android Studio.
+
+
+## Generate App Bundle(Google Play)
+
+Checking this option allows you to package your game as an App Bundle format for uploading to the Google Play Store. For more information, refer to the [Android Developer - App Bundle](https://developer.android.google.cn/guide/app-bundle/).
+
+## Other Options
+
+Some SDK and NDK options need to be set in the preferences. In addition to setting them in the preferences, you can also pass specified parameters through the build command line.
+
+**sdkPath**: Specify the SDK path
+**ndkPath**: Specify the NDK path
+
+You can export the build configuration and add the corresponding parameters in the Android options.
+
+## Build Parameter Interface Definition (used to modify parameters during command line builds)
+
+```ts
+interface IOptions {
+ packageName: string;
+ resizeableActivity: boolean;
+ maxAspectRatio: string;
+ orientation: {
+ landscapeRight: boolean;
+ landscapeLeft: boolean;
+ portrait: boolean;
+ upsideDown: boolean;
+ },
+
+ apiLevel: number;
+ appABIs: IAppABI[];
+
+ useDebugKeystore: boolean;
+ keystorePath: string;
+ keystorePassword: string;
+ keystoreAlias: string;
+ keystoreAliasPassword: string;
+
+ appBundle: boolean;
+ androidInstant: boolean;
+ inputSDK: boolean;
+ remoteUrl: string;
+ sdkPath: string;
+ ndkPath: string;
+ javaHome?: string;
+ javaPath?: string;
+
+ swappy: boolean;
+
+ renderBackEnd: {
+ vulkan: boolean;
+ gles3: boolean;
+ gles2: boolean;
+ }
+}
diff --git a/versions/4.0/en/editor/publish/android/build-setup-evn-android.md b/versions/4.0/en/editor/publish/android/build-setup-evn-android.md
new file mode 100644
index 0000000000..b21d083a70
--- /dev/null
+++ b/versions/4.0/en/editor/publish/android/build-setup-evn-android.md
@@ -0,0 +1,106 @@
+# Android Development Environment Setup
+
+## Download Android Studio
+
+Developers should download the appropriate IDE from the [official Android Studio](https://developer.android.com/studio).
+
+Reference Setting up the [Native Development Environment](../setup-native-development.md#Android%20Platform%20Dependencies) to set up the development environment
+
+## Download and install JDK
+
+Reference [Native Development Environment](../setup-native-development.md#Downloading%20the%20Java%20SDK (JDK))
+
+Type `java -version` in the terminal to verify if the installation is successful.
+
+
+
+> Please refer to [How do I set or change the PATH system variable?](https://www.java.com/en/download/help/path.html) to set up your environment
+>
+> **Note**:The author utilizes [OpenJDK](https://openjdk.org/), which has similar features as the JDK but follows another open-source protocol.
+
+Download and install the Android SDK
+
+### Auto Download
+
+Here is an example of how to download Android SDK through Android Studio
+
+1. Start Android Studio
+
+2. Open the Settings/Preferences panel from the main menu
+ 
+
+ > The name of the setting panel differs on the platform. It is called **Settings** on Windows but **Preferences** on MacOS.
+
+3. Navigate to the Android SDK page in the Settings/Preferences panel.
+ 
+
+4. Select at least one suitable SDK to download. You can choose the recommended version mentioned in [Downloading the SDK and NDK required to publish to the Android platform](../setup-native-development.md#Downloading%20the20SDK20and20NDK20required20to20publish20to20the%20Android%20platform).
+
+ - As an example, we will be using Android 11.0 (R). Check the box next to the name and then click either the OK or Apply button to proceed
+
+ - Click the OK button in the pop-up dialog
+ 
+
+ - Please wait until the download is finished
+ 
+
+### Manually downloading the Android SDK
+
+In case of network connectivity issues, you can manually download the Android SDK and put it in the directory configuring in **Android SDK Location**.
+
+You could click the **Edit** button to choose a different path.
+
+
+
+You can change to use SDK mirrors(Optional) by setting HTTP Proxy in Android Studio.
+**Auto-detect proxy settings:** In the Settings panel of Android Studio, navigate to the HTTP Proxy and select the **Auto-detect proxy settings** option, and then input the mirror links below.
+
+
+
+**Choose specific mirrors:** Here are some alternative mirrors for the Android SDK and Gradle that can help developers resolve download issues when downloading failed from the official website. However, if these mirrors do not work, you may need to search for other mirrors.
+
+| Mirror | Address |
+| :------- | :----------------------------------------------------- |
+| Tencent(CN) | |
+| AliCloud(CN) | |
+
+> In case these mirrors are not working, please search for other valid mirrors.
+
+## Download And Install Android NDK
+
+Please refer to [Downloading the SDK and NDK required to publish to the Android platform](../setup-native-development.md#Downloading%20the%20SDK%20and%20NDK%20required%20to%20publish%20to%20the%20Android%20platform) to download the appropriate version of Android NDK(**r18~21**).
+
+### Download the Android NDK from Android Studio
+
+Navigate to the **Android SDK** page in Android Studio **Settings** panel.
+
+> **Note**: check **Show Package Details**
+> 
+
+
+
+Make sure to select the appropriate version to download. If the list fails to refresh, you can follow the steps in the next section to manually download the Android NDK.
+
+### Manually download
+
+You could find the historical versions of Android NDK [here](https://github.com/android/ndk/wiki/Unsupported-Downloads#r20b)
+
+For instance, let's consider the version r20b, which can be found in the link provided above. Make sure to select the appropriate version according to your operating system, and extract it to the directory previously set as the Android SDK Location.
+
+
+
+## Configure Android SDK and NDK in Cocos Creator
+
+Navigate to the **Preferences** panel in Cocos Creator by clicking the **File** -> **Preferences** menu. From there go to the **Program Manager** page and configure the **Android SDK** and **Android NDK** properties with the following images.
+
+
+
+The path should be like follows:
+
+**NDK**:
+
+
+
+**SDK**:
+
+
diff --git a/versions/4.0/en/editor/publish/android/images/accept.png b/versions/4.0/en/editor/publish/android/images/accept.png
new file mode 100644
index 0000000000..d11260cc42
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/accept.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/android-keystore-panel.png b/versions/4.0/en/editor/publish/android/images/android-keystore-panel.png
new file mode 100644
index 0000000000..76f1b51ac9
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/android-keystore-panel.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/android-sdk-preference.png b/versions/4.0/en/editor/publish/android/images/android-sdk-preference.png
new file mode 100644
index 0000000000..838577f99f
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/android-sdk-preference.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/apk.png b/versions/4.0/en/editor/publish/android/images/apk.png
new file mode 100644
index 0000000000..349353c1c0
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/apk.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/as-open-menu.png b/versions/4.0/en/editor/publish/android/images/as-open-menu.png
new file mode 100644
index 0000000000..b1f57b5d4c
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/as-open-menu.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/as-open-proj.png b/versions/4.0/en/editor/publish/android/images/as-open-proj.png
new file mode 100644
index 0000000000..9eb58e9f8e
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/as-open-proj.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/as-setting.png b/versions/4.0/en/editor/publish/android/images/as-setting.png
new file mode 100644
index 0000000000..cb72db0d6a
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/as-setting.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/background-task.png b/versions/4.0/en/editor/publish/android/images/background-task.png
new file mode 100644
index 0000000000..0977698682
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/background-task.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/build-apk-success.png b/versions/4.0/en/editor/publish/android/images/build-apk-success.png
new file mode 100644
index 0000000000..0fb0f4a4b9
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/build-apk-success.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/build-apk.png b/versions/4.0/en/editor/publish/android/images/build-apk.png
new file mode 100644
index 0000000000..b5692a05ec
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/build-apk.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/build-menu.png b/versions/4.0/en/editor/publish/android/images/build-menu.png
new file mode 100644
index 0000000000..3d4968bcbb
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/build-menu.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/build-options-android.png b/versions/4.0/en/editor/publish/android/images/build-options-android.png
new file mode 100644
index 0000000000..894aabe3e4
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/build-options-android.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/build.png b/versions/4.0/en/editor/publish/android/images/build.png
new file mode 100644
index 0000000000..a81485fb5b
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/build.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/building.png b/versions/4.0/en/editor/publish/android/images/building.png
new file mode 100644
index 0000000000..427d0a9987
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/building.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/cc-build-menu.png b/versions/4.0/en/editor/publish/android/images/cc-build-menu.png
new file mode 100644
index 0000000000..83935002d6
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/cc-build-menu.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/check-err.png b/versions/4.0/en/editor/publish/android/images/check-err.png
new file mode 100644
index 0000000000..4978158a95
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/check-err.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/component-installer.png b/versions/4.0/en/editor/publish/android/images/component-installer.png
new file mode 100644
index 0000000000..f57a8b2f40
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/component-installer.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/confirm-change.png b/versions/4.0/en/editor/publish/android/images/confirm-change.png
new file mode 100644
index 0000000000..3e6d57aadb
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/confirm-change.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/create-scene.png b/versions/4.0/en/editor/publish/android/images/create-scene.png
new file mode 100644
index 0000000000..7fa7f6560d
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/create-scene.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/create-sign.png b/versions/4.0/en/editor/publish/android/images/create-sign.png
new file mode 100644
index 0000000000..5f633747ed
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/create-sign.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/debug-keystore.png b/versions/4.0/en/editor/publish/android/images/debug-keystore.png
new file mode 100644
index 0000000000..c0f2c237bd
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/debug-keystore.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/download-ndk-by-as.png b/versions/4.0/en/editor/publish/android/images/download-ndk-by-as.png
new file mode 100644
index 0000000000..40ddd3dc32
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/download-ndk-by-as.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/download-ndk.png b/versions/4.0/en/editor/publish/android/images/download-ndk.png
new file mode 100644
index 0000000000..37b1acf917
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/download-ndk.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/download-sdk.png b/versions/4.0/en/editor/publish/android/images/download-sdk.png
new file mode 100644
index 0000000000..07b8a8bcc7
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/download-sdk.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/downloading-complete.png b/versions/4.0/en/editor/publish/android/images/downloading-complete.png
new file mode 100644
index 0000000000..70f6c65565
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/downloading-complete.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/downloading.png b/versions/4.0/en/editor/publish/android/images/downloading.png
new file mode 100644
index 0000000000..398f61dcaf
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/downloading.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/find-proj.png b/versions/4.0/en/editor/publish/android/images/find-proj.png
new file mode 100644
index 0000000000..ac741c9f4d
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/find-proj.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/find-required-version.png b/versions/4.0/en/editor/publish/android/images/find-required-version.png
new file mode 100644
index 0000000000..f284735b3e
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/find-required-version.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/find-sdk-version.png b/versions/4.0/en/editor/publish/android/images/find-sdk-version.png
new file mode 100644
index 0000000000..8fc2e931a9
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/find-sdk-version.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/game-package-name.png b/versions/4.0/en/editor/publish/android/images/game-package-name.png
new file mode 100644
index 0000000000..f838d433cd
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/game-package-name.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/gen-apk.png b/versions/4.0/en/editor/publish/android/images/gen-apk.png
new file mode 100644
index 0000000000..df8ae2fbab
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/gen-apk.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/gen-sign-apk.png b/versions/4.0/en/editor/publish/android/images/gen-sign-apk.png
new file mode 100644
index 0000000000..e3249799ab
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/gen-sign-apk.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/http-proxy.png b/versions/4.0/en/editor/publish/android/images/http-proxy.png
new file mode 100644
index 0000000000..ffa66da5ae
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/http-proxy.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/install-ndk-by-as.png b/versions/4.0/en/editor/publish/android/images/install-ndk-by-as.png
new file mode 100644
index 0000000000..81e07c3974
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/install-ndk-by-as.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/interrupt-sync.png b/versions/4.0/en/editor/publish/android/images/interrupt-sync.png
new file mode 100644
index 0000000000..f10fdbe28d
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/interrupt-sync.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/java-ts.png b/versions/4.0/en/editor/publish/android/images/java-ts.png
new file mode 100644
index 0000000000..e6e0a28319
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/java-ts.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/missing-sdk.png b/versions/4.0/en/editor/publish/android/images/missing-sdk.png
new file mode 100644
index 0000000000..4e3de76a2c
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/missing-sdk.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/ndk-dir.png b/versions/4.0/en/editor/publish/android/images/ndk-dir.png
new file mode 100644
index 0000000000..adb9459b76
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/ndk-dir.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/new-build-task.png b/versions/4.0/en/editor/publish/android/images/new-build-task.png
new file mode 100644
index 0000000000..6ac624a9b3
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/new-build-task.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/open-with-as.png b/versions/4.0/en/editor/publish/android/images/open-with-as.png
new file mode 100644
index 0000000000..42cb349157
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/open-with-as.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/open.png b/versions/4.0/en/editor/publish/android/images/open.png
new file mode 100644
index 0000000000..cbc97681ab
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/open.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/package-name.png b/versions/4.0/en/editor/publish/android/images/package-name.png
new file mode 100644
index 0000000000..0fd4824c87
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/package-name.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/preference.png b/versions/4.0/en/editor/publish/android/images/preference.png
new file mode 100644
index 0000000000..850cf3a115
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/preference.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/program.png b/versions/4.0/en/editor/publish/android/images/program.png
new file mode 100644
index 0000000000..f734f91b7b
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/program.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/progress.png b/versions/4.0/en/editor/publish/android/images/progress.png
new file mode 100644
index 0000000000..53048055b7
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/progress.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/project.png b/versions/4.0/en/editor/publish/android/images/project.png
new file mode 100644
index 0000000000..2bd2bef86c
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/project.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/render-backend.png b/versions/4.0/en/editor/publish/android/images/render-backend.png
new file mode 100644
index 0000000000..b5e88160a7
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/render-backend.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/sdk-component-setup.png b/versions/4.0/en/editor/publish/android/images/sdk-component-setup.png
new file mode 100644
index 0000000000..b3dd272f98
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/sdk-component-setup.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/sdk-dir.png b/versions/4.0/en/editor/publish/android/images/sdk-dir.png
new file mode 100644
index 0000000000..d127103c27
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/sdk-dir.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/sdk-location.png b/versions/4.0/en/editor/publish/android/images/sdk-location.png
new file mode 100644
index 0000000000..86a8844d48
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/sdk-location.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/select-platform.png b/versions/4.0/en/editor/publish/android/images/select-platform.png
new file mode 100644
index 0000000000..d160c93e08
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/select-platform.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/select-sdk.png b/versions/4.0/en/editor/publish/android/images/select-sdk.png
new file mode 100644
index 0000000000..44b4ab4328
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/select-sdk.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/show-log.png b/versions/4.0/en/editor/publish/android/images/show-log.png
new file mode 100644
index 0000000000..9e9cb4d6cb
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/show-log.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/show-package-details.png b/versions/4.0/en/editor/publish/android/images/show-package-details.png
new file mode 100644
index 0000000000..832618e2b5
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/show-package-details.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/start-scene.png b/versions/4.0/en/editor/publish/android/images/start-scene.png
new file mode 100644
index 0000000000..7ac450b1ad
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/start-scene.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/target-api-level.png b/versions/4.0/en/editor/publish/android/images/target-api-level.png
new file mode 100644
index 0000000000..b6006ef0ee
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/target-api-level.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/terminal.png b/versions/4.0/en/editor/publish/android/images/terminal.png
new file mode 100644
index 0000000000..2d152f9bb0
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/terminal.png differ
diff --git a/versions/4.0/en/editor/publish/android/images/verify-setting.png b/versions/4.0/en/editor/publish/android/images/verify-setting.png
new file mode 100644
index 0000000000..cd75d0091a
Binary files /dev/null and b/versions/4.0/en/editor/publish/android/images/verify-setting.png differ
diff --git a/versions/4.0/en/editor/publish/android/index.md b/versions/4.0/en/editor/publish/android/index.md
new file mode 100644
index 0000000000..54a2a55c35
--- /dev/null
+++ b/versions/4.0/en/editor/publish/android/index.md
@@ -0,0 +1,21 @@
+# Publishing Android Apps
+
+This article will introduce the process of publish a Cocos Creator project to Android apps.
+
+## Content
+
+- [Android Publishing Example](./build-example-android.md)
+- [Build Options - Android](build-options-android.md)
+- [JavaScript and iOS/macOS Communication with Reflection](../../../advanced-topics/oc-reflection.md)
+- [JavaScript and Objective-C Communication using JsbBridge](../../../advanced-topics/js-oc-bridge.md)
+- [Features and System Versions](../../../advanced-topics/supported-versions.md)
+
+## Read More
+
+- [Setting up Native Development Environment](../setup-native-development.md)
+- [Build Panel](../build-panel.md)
+- [General Build Panel](../build-options.md)
+- [General Native Build Options](../native-options.md)
+- [Debugging JavaScript on Native Platforms](../debug-jsb.md)
+- [Build Process and FAQ](../build-guide.md)
+- [Native Platform Secondary Development Guide](../../../advanced-topics/native-secondary-development.md)
diff --git a/versions/4.0/en/editor/publish/app-clip/cocos-proj.png b/versions/4.0/en/editor/publish/app-clip/cocos-proj.png
new file mode 100644
index 0000000000..81f1e52e74
Binary files /dev/null and b/versions/4.0/en/editor/publish/app-clip/cocos-proj.png differ
diff --git a/versions/4.0/en/editor/publish/app-clip/other-proj.png b/versions/4.0/en/editor/publish/app-clip/other-proj.png
new file mode 100644
index 0000000000..652e667ef6
Binary files /dev/null and b/versions/4.0/en/editor/publish/app-clip/other-proj.png differ
diff --git a/versions/4.0/en/editor/publish/app-clip/ui-build.png b/versions/4.0/en/editor/publish/app-clip/ui-build.png
new file mode 100644
index 0000000000..c7eefa7e6c
Binary files /dev/null and b/versions/4.0/en/editor/publish/app-clip/ui-build.png differ
diff --git a/versions/4.0/en/editor/publish/build-guide.md b/versions/4.0/en/editor/publish/build-guide.md
new file mode 100644
index 0000000000..9c473b165e
--- /dev/null
+++ b/versions/4.0/en/editor/publish/build-guide.md
@@ -0,0 +1,252 @@
+# Build Process and FAQ
+
+## Introduction to the Build Infrastructure
+
+The build process mainly includes the following two parts:
+
+- **General build processing**
+- **Build processing for each platform**
+
+Due to the adjustment of the build mechanism in v3.0, the build process of different platforms is injected into the **Build** panel in the form of **build plugins**, each participating in the build process. The build options specific to each platform are displayed in the **Build** panel in the form of expanded options. Developers can make custom build options appear in the **Build** panel via the [build plugin](custom-build-plugin.md).
+
+
+
+## General Build Processing Flow
+
+The general Build process of Cocos Creator mainly includes the following contents:
+
+1. Initialization of build options
+2. Build data organization
+3. Write the built resources to the file system
+4. Organize `settings.json`/`config.json` data
+5. UUID compression and file writing in `config.json`
+
+### Initialization of Build options
+
+This step is mainly for initializing the **primal options** passed to the build during the build to **build internal options**, completing the format conversion of some of the build options, initialize project configuration, initialize the asset data of the build asset database, and check the latest asset information and classify it.
+
+### Build data organization
+
+When building, the editor will first sort out the current scenes involved in the build and assets in all [Bundles](../../asset/bundle.md) folders and then search for their dependent assets through engine deserialization, and recursively find a list of all the assets that need to be packaged. After the asset list is summarized, the assets will be classified according to the `Bundle` configuration, and script compiling tasks, image compression tasks, and json grouping information will be collected.
+
+> **Notes**:
+>
+> 1. The engine will load all user scripts before deserialization. Whether the script is successfully loaded will directly affect the deserialization. If the script is not correctly written, it will cause the build to fail.
+> 2. If a dependency asset is found missing during the asset sorting process, an error will be reported but the build will normally continue. Although the build is allowed to continue successfully, it does not mean that the problem does not need to be solved. If the missing assets are not solved, it is difficult to guarantee that the built game package has no problems.
+
+### Writing the built assets to the file system
+
+The built assets will be packaged into `assets/[Bundle name]` under the corresponding platform release package directory according to the configuration of the [Asset Bundle](../../asset/bundle.md#configuration) after the build is completed. The directory structure is as follows:
+
+
+
+For more information about `Asset Bundle` configuration, building, file description, etc., please refer to the [Asset Bundle](../../asset/bundle.md) documentation.
+
+After organizing the basic build tasks, the build will loop through all the `Bundles`, executing the asset packaging tasks that each `Bundle` needs to handle in turn to generate these `Bundle` asset packages.
+
+Each `Bundle` goes through the following asset handling process:
+
+- **Script Building**: scripts within the editor are divided into [plug-in scripts](../../scripting/external-scripts.md) and **non-plugin scripts**, with different rules for handling different kinds.
+
+ - **Plug-in scripts**: directly copy the source files according to the original directory structure to the `src` directory under the release package directory generated after the build, the plug-in script does not support any script form that needs to be compiled, such as `TypeScript` or `JavaScript (ES6)`. The asset information of the plug-in script will be written into the jsList array in `settings`.
+
+ - **Non-plugin scripts**: packaged into `project.js` and placed in the corresponding `src` directory. Checking the `sourceMap` option will generate the corresponding `.map` file, and determine whether the script is compressed according to the `debug` option.
+
+- **Auto Atlas Processing**: queries the Auto Atlas asset list within the project, packaging the SpriteFrame small images under the atlas into a large image, generating serialized files, etc. according to the configuration of the Auto Atlas resource. This step will also modify the `json` grouping information, asset grouping information, and add texture compression tasks.
+
+- **Texture Compression**: according to the organized image compression task, the image assets are compressed and written into the build folder.
+
+- **Engine Script Compilation**: according to the configuration in **Main Menu** -> **Project Settings** -> **Feature Cropping**, remove the unused engine modules and pack them into the `cocos-js` directory. Checking the `sourceMap` option in the **Build** panel will generate the corresponding `.map` file, and determine whether the script is compressed according to the `debug` option.
+
+ The main steps of engine compilation include:
+
+ - Get **engine module information in project settings**.
+
+ - **Check** whether the compilation options of the engine in the **cache** are consistent with the current options to be compiled, and if they are, use the cache directly.
+
+ - If compilation is needed, execute the task of packaging the engine, then copy the compiled js file and save the engine's cache judgment information file.
+
+ When compiling the engine, [output log information](./build-panel.md#build-log) can be viewed:
+
+ 
+
+ Regarding the reuse rules of engine files, it is necessary to elaborate:
+ The packaged engine file will be placed in the editor's global temporary directory (use `Build.globalTempDir` to look up the cache address during the build process). The cache file is stored as the name according to the hash value generated by the parameters that will affect the engine compilation.
+
+ ```bash
+ global-temp-folder
+ |--CocosCreator
+ |--x.xx(3.0.0)
+ |--builder
+ |--engine
+ |--1dc4a547f9...63a43bb8965.watch-files.json
+ |--1dc4a547f9...63a43bb8965 (engine folder)
+ |--1dc4a547f9...63a43bb8965.meta (folder)
+ ...
+ ```
+
+ As long as any relevant engine build parameters are changed, the engine will be recompiled. Parameters that specifically affect the use of the build engine cache are:
+
+ - debug: whether to open the debug mode
+ - includeModules: engine module settings
+ - sourceMaps: whether to enable sourceMaps
+ - platform: build platform
+ - Engine modification time
+ - Whether to check the **Separate Engine** in the **Build** panel (only WeChat Mini Game)
+ - Use engine path, engine version number
+
+- **JSON build**: When serializing `JSON`, it will be merged and written into the file system (in the folder `assets/xxxBundle/import`) according to the `JSON` grouping and the `Bundle` to which it belongs. **If it is in release mode, it will also compress the UUID in the serialized JSON**.
+
+- **Common Asset Copy**: Some raw assets will be directly copied from the `library` to the built folder `assets/xxxBundle/native`.
+
+- **md5 processing**: Add the `.md5` suffix to all the assets, project scripts and engine files in the `assets` folder, and organize the data to be recorded in the `settings.json`.
+
+- **`application.js` template file generation**: dynamically generates the `application.js` file according to user options and generate it to the release package directory `src` generated after the build.
+
+### Organizing `settings.json`/`config.json` and configuring JSON data
+
+It is mainly to prepare the necessary configuration information for the game launch based on the asset data compiled previously.
+
+#### settings.json
+
+`settings.json` records the basic configuration information of the whole game package, which will directly affect the initialization of the game package.
+
+The description of the `settings.json` configuration is as follows:
+
+```js
+{
+ debug: boolean; // Whether it is in debug mode, depends on the settings in the Build panel.
+ designResolution: ISettingsDesignResolution; // Canvas resolution setting, depends on the settings of the Project Data page in the Project Settings panel.
+ jsList: string[];
+ launchScene: string; // URL of the initial scene.
+ moduleIds: string[]; // Information about all user script components.
+ platform: string;
+ renderPipeline: string; // renderPipeline information, depends on the settings of the Project Data page in the Project Settings panel.
+ physics?: IPhysicsConfig; // Physics module settings (only generated when the physics engine module is checked).
+ BundleVers: Record; // Bundle's md5 file value.
+ subpackages: string[]; // subpackage information.
+ remoteBundles: string[]; // Record the collection of remote Bundle.
+ server: string; // Record the remote server address (note: before v3.4 this option was stored in the 'application.js' file).
+ hasResourcesBundle: boolean; // Does it contain the built-in Bundle "resources".
+ hasStartSceneBundle: boolean; // Does it contain the built-in Bundle "start-scene".
+ customJointTextureLayouts?: ICustomJointTextureLayout[];
+ macros?: Record; // Engine macro configuration values in the Project Settings panel.
+}
+```
+
+#### config.json
+
+Each Bundle asset package has a `config.json`, which records basic information such as assets and scripts for the entire `Bundle`, which will directly affect the loading of the `Bundle` package.
+
+The description of the `config.json` configuration is as follows:
+
+```js
+{
+ importBase: string; // The name of the import directory in the Bundle, usually 'import'.
+ nativeBase: string; // The name of the native directory in native, usually 'native'.
+ name: string; // The name of the Bundle, the Bundle can be loaded by the Bundle name
+ deps: string[]; // Other Bundle names that this Bundle depends on.
+ scenes: Array<{url: string, uuid: string}>; // The array of scene information contained in the Bundle.
+ rawAssets: { [index: string]: { [uuid: string]: string[] } };
+ // Store the URL and type of the asset loaded under 'resources'
+ // Example: "bba00d3a-2f17-4511-b47c-0d584b21b763@6c48a": ["test/right/texture", "cc.Texture2D", "bba0...@6c48a"]
+ // "bba0...@6c48a": ["test/right/texture", 1, 1]
+ packs: Record; // json group information.
+ versions: {
+ import: Array;
+ native: Array;
+ }; // Only available after md5Cache is checked, the array part is stored in the format of [uuid_1, md5_1, uuid_2, md5_2, ...], where uuid_1 is a simple number indicating that the storage is the uuid index in the uuids array.
+ uuids: string[]; // uuid array, only in release mode.
+ types?: string[]; // Resource type array, only in release mode.
+ encrypted?: boolean; // Marks whether the script in the Bundle is encrypted, active on the native platform.
+ isZip?: boolean; // Is it in ZIP mode.
+ zipVersion?: string; // MD5 Hash value of ZIP package.
+}
+```
+
+The structure here only lists the structure of `settings.json` and `config.json` in a general sense. In fact, these parameters will vary after different platform builds.
+
+### Compressing config.json
+
+Before generating the `config.json` file, the `UUID` information in the file will be compressed according to whether it is in release mode or not, understanding this rule will be helpful to find the location of the file after the asset is built.
+
+The `UUIDs` used in the `Bundle` will be sorted during the build, and those that appear **twice or more** will be stored in the `uuids` array, and the location of the previously used `UUID` will be replaced with the index.
+
+All `types` that appear **twice and more** are also stored in the `types` array, and the previously used position is replaced with the index.
+
+#### Build assets
+
+This step generates project asset files other than scripts, since scripts are compiled and processed separately as special files. The assets are re-serialized after deserialization is performed during the packaging process to reduce the package size after packaging. Multiple serialized JSONs are combined into a single file based on the JSON grouping information collated from the previous data, e.g. the serialized files of the `texture` asset are all packaged into a single JSON file.
+
+## Building of each platform
+
+The Build process provides hook functions that build the lifecycle, which is convenient for developers to participate in the building during different processing periods of the building and affect the building result. At the same time, the build also provides a way for developers to directly add some custom build options. The corresponding new parameters can be displayed directly in the **Build** panel through simple configuration. For details, please refer to the [Extending Build Process](custom-build-plugin.md) documentation. The build options injected by the build plugin will be stored in `options.packages[pkgName]`, the current way of writing option parameters built through the command line also needs to follow this rule. The rules for the corresponding parameters can be referenced by clicking **Export Build Config** at the top right of the **Build** panel.
+
+### Compilation/generation process of each platform
+
+The build process of all platforms that require support for separate compilation and generation have been split. Some developers may wonder why the current mini game platform has a new **Make** button. In fact this part of the logic has always existed before, but it is merged in the **build** process and cannot be controlled separately.
+
+The **build** of the editor is similar to the function of an **export game package for the corresponding platform**, which is mainly to complete the interface of the engine to each platform and the compatibility of the basic format of the game package, which does not mean that all the work is completed. Each platform usually has its own compilation process, such as the compilation and upload function of the developer tools that come with the WeChat Mini Game platform, and the compilation, running and debugging functions of the relevant IDE for each native platform. If the developer needs to customize the packaging process for a specific platform, the editor needs to support the process of splitting in order to better access.
+
+## FAQ Guide
+
+The entire build process is in a single worker, to view the log information of the build process or view the complete call stack when an error occurs, click on the main menu, then select **Developer -> Open Build DevTools**. In fact, a lot of log information will be output when building, but in order not to interfere with users, by default only error and important information will be printed to the editor's **Console** panel, and the log information in the devtools is the most complete.
+
+> **Note**: before building **please make sure that the scene participating in the building can be previewed normally**. Loss of assets in some scenes or other script problems can be exposed during the preview stage. Building under the condition that the preview is normal can save time and troubleshoot better.
+
+### Asset loading 404 errors
+
+In case of a 404 error, please copy the UUID in the log that reported the error resource loss and search for the corresponding resource in **Assets** panel to check whether the resources that the resource depends on are normal. Resource loading 404 errors usually occur under the following situations:
+
+1. **Resources that are not placed in the Bundle are dynamically loaded in the script**.
+
+ - **Reason**: Through the above introduction, we know that only the resources and their dependent resources in the Bundle directory, as well as the resources and their dependent resources participating in the build scene will be packaged into the final build folder, and **only the resource URL directly put into the `Bundle` folder will be written to the `config.json`**. If a resource is used in the script but the resource is not placed in any Bundle directory, a 404 error will appear when it is loaded.
+
+ - **Solution**: Move the used resources to the Bundle folder.
+
+2. **There is a problem importing the loaded resource, and the data cannot be generated normally to the library**
+
+ - **Reason**: All the original data is obtained by reading the asset files in the `library` during the build. If the import fails, the correct corresponding asset information will not be obtained.
+
+ - **Solution**: Find the corresponding asset through **Assets** panel, right-click, and select **Reimport Asset** in the menu.
+
+3. **Asset Loss**
+
+ - **Reason**: As mentioned in the previous construction process, **asset construction will go through the reverse sequence to find dependent assets**, and the most frequent problem is that the dependent assets are accidentally during the project iteration process delete and cause asset loss. The loss of these assets may not usually be noticed, but once the build is performed, it will be exposed.
+
+ - **Solution**: Use the code editor to find out which assets the `UUID` is referenced, and modify the corresponding assets.
+
+### Script asset loading error
+
+As mentioned in the previous section of **Building Data Sorting**, the script environment needs to be configured when building. If the error message is related to the script, please refer to the error content to modify the script. If it is unknown which script is reporting the error, find the `UUID` of the corresponding script in the error message call stack, and then find the location in the **Assets** panel.
+
+### How to find the big picture after the small picture is automatically combined
+
+The Auto Atlas will print out the UUID information of the original small image and the synthesized large image during the build process, which can be found in the build devtools, and then use the UUID of the composite large image found to generate the `XXXBundle/native` after packaging. You can view it in the directory. If there are too many combined images, open the build `log` file and search for the UUID.
+
+
+
+### How to decompress UUIDs
+
+In **release** mode, the packaged asset JSON file and the `UUID` in `config.json` are compressed and need to be unzipped to find the corresponding assets in the original project. There are some built-in tools and methods in the build process. On the global variable Build, directly click **Developer -> Build DevTools** in the main menu, the original `UUID` can be queried in the console by entering the following command:
+
+```js
+Build.Utils.decompressUuid('425o80X19KipOK7J1f5hsN');
+// 42e68f34-5f5f-4a8a-938a-ec9d5fe61b0d
+```
+
+
+
+### Engine compilation failed
+
+If the engine fails to compile, please check if the installation package is complete, if the modified built-in engine code is correct, and if you are using a custom engine, if the path is correct, etc.
+
+### After switching to a custom engine and rebuilding, Android Studio still uses the default engine files
+
+In Android Studio, open the `Build` menu and click the `Refresh Linked C++ Projects` button to use the code files from the new engine directory.
+
+### Other errors
+
+If errors are encountered that cannot be resolved, please send feedback to the [Cocos Forum](https://discuss.cocos2d-x.org/c/creator/33) with the version of Creator, build options configuration, build log file from the build task, and a demo that reproduces the issue.
diff --git a/versions/4.0/en/editor/publish/build-guide/build-atlas.jpg b/versions/4.0/en/editor/publish/build-guide/build-atlas.jpg
new file mode 100644
index 0000000000..204ab96a23
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-guide/build-atlas.jpg differ
diff --git a/versions/4.0/en/editor/publish/build-guide/build-engine.jpg b/versions/4.0/en/editor/publish/build-guide/build-engine.jpg
new file mode 100644
index 0000000000..f60f377f3b
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-guide/build-engine.jpg differ
diff --git a/versions/4.0/en/editor/publish/build-guide/bundle.png b/versions/4.0/en/editor/publish/build-guide/bundle.png
new file mode 100644
index 0000000000..a0591ef16e
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-guide/bundle.png differ
diff --git a/versions/4.0/en/editor/publish/build-guide/web.png b/versions/4.0/en/editor/publish/build-guide/web.png
new file mode 100644
index 0000000000..3e8389c71f
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-guide/web.png differ
diff --git a/versions/4.0/en/editor/publish/build-open-data-context.md b/versions/4.0/en/editor/publish/build-open-data-context.md
new file mode 100644
index 0000000000..f036711d4c
--- /dev/null
+++ b/versions/4.0/en/editor/publish/build-open-data-context.md
@@ -0,0 +1,108 @@
+# Access to Open Data Context
+
+Currently, platforms such as **WeChat**, **Baidu**, and **Douyin Mini Game** have added the concept of **Open Data Context**, which is a separate game execution environment, in order to protect their social relationship chain data. The resources, engines, and applications in the **Open Data Context** are completely isolated from the main context, and only in the **Open Data Context** can developers access the relationship chain data through the open interface provided by the platform to implement some features such as leaderboards.
+
+In **Cocos Creator 3.0**, we deprecate the Canvas Renderer module and replaced it with a lightweight front-end Canvas engine based on **XML** + **CSS** designed by WeChat team. The engine is integrated into the **Cocos Creator 3.0**'s built-in **Open Data Context** project template, which allows developers to implement a leaderboard-like feature based on the template with a few basic front-end skills.
+
+## SubContextView Component Description
+
+Since the **Open Data Context** can only be rendered on the off-screen canvas called **sharedCanvas**, you need a node in your project to act as a container for rendering the **Open Data Context**, and add the `SubContextView` component to that node, which will render the **sharedCanvas** to the container node.
+
+The `SubContextView` component contains two main properties, **Design Resolution Size** and **FPS**.
+
+
+
+### Design Resolution Size
+
+If you set the **Design Resolution Size** of the `SubContextView` component to **640 * 960**, the size of the **sharedCanvas** will be set to **640 * 960** during the component's `onLoad` phase. This means that after the build, the **Open Data Context Project** is rendered on an off-screen canvas of **640 * 960**. Then, when customizing the **Open Data Context** (see below), the maximum size of the tag style in `style.js` is **640 * 960**, otherwise the rendered content will be off the canvas. Example:
+
+```js
+// style.js
+export default {
+ container: {
+ width: 640, // max width
+ height: 960, // max height
+ },
+}
+```
+
+To avoid this part of the data coupling, setting a percentage adaptation to the size is supported. Example:
+
+```js
+// style.js
+export default {
+ container: {
+ width: '100%',
+ height: '100%',
+ },
+}
+```
+
+In the actual rendering process, the engine will adopt the **SHOW ALL** adaptation policy to render the **sharedCanvas** to the `SubContextView` component node to avoid the UI distortion caused by stretching during rendering. For example, in the following two images, we are using `SubContextView` component nodes of different sizes, and the **Open Data Context** texture will not be stretched.
+
+
+
+
+
+### Setting FPS
+
+The **FPS** property is primarily used to set how often the main context will update the **sharedCanvas** on the `SubContextView` component to avoid performance loss due to frequent updates to the **Open Data Context** texture.
+
+## Release Process
+
+1. Open the project and double-click the scene, then add the `SubContextView` component to the node on which you need to render the **Open Data Context**.
+
+2. After the scene is set, save the scene, and then open the **Build** panel in **Menu -> Project**, select the **WeChat** / **Baidu** / **Douyin Mini Game** platform you want to release, check **Generate Open Data Context Template**, and then click **Build**.
+
+ 
+
+3. After the build is complete, click the **Folder Icon** button at the end of **Buid Path**, you'll see an **openDataContext** folder (e.g.: `build/wechatgame/openDataContext`), which is an **Open Data Context** project template built into Cocos Creator, in the distribution folder of the corresponding game platform.
+
+ 
+
+ Developers can customize the required **Open Data Context** content based on this template, and the customization methods are described below. When built again, if the **openDataContext** folder exists in the `build` directory, it will be skipped directly and the developer does not have to worry about the customized **Open Data Context Project** being overwritten.
+
+4. Open the build distribution (e.g.: `build/wechatgame`) using the DevTools of the corresponding mini game platformer to open the mini-game project to view the **Open Data Context** content.
+
+ 
+
+ > **Note**: in the **Open Data Context** of **Baidu** platform, since the image can only load player avatars returned from Baidu, the local avatar image may not be loaded in the generated template project.
+
+## Customization on Open Data Context Project
+
+Before customizing an **Open Data Context** project, developers need to know some basic information:
+- [minigame-canvas-engine quick start[cn]](https://wechat-miniprogram.github.io/minigame-canvas-engine/overview/guide.html)
+- [doT template engine use](http://olado.github.io/doT/?spm=a2c6h.12873639.0.0.36f45227oKu0XO)
+
+With this basic information in mind, let's take a look at the **Open Data Context** template generated by default after the build, with the following directory structure:
+
+
+
+- **render/dataDemo.js**: Simulates some random data of the leaderboards, where the developer can request the relational chain data from the platform and pass it to the **doT template engine** to generate relevant XML text
+- **render/style.js**: To record CSS style text information, refer to [Style documentation [cn]](https://wechat-miniprogram.github.io/minigame-canvas-engine/api/style.html#%E5%B8%83%E5%B1%80)
+- **render/template.js**: To record XML text information, the project uses the template engine to generate XML text by default. Refer to [Tag documentation [cn]](https://wechat-miniprogram.github.io/minigame-canvas-engine/api/tags.html#%E6%A0%87%E7%AD%BE%E5%88%97%E8%A1%A8).
+- **render/avatar.png**: Header images for display in **Open Data Context** project template, can be deleted.
+- **engine.js**: source code of Canvas engine
+- **index.js**: **Open Data Context Project** entry file where the **Open Data Context** is rendered by passing XML text and CSS styles to the Canvas engine
+
+## Recommended practices
+
+1. Since the build directory generated after the build of the project is excluded from version control by default by git, if you want to include your custom **Open Data Context** in version control, you can put the `openDataContext` folder (e.g.: `build/wechatgame/openDataContext`) into your project's `build-templates` directory. Please refer to [Custom Project Build Process](./custom-project-build-template.md) documentation.
+
+2. In an **Open Data Context Project**, if you need to listen to messages from the main context, you need to first determine whether the message comes from the main context engine, using the WeChat interface as an example:
+
+ ```js
+ wx.onMessage(res => {
+ if (!(res && res.type === 'engine')) {
+ console.log('do something...');
+ }
+ });
+ ```
+
+ When the main context sends a message to the open data context, it is recommended to include a `type` message to avoid handling the wrong message source. For example, the `res.type === 'engine'` in the above code means that the message comes from the main context engine.
+
+## Reference documentation
+
+- [WeChat official document -- Canvas engine for mini games [cn]](https://wechat-miniprogram.github.io/minigame-canvas-engine/)
+- [minigame-canvas-engine source code](https://github.com/wechat-miniprogram/minigame-canvas-engine)
+- [doT template engine](http://olado.github.io/doT/?spm=a2c6h.12873639.0.0.36f45227oKu0XO)
diff --git a/versions/4.0/en/editor/publish/build-open-data-context/adaption-1.png b/versions/4.0/en/editor/publish/build-open-data-context/adaption-1.png
new file mode 100644
index 0000000000..1bb192df80
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-open-data-context/adaption-1.png differ
diff --git a/versions/4.0/en/editor/publish/build-open-data-context/adaption-2.png b/versions/4.0/en/editor/publish/build-open-data-context/adaption-2.png
new file mode 100644
index 0000000000..4883df8447
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-open-data-context/adaption-2.png differ
diff --git a/versions/4.0/en/editor/publish/build-open-data-context/build-output.png b/versions/4.0/en/editor/publish/build-open-data-context/build-output.png
new file mode 100644
index 0000000000..a227816372
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-open-data-context/build-output.png differ
diff --git a/versions/4.0/en/editor/publish/build-open-data-context/folder-structure.png b/versions/4.0/en/editor/publish/build-open-data-context/folder-structure.png
new file mode 100644
index 0000000000..5fb48ca3a2
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-open-data-context/folder-structure.png differ
diff --git a/versions/4.0/en/editor/publish/build-open-data-context/generate-template.png b/versions/4.0/en/editor/publish/build-open-data-context/generate-template.png
new file mode 100644
index 0000000000..8899376e1d
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-open-data-context/generate-template.png differ
diff --git a/versions/4.0/en/editor/publish/build-open-data-context/show-in-devtool.png b/versions/4.0/en/editor/publish/build-open-data-context/show-in-devtool.png
new file mode 100644
index 0000000000..930ff2a608
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-open-data-context/show-in-devtool.png differ
diff --git a/versions/4.0/en/editor/publish/build-open-data-context/sub-context-view.png b/versions/4.0/en/editor/publish/build-open-data-context/sub-context-view.png
new file mode 100644
index 0000000000..e08694bff2
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-open-data-context/sub-context-view.png differ
diff --git a/versions/4.0/en/editor/publish/build-options.md b/versions/4.0/en/editor/publish/build-options.md
new file mode 100644
index 0000000000..fdf36d189d
--- /dev/null
+++ b/versions/4.0/en/editor/publish/build-options.md
@@ -0,0 +1,181 @@
+# General Build Options
+
+## General Build Options
+
+For the general build options in the **Build** panel are as follows:
+
+
+
+### Build Path
+
+There are two input boxes in the Build Path:
+
+
+
+- The first input box is used to specify the build path of the project. The path can be entered directly in the input box or selected via the magnifying glass button next to it. Starting from v3.1, support to switch the following two paths to use:
+
+ 
+
+ - **file**: The specified build path is an **absolute path**, which is the way used in previous versions.
+ - **project**: The specified build path is a **relative path**, and the selected path can only be in the project directory. When using this path, some path-related configurations (e.g. Icon) in the build options are recorded as relative paths, making it easier for team members to share configurations across devices.
+
+ The default build path is the `build` folder in the project directory. If a version control system such as Git or SVN is used, the `build` folder can be ignored in version control.
+
+ > **Note**: Spaces, illegal characters and Chinese are not allowed in the Build Path.
+
+- The second input box is used to specify the name of the build task when the project is built and the name of the release package generated after the build. The default is the name of the current build platform, and for each additional build of the same platform, the **-001** suffix will be added to the original one, and so on. After the build is completed, click the folder icon behind the input box to open the project release package directory.
+
+### Start Scene
+
+It is necessary to set the first scene to enter after opening the game. One way is to search for the desired scene in the list of **Included Scenes**, move the mouse to the desired scene bar, and then click the button that appears on the right to set it as the start scene.
+
+
+
+### Scenes that Participate in Build (Included Scenes)
+
+During the build process, all the assets and scripts in the bundle will be packaged except for the `resources` folder in the project directory and the assets and scripts in the bundle. Other assets are packaged on demand according to the scenes involved in the build and the asset referenced in the `bundle`. Therefore, removing the check box for scenes that do not need to be released can reduce the size of the project release package generated after the build.
+
+### Bundles
+
+As of v3.8, developers can decide whether a Bundle should participate in a build based on the needs of the project.
+
+
+
+- Select all: all Bundles will participate in the build.
+- Uncheck it to select the Bundle you want to participate in the build from the dropdown box.
+
+ 
+
+ > Main and engine built-in internal bundles cannot be canceled.
+
+### Embed Shared Script in Bundle
+
+
+
+Whether to embed shared scripts in bundle when build.
+
+> This option is read only, and only switched with the build button changes from **Normal Build** or **Build Bundle** in the **Build** panel.
+
+- Unchecked:
+ When building a Bundle, if there are shared scripts inside the Bundle, they will not be built inside the Bundle, but the script inside the Bundle will be built separately inside bundle.js in src/chunk. Therefore, the bundles built in this way are integrated with the project, which means that such bundles are smaller in size, but cannot exist separately from the project.
+- When checked:
+ The scripts inside the bundle are not built into the public JS library but inside the bundle. Such Bundle can be run independently from the project (because the required scripts are inside the Bundle, and Bundles referencing the same code may have duplicated parts), and can be loaded and run correctly even in other projects, but the drawback is that because the script resources are inside the Bundle, the final size of the Bundle will be larger.
+
+### MD5 Cache
+
+Adding MD5 information to all the asset file names after building can solve the problem of CDN or browser asset caching.
+
+After enabling, if the asset cannot be loaded, it means that the renamed new file cannot be found. This is usually caused by some third-party assets not being loaded through the `assetManager`. In this case, you can use the following method to convert the URL before loading, and the converted path can be loaded correctly.
+
+```typescript
+const uuid = assetManager.utils.getUuidFromURL(url);
+url = assetManager.utils.getUrlWithUuid(uuid);
+```
+
+> **Note**: after MD5 Cache is enabled on the native platform, if assets cannot be loaded, it is usually caused by some third-party assets used in C++ not being loaded through the `assetManager`. It can also be solved by converting the URL with the following code:
+>
+> ```cpp
+> auto cx = ScriptingCore::getInstance()->getGlobalContext();
+> JS::RootedValue returnParam(cx);
+> ScriptingCore::getInstance()->evalString("cc.assetManager.utils.getUrlWithUuid(cc.assetManager.utils.getUuidFromURL('url'))", &returnParam);
+>
+> string url;
+> jsval_to_string(cx, returnParam, &url);
+> ```
+
+### Main Bundle Compression Type
+
+Set the compression type of the main bundle. For details, please refer to the [Asset Bundle — compression type](../../asset/bundle.md#compression-type) documentation.
+
+### Main Bundle is Remote
+
+This option is optional and needs to be used in conjunction with the **Resources Server Address** option.
+
+After checking, the main package will be configured as a remote package, and its related dependent assets will be built to the [built-in Asset Bundle — main](../../asset/bundle.md#the-built-in-asset-bundle) under the `remote` directory of the release package. The developer needs to upload the entire `remote` folder to the remote server.
+
+### Debug Mode
+
+If this option is unchecked, the build is running in release mode, compressing and obfuscating asset UUID, built engine scripts and project scripts, and subcontracting the JSON of similar assets to reduce the number of asset loadings.
+
+If this option is checked, the build is running in debug mode. At the same time, the **Source Maps** option can be checked, which is more convenient for locating problems.
+
+### Mangle Engine Internal Properties
+This feature is supported since v3.8.6. When enabled, it mangles internal properties in the engine's TypeScript code, effectively reducing code size. After the project is built, an `engine-mangle-config.json` configuration file will be generated in the root directory, where users can customize and add properties to be mangled. This feature currently does not support native platforms. If the project has enabled the engine separation plugin feature, this configuration will be ignored during build. For detailed usage instructions, please refer to [Mangle Engine Internal Properties](../../advanced-topics/mangle-properties.md)
+
+### Inline Enums
+
+This feature is supported since v3.8.6. When enabled, it replaces enum values in the engine's TypeScript code with specific numerical values and disables enum reverse-mapping functionality, effectively reducing code size. If you need to generate reverse-mapping for certain enums, you can use the 'cc.Enum(your_enum)' function to decorate the corresponding enum to dynamically generate reverse-mapping. If the project has enabled the engine separation plugin feature, this configuration will be ignored during build.
+
+### Source Maps
+
+Check this option to generate sourcemap. The engine files and project scripts will be compressed by default during the build.
+
+As JavaScript is becoming more and more complex, most of the source code (development code) has to be compiled and converted before it can be put into the production environment, which makes the actual running code different from the source code. This makes it impossible to locate the source code during debugging. The Source Map can map the converted code to the source code, that is, the converted code corresponds to the location of the source code before the conversion. In this way, when a problem occurs, it is possible to directly view and debug the source code, making it easier to locate the problem. For details, please refer to the [Use source maps](https://developer.chrome.com/docs/devtools/javascript/source-maps/) documentation.
+
+### Replace Splash Screen
+
+When the mouse is moved to this option, the **Edit Icon** button will appear. Click this button to open the splash screen setting panel, and the data will be saved in real time after editing.
+
+
+
+- **TotalTime**: the total time (milliseconds) to display the inset screen, minimum 500 milliseconds
+- **Image Size Multiplier**: the zoom ratio of the image, the minimum is 100%
+- **Preview**: If you want to change the splash screen image, hover your mouse over the preview window and click the '+' button, then select a new image path.
+
+If you want to disable the splash screen, please refer to [Introduction to Build Options](./publish/build-options.md) for details.
+
+> **Note**:
+> 1. After selecting different build platforms in the build options, adjusting the screen insertion rules again can achieve the diversity of screen insertion on different platforms
+> 2. the screen insertion will only take effect after the package, not during the preview.
+> 3. Some countries and regions are not open for full screen insertion, we apologize for any inconvenience caused to you.
+
+### Erase module structure (experimental)
+
+If this option is checked, the script import speed is faster, but module features such as `import.meta`, `import()`, etc. cannot be used.
+
+### Skip Compress Texture
+
+The default is 'false'. If this option is checked, the build skips the entire texture compression process to reduce build time. The command parameter is `skipCompressTexture`.
+
+### Engine Config
+
+As of 3.8.3, it is possible to configure some of the engine module configurations in the build panel, making it easier to select different physical backends for different platform or build tasks, etc.
+
+
+
+The following configuration changes are currently supported:
+
+| Configuration | Optional | Description | Default |
+| --- | --- | --- | --- |
+| CLEANUP_IMAGE_CACHE | `Inherit Project Setting`, `On`, `Off` | Whether to clear the original image cache after uploaded a texture to GPU | `Inherit Project Setting` |
+| 2D Physics | `Inherit Project Setting`, `Box 2D`, `Built-In` | - | Inherit Project Setting |
+| 3D Physics | `Inherit Project Setting`, `Bullet`, `cannon`, `PhysX`, `built-in` | - |Inherit Project Setting|
+| WebGL 2.0 | `Inherit Project Setting`, `On`, `Off` | - | Inherit Project Setting|
+| Bundle Mode Of Native Code | `Wasm + AsmJS`, `Wasm`, `AsmJS` | It mainly affects the native module packing format of Physics, Spine, etc., in which Wasm mode can improve the performance of games to a certain extent. Since the support degree of different game platforms is not consistent, please judge the choice according to the actual official support data. | Wasm + AsmJS|
+| Enable Wasm Brotli compression | `On`, `Off` | Enabling this will reduce the size of the wasm package, which will take slightly longer to load due to the need to decompress it at runtime | Off |
+
+The above options will be shown or hidden according to the selection of the actual module in the project settings, e.g. `If the 2D Physical Module is not checked in the project settings, the corresponding option will not appear`.
+
+### Cocos Service Config Set
+
+This option is used to display all the services integrated in the [Service](https://service.cocos.com/document/en/) panel for the current project.
+
+## Related Build Options for Each Platform
+
+Due to the adjustment of the current build mechanism, the processing of different platforms is injected into the **Build** panel in the form of a plugin. After selecting the platform to build in the **Platform** option of the **Build** panel, notice the expanded options of the corresponding platform. The name of the expanded option is the platform plug-in name, in the editor main menu **Extensions -> Extension Manager -> Internal** to see various platform plug-ins.
+
+For the relevant build options of each platform, please refer to:
+
+- [Publish to Web Platform](publish-web.md)
+- [Publish to Mini Game Platform](publish-mini-game.md)
+- [Publish to Facebook Instant Games](publish-fb-instant-games.md)
+- [Publish to Native Platform](native-options.md#%E6%9E%84%E5%BB%BA%E9%80%89%E9%A1%B9)
+- [Publish to Google Play](google-play/build-example-google-play.md)
+- [Publish to Google Play On Games](google-play-games/index.md)
+- [Publish to HarmonyOS Platform](publish-huawei-ohos.md)
+
+Cocos Creator supports custom extension build plugins, handled in the same way as platform plugins. For details, please refer to the [Extension Build Process](custom-build-plugin.md) documentation.
+
+## Configuration of Other Options Involved in the Build
+
+The configuration of **Project -> Project Settings** in the menu bar of the editor will affect the result of the project build. For details, please refer to the [Project Settings](../project/index.md) documentation.
diff --git a/versions/4.0/en/editor/publish/build-options/build-path.png b/versions/4.0/en/editor/publish/build-options/build-path.png
new file mode 100644
index 0000000000..c7af2406b8
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-options/build-path.png differ
diff --git a/versions/4.0/en/editor/publish/build-options/bundle-option.png b/versions/4.0/en/editor/publish/build-options/bundle-option.png
new file mode 100644
index 0000000000..1cc28e07c3
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-options/bundle-option.png differ
diff --git a/versions/4.0/en/editor/publish/build-options/bundle-select.png b/versions/4.0/en/editor/publish/build-options/bundle-select.png
new file mode 100644
index 0000000000..5ce18986fa
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-options/bundle-select.png differ
diff --git a/versions/4.0/en/editor/publish/build-options/embed-script-in-bundle.png b/versions/4.0/en/editor/publish/build-options/embed-script-in-bundle.png
new file mode 100644
index 0000000000..d2885d3322
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-options/embed-script-in-bundle.png differ
diff --git a/versions/4.0/en/editor/publish/build-options/engine-config.png b/versions/4.0/en/editor/publish/build-options/engine-config.png
new file mode 100644
index 0000000000..1199c7cd77
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-options/engine-config.png differ
diff --git a/versions/4.0/en/editor/publish/build-options/options.png b/versions/4.0/en/editor/publish/build-options/options.png
new file mode 100644
index 0000000000..9feedda14b
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-options/options.png differ
diff --git a/versions/4.0/en/editor/publish/build-options/path.png b/versions/4.0/en/editor/publish/build-options/path.png
new file mode 100644
index 0000000000..28dc222608
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-options/path.png differ
diff --git a/versions/4.0/en/editor/publish/build-options/set-start-scene.png b/versions/4.0/en/editor/publish/build-options/set-start-scene.png
new file mode 100644
index 0000000000..3749b39e45
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-options/set-start-scene.png differ
diff --git a/versions/4.0/en/editor/publish/build-options/splash-setting.png b/versions/4.0/en/editor/publish/build-options/splash-setting.png
new file mode 100644
index 0000000000..be24ce2a99
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-options/splash-setting.png differ
diff --git a/versions/4.0/en/editor/publish/build-options/start_scene.png b/versions/4.0/en/editor/publish/build-options/start_scene.png
new file mode 100644
index 0000000000..0d3583c299
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-options/start_scene.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel.md b/versions/4.0/en/editor/publish/build-panel.md
new file mode 100644
index 0000000000..cdfb53af21
--- /dev/null
+++ b/versions/4.0/en/editor/publish/build-panel.md
@@ -0,0 +1,129 @@
+# About the Build Panel
+
+Click **Project -> Build** in the main menu of the editor or use the shortcut key `Ctrl/Cmd + Shift + B` to open the **Build** panel:
+
+
+
+If a platform has already been built, open the **Build** panel to enter the **Build Task** page. The build of each platform for v3.0 is carried out in the form of a build task, similar to a download task:
+
+
+
+## Build Panel
+
+In the **Build** panel, select the platform to be built, and then configure the [build options](build-options.md). After the configuration is complete, click the **Build** button in the lower right corner to jump to the **Build Task** page to execute the build process. Another way is to click the **Close (X)** button in the upper right corner to enter the **Build Task** page.
+
+There are three function buttons at the top of the panel:
+
+
+
+- : click this button to jump to the official manual documentation of the current platform.
+
+- **Import**: click this button to import the JSON file that saves the configuration of the build options.
+
+- **Export**: click this button to export the current platform's build option configuration as a JSON file for the [command line build](publish-in-command-line.md), or share it among project members. The exported configuration is differentiated according to the platform. When using the command line to build, specify the file path of the build parameter `configPath` as the exported JSON configuration file path.
+
+> **Notes**:
+>
+> 1. It is meaningless to build a project without a scene, if there is no scene in the currently opened project, a prompt will appear to create a scene first when opening the **Build** panel:
+>
+> 
+>
+> 2. Before building, please make sure that the current scene has been saved, otherwise when click the **Build** button, and a pop-up prompt will be displayed. Choose **Save**, **Ignore** or **Cancel**. Select **Save** and **Ignore** to continue the build process.
+>
+> 
+
+## Build Tasks
+
+On the **Build Tasks** page, developers can view the current platform's build progress and build results.
+
+- **Building**: the progress bar is displayed as **blue**.
+- **Build success**: the progress bar reaches 100%, and the actual build time is output and displayed as **green**.
+- **Build failed**: the progress bar reaches 100%, prompting the reason for the failure of the build or an error message, and it is displayed as **red**.
+
+
+
+There are three buttons at the top of the page, including **New Build Task**, **Open Build DevTools** and **Clear Build Cache**:
+
+- **New Build Task**: click this button to return to the **Build** panel, select a new platform to build.
+
+- : click this button to open the Build DevTools, and view all the log information generated during the build process, including the call stack.
+
+- : clear the build cache. In order to reuse the reusable build results, and in order to speed up the build and reduce memory usage when rebuilding, many processes in the build process have added cache management mechanisms, such as compressed textures, automatic atlas generation, engine compilation, and resources being serialized JSON, etc. Under normal circumstances, this part of the cached data does not need to be manually cleaned, but if it is needed to avoid cache interference under special circumstances, click this button to clear the cached data.
+
+ The project-related resource cache will be stored in the project directory, and the engine compilation-related cache will be stored in the global directory. Developers can choose to clear the project cache, the global cache, or all of them according to their needs.
+
+ 
+
+### Platform Build Tasks
+
+The build of each platform is carried out in the form of a **build task**, similar to a download task. The name of the platform build task depends on the **Build Path** option in the **Build** panel. For details, please refer to the [Build Options](build-options.md) documentation.
+
+
+
+Each building task has corresponding function buttons for easy use.
+
+**The remove (X) button at the top right of the build task** is used to remove the current build task. Choose **Remove records only** or **Remove source files**. **Remove source files** means to delete the project release package generated in the `build` directory after the corresponding platform is built.
+
+
+
+**The buttons at the bottom left of the build task include**:
+
+- : click this button to open the project release package generated after the corresponding platform is built (the default is in the `build` directory).
+
+- : click this button to return to the **Build** panel, modify the build options configured during the last build of the corresponding platform, and then click the **Build** button at the bottom right to rebuild. For details, please refer to the content in the **Modify Build Options** section below.
+
+- : click this button to return to the **Build** panel to view the build options configured during the last build of the corresponding platform.
+
+- : click this button to open the log file generated by the corresponding platform during the build process. For more information, please refer to the content in the **Building Log Information View** section below.
+
+**The button at the bottom right of the build task** is mainly used for each platform to execute the release process such as generation, operation, and upload according to the platform requirements after the completion of the build. The **Build** button is used to rebuild.
+
+After each platform is built, the build options configuration information related to the build will be saved in the `profiles/v2/packages/builder.json` file in the project directory, as long as the build of the corresponding platform is not deleted on the **Build Tasks** page or delete the project release package in the `build` directory. To view the build option configuration of the last build after reopening the editor, and continue to run the preview, etc.
+
+For the specific release process of each platform, please refer to:
+
+- [Publish to Native platform](native-options.md)
+- [Publish to Mini Game platform](publish-mini-game.md)
+
+### Modifying Build Options
+
+Click the edit button at the bottom left of the build task to return to the **Build** panel to modify the build options configured during the last build for rebuilding. Since it is only possible to modify the build option configuration during the last build of the current platform, the **Platform** option on the page is grayed out and cannot be modified.
+
+
+
+Click the  button to the right of the edit button to view the configuration of the build options during the last build of the current platform.
+
+After the modification is completed, clicking the **Build** button will clear the project release package generated after the last build and rebuild. Or click the **X** button at the top right of the **Build** panel to return to the **Build Tasks** page, and then click the **Build** button at the bottom right of the platform build task to rebuild.
+
+> **Note**: in order to avoid accidentally deleting customized content, the native platform only updates project resources when rebuilding, and does not overwrite the original native project content. Therefore, when returning to the **Build** panel to modify the previously configured build options, the native platform-related build options are in the **disabled** state. To regenerate the project, please create a new build task.
+
+If the **Build** button is not clicked to rebuild after modifying the configuration, the modified configuration will also be saved. If the configuration in the current **Build** panel is inconsistent with the configuration in the project release package in the `build` directory generated after the last build, a yellow * key will be displayed at the top of the **Build** panel.
+
+
+
+### Build Log Information View
+
+Since the build process will generate a lot of log information, only error messages will be printed to the editor's **console** panel by default.
+
+To view all the log information, there are the following operations:
+
+- **Open the Build DevTools**
+
+ To view, click **Developer -> Open Build DevTools** in the main menu or click the  button at the top right of the **Build Task** page. All log information printed during the build process includes the call stack.
+
+- **Open the build logging file**
+
+ The error message generated during each build process will be recorded and stored in the `temp/builder/log` folder under the project directory. Click the  button at the bottom right of the build task to view it. When feedback on build related issues, directly paste the file to locate the problem.
+
+### Build Queue and Interrupt Build
+
+
+
+You can still add a new build task during the build process, and the new build task will be added to the build queue.
+During the build process, you can click the X button on the right side of the build task to interrupt the current build task.
+
+### Build Bundle Only
+
+
+
+Cocos Creator supports **Build Bundles Only** since v3.8. All selected Bundles can be built at once when building the project. Unlike building individual Bundles, the **Build Bundles Only** option will build all Bundles and store public assets in high-priority Bundles.
diff --git a/versions/4.0/en/editor/publish/build-panel/build-dropdown.png b/versions/4.0/en/editor/publish/build-panel/build-dropdown.png
new file mode 100644
index 0000000000..d281ef19b0
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/build-dropdown.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/build-options.png b/versions/4.0/en/editor/publish/build-panel/build-options.png
new file mode 100644
index 0000000000..2b6d7d4032
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/build-options.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/build-page.png b/versions/4.0/en/editor/publish/build-panel/build-page.png
new file mode 100644
index 0000000000..27601c7e69
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/build-page.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/build-panel.png b/versions/4.0/en/editor/publish/build-panel/build-panel.png
new file mode 100644
index 0000000000..bdcdef7e19
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/build-panel.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/build-task.png b/versions/4.0/en/editor/publish/build-panel/build-task.png
new file mode 100644
index 0000000000..b4f9c55041
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/build-task.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/clean-window.png b/versions/4.0/en/editor/publish/build-panel/clean-window.png
new file mode 100644
index 0000000000..c5c1f14847
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/clean-window.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/clean.png b/versions/4.0/en/editor/publish/build-panel/clean.png
new file mode 100644
index 0000000000..dbb3eb80e5
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/clean.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/clear-build-data.png b/versions/4.0/en/editor/publish/build-panel/clear-build-data.png
new file mode 100644
index 0000000000..18787d3ee9
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/clear-build-data.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/create-scene-first.png b/versions/4.0/en/editor/publish/build-panel/create-scene-first.png
new file mode 100644
index 0000000000..00fb132de7
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/create-scene-first.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/debug.png b/versions/4.0/en/editor/publish/build-panel/debug.png
new file mode 100644
index 0000000000..a79e2c802e
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/debug.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/doc.png b/versions/4.0/en/editor/publish/build-panel/doc.png
new file mode 100644
index 0000000000..93174e837e
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/doc.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/edit-build-option.png b/versions/4.0/en/editor/publish/build-panel/edit-build-option.png
new file mode 100644
index 0000000000..fd2a7a2eb9
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/edit-build-option.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/editing.png b/versions/4.0/en/editor/publish/build-panel/editing.png
new file mode 100644
index 0000000000..d1f1672fd5
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/editing.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/folder.png b/versions/4.0/en/editor/publish/build-panel/folder.png
new file mode 100644
index 0000000000..ebd78f5c37
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/folder.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/interrupt.gif b/versions/4.0/en/editor/publish/build-panel/interrupt.gif
new file mode 100644
index 0000000000..53fd0ba02c
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/interrupt.gif differ
diff --git a/versions/4.0/en/editor/publish/build-panel/log-file.png b/versions/4.0/en/editor/publish/build-panel/log-file.png
new file mode 100644
index 0000000000..114b419cfa
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/log-file.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/log.jpg b/versions/4.0/en/editor/publish/build-panel/log.jpg
new file mode 100644
index 0000000000..4a08f8346c
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/log.jpg differ
diff --git a/versions/4.0/en/editor/publish/build-panel/options.png b/versions/4.0/en/editor/publish/build-panel/options.png
new file mode 100644
index 0000000000..4142fb45ba
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/options.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/panel.png b/versions/4.0/en/editor/publish/build-panel/panel.png
new file mode 100644
index 0000000000..d30372f059
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/panel.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/remove-build-task.png b/versions/4.0/en/editor/publish/build-panel/remove-build-task.png
new file mode 100644
index 0000000000..2df63897c9
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/remove-build-task.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/save-scene.png b/versions/4.0/en/editor/publish/build-panel/save-scene.png
new file mode 100644
index 0000000000..b9b16afaeb
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/save-scene.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/setting.png b/versions/4.0/en/editor/publish/build-panel/setting.png
new file mode 100644
index 0000000000..3f1796e726
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/setting.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/settings.png b/versions/4.0/en/editor/publish/build-panel/settings.png
new file mode 100644
index 0000000000..9b358ab52a
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/settings.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/subpackage/subpackage-config.png b/versions/4.0/en/editor/publish/build-panel/subpackage/subpackage-config.png
new file mode 100644
index 0000000000..4e4f2ee0cd
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/subpackage/subpackage-config.png differ
diff --git a/versions/4.0/en/editor/publish/build-panel/view_build_parameter.png b/versions/4.0/en/editor/publish/build-panel/view_build_parameter.png
new file mode 100644
index 0000000000..db83c1cf16
Binary files /dev/null and b/versions/4.0/en/editor/publish/build-panel/view_build_parameter.png differ
diff --git a/versions/4.0/en/editor/publish/custom-build-plugin.md b/versions/4.0/en/editor/publish/custom-build-plugin.md
new file mode 100644
index 0000000000..d42c5305c8
--- /dev/null
+++ b/versions/4.0/en/editor/publish/custom-build-plugin.md
@@ -0,0 +1,497 @@
+# Extending Build Process
+
+To build a platform plug-in a common editor plug-in format is required. For the basic structure of the plug-in, please refer to the [First Extension](../extension/first.md) documentation . To extend the build function, it is necessary to understand the overall process of the build. Please read the [Introduction to the build process and FAQ guide](./build-guide.md) documentation.
+
+## Quick start
+
+1. Click **Project -> New Build Extension** in the menu bar of the editor, and select **Global**/**Project** to create a build extension package.
+
+ - If selecting **Global**, the build extension will be applied to all Cocos Creator projects. The path of **Global** is:
+
+ - **Windows**: `%USERPROFILE%\.CocosCreator\extensions`
+
+ - **macOS**: `$HOME/.CocosCreator/extensions`
+
+ - If selecting **Project**, this will apply the build extension to the specified Cocos Creator project. The path of **Project** is:
+
+ - `$Your project address/extensions`
+
+2. After the build extension is created, notice the generation path of the plugin in the **Console**. Click on the path to open the build extension package in the file manager of the operating system.
+
+ 
+
+3. Before enabling the build extension, execute `npm install` in the directory to install some dependent **@types** modules to compile normally. The interface definition that comes with the editor has been generated under the **@types** folder in the root directory. **Developer -> Export.d.ts** from the menu bar of the editor shows the latest interface definitions.
+
+4. Click **Extension -> Extension Manager** in the menu bar of the editor to open the **Extension Manager** panel. Then select the **Project**/**Global** tab in the **Extension Manager**, and click the **Refresh Icon** button to see the build extension just added. Then click the **Enable** button on the right to run the plug-in normally.
+
+ 
+
+5. After the build extension is enabled, open the **Build** panel, notice the expansion bar of the build extension plugin. Click **Build** to join the build process.
+
+ 
+
+6. To modify the content of the built extension, directly modify the build extension package under the `extensions` directory, review the `readme.md` file in the build extension package directory for details. Find the corresponding build extension in the **Extension Manager**, and click the **Reload** icon button. The extension in the editor will re-run with the latest code and files.
+
+ 
+
+## Basic configuration process
+
+To extend the build function of the plug-in, add the `builder` field to the `contributions` in `package.json`, and the relative path configuration of the corresponding module can be passed to the specified platform in the field.
+
+Example `package.json`:
+
+```json
+// package.json
+
+{
+ "contributions": {
+ "builder": "./dist/builder"
+ }
+}
+```
+
+> **Note**: the `builder` field specifies the `./dist/builder.js` start script is the compiled script, and the source file of the start script is located in `./source/builder.ts`. To configure the start script, change it in the source file.
+
+### Start script configuration
+
+The plugin entry configuration code example is shown below:
+
+```ts
+// builder.ts
+
+// Allow external developers to replace parts of the build asset handler module. Please refer to the "Custom Texture Compression Processing" section below for details.
+export const assetHandlers: string = './asset-handlers';
+
+export const configs: IConfigs = {
+ 'web-mobile': {
+ hooks: './hooks',
+ options: {
+ remoteAddress: {
+ label: 'i18n:xxx',
+ render: {
+ ui: 'ui-input',
+ attributes: {
+ placeholder: 'Enter remote address...',
+ },
+ },
+ // Validation rules, there are currently several commonly used validation rules built in, and the rules that need to be customized can be configured in the "verifyRuleMap" field
+ verifyRules: ['require', 'http'],
+ },
+ enterCocos: {
+ label: 'i18n:cocos-build-template.options.enterCocos',
+ description: 'i18n:cocos-build-template.options.enterCocos',
+ default: '',
+ render: {
+ // Please click "Developer -> UI Components" in the menu bar of the editor to view a list of all supported UI components.
+ ui: 'ui-input',
+ attributes: {
+ placeholder: 'i18n:cocos-build-template.options.enterCocos',
+ },
+ },
+ verifyRules: ['ruleTest']
+ }
+ },
+ verifyRuleMap: {
+ ruleTest: {
+ message: 'i18n:cocos-build-template.ruleTest_msg',
+ func(val, option) {
+ if (val === 'cocos') {
+ return true;
+ }
+ return false;
+ }
+ }
+ }
+ },
+};
+```
+
+Please pay extra attention to the following points when writing start scripts:
+
+1. The environment variables in different processes will be different. The start script will be loaded by the rendering process and the main process at the same time, do not use the editor interface that only exists in a single process in the start script.
+
+2. There are two ways to configure the key of `config`:
+
+ - One is for a single platform configuration, and the key is filled in as **platform plugin name** (available in the editor menu bar **Extensions -> Extension Manager -> Internal** to view the platform plug-in name).
+
+ - One is the configuration for all platforms, the key is filled in as `*`. These two configuration methods are mutually exclusive, please do not use them in the same build extension package.
+
+ > **Note**: these two configuration methods are mutually exclusive, please do not use both in the same build extension package. Otherwise the configuration for a single platform (key value `platform build plugin name`) will overwrite the configuration for all platforms (key value `*`).
+
+## Customizing Build Panel Options
+
+There are currently two ways to add build options to the interface: **options automatic rendering configuration method** and **panel custom panel configuration method** (>=3.8.2). The former automatically renders the content of the options configuration in the build panel and performs data update operations after some operations, while the latter adds a panel configuration to place the content of a custom panel, and the build will use this configuration to render with `ui-panel`.
+To facilitate testing, this article will use `web-mobile` as an example to demonstrate how to add new options to the build panel and display them.
+
+### Options Automatic Rendering Configuration Method
+
+Create a new `src/builder.ts` script file and write the following code in `builder.ts`:
+
+```ts
+import { BuildPlugin, IBuildTaskOption } from "../@types/packages/builder/@types";
+
+export const load: BuildPlugin.load = function() {
+ console.debug('custom-build-example load');
+};
+
+export const unload: BuildPlugin.load = function() {
+ console.debug('custom-build-example unload');
+};
+
+export const configs:BuildPlugin.Configs = {
+ 'web-mobile': {
+ options: {
+ testInput: {
+ label: 'testVar',
+ description: 'this is a test input.',
+ default: '',
+ render: {
+ ui: 'ui-input',
+ attributes: {
+ placeholder: 'Enter numbers',
+ },
+ },
+ verifyRules: ['required','ruleTest']
+ },
+ testCheckbox: {
+ label: 'testCheckbox',
+ description: 'this is a test checkbox.',
+ default: false,
+ render: {
+ ui: 'ui-checkbox',
+ },
+ },
+ },
+ verifyRuleMap: {
+ ruleTest: {
+ message: 'length of content should be less than 6.',
+ func(val: any, option: IBuildTaskOption) {
+ if (val.length < 6) {
+ return true;
+ }
+ return false;
+ }
+ }
+ }
+ },
+};
+```
+
+In the above `configs`, we define two parameters:
+
+- `testInput`: string - String variable, modified by input box
+- `testCheckbox`: boolean - Boolean variable, modified by checkbox
+
+The meanings of each field in the configuration of build options are as follows:
+
+- `label`: string - Required, the name of this parameter displayed on the interface, supports `i18n:key` configuration
+- `description`: string - Optional, brief description information, used for displaying hints when the mouse hovers over the label, supports `i18n:key` configuration
+- `default`: any - Optional, the default value of the parameter
+- `render`: {} - Required, configure information about the rendered component
+ - `ui`: string - Required, UI component name, please refer to the documentation [UI components](../extension/ui.md)
+ - `attributes`: {} - Optional, properties required by the UI component, please refer to the documentation [UI components](../extension/ui.md)
+
+- `verifyRules`: [] - Optional, parameter verification rules
+- `verifyRuleMap`: [] - Optional, custom parameter verification rule functions. Refer to the section below on [parameter validation rules](#rules-for-customizing-build-panels)
+
+After executing `npm run build` to compile this extension and refresh it, open the build panel and you can see two additional build parameters at the end of the web-mobile build task, as shown in the following figure:
+
+
+
+### Panel customization method (>=3.8.2)
+
+Create a new `src/builder.ts` script file and write the following code in `builder.ts`:
+
+```ts
+import { BuildPlugin, IBuildTaskOption } from "../@types/packages/builder/@types";
+
+export const configs:BuildPlugin.Configs = {
+ 'web-mobile': {
+ panel: './panel',
+ }
+};
+ ```
+
+Create a new `src/panel.ts` script file and write the following code in `panel.ts`:
+
+```ts
+import { ICustomPanelThis, ITaskOptions } from '../@types';
+import { PACKAGE_NAME } from './global';
+let panel: ICustomPanelThis;
+
+export const style = ``;
+
+export const template = `
+
+
+
+
+
+
+`;
+
+export const $ = {
+ root: '.build-plugin',
+ hideLink: 'ui-checkbox',
+ link: '#link',
+};
+
+/**
+ * all change of options dispatched will enter here
+ * @param options
+ * @param key
+ * @returns
+ */
+export async function update(options: ITaskOptions, key: string) {
+ if (key) {
+ return;
+ }
+ // when import build options, key will bey ''
+ init();
+}
+
+export function ready(options: ITaskOptions) {
+ // @ts-ignore
+ panel = this as ICustomPanelThis;
+ panel.options = options;
+ init();
+}
+
+export function close() {
+ panel.$.hideLink.removeEventListener('change', onHideLinkChange);
+}
+
+function init() {
+ panel.$.hideLink.value = panel.options.hideLink;
+ updateLink();
+ panel.$.hideLink.addEventListener('change', onHideLinkChange);
+}
+
+function onHideLinkChange(event: any) {
+ panel.options.hideLink = event.target.value;
+ // Note: dispatch the change to build panel
+ panel.dispatch('update', `packages.${PACKAGE_NAME}.hideLink`, panel.options.hideLink);
+ updateLink();
+}
+
+function updateLink() {
+ if (panel.options.hideLink) {
+ panel.$.link.style.display = 'none';
+ } else {
+ panel.$.link.style.display = 'block';
+ }
+}
+```
+
+#### Rules for customizing build panels
+
+The above code comes from a simple example code in the template of a custom build plugin. You can choose other front-end frameworks to develop the interface more conveniently according to your preferences. Just pay attention to the following rules:
+
+ 1. The file content rules of the panel are rendered by ui-panel, and need to follow the relevant component rules, which basically refer to the variables or lifecycle hooks exposed in the above example code.
+ 2. The `ready` function of the panel will be called after the panel has been loaded. According to needs, you can do some dom element initialization, event binding, or some front-end framework initialization binding in this function.
+ 3. The `close` function of the panel will be called when the panel is closed. According to needs, you can do some event unregistration, object destruction, etc. in this function.
+
+ 4. The `update` function of the panel will be called whenever any build option changes (including those sent by itself). If necessary, you can add this hook here. At the same time, when the build panel has an action of importing configuration, you can also do some updating of the customization panel in this function. At this time, `key` is an empty string.
+
+ 5. If the interaction in the customized panel involves updating the build option, including the data update that may be done during the initialization process, you must use `panel.dispatch('update', key, value, error)` to perform the update, where `key` needs to follow the format of `packages.${PACKAGE_NAME}.key`. Only after calling it will the data be synchronized to the final build option when building. Sending an error mainly affects the disablement status of the build button, and error is an optional parameter.
+
+ 6. If the interaction in the customized panel involves reading the build option, you need to use `panel.options.key`
+
+### Start script interface definition
+
+The detailed interface definition is described as follows:
+
+```ts
+declare type IConfigs = Record;
+declare interface IBuildPlugin {
+ hooks?: string; // Storage path of hook function
+ options?: IDisplayOptions; // Platform parameter configuration that needs to be injected
+ verifyRuleMap?: IVerificationRuleMap; // Register parameter verification rule function
+}
+declare type IDisplayOptions = Record;
+declare interface IConfigItem {
+ // The default value, the registered default value will be in the "options.[platform].xxx" field in the plugin configuration
+ default?: any;
+
+ render: ?{
+ // The rules for rendering UI components are consistent with the unified rules at "ui-prop". Only configurations with UI properties specified will be displayed on the Build panel
+ ui?: string;
+ // The configuration parameters passed to the UI component
+ attributes?: IUiOptions;
+ };
+
+ // Configure the displayed name, if you need to translate, then pass in "i18n:${key}"
+ label?: string;
+
+ // A brief description of the setting, which will be displayed on the title when the mouse hovers over the configuration name.
+ description?: string;
+
+ // Type of configuration
+ type?: 'array' | 'object';
+
+ // If type is an array, the data will be rendered according to the specified data type and "itemConfigs"
+ itemConfigs?: Record | IConfigItem[];
+}
+
+declare interface IUiOptions extends IOptionsBase {
+ // Validation rules array, build provides some basic rules, and you can also specify new validation rules through “verifyRuleMap”. Only when pass in “require” will be a valueless checksum, otherwise only when there is a value.
+ verifyRules?: string[];
+}
+
+declare interface IUiOptions extends IOptionsBase {
+ class?: string | string[]; // The name of the style that needs to be set on the current "ui-prop"
+}
+```
+
+For the interface definition of `IOptionsBase` please refer to [ui-prop automatic rendering rule definition](../extension/ui.md).
+
+## Custom build hook function code configuration
+
+In the script module defined by the hooks field in the entry configuration, hook functions can be written that build the life cycle. In different hook functions, the data received will be different. All hook functions run in the build process, and the engine method can be used directly in the build process.
+
+The relationship between the public hook function and the life cycle of the build can be seen in the following figure:
+
+
+
+The rough interface definition of hook function is as follows:
+
+```ts
+declare interface IHook {
+ throwError?: boolean; // The hook function injected by the plugin, whether to exit the build process directly and show the build failure when the execution fails.
+ // ------------------ hook function --------------------------
+ onBeforeBuild?: IBaseHooks;
+ onBeforeCompressSettings?: IBaseHooks;
+ onAfterCompressSettings?: IBaseHooks;
+ onAfterBuild?: IBaseHooks;
+
+ // Compile the generated hook function (only valid if the platform's build process has a "Make" step)
+ onBeforeMake?: (root: string, options: IBuildTaskOptions) => void | Promise;
+ onAfterMake?: (root: string, options: IBuildTaskOptions) => void | Promise;
+}
+type IBaseHooks = (options: IBuildTaskOptions, result?: IBuildResult) => void | Promise;
+```
+
+> **Notes**:
+> 1. the `result` parameter can be accessed only at the beginning of `onBeforeCompressSettings`, and the `options` passed to the hook function is a copy of the `options` used in the actual build process, and only used as a reference for information acquisition, so directly modifying it does not really affect the build process, although it can be modified successfully. To modify the build parameters, please set in the `options` field of the entry configuration code. Due to the numerous interface definitions, you can refer to the `@types/packages/builder` folder in the build extension package for detailed interface definitions.
+> 2. The hook function is allowed to be an asynchronous function, and the build will await the completion of the hook function execution before executing the next process by default.
+
+A simple example:
+
+```ts
+export function onBeforeBuild(options) {
+ // Todo some thing...
+}
+export async function onBeforeCompressSettings(options, result) {
+ // Todo some thing...
+}
+```
+
+### Custom texture compression processing
+
+The `assetHandler` path configuration specified in the **start script configuration** above allows external developers to register some asset handling functions to replace the engine's handler module when building partial assets. Currently only **texture compression** handler registration is available.
+
+Creator provides its own compression tools to handle compressed texture assets at build time, but does not focus on image compression because it needs to be compatible with different user environments and usually the compression tools are chosen to work on most computers rather than the most efficient ones. Therefore, Creator has opened up a plug-in mechanism in v3.4, **which allows users to directly register compression processing functions for the corresponding texture assets, which will be called at the appropriate processing time when building**.
+
+The specific steps are as follows:
+
+1. In the start script, write the relative path of the `assetHandlers` module script:
+
+ ```ts
+ export const assetHandlers = './asset-handlers';
+ ```
+
+2. In the `assetHandlers` script module, the `compressTextures` function has been opened up for developers to write the corresponding handler function directly in `compressTextures`, which will be called during the texture compression phase of the build.
+
+ The handler function takes the current array of remaining unprocessed texture compression tasks and removes them from the original array when processing is complete. Texture compression tasks that are not removed are considered unprocessed and are placed in the next corresponding processing function until all processing functions have been processed, and if there are still unprocessed texture compression tasks, they are placed back in the Creator's original texture compression process.
+
+ When there are multiple plugins registered with texture compression handler functions, they are executed in the order in which the plugins are started. If the previous plugin processes all the texture compression tasks, the subsequent plugins registered with the handler functions will not receive the tasks.
+
+ The code example is as follows:
+
+ ```ts
+ type ITextureCompressType =
+ | 'jpg'
+ | 'png'
+ | 'webp'
+ | 'pvrtc_4bits_rgb'
+ | 'astc_12x12'; // See interface definition for detailed format
+ interface ICompressTasks {
+ src: string; // Source file address
+ dest: string; // Address of the generated target file (default suffix is PNG, other types need to be changed manually)
+ quality: number | IPVRQuality | IASTCQuality | IETCQuality; // Compression quality 0 - 100 or other compression levels
+ format: ITextureCompressType; // Compression type
+ }
+ export async function compressTextures(tasks: ICompressTasks[]) {
+ for (let i = 0; i < Array.from(tasks).length; i++) {
+ const task = Array.from(tasks)[i];
+ if (task.format ! == 'jpg') {
+ // Texture compression tasks that are skipped are passed to the next processing function until they finally enter the Creator's original build-time texture compression process
+ continue;
+ }
+ task.dest = task.dest.replace('.png', '.jpg');
+ await pngToJPG(task.src, task.dest, task.quality);
+ // Remove the finished texture compression task from tasks, so that it will not be processed again when building
+ tasks.split(i, 1);
+ }
+ }
+ ```
+
+## Debugging build extension plugins
+
+When the build extension plugin is involved in the build process, the associated code runs in the following three processes:
+
+- **Main Process**: executes the start script and its dependent assets.
+- **Rendering Process**: executes some of the fields registered in the start script to the **Build** panel.
+- **Build Process**: executes the script defined in the `hooks` field of the start script.
+
+### Main Process (Start Script)
+
+The main process mainly executes the start script used in the build extension plugin to participate in the build process (the script specified in the `builder` field), and the plugin's own start script (the script specified in the `main` field).
+
+When the code running in the main process is modified, the plugin must be restarted and then the process to be updated must be refreshed (this will be optimized later to try to solve the code update problem with a single restart, but refreshing is still the most thorough reloading method). The main process currently does not have a more appropriate debugging method, you can use the command line to open the editor to view the main process code log to assist debugging:
+
+```bash
+// Mac
+/Applications/CocosCreator/Creator/3.0.0/CocosCreator.app/Contents/MacOS/CocosCreator --project projectPath
+
+// Windows
+... \CocosCreator.exe --project projectPath
+```
+
+### Rendering Process (Build Panel)
+
+The start script of the build extension plugin has some fields that are registered to the **Build** panel, such as the display configuration of `options`, the `panel` field, and the `panel` script itself, which is loaded and executed in the render process. The rendering process is actually the window's own execution process. Open the DevTools to debug the `dom` elements, styles, scripts, etc. on the **Build** panel.
+
+If the code registered to the **Build** panel is modified, refresh the panel without restarting the plugin.
+
+- **Open the DevTools for the rendering process of the Build panel**
+
+ Click on the **Build** panel and press the shortcut **Ctrl + Shift + I** (Windows) or **Command + Option + I** (Mac) to open the DevTools for the **Build** panel.
+
+- **How to reload (refresh) the panel**
+
+ Press **Ctrl/Command + R** after clicking on the **Build** panel or the DevTool in the **Build** panel.
+
+### Build Process (`hooks` Script)
+
+The actual execution phase of the build is a separate worker process, ensuring that even if an abnormal crash occurs, it will not affect the normal use of other windows. The scripts defined in the `hooks` field of the start script are also loaded and executed in this separate worker process.
+
+If only the script defined in the `hook` field is modified, the build process can be refreshed without restarting the plugin. To do this, press **Ctrl/Command + R** after opening the build DevTools, as in the **Build** panel above.
+
+#### Opening the DevTools for the build process
+
+This includes the following three ways:
+
+1. Click the **Open Build DevTools** button at the top right of the build task window in the **Build** panel.
+
+ 
+
+2. Click **Developers -> Open Build DevTools** in the main editor menu to open it.
+
+3. In any plugin code or in the console, execute the following code:
+
+ ```ts
+ Editor.Message.send('builder', 'open-devtools');
+ ```
+
+ `Editor.Message` can be extended to suit additional needs. For example, developers can catch errors in the code written to build the plugin, and automatically open DevTools once there is an exception or something like that.
diff --git a/versions/4.0/en/editor/publish/custom-build-plugin/cocos-build-template-menu.png b/versions/4.0/en/editor/publish/custom-build-plugin/cocos-build-template-menu.png
new file mode 100644
index 0000000000..879cbd9f23
Binary files /dev/null and b/versions/4.0/en/editor/publish/custom-build-plugin/cocos-build-template-menu.png differ
diff --git a/versions/4.0/en/editor/publish/custom-build-plugin/custom-build-compress-tex-option.png b/versions/4.0/en/editor/publish/custom-build-plugin/custom-build-compress-tex-option.png
new file mode 100644
index 0000000000..bcfb711f1d
Binary files /dev/null and b/versions/4.0/en/editor/publish/custom-build-plugin/custom-build-compress-tex-option.png differ
diff --git a/versions/4.0/en/editor/publish/custom-build-plugin/custom-build-example-hooks-log.png b/versions/4.0/en/editor/publish/custom-build-plugin/custom-build-example-hooks-log.png
new file mode 100644
index 0000000000..0adba31ae8
Binary files /dev/null and b/versions/4.0/en/editor/publish/custom-build-plugin/custom-build-example-hooks-log.png differ
diff --git a/versions/4.0/en/editor/publish/custom-build-plugin/custom-build-example-options.png b/versions/4.0/en/editor/publish/custom-build-plugin/custom-build-example-options.png
new file mode 100644
index 0000000000..6679e0a73e
Binary files /dev/null and b/versions/4.0/en/editor/publish/custom-build-plugin/custom-build-example-options.png differ
diff --git a/versions/4.0/en/editor/publish/custom-build-plugin/custom-build-example-validator-errormsg.png b/versions/4.0/en/editor/publish/custom-build-plugin/custom-build-example-validator-errormsg.png
new file mode 100644
index 0000000000..da777f98ec
Binary files /dev/null and b/versions/4.0/en/editor/publish/custom-build-plugin/custom-build-example-validator-errormsg.png differ
diff --git a/versions/4.0/en/editor/publish/custom-project-build-template.md b/versions/4.0/en/editor/publish/custom-project-build-template.md
new file mode 100644
index 0000000000..bcc9c87102
--- /dev/null
+++ b/versions/4.0/en/editor/publish/custom-project-build-template.md
@@ -0,0 +1,74 @@
+# Custom Project Build Template
+
+**Cocos Creator** supports custom build templates for each project. Add a `build-templates/[platform]` folder to the project path, and divide the sub-folder according to the **platform name**. Then all the files in this folder will be automatically **copied** to the build generated project according to the corresponding folder structure after the build. Currently, all platforms except the native platform support this function, the specific **platform name** can be referred to as the following **custom build template supported platform list**.
+
+Folder Structure:
+
+```bash
+project-folder
+ |--assets
+ |--build
+ |--build-templates
+ |--web-mobile
+ // The file to be added, such as index.html
+ |--index.html
+```
+
+If the current platform is `Web-Mobile`, then `build-templates/web-mobile/index.html` will be copied to `build/web-mobile/index.html`.
+
+In addition, the file types currently supported by the build template include **ejs type** and **json type**. These two types will not copied directly but rather parsed. Please refer to the **Special Custom Build Template Platform support list** below for details on the support for these two template types by platform.
+
+## `ejs` type
+
+Since the content of the package is not guaranteed to be exactly the same in every version, when the build template within the editor is updated, the developer also needs to update the build template within their project. For example, if the MD5 Cache option is checked at build time, taking `index.html` on the web platform as an example, the `css` file referenced in it will have an MD5 Hash suffix, which may not match the one in the original template and may not work.
+To optimize this problem, a new way is added to use the template. Click on **Project -> Create Preview Template** in the main menu, and an `ejs` template file will be generated for the corresponding platform.
+
+
+
+Developers only need to customize the generated build template in the `.ejs`, the build will automatically synchronize the updates of the editor build template to the custom build template, and the frequently changed content will be synchronized to the sub-template (`.ejs`) referenced by the template, so that the custom build template can be updated manually without frequent updates.
+
+Taking the creation of a Web Mobile build template as an example, the generated build template directory structure is as follows:
+
+
+
+> **Note**: the copy template occurs after the rendered template. For example, if both `index.ejs` and `index.html` exist in this directory, the final packaged package will be the `index.html` file instead of the `index.ejs` rendered file.
+
+### `json` Type
+
+Many mini games have their own configuration `JSON` files, like `game.json` to WeChat Mini Games. Files in the build templates folder will just copy in **default**, but this configuration JSON will be merged instead of overwrite. Of course, it doesn't mean that all `JSON` file will be merged, you can check it in the tables below.
+
+## Special Custom Build Template supported Platform list
+
+Most files placed in the `build-templates/[platform]` directory will be copied directly to the corresponding directory. In addition, many platforms support some template files with special name formats. The supported file with special name formats for build templates by the platform are as follows:
+
+| Platform | Actual Name | Supported File Type |
+| :-------- | :---------- | :----------- |
+| **Huawei AGC** | huawei-agc | `index.ejs` |
+| **Alipay Mini Game** | alipay-mini-game | `game.json` |
+| **Taobao Mini Game** | taobao-mini-game | `game.json`、`mini.project.json` |
+| **Douyin Mini Game** | bytedance-mini-game | `game.ejs`、`game.json`、`project.config.json` |
+| **OPPO Mini Game** | oppo-mini-game | `manifest.json` |
+| **Huawei Quick Game** | huawei-quick-game | `game.ejs` |
+| **Cocos Play** | cocos-play | `game.config.json` |
+| **vivo Mini Game** | vivo-mini-game | `project.config.json` |
+| **Baidu Mini Game** | baidu-mini-game | `game.json`, `project.swan.json` |
+| **WeChat Mini Game** | wechatgame | `game.ejs`, `game.json`, `project.config.json` |
+| **Web Desktop** | web-desktop | `index.ejs` |
+| **Web Mobile** | web-mobile | `index.ejs` |
+| **Native** | native | `index.ejs` |
+
+
\ No newline at end of file
diff --git a/versions/4.0/en/editor/publish/custom-project-build-template/build-process-public.drawio b/versions/4.0/en/editor/publish/custom-project-build-template/build-process-public.drawio
new file mode 100644
index 0000000000..475c2ed70c
--- /dev/null
+++ b/versions/4.0/en/editor/publish/custom-project-build-template/build-process-public.drawio
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/versions/4.0/en/editor/publish/custom-project-build-template/build-process.jpg b/versions/4.0/en/editor/publish/custom-project-build-template/build-process.jpg
new file mode 100644
index 0000000000..eb6311ab8c
Binary files /dev/null and b/versions/4.0/en/editor/publish/custom-project-build-template/build-process.jpg differ
diff --git a/versions/4.0/en/editor/publish/custom-project-build-template/build-template.png b/versions/4.0/en/editor/publish/custom-project-build-template/build-template.png
new file mode 100644
index 0000000000..25501118a4
Binary files /dev/null and b/versions/4.0/en/editor/publish/custom-project-build-template/build-template.png differ
diff --git a/versions/4.0/en/editor/publish/custom-project-build-template/console.png b/versions/4.0/en/editor/publish/custom-project-build-template/console.png
new file mode 100644
index 0000000000..fcd6c19463
Binary files /dev/null and b/versions/4.0/en/editor/publish/custom-project-build-template/console.png differ
diff --git a/versions/4.0/en/editor/publish/custom-project-build-template/dev_tools.png b/versions/4.0/en/editor/publish/custom-project-build-template/dev_tools.png
new file mode 100644
index 0000000000..5b1f4122e6
Binary files /dev/null and b/versions/4.0/en/editor/publish/custom-project-build-template/dev_tools.png differ
diff --git a/versions/4.0/en/editor/publish/custom-project-build-template/enable-plugin.png b/versions/4.0/en/editor/publish/custom-project-build-template/enable-plugin.png
new file mode 100644
index 0000000000..60735e197b
Binary files /dev/null and b/versions/4.0/en/editor/publish/custom-project-build-template/enable-plugin.png differ
diff --git a/versions/4.0/en/editor/publish/custom-project-build-template/plugin-template.png b/versions/4.0/en/editor/publish/custom-project-build-template/plugin-template.png
new file mode 100644
index 0000000000..03a30f79f0
Binary files /dev/null and b/versions/4.0/en/editor/publish/custom-project-build-template/plugin-template.png differ
diff --git a/versions/4.0/en/editor/publish/custom-project-build-template/reload.png b/versions/4.0/en/editor/publish/custom-project-build-template/reload.png
new file mode 100644
index 0000000000..cae0cc7dd7
Binary files /dev/null and b/versions/4.0/en/editor/publish/custom-project-build-template/reload.png differ
diff --git a/versions/4.0/en/editor/publish/custom-project-build-template/web-mobile.png b/versions/4.0/en/editor/publish/custom-project-build-template/web-mobile.png
new file mode 100644
index 0000000000..24d68d3a46
Binary files /dev/null and b/versions/4.0/en/editor/publish/custom-project-build-template/web-mobile.png differ
diff --git a/versions/4.0/en/editor/publish/debug-jsb.md b/versions/4.0/en/editor/publish/debug-jsb.md
new file mode 100644
index 0000000000..46f89df8d4
--- /dev/null
+++ b/versions/4.0/en/editor/publish/debug-jsb.md
@@ -0,0 +1,91 @@
+# Debugging JavaScript on Native Platforms
+
+After a game is released on the native platform, because the runtime environment is different, there may be some bugs that cannot be reproduced in the browser preview. This means it is necessary to debug it directly on the native platform. **Cocos Creator** makes it easy to debug JavaScript remotely in the native platforms.
+
+## Debugging on Android / iOS
+
+If a game can only run on a physical device, then the packaged game must be debugged on a physical device. Debugging steps are as follows:
+
+- Make sure that the Android / iOS device is on the same LAN as Windows or Mac.
+- Select the **Android/iOS** platform and **Debug** mode in the **Build** panel to build, compile and run a project (for the iOS platform, it is recommended to connect to the physical device via Xcode to compile and run).
+- Open this address with Chrome browser: `devtools://devtools/bundled/js_app.html?v8only=true&ws=Local IP of the device:43086/00010002-0003-4004-8005-000600070008`.
+
+ 
+
+>If the port is occupied, the port will auto-increment by +1. If you cannot connect, please check the port number printed in the console when the App starts.
+>It is recommended to check the "Debug" and "Source Maps" options when buiding. This ensures that the corresponding JavaScript code is displayed in an expanded format.
+
+## Debugging on Windows / Mac
+
+The steps for debugging a game on the Windows / Mac platform are similar to the Android / iOS, just compile the project and run it in the IDE.
+
+- Compile and run the packaged project with the IDE (Visual Studio for Windows and Xcode for Mac).
+- Open Chrome while the game is running and enter the address: `devtools://devtools/bundled/js_app.html?v8only=true&ws=127.0.0.1:6086/00010002-0003-4004-8005-000600070008` to debug it.
+
+ 
+
+## Using `lldb` to view the current JS call stack
+
+By using breakpoints in C++, we can easily see the C++ call stack, but not the JS call stack at the same time, which often breaks the debugging experience. The features provided by `lldb` allow doing a lot of things during debugging, including viewing the call stack.
+
+Both **Xcode** and **Android Studio** use `lldb` as debugger by default. For more details, please refer to the [LLDB Guide](https://lldb.llvm.org/use/tutorial.html) documentation.
+
+### Global configuration of `lldb`
+
+`lldb` will load `~/.lldbinit` at startup, for example the following configuration:
+
+`~ % cat ~/.lldbinit`
+
+```
+target stop-hook add
+po se::ScriptEngine::getInstance()->getCurrentStackTrace()
+DONE
+```
+
+The behavior after setting **every breakpoint** and executing the following code to output the JS call stack:
+
+```txt
+po se::ScriptEngine::getInstance()->getCurrentStackTrace()
+```
+
+For more information on the usage of `target stop-hook`, please refer to the [Examining Variables](https://lldb.llvm.org/use/map.html#examining-variables) documentation.
+
+However, this approach has an obvious drawback: it works for **all projects** and will result in an error if the corresponding symbol does not exist for other projects.
+
+### Configuring `lldb` in Xcode
+
+#### Editing `Action` in breakpoints in Xcode (only triggered for specific breakpoints)
+
+
+
+Enter the following command in the **Debugger Command**:
+
+```txt
+po se::ScriptEngine::getInstance()->getCurrentStackTrace()
+```
+
+For more information about the usage of `target stop-hook`, please refer to the [Evaluating Expressions](https://lldb.llvm.org/use/map.html#evaluating-expressions) documentation.
+
+#### Setting `stop hook`
+
+After the breakpoint is triggered, a callback needs to be added to the lldb console. More calls can be made for specific breakpoints: the
+
+
+
+As above, the call stack can also be viewed by executing the following code:
+
+```txt
+po se::ScriptEngine::getInstance()->getCurrentStackTrace()
+```
+
+### Configuring `lldb` in Android Studio
+
+Configure in the **Run -> Debug Configuration -> Debugger** interface of **Android Studio**:
+
+
+
+Android Studio also provides a `lldb console` similar to Xcode.
+
+## Advanced Debugging Guide
+
+To debug in Release mode, or need to debug a customized native engine, please refer to the more detailed [JSB 2.0 Usage Guide: Remote Debugging and Profile](../../advanced-topics/JSB2.0-learning.md) documentation.
diff --git a/versions/4.0/en/editor/publish/debug-jsb/as-brk-point-action.png b/versions/4.0/en/editor/publish/debug-jsb/as-brk-point-action.png
new file mode 100644
index 0000000000..ffa52225f1
Binary files /dev/null and b/versions/4.0/en/editor/publish/debug-jsb/as-brk-point-action.png differ
diff --git a/versions/4.0/en/editor/publish/debug-jsb/simulator-run.png b/versions/4.0/en/editor/publish/debug-jsb/simulator-run.png
new file mode 100644
index 0000000000..b365e75e36
Binary files /dev/null and b/versions/4.0/en/editor/publish/debug-jsb/simulator-run.png differ
diff --git a/versions/4.0/en/editor/publish/debug-jsb/v8-android-debug.png b/versions/4.0/en/editor/publish/debug-jsb/v8-android-debug.png
new file mode 100644
index 0000000000..c866cd1813
Binary files /dev/null and b/versions/4.0/en/editor/publish/debug-jsb/v8-android-debug.png differ
diff --git a/versions/4.0/en/editor/publish/debug-jsb/v8-win32-debug.png b/versions/4.0/en/editor/publish/debug-jsb/v8-win32-debug.png
new file mode 100644
index 0000000000..7061257b84
Binary files /dev/null and b/versions/4.0/en/editor/publish/debug-jsb/v8-win32-debug.png differ
diff --git a/versions/4.0/en/editor/publish/debug-jsb/xcode-brk-point-action.png b/versions/4.0/en/editor/publish/debug-jsb/xcode-brk-point-action.png
new file mode 100644
index 0000000000..bdf435936d
Binary files /dev/null and b/versions/4.0/en/editor/publish/debug-jsb/xcode-brk-point-action.png differ
diff --git a/versions/4.0/en/editor/publish/debug-jsb/xcode-brk-point-lldb.png b/versions/4.0/en/editor/publish/debug-jsb/xcode-brk-point-lldb.png
new file mode 100644
index 0000000000..43c623776c
Binary files /dev/null and b/versions/4.0/en/editor/publish/debug-jsb/xcode-brk-point-lldb.png differ
diff --git a/versions/4.0/en/editor/publish/google-play-games/build-and-run.md b/versions/4.0/en/editor/publish/google-play-games/build-and-run.md
new file mode 100644
index 0000000000..07eee343aa
--- /dev/null
+++ b/versions/4.0/en/editor/publish/google-play-games/build-and-run.md
@@ -0,0 +1,60 @@
+# Build and Run
+
+
+
+In this section we will describe how to develop and test an existing APK with the HPE simulator.
+
+## Preparation
+
+First you need to prepare an Android Studio project published by Cocos Creator, if you are not familiar with this, we recommend you to refer to [Android Build Example](./android/build-example.md)
+
+## Start the emulator
+
+First you need to launch the emulator by finding the emulator icon in the OS toolbar and selecting **Launch Emulator**:
+
+
+
+After starting:
+
+
+
+## Installing the app
+
+Let's review a little how to build the APK via Android Studio, just click on the following menu:
+
+
+
+After a successful build, you can find the corresponding APK file in the project directory.
+
+### Start ADB
+
+Next you need to install the APK to the emulator, find the adb command and enter:
+
+> adb is usually found in the SDK/plat-form directory of Android. You may consider adding this directory to the environment variables so that it is available anywhere.
+
+```bash
+adb devices
+```
+
+Used to check if the emulator is properly connected.
+
+
+
+If `localhost:6520 offline` is displayed or the devices are not displayed, restart the emulator or type: `adb connect localhost:6520` from within the command line.
+
+### Install the application
+
+Find the directory where the apk was previously stored and type in the command line.
+
+```bash
+adb install C:/yourpath/yourgame.apk
+
+```
+
+
+
+## Start the application
+
+If you want to find the installed application, find the application icon in the screen by swiping up and then click on it to launch the application:
+
+
diff --git a/versions/4.0/en/editor/publish/google-play-games/build-and-run/adb-devices.png b/versions/4.0/en/editor/publish/google-play-games/build-and-run/adb-devices.png
new file mode 100644
index 0000000000..96ae1ac74d
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play-games/build-and-run/adb-devices.png differ
diff --git a/versions/4.0/en/editor/publish/google-play-games/build-and-run/after-start-simulator.png b/versions/4.0/en/editor/publish/google-play-games/build-and-run/after-start-simulator.png
new file mode 100644
index 0000000000..bd3724b294
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play-games/build-and-run/after-start-simulator.png differ
diff --git a/versions/4.0/en/editor/publish/google-play-games/build-and-run/build-apk.png b/versions/4.0/en/editor/publish/google-play-games/build-and-run/build-apk.png
new file mode 100644
index 0000000000..2eb37c9faf
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play-games/build-and-run/build-apk.png differ
diff --git a/versions/4.0/en/editor/publish/google-play-games/build-and-run/find-adb.png b/versions/4.0/en/editor/publish/google-play-games/build-and-run/find-adb.png
new file mode 100644
index 0000000000..08cb108dd2
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play-games/build-and-run/find-adb.png differ
diff --git a/versions/4.0/en/editor/publish/google-play-games/build-and-run/install-apk.png b/versions/4.0/en/editor/publish/google-play-games/build-and-run/install-apk.png
new file mode 100644
index 0000000000..61e2bf1876
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play-games/build-and-run/install-apk.png differ
diff --git a/versions/4.0/en/editor/publish/google-play-games/build-and-run/run-on-hpe.png b/versions/4.0/en/editor/publish/google-play-games/build-and-run/run-on-hpe.png
new file mode 100644
index 0000000000..56ff530221
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play-games/build-and-run/run-on-hpe.png differ
diff --git a/versions/4.0/en/editor/publish/google-play-games/build-and-run/show-apps.png b/versions/4.0/en/editor/publish/google-play-games/build-and-run/show-apps.png
new file mode 100644
index 0000000000..78220a4587
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play-games/build-and-run/show-apps.png differ
diff --git a/versions/4.0/en/editor/publish/google-play-games/build-and-run/start-simulator.png b/versions/4.0/en/editor/publish/google-play-games/build-and-run/start-simulator.png
new file mode 100644
index 0000000000..1f7cd19b8b
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play-games/build-and-run/start-simulator.png differ
diff --git a/versions/4.0/en/editor/publish/google-play-games/external-storage/external-permissions.png b/versions/4.0/en/editor/publish/google-play-games/external-storage/external-permissions.png
new file mode 100644
index 0000000000..f1b69f96ac
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play-games/external-storage/external-permissions.png differ
diff --git a/versions/4.0/en/editor/publish/google-play-games/external-storage/permission.png b/versions/4.0/en/editor/publish/google-play-games/external-storage/permission.png
new file mode 100644
index 0000000000..16f75be236
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play-games/external-storage/permission.png differ
diff --git a/versions/4.0/en/editor/publish/google-play-games/index.md b/versions/4.0/en/editor/publish/google-play-games/index.md
new file mode 100644
index 0000000000..e732a1894c
--- /dev/null
+++ b/versions/4.0/en/editor/publish/google-play-games/index.md
@@ -0,0 +1,86 @@
+# Google Play Games on PC
+
+[Google Play Games (GPG)](https://play.google.com/googleplaygames#section-system-requirements) is a related technology developed by Google that allows you to publish and play your mobile APK on PC.
+
+Starting from v3.8, Cocos Creator will provide support for publishing to GPG. This will help your Android version of the game to be published on PC platform for more growth.
+
+In order to publish on GPG smoothly, we recommend you to read the [GPG official website](https://developer.android.com/games/playgames/overview?hl=zh-cn) first to get involved with GPG SDK quickly.
+
+## Integration Guide
+
+In order to get your app on the shelf smoothly, please check that the following steps are all set.
+
+1. In order for the game to run on Windows (both intel and AMD chips), you need to build it with x86 architecture. When building in Cocos Creator, check [APP ABI](./native-options.md#app-abi) and check the box x86_64:
+
+ 
+
+ > x86_64 supports both x86 and x64 builds, so we recommend that you check x86_64 for future changes in requirements.
+
+2. The highest version of OpenGL ES supported by Cocos Creator is 3.1, please check the GLES options in the following figure if you want your application supports OpenGL ES.
+3. Vulkan version is not higher than 1.1. For Cocos Creator to support Vulkan, you need to check Vulkan in the build options, please refer to the figure below.
+
+ 
+
+4. The relevant mobile platform features and permissions need to be removed, according to the [Functional testing requirements](https://developer.android.com/games/playgames/pc-compatibility?hl=zh-cn#unsupported-features-1) and [Quality testing requirements](https://developer.android.com/games/playgames/pc-compatibility?hl=zh-cn#unsupported-features-2). Currently, the default build of Cocos Creator does not cover these features or permissions.
+5. Remove the Permissions dialog for Android apps, [Details](https://developer.android.com/games/playgames/pc-compatibility#permissions-dialogs).
+6. Remove the unsupported Google Play API, [Details](https://developer.android.com/games/playgames/pc-compatibility#unsupported-google-apis).
+7. Enable scoped storage when the application needs to read and write to external storage, example is as follows:
+
+ - Find AndroidManifest.xml in the project directory.
+
+ 
+
+ - After adding the permissions:
+
+ 
+
+ - Fore more details, please refer to [Enable scoped storage](https://developer.android.com/games/playgames/pc-compatibility#scoped-storage).
+
+8. Scaling UI
+
+ Cocos Creator supports adaptive UI. For most mobile games, the resolution is determined when the app is launched, so there is no need to consider the adaptation, but on GPG, since the user can resize the window through the outside of the window, you need to adapt the resolution separately.
+
+ We recommend you to select **Widget** component and make sure its **Align Mode** is **On_WINDOW_RESIZE** or **ALWAYS**.
+
+ 
+
+ - [GPG Interface Scaling](https://developer.android.com/games/playgames/graphics?hl=zh-cn#ui-scaling)
+ - [Multi-resolution Adaptation Scheme](../../../ui-system/components/engine/multi-resolution.md)
+ - [Widget Component Reference](../../../ui-system/components/editor/widget.md) Adaptation of child UI
+
+ For more details, see [UI Practice Guide](../../../ui-system/components/engine/usage-ui.md)
+
+ For adapting devices with large screens, you can refer to Google [Responsive Layout for Large Screen Device Development](https://developer.android.com/large-screens).
+
+
+
+9. GPG requires support for a 16:9 aspect ratio. For an ideal player experience, the game should also support 21:9, 16:10 and 3:2.
+Portrait mode games only need to support a 9:16 aspect ratio. If your game lacks landscape support, Google Play Games will render black bars in full screen mode. Again, see the **Widget** component section above.
+1. Adapting to window transformations, the resolution rendered by GPG games will change the game's rendering resolution at game startup, at window resize, and when switching between full-screen and window models, [details](https://developer.android.com/games/playgames/graphics#dynamic-display).
+2. To ensure that users do not lose progress when switching between mobile devices and PCs, please check that your game meets Google's requirements for continuity, see [About continuity and cross-device play](https://developer.android.com/games/playgames/identity?hl=zh-cn)
+
+## Release process
+
+The GPG release process is similar to the Android release process, you can refer to the following documents for release support.
+
+- [install-and-run](./build-and-run.md)
+- [Android build example](./android/build-example.md)
+- [native-release](../native-options.md)
+
+## Content
+
+- [Integration with Input SDK](../gpg-input-sdk.md)
+
+## Related links
+
+- [GPG official website](https://developer.android.com/games/playgames/overview?hl=zh-cn)
+
+## Interface descriptions
+
+To determine whether the runtime is HPE, use the following code:
+
+```ts
+if( sys.hasFeature(sys.Feature.HPE) ) {
+ ...
+}
+```
diff --git a/versions/4.0/en/editor/publish/google-play-games/index/app-abi.png b/versions/4.0/en/editor/publish/google-play-games/index/app-abi.png
new file mode 100644
index 0000000000..806c016d67
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play-games/index/app-abi.png differ
diff --git a/versions/4.0/en/editor/publish/google-play-games/index/hyper-resolution.png b/versions/4.0/en/editor/publish/google-play-games/index/hyper-resolution.png
new file mode 100644
index 0000000000..5d733ecc7a
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play-games/index/hyper-resolution.png differ
diff --git a/versions/4.0/en/editor/publish/google-play-games/index/render-backend.png b/versions/4.0/en/editor/publish/google-play-games/index/render-backend.png
new file mode 100644
index 0000000000..84eee6f6be
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play-games/index/render-backend.png differ
diff --git a/versions/4.0/en/editor/publish/google-play-games/scale-ui/scale-ui.png b/versions/4.0/en/editor/publish/google-play-games/scale-ui/scale-ui.png
new file mode 100644
index 0000000000..2d22bb6147
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play-games/scale-ui/scale-ui.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/build-example-google-play.md b/versions/4.0/en/editor/publish/google-play/build-example-google-play.md
new file mode 100644
index 0000000000..2aa6da03a2
--- /dev/null
+++ b/versions/4.0/en/editor/publish/google-play/build-example-google-play.md
@@ -0,0 +1,142 @@
+# Google Play Build Example
+
+This article demonstrates the process of publishing a Cocos Creator project as a Google Play application.
+
+Please prepare a Cocos Creator project with at least one scene.
+
+
+
+## Setting Up the Publishing Environment
+
+To publish a Google Play native application, you need to install the Android Studio development environment, along with specific versions of JDK (or OpenSDK), Android SDK, and NDK. For details, please refer to [Configure Android Native Development Environment](../setup-native-development.md).
+
+## Publishing Process
+
+Next, in Cocos Creator, find the **Project** menu, click the **Build** button to open the **Build** panel.
+
+### Creating a Build Task
+
+1. Select **Project** -> **Build** menu to open the build panel
+
+ 
+
+2. Click the **New Build Task** option in the panel:
+
+ 
+
+3. Select Google Play as the build platform:
+
+ 
+
+4. Select at least one scene as the initial loading scene. When there is only one scene, it will be added by default:
+
+ 
+
+5. Enable ADPF (Optional)
+
+ 
+
+6. Refer to [Android Platform Build Options - Render Backend](../../../../en/editor/publish/native-options.md#%E6%B8%B2%E6%9F%93%E5%90%8E%E7%AB%AF) to select the render backend
+
+ 
+
+7. Enter the package name
+
+ 
+
+ > For naming conventions, please refer to [Application ID Name](../../../../en/editor/publish/native-options.md#%E5%BA%94%E7%94%A8-id-%E5%90%8D%E7%A7%B0)
+
+8. Change Application Icon (Optional)
+
+
+
+9. Select Target API Level
+
+ 
+
+ > If there's no dropdown box, please check if the **SDK and NDK Configuration** above is correct.
+
+10. Enable Google Play Instant (Optional)
+
+ 
+
+11. Enable Google Play Billing Feature
+
+ 
+
+ > Without checking this option, you cannot use the Google Play Billing interface
+
+For other options, please refer to [Android Platform Build Options](../../../../en/editor/publish/native-options.md#android-%E5%B9%B3%E5%8F%B0%E6%9E%84%E5%BB%BA%E9%80%89%E9%A1%B9) for configuration.
+
+### Build and Publish
+
+1. Build: Click the **Build** button below to create a new build task and start building
+
+ 
+
+2. Wait for the build to complete
+
+ 
+
+#### Generate AAB Package via Creator
+1. Click **Generate**
+
+ 
+
+2. Wait for the generation to complete
+
+ 
+
+3. Click the button below to open the generated project:
+
+ 
+
+4. Find the publish directory
+
+ 
+
+5. Find the generated AAB package
+
+ 
+
+#### Generate AAB Package via Android Studio
+1. 找到工程对应的目录
+
+ 
+
+2. Open Android Studio menu:
+
+ 
+
+3. Open the built project at `{project path}/build/google-play/proj`:
+
+ 
+
+4. Build APK using Android Studio
+
+ After opening Android Studio, it will take some time for preparation. Once Android Studio has finished preparing the project, you can package the APK. The preparation process might take a while. If there's no response for a long time, please check your network or switch to another mirror. If you need to interrupt the current background task, you can refer to the following closing method:
+
+ > When Android Studio has background tasks, you can click the background task bar at the bottom of the window:
+ >
+ > 
+ >
+ > Click the × on the right in the popup window to end the background task:
+ >
+ > 
+
+5. Open the **Build** menu and select **Build Bundle(s) / APK(s)**:
+
+ 
+
+6. After successful publication, you can find the Debug version of the APK in the proj/build directory:
+
+ 
+
+## Others
+Other aspects are basically the same as Android. You can refer to [Android Build Example](../../../../en/editor/publish/android/build-example-android.md)
+
+## Google Play Billing
+[Google Play Billing Documentation](./google-play-billing-example.md)
+
+## Google Play Game Services
+[Google Play Game Services Documentation](./google-play-game-services.md)
\ No newline at end of file
diff --git a/versions/4.0/en/editor/publish/google-play/game-services-images/achievement-infos.png b/versions/4.0/en/editor/publish/google-play/game-services-images/achievement-infos.png
new file mode 100644
index 0000000000..7acf5263ba
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/game-services-images/achievement-infos.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/game-services-images/application-id.png b/versions/4.0/en/editor/publish/google-play/game-services-images/application-id.png
new file mode 100644
index 0000000000..dbefa9be71
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/game-services-images/application-id.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/game-services-images/config-application-id-en.png b/versions/4.0/en/editor/publish/google-play/game-services-images/config-application-id-en.png
new file mode 100644
index 0000000000..e3990558ad
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/game-services-images/config-application-id-en.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/game-services-images/config-application-id-zh.png b/versions/4.0/en/editor/publish/google-play/game-services-images/config-application-id-zh.png
new file mode 100644
index 0000000000..20c3732c14
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/game-services-images/config-application-id-zh.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/game-services-images/create-achievements.png b/versions/4.0/en/editor/publish/google-play/game-services-images/create-achievements.png
new file mode 100644
index 0000000000..9e23c4f454
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/game-services-images/create-achievements.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/game-services-images/credentials-infos.png b/versions/4.0/en/editor/publish/google-play/game-services-images/credentials-infos.png
new file mode 100644
index 0000000000..6cfddec84a
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/game-services-images/credentials-infos.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/game-services-images/default-achievements.png b/versions/4.0/en/editor/publish/google-play/game-services-images/default-achievements.png
new file mode 100644
index 0000000000..a71db97f2c
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/game-services-images/default-achievements.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/game-services-images/google-cloud-new-oauth-client-id.png b/versions/4.0/en/editor/publish/google-play/game-services-images/google-cloud-new-oauth-client-id.png
new file mode 100644
index 0000000000..011d673f08
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/game-services-images/google-cloud-new-oauth-client-id.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/game-services-images/new-credentials.png b/versions/4.0/en/editor/publish/google-play/game-services-images/new-credentials.png
new file mode 100644
index 0000000000..018e58075a
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/game-services-images/new-credentials.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/game-services-images/no-config-application-id-error.png b/versions/4.0/en/editor/publish/google-play/game-services-images/no-config-application-id-error.png
new file mode 100644
index 0000000000..f265a4f699
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/game-services-images/no-config-application-id-error.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/game-services-images/publish-achievement.png b/versions/4.0/en/editor/publish/google-play/game-services-images/publish-achievement.png
new file mode 100644
index 0000000000..de52b1d02f
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/game-services-images/publish-achievement.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/google-play-billing-example.md b/versions/4.0/en/editor/publish/google-play/google-play-billing-example.md
new file mode 100644
index 0000000000..32ee528a60
--- /dev/null
+++ b/versions/4.0/en/editor/publish/google-play/google-play-billing-example.md
@@ -0,0 +1,90 @@
+# Using the Google Play Billing
+
+## Import the API
+```ts
+import { google } from 'cc'
+```
+
+## Initialize BillingClient
+```ts
+import { google } from 'cc'
+this._client = google.billing.BillingClient.newBuilder().enablePendingPurchases(
+ google.billing.PendingPurchasesParams.newBuilder().enableOneTimeProducts().build()
+ ).setListener({
+ onPurchasesUpdated: (billingResult: google.billing.BillingResult, purchases: google.billing.Purchase[]): void => {
+ // TODO: Handle purchase updates
+ }
+ }).build();
+```
+
+## Connect to Google Play
+```ts
+this._client.startConnection({
+ onBillingServiceDisconnected: (): void => {
+ // TODO: Handle connection failure
+ },
+ onBillingSetupFinished: (billingResult: google.billing.BillingResult): void => {
+ // TODO: Handle successful connection
+ }
+});
+```
+
+## Show Available Products
+```ts
+const product = google.billing.QueryProductDetailsParams.Product.newBuilder()
+ .setProductId("productId")
+ .setProductType(google.billing.BillingClient.ProductType.INAPP)
+ .build();
+const params = google.billing.QueryProductDetailsParams.newBuilder().setProductList([product]).build();
+this._client.queryProductDetailsAsync(params, {
+ onProductDetailsResponse: (billingResult: google.billing.BillingResult, productDetailsList: google.billing.ProductDetails[]): void => {
+ // TODO: Product query callback
+ }
+});
+```
+
+## Launch Purchase Flow
+```ts
+const params = google.billing.BillingFlowParams.newBuilder().setProductDetailsParamsList(
+ [google.billing.BillingFlowParams.ProductDetailsParams.newBuilder().setProductDetails(productDetails).build()]
+ ).build();
+this._client.launchBillingFlow(params);
+```
+
+## Consumable Products
+```ts
+this._client.consumeAsync(google.billing.ConsumeParams.newBuilder().setPurchaseToken(this._purchases[0].getPurchaseToken()).build(), {
+ onConsumeResponse: (billingResult: google.billing.BillingResult, token: string): void => {
+ // TODO: Consumption callback
+ }
+});
+```
+
+## Non-Consumable Products
+```ts
+this._client.acknowledgePurchase(
+ google.billing.AcknowledgePurchaseParams.newBuilder().setPurchaseToken(this._purchases[0].getPurchaseToken()).build(), {
+ onAcknowledgePurchaseResponse: (billingResult: google.billing.BillingResult): void => {
+ // TODO
+ }
+ });
+```
+
+## Query Purchased Products
+```ts
+this._client.queryPurchasesAsync(
+ google.billing.QueryPurchasesParams.newBuilder().setProductType(google.billing.BillingClient.ProductType.INAPP).build(), {
+ onQueryPurchasesResponse: (billingResult: google.billing.BillingResult, purchaseList: google.billing.Purchase[]) : void => {
+ // TODO: Purchased products callback
+ }
+});
+```
+
+## Query User Billing Configuration
+```ts
+this._client.getBillingConfigAsync(google.billing.GetBillingConfigParams.newBuilder().build(), {
+ onBillingConfigResponse: (billingResult: google.billing.BillingResult, billingConfig: google.billing.BillingConfig) : void => {
+ // TODO: Get user config callback
+ }
+});
+```
\ No newline at end of file
diff --git a/versions/4.0/en/editor/publish/google-play/google-play-game-services.md b/versions/4.0/en/editor/publish/google-play/google-play-game-services.md
new file mode 100644
index 0000000000..cd6ebce8f4
--- /dev/null
+++ b/versions/4.0/en/editor/publish/google-play/google-play-game-services.md
@@ -0,0 +1,143 @@
+# Google Play Build Example
+
+This feature is only available on the Google Play platform. Please refer to [Publish Google Play Example](./build-example-google-play.md)
+
+### Auto Sign-in
+When players launch a game with auto sign-in enabled, they can sign in without interacting with the sign-in prompt. Players can enable auto sign-in either in the Google Play Games app or through the initial sign-in prompt displayed in the game.
+
+#### Google Cloud Backend Configuration
+
+- Create Credentials
+
+
+
+You need to create an OAuth client ID in Google Cloud before you can see it in the credentials section of the Google Console.
+
+### Google Play Console Backend Configuration
+[Reference Documentation](https://developer.android.com/games/pgs/console/setup?hl=en#add_your_game_to_the)
+
+1. Add New Credentials
+
+2. Fill in Credential Information
+
+3. Creation Completed
+
+The Application ID highlighted in the red box is what you'll need to fill in below.
+4. After building for the Google Play platform, users need to configure the application ID.
+
+For English applications, configure in English:
+
+For Chinese applications, configure in Chinese:
+
+
+You can configure both English and Chinese simultaneously.
+
+If not configured, you'll see the following error:
+
+
+#### Usage Example
+1. Initialize SDK:
+```typescript
+import { google } from 'cc';
+// Initialize Play Games SDK
+google.play.PlayGamesSdk.initialize();
+```
+
+2. Get Login Result
+```typescript
+ gameSignInClient.isAuthenticated().addOnCompleteListener({
+ onComplete: (isAuthenticatedTask: google.play.Task) => {
+ const isAuthenticated =
+ (isAuthenticatedTask.isSuccessful() &&
+ isAuthenticatedTask.getResult().isAuthenticated());
+ if (isAuthenticated) {
+ // Continue with Play Games Services
+ } else {
+ // Disable your integration with Play Games Services or show a
+ // login button to ask players to sign-in. Clicking it should
+ // call GamesSignInClient.signIn().
+ }
+ },
+ });
+```
+
+### Achievements
+Achievements are an excellent way to increase user engagement in your game. You can implement achievements to encourage players to try features they might not normally use or to play the game in completely different ways. Achievements also allow players to compare their game progress and easily engage in friendly competition.
+
+#### Google Backend Configuration
+1. Create Achievement
+
+2. Fill in Achievement Information
+
+3. Publish Achievement Information
+
+
+Usage Examples:
+1. Display Achievements:
+```typescript
+import { google } from 'cc';
+// Show default achievements interface
+google.play.PlayGames.getAchievementsClient().showAchievements();
+```
+The display effect is shown below:
+
+
+
+2. Unlock Achievement:
+```typescript
+import { google } from 'cc';
+google.play.PlayGames.getAchievementsClient().unlock("achievementId");
+```
+
+If the achievement is incremental (requires several steps to unlock), call AchievementsClient.increment() instead:
+```typescript
+import { google } from 'cc';
+google.play.PlayGames.getAchievementsClient().increment("achievementId", 1);
+```
+Google Play Games Services will automatically unlock the achievement when the completed steps meet the requirement.
+
+3. Load All Achievement Information:
+```typescript
+ import { google } from 'cc';
+ const achievementsClient = google.play.PlayGames.getAchievementsClient();
+ achievementsClient.load(false).addOnSuccessListener({
+ onSuccess: (data: google.play.AnnotatedData) => {
+ this.addLog("isStale : " + data.isStale());
+ const achievements = data.get();
+ for(let i = 0; i < achievements.getCount(); ++i) {
+ str += `getCurrentSteps : ${achievements.get(i).getCurrentSteps()}\n`;
+ str += `getState : ${achievements.get(i).getState()}\n`;
+ str += `getTotalSteps : ${achievements.get(i).getTotalSteps()}\n`;
+ str += `getType : ${achievements.get(i).getType()}\n`;
+ str += `getLastUpdatedTimestamp : ${achievements.get(i).getLastUpdatedTimestamp()}\n`;
+ str += `getXpValue : ${achievements.get(i).getXpValue()}\n`;
+ str += `getAchievementId : ${achievements.get(i).getAchievementId()}\n`;
+ str += `getDescription : ${achievements.get(i).getDescription()}\n`;
+ str += `getFormattedCurrentSteps : ${achievements.get(i).getFormattedCurrentSteps()}\n`;
+ str += `getFormattedTotalSteps : ${achievements.get(i).getFormattedTotalSteps()}\n`;
+ str += `getName : ${achievements.get(i).getName()}\n`;
+ str += `getRevealedImageUrl : ${achievements.get(i).getRevealedImageUrl()}\n`;
+ str += `getUnlockedImageUrl : ${achievements.get(i).getUnlockedImageUrl()}\n\n`;
+ }
+ console.log(str);
+ }
+ });
+```
+
+4. Reveal Hidden Achievement:
+```typescript
+import { google } from 'cc';
+google.play.PlayGames.getAchievementsClient().reveal();
+```
+
+### Recall API
+To communicate with Google's servers using the correct information, you need to request a Recall session ID from the client SDK and send it to your game server.
+```typescript
+const recallClient = google.play.PlayGames.getRecallClient();
+recallClient.requestRecallAccess().addOnSuccessListener({
+ onSuccess: (recallAccess: google.play.RecallAccess) => {
+ const recallSessionId = recallAccess.getSessionId();
+ // Send the recallSessionId to your game server
+ }
+})
+```
\ No newline at end of file
diff --git a/versions/4.0/en/editor/publish/google-play/images/apk.png b/versions/4.0/en/editor/publish/google-play/images/apk.png
new file mode 100644
index 0000000000..759cfb4137
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/apk.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/as-open-menu.png b/versions/4.0/en/editor/publish/google-play/images/as-open-menu.png
new file mode 100644
index 0000000000..b1f57b5d4c
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/as-open-menu.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/as-open-proj.png b/versions/4.0/en/editor/publish/google-play/images/as-open-proj.png
new file mode 100644
index 0000000000..80996bac67
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/as-open-proj.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/background-task.png b/versions/4.0/en/editor/publish/google-play/images/background-task.png
new file mode 100644
index 0000000000..0977698682
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/background-task.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/build-apk.png b/versions/4.0/en/editor/publish/google-play/images/build-apk.png
new file mode 100644
index 0000000000..393c5647a9
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/build-apk.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/build.png b/versions/4.0/en/editor/publish/google-play/images/build.png
new file mode 100644
index 0000000000..ddcd705d67
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/build.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/building.png b/versions/4.0/en/editor/publish/google-play/images/building.png
new file mode 100644
index 0000000000..7a93b2c8a5
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/building.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/cc-build-menu.png b/versions/4.0/en/editor/publish/google-play/images/cc-build-menu.png
new file mode 100644
index 0000000000..3fc866d77d
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/cc-build-menu.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/custom-icon.png b/versions/4.0/en/editor/publish/google-play/images/custom-icon.png
new file mode 100644
index 0000000000..75a2c2684b
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/custom-icon.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/enable-adpf.png b/versions/4.0/en/editor/publish/google-play/images/enable-adpf.png
new file mode 100644
index 0000000000..9831d84afe
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/enable-adpf.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/enable-google-play-billing.png b/versions/4.0/en/editor/publish/google-play/images/enable-google-play-billing.png
new file mode 100644
index 0000000000..63e6e4bb35
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/enable-google-play-billing.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/enable-google-play-instant.png b/versions/4.0/en/editor/publish/google-play/images/enable-google-play-instant.png
new file mode 100644
index 0000000000..42d5fd2232
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/enable-google-play-instant.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/find-proj.png b/versions/4.0/en/editor/publish/google-play/images/find-proj.png
new file mode 100644
index 0000000000..afd2da6796
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/find-proj.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/find-publish-dir.png b/versions/4.0/en/editor/publish/google-play/images/find-publish-dir.png
new file mode 100644
index 0000000000..9f22dd0b5c
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/find-publish-dir.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/find-release-aab.png b/versions/4.0/en/editor/publish/google-play/images/find-release-aab.png
new file mode 100644
index 0000000000..c3b0bfb178
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/find-release-aab.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/game-package-name.png b/versions/4.0/en/editor/publish/google-play/images/game-package-name.png
new file mode 100644
index 0000000000..bb088b8f61
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/game-package-name.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/interrupt-sync.png b/versions/4.0/en/editor/publish/google-play/images/interrupt-sync.png
new file mode 100644
index 0000000000..f10fdbe28d
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/interrupt-sync.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/make.png b/versions/4.0/en/editor/publish/google-play/images/make.png
new file mode 100644
index 0000000000..02085c14d1
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/make.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/making.png b/versions/4.0/en/editor/publish/google-play/images/making.png
new file mode 100644
index 0000000000..aeaf651840
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/making.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/new-build-task.png b/versions/4.0/en/editor/publish/google-play/images/new-build-task.png
new file mode 100644
index 0000000000..71707a9373
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/new-build-task.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/open.png b/versions/4.0/en/editor/publish/google-play/images/open.png
new file mode 100644
index 0000000000..8c4841ae51
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/open.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/project.png b/versions/4.0/en/editor/publish/google-play/images/project.png
new file mode 100644
index 0000000000..2bd2bef86c
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/project.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/render-backend.png b/versions/4.0/en/editor/publish/google-play/images/render-backend.png
new file mode 100644
index 0000000000..83a171bddd
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/render-backend.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/select-platform.png b/versions/4.0/en/editor/publish/google-play/images/select-platform.png
new file mode 100644
index 0000000000..c8eca190bb
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/select-platform.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/start-scene.png b/versions/4.0/en/editor/publish/google-play/images/start-scene.png
new file mode 100644
index 0000000000..5eb6e1b57e
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/start-scene.png differ
diff --git a/versions/4.0/en/editor/publish/google-play/images/target-api-level.png b/versions/4.0/en/editor/publish/google-play/images/target-api-level.png
new file mode 100644
index 0000000000..b6006ef0ee
Binary files /dev/null and b/versions/4.0/en/editor/publish/google-play/images/target-api-level.png differ
diff --git a/versions/4.0/en/editor/publish/gpg-input-sdk.md b/versions/4.0/en/editor/publish/gpg-input-sdk.md
new file mode 100644
index 0000000000..26ecdf3dc7
--- /dev/null
+++ b/versions/4.0/en/editor/publish/gpg-input-sdk.md
@@ -0,0 +1,150 @@
+# Integrating Input SDK
+
+The Input SDK provides a unified interface that allows players to easily find the mouse and keyboard bindings for your game on Google Play Games for PC, thereby enhancing their gaming experience.
+
+## Prerequisites
+
+If you are using Input SDK on a new Android build, simply check the Input SDK option in the build panel.
+
+If the Android project was built previously, you will need to manually add the following code to the `native/engine/android/app/build.gradle` file.
+
+```txt
+dependencies {
+ implementation 'com.google.android.libraries.play.games:inputmapping:1.0.0-beta'
+ ...
+}
+```
+
+## Create a the class named `MyInputMapProvider`
+
+Create a new file `MyInputMapProvider.java` which contains the following code:
+
+```java
+ public class MyInputMapProvider implements InputMappingProvider {
+ public enum InputEventIds {
+ JUMP,
+ LEFT,
+ RIGHT,
+ USE,
+ SPECIAL_JUMP,
+ SPECIAL_DUCK,
+ CMB_MOVE,
+ CMB_DASH,
+ CMB_WAYPOINT
+ }
+
+ @Override
+ public InputMap onProvideInputMap() {
+ InputAction jumpInputAction = InputAction.create(
+ getString(R.string.key_jump),
+ InputEventIds.JUMP.ordinal(),
+ InputControls.create(
+ Collections.singletonList(KeyEvent.KEYCODE_SPACE),
+ Collections.emptyList()
+ )
+ );
+ InputAction leftAction = InputAction.create(
+ getString(R.string.key_Left),
+ InputEventIds.LEFT.ordinal(),
+ InputControls.create(
+ Collections.singletonList(KeyEvent.KEYCODE_DPAD_LEFT),
+ Collections.emptyList()
+ )
+ );
+ InputAction rightAction = InputAction.create(
+ getString(R.string.key_Right),
+ InputEventIds.RIGHT.ordinal(),
+ InputControls.create(
+ Collections.singletonList(KeyEvent.KEYCODE_DPAD_RIGHT),
+ Collections.emptyList()
+ )
+ );
+
+ InputAction cmbMove = InputAction.create(
+ getString(R.string.key_Move),
+ InputEventIds.CMB_MOVE.ordinal(),
+ InputControls.create(
+ Collections.emptyList(),
+ Collections.singletonList(InputControls.MOUSE_RIGHT_CLICK)
+ )
+ );
+ InputAction cmbDash = InputAction.create(
+ getString(R.string.key_Dash),
+ InputEventIds.CMB_DASH.ordinal(),
+ InputControls.create(
+ Arrays.asList(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_SPACE),
+ Collections.emptyList()
+ )
+ );
+ InputAction cmbWaypoint = InputAction.create(
+ getString(R.string.key_Waypoint),
+ InputEventIds.CMB_WAYPOINT.ordinal(),
+ InputControls.create(
+ Collections.singletonList(KeyEvent.KEYCODE_SHIFT_LEFT),
+ Collections.singletonList(InputControls.MOUSE_RIGHT_CLICK)
+ )
+ );
+ InputGroup movementInputGroup = InputGroup.create(
+ getString(R.string.key_BasicMove),
+ Arrays.asList(jumpInputAction, leftAction, rightAction, cmbMove, cmbDash, cmbWaypoint)
+ );
+ return InputMap.create(
+ Arrays.asList(movementInputGroup),
+ MouseSettings.create(true, true)
+ );
+ }
+ }
+
+```
+
+## Add binding names for keys
+
+Define key code names in the `res/values/strings.xml` file to enable internationalization of the app. These descriptions will be used in the previous steps to provide context and clarity for the user when mapping input events to corresponding actions.
+
+```xml
+
+ ...
+ Jump
+ Left
+ Right
+ Move
+ Dash
+ Add Waypoint
+ Basic Movement
+
+```
+
+## Register `InputMapping`
+
+To register the `InputMapping`, modify `AppActivity.java` located in `native\engine\android\app\src\main\cocos\game` by adding the necessary code.
+
+```java
+ ...
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ...
+
+ InputMappingClient inputMappingClient = Input.getInputMappingClient(this);
+ inputMappingClient.setInputMappingProvider(new MyInputMapProvider());
+ }
+ ...
+
+ @Override
+ protected void onDestroy() {
+ InputMappingClient inputMappingClient = Input.getInputMappingClient(this);
+ inputMappingClient.clearInputMappingProvider();
+
+ super.onDestroy();
+ ...
+ }
+
+```
+
+## Test Result
+
+To bring up the page, use Shift + Tab while running on the HPE emulator provided by Google Play Games.
+
+
+
+Refer to the [official documentation](https://developer.android.com/games/playgames/input-sdk-start) of the Input SDK for more details.
diff --git a/versions/4.0/en/editor/publish/index.md b/versions/4.0/en/editor/publish/index.md
new file mode 100644
index 0000000000..63e8f00f25
--- /dev/null
+++ b/versions/4.0/en/editor/publish/index.md
@@ -0,0 +1,46 @@
+# Publish to Multiple Platforms
+
+Thanks to the Cocos Creator's dual-core engine architecture (the C++ core is for native platforms and the TS core is for web and mini-game platform), projects created with Cocos Creator can run smoothly on native, web, and mini-game platforms. This truly achieves the goal of developing once, run everywhere.
+
+## Supported Platforms
+
+- [iOS](./ios/index.md)
+- [Android](./android/index.md)
+- [HuaWei AppGallery Connect](./publish-huawei-agc.md)
+- [Huawei HarmonyOS](./publish-huawei-ohos.md)
+- [Google Play](google-play/build-example-google-play.md)
+- [Google Play On Games](google-play-games/index.md)
+- [macOS](./ios/index.md)
+- [Windows](./windows/index.md)
+- [Web Mobile - H5](./publish-web.md)
+- [Web Web Desktop](publish-web.md)
+- [Facebook Instant Games](./publish-fb-instant-games.md)
+- [WeChat Mini Games](./publish-wechatgame.md)
+- [Douyin Mini Games](./publish-bytedance-mini-game.md)
+- [Facebook Instant Games](./publish-fb-instant-games.md)
+- [OPPO Mini Games](./publish-oppo-mini-game.md)
+- [Huawei Quick Games](./publish-huawei-quick-game.md)
+- [vivo Mini Games](./publish-vivo-mini-game.md)
+- [Honor Mini Games](./publish-honor-mini-game.md)
+
+## Preparation
+
+The preparation that needs to be done before publishing includes getting familiar with following concepts:
+
+- [Build Panel](build-panel.md)
+- [Build Options](build-options.md)
+
+Developers can also publish projects via the command line. For details, please refer to the [Publish from the Command Line](publish-in-command-line.md) documentation.
+
+## Advanced
+
+If you have a certain degree of familiarity and understanding of the build process, it is possible customize the build template and extend the build process. For details, please refer to the following documents:
+
+- [Introduction to the Build Process and FAQ](build-guide.md)
+- [Custom Project Build Process](custom-project-build-template.md)
+- [Extended Build Process](custom-build-plugin.md)
+
+## Additional Resources
+
+- [Cocos Technical Support](https://www.cocos.com/en/assistant)
+- [Cocos Official Forum](https://discuss.cocos2d-x.org/)
diff --git a/versions/4.0/en/editor/publish/ios/build-example-ios.md b/versions/4.0/en/editor/publish/ios/build-example-ios.md
new file mode 100644
index 0000000000..cf76a6453b
--- /dev/null
+++ b/versions/4.0/en/editor/publish/ios/build-example-ios.md
@@ -0,0 +1,88 @@
+# iOS Publishing Example
+
+This article will demonstrate the process of publishing a Cocos Creator project as an iOS application. Before getting started, you will need the following preparations:
+
+- A macOS device with Xcode installed
+- An Apple Developer account
+
+## Publishing Process
+
+### Register an Apple Developer account
+
+Firstly, you need to have an Apple Developer account. If you don't have one, please go to the [registration page](https://appleid.apple.com/account) to create an account.
+
+### Verify the macOS System and Xcode Version
+
+Publishing iOS apps via Cocos Creator environment requirements:
+
+- Xcode version **11.5** or above.
+- macOS version **10.14** or above.
+
+> **Note**: By default, the corresponding Xcode version in the App Store matches the system. If you want to use a specific version of Xcode, you can download it from the [Xcode download page](https://developer.apple.com/xcode/download/).
+
+### Prepare a Test Project
+
+Open an existing project or create a new one.
+
+### Build
+
+
+
+As shown in the image above, select **Project -> Build** from the top menu in Cocos Creator to open the build panel.
+
+
+
+#### General Options
+
+In the blue section on the left side of the image, you can find the common parameters that need to be configured for all platforms supported by Cocos Creator. For more details, you can refer to the [General Build Options](./../build-options.md) page.
+
+#### iOS Specific Options
+
+Choose the platform as **iOS**, and as you scroll down the panel, you will see the red section on the right side. These are the configurations specific to the `native` and `iOS` platforms. For more details, please refer to the [General Native Build Options](./../native-options.md) and [Build Options - iOS](./build-options-ios.md) pages.
+
+#### Bundle Identifier
+
+The Bundle Identifier is a required configuration. It is generally in the format of `com.mycompany.myproduct`. For example, in this example, it is set to `com.cocos.testios`.
+
+#### Perform the Build
+
+After completing the configurations, click the **Build** button to generate the Xcode project.
+
+Once the build is successful, you can click the open file button as shown below to open the generated project folder.
+
+
+
+If you haven't changed the build path, you can find the `build/ios/proj` directory in the project root, which contains the following files:
+
+
+
+### Compile and Run in Xcode
+
+Double-click on `build/ios/proj/.xcodeproj` to open the Xcode project.
+
+
+
+Select `-mobile` as the build target, choose a suitable simulator or a connected iOS device, and click the compile and run button to start the project.
+
+
+
+## Read More
+
+### Script-Native Communication
+
+Sometimes, projects need to call iOS system functions from the script layer, or when integrating a third-party iOS SDK, it is necessary to call its API through script code. In such cases, the communication mechanism between the script layer and the native layer is required.
+
+For communication mechanisms, please refer to:
+
+- [JavaScript and iOS/macOS Communication with Reflection](../../../advanced-topics/oc-reflection.md)
+- [JavaScript and Objective-C Communication using JsbBridge](./../../../advanced-topics/js-oc-bridge.md)
+
+### Debugging JavaScript on Native Platforms
+
+Some issues only occur on specific devices and environments. If you can debug the code on the corresponding situation, you can quickly identify the problem and find a solution.
+
+Cocos Creator provides a native debugging mechanism that allows you to easily debug game code on a device. For more details, please refer to [Debugging JavaScript on Native Platforms](./../debug-jsb.md).
+
+## Features and System Versions
+
+Different features rely on specific system versions. Please refer to [Features and System Versions](./../../../advanced-topics/supported-versions.md) for more details.
diff --git a/versions/4.0/en/editor/publish/ios/build-options-ios.md b/versions/4.0/en/editor/publish/ios/build-options-ios.md
new file mode 100644
index 0000000000..1d7984592c
--- /dev/null
+++ b/versions/4.0/en/editor/publish/ios/build-options-ios.md
@@ -0,0 +1,50 @@
+# Build Options - iOS
+
+
+
+## Executable Name
+
+This a field used to specify the name of the main executable file of an application, which is stored in the app's Info.plist file. If not provided, the system will generate a default value based on the app name field. The value for this field must adhere to a specific format, containing only numbers, letters, underscores (_) and hyphens (-).
+
+## Bundle Identifier
+
+The package name, usually in reverse order of the product website URL, such as `com.mycompany.myproduct`.
+
+> **Note**: The package name can only contain numbers (0-9), letters (A-Z, a-z), hyphens (-), and dots (.), and the last part of the package name must start with a letter and cannot start with an underscore or a number. For more details, please refer to [Bundle Identifier](https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleidentifier).
+
+## Skip the update of Xcode project
+
+By default, each build will execute the CMake command to generate an Xcode project. However, if modifications or configurations are made to the generated Xcode project, such as integrating an SDK with CocoaPods, this could cause issues, as these modifications will be reverted in the next build.
+
+However, if this option is checked, subsequent builds will no longer update or overwrite the configuration of the Xcode project.
+
+It should be noted that other changes related to CMake, such as adding C++ source code, will no longer trigger the regeneration of the Xcode project.
+
+## Orientation
+
+The screen orientation currently includes three options: **Portrait**, **Landscape Left**, and **Landscape Right**.
+
+- **Portrait:** The screen is in an upright position with the Home button at the bottom.
+- **Landscape Left:** The screen is in a landscape position with the Home button on the left side of the screen.
+- **Landscape Right:** The screen is in a landscape position with the Home button on the right side of the screen.
+
+## OS Target
+
+This defines the default launch system, types can be used are as follows:
+
+- iPhone OS: Run on real iOS devices, e.g. an iPhone, and iPad.
+- iOS Simulator: Run on the iOS simulator.
+
+These is just the default value and can be modified at any time in Xcode.
+
+## Render Backend
+
+The Render Backend currently supports **METAL**. For more details, refer to the official documentation on [Metal](https://developer.apple.com/cn/metal/).
+
+## Developer Team
+
+This option is used to configure the Apple Developer account used for signing the app when building and compiling the iOS project. If you manually configure this information in Xcode during compilation, the configuration in Xcode takes precedence. When performing a rebuild, the value of this option will override the value configured in Xcode.
+
+## Target iOS Version
+
+This option is used to specify the iOS software version when publishing to the iOS platform, with a default value of 12.0. The version number after the build will be recorded in the `TARGET_IOS_VERSION` field in the `build/ios/proj/cfg.cmake` file.
diff --git a/versions/4.0/en/editor/publish/ios/images/ios-build-open-path.png b/versions/4.0/en/editor/publish/ios/images/ios-build-open-path.png
new file mode 100644
index 0000000000..5c8fb969ce
Binary files /dev/null and b/versions/4.0/en/editor/publish/ios/images/ios-build-open-path.png differ
diff --git a/versions/4.0/en/editor/publish/ios/images/ios-build-options.png b/versions/4.0/en/editor/publish/ios/images/ios-build-options.png
new file mode 100644
index 0000000000..1a3368fa05
Binary files /dev/null and b/versions/4.0/en/editor/publish/ios/images/ios-build-options.png differ
diff --git a/versions/4.0/en/editor/publish/ios/images/ios-build-panel-a.png b/versions/4.0/en/editor/publish/ios/images/ios-build-panel-a.png
new file mode 100644
index 0000000000..0054002269
Binary files /dev/null and b/versions/4.0/en/editor/publish/ios/images/ios-build-panel-a.png differ
diff --git a/versions/4.0/en/editor/publish/ios/images/ios-build-panel-b.png b/versions/4.0/en/editor/publish/ios/images/ios-build-panel-b.png
new file mode 100644
index 0000000000..e4148b4fdc
Binary files /dev/null and b/versions/4.0/en/editor/publish/ios/images/ios-build-panel-b.png differ
diff --git a/versions/4.0/en/editor/publish/ios/images/ios-build-panel.png b/versions/4.0/en/editor/publish/ios/images/ios-build-panel.png
new file mode 100644
index 0000000000..bb063c6fd6
Binary files /dev/null and b/versions/4.0/en/editor/publish/ios/images/ios-build-panel.png differ
diff --git a/versions/4.0/en/editor/publish/ios/images/ios-run.png b/versions/4.0/en/editor/publish/ios/images/ios-run.png
new file mode 100644
index 0000000000..f995fcb15e
Binary files /dev/null and b/versions/4.0/en/editor/publish/ios/images/ios-run.png differ
diff --git a/versions/4.0/en/editor/publish/ios/images/ios-xcode-folder.png b/versions/4.0/en/editor/publish/ios/images/ios-xcode-folder.png
new file mode 100644
index 0000000000..e1a7dd0e68
Binary files /dev/null and b/versions/4.0/en/editor/publish/ios/images/ios-xcode-folder.png differ
diff --git a/versions/4.0/en/editor/publish/ios/images/ios-xcode-showcase.png b/versions/4.0/en/editor/publish/ios/images/ios-xcode-showcase.png
new file mode 100644
index 0000000000..ae439ebaae
Binary files /dev/null and b/versions/4.0/en/editor/publish/ios/images/ios-xcode-showcase.png differ
diff --git a/versions/4.0/en/editor/publish/ios/images/project-build-menu.png b/versions/4.0/en/editor/publish/ios/images/project-build-menu.png
new file mode 100644
index 0000000000..d5cec7521f
Binary files /dev/null and b/versions/4.0/en/editor/publish/ios/images/project-build-menu.png differ
diff --git a/versions/4.0/en/editor/publish/ios/index.md b/versions/4.0/en/editor/publish/ios/index.md
new file mode 100644
index 0000000000..33fcf8373f
--- /dev/null
+++ b/versions/4.0/en/editor/publish/ios/index.md
@@ -0,0 +1,21 @@
+# Publishing iOS Apps
+
+Cocos Creator supports publishing iOS Apps, but it requires at least one macOS device and one Apple developer account.
+
+## Content
+
+- [iOS Publishing Example](./build-example-ios.md)
+- [Build Options - iOS](build-options-ios.md)
+- [JavaScript and iOS/macOS Communication with Reflection](../../../advanced-topics/oc-reflection.md)
+- [JavaScript and Objective-C Communication using JsbBridge](../../../advanced-topics/js-oc-bridge.md)
+- [Features and System Versions](../../../advanced-topics/supported-versions.md)
+
+## Read More
+
+- [Setting up Native Development Environment](../setup-native-development.md)
+- [Build Panel](../build-panel.md)
+- [General Build Panel](../build-options.md)
+- [General Native Build Options](../native-options.md)
+- [Debugging JavaScript on Native Platforms](../debug-jsb.md)
+- [Build Process and FAQ](../build-guide.md)
+- [Native Platform Secondary Development Guide](../../../advanced-topics/native-secondary-development.md)
diff --git a/versions/4.0/en/editor/publish/mac/build-example-mac.md b/versions/4.0/en/editor/publish/mac/build-example-mac.md
new file mode 100644
index 0000000000..2d9365ff66
--- /dev/null
+++ b/versions/4.0/en/editor/publish/mac/build-example-mac.md
@@ -0,0 +1,103 @@
+# macOS Publishing Example
+
+This article will demonstrate the process of publishing a Cocos Creator project as a macOS application. Before getting started, you will need the following preparations:
+
+- A macOS device
+- Xcode installed
+
+## Publishing Process
+
+### Verify the macOS System and Xcode Version
+
+Publishing macOS desktop apps via Cocos Creator environment requirements:
+
+- Xcode version **11.5** or above.
+- macOS version **10.14** or above.
+
+> **Note**: By default, the corresponding Xcode version in the App Store matches the system. If you want to use a specific version of Xcode, you can download it from the [Xcode download page](https://developer.apple.com/xcode/download/).
+
+### Prepare a Test Project
+
+Open an existing project or create a new one.
+
+### Build
+
+
+
+As shown in the image above, select **Project -> Build** from the top menu in Cocos Creator to open the build panel.
+
+
+
+#### General Options
+
+In the blue section on the left side of the image, you can find the common parameters that need to be configured for all platforms supported by Cocos Creator. For more details, you can refer to the [General Build Options](./../build-options.md) page.
+
+#### macOS Specific Options
+
+Choose the platform as **Mac**, and as you scroll down the panel, you will see the red section on the right side. These are the configurations specific to the `native` and `Mac` platforms. For more details, please refer to the [General Native Build Options](./../native-options.md) and [Build Options - macOS](./build-options-mac.md) pages.
+
+#### Bundle Identifier
+
+The Bundle Identifier is a required configuration. It is generally in the format of `com.mycompany.myproduct`. For example, in this example, it is set to `com.cocos.mac`.
+
+#### Perform the Build
+
+After completing the configurations, click the **Build** button to generate the Xcode project.
+
+Once the build is successful, you can click the open file button as shown below to open the generated project folder.
+
+
+
+If you haven't changed the build path, you can find the `build/mac/proj` directory in the project root, which contains the following files:
+
+
+
+### Compile and Run in Xcode
+
+Double-click on `build/mac/proj/.xcodeproj` to open the Xcode project.
+
+
+
+Select `-desktop` as the build target, choose a suitable simulator or a connected Mac device, and click the compile and run button to start the project.
+
+
+
+### Modifying Resolution
+
+You can modify the resolution by editing `_windowInfo` in `native/engine/common/classes/Game.cpp`:
+
+The default resolution is 800 x 600. Let's take the example of changing the resolution to 800 x 400.
+
+```C++
+int Game::init() {
+ _windowInfo.title = GAME_NAME;
+ // configure window size
+ _windowInfo.width = 800;
+ _windowInfo.height = 400;
+}
+```
+
+After making the modifications, compile and run the project again in Xcode. The effect should be as shown in the following image:
+
+
+
+## Read More
+
+### Script-Native Communication
+
+Sometimes, projects need to call macOS system functions from the script layer, or when integrating a third-party macOS SDK, it is necessary to call its API through script code. In such cases, the communication mechanism between the script layer and the native layer is required.
+
+For communication mechanisms, please refer to:
+
+- [JavaScript and iOS/macOS Communication with Reflection](../../../advanced-topics/oc-reflection.md)
+- [JavaScript and Objective-C Communication using JsbBridge](./../../../advanced-topics/js-oc-bridge.md)
+
+### Debugging JavaScript on Native Platforms
+
+Some issues only occur on specific devices and environments. If you can debug the code on the corresponding situation, you can quickly identify the problem and find a solution.
+
+Cocos Creator provides a native debugging mechanism that allows you to easily debug game code on a device. For more details, please refer to [Debugging JavaScript on Native Platforms](./../debug-jsb.md).
+
+## Features and System Versions
+
+Different features rely on specific system versions. Please refer to [Features and System Versions](./../../../advanced-topics/supported-versions.md) for more details.
diff --git a/versions/4.0/en/editor/publish/mac/build-options-mac.md b/versions/4.0/en/editor/publish/mac/build-options-mac.md
new file mode 100644
index 0000000000..e0fbe2643c
--- /dev/null
+++ b/versions/4.0/en/editor/publish/mac/build-options-mac.md
@@ -0,0 +1,33 @@
+# Build Options - macOS
+
+
+
+## Executable Name
+
+This a field used to specify the name of the main executable file of an application, which is stored in the app's Info.plist file. If not provided, the system will generate a default value based on the app name field. The value for this field must adhere to a specific format, containing only numbers, letters, underscores (_) and hyphens (-).
+
+## Bundle Identifier
+
+The package name, usually in reverse order of the product website URL, such as `com.mycompany.myproduct`.
+
+> **Note**: The package name can only contain numbers (0-9), letters (A-Z, a-z), hyphens (-), and dots (.), and the last part of the package name must start with a letter and cannot start with an underscore or a number. For more details, please refer to [Bundle Identifier](https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleidentifier).
+
+## Target Version
+
+This option is primarily used to specify the target system version when publishing for the Mac platform, with a default value of 10.14. The version number after the build will be recorded in the `TARGET_OSX_VERSION` field of the `build/mac/proj/cfg.cmake` file in the project directory.
+
+## Support Apple Silicon
+
+This option is used to provide better prompts for known engine module support issues on Apple M1 (Silicon) architecture devices.
+
+## Skip the update of Xcode project
+
+By default, each build will execute the CMake command to generate an Xcode project. However, if modifications or configurations are made to the generated Xcode project, such as integrating an SDK with CocoaPods, this could cause issues, as these modifications will be reverted in the next build.
+
+However, if this option is checked, subsequent builds will no longer update or overwrite the configuration of the Xcode project.
+
+It should be noted that other changes related to CMake, such as adding C++ source code, will no longer trigger the regeneration of the Xcode project.
+
+### Render Backend
+
+The Render Backend currently supports **METAL**. For more details, refer to the official documentation on [Metal](https://developer.apple.com/cn/metal/).
diff --git a/versions/4.0/en/editor/publish/mac/images/build-open-path-mac.png b/versions/4.0/en/editor/publish/mac/images/build-open-path-mac.png
new file mode 100644
index 0000000000..d9c17541cf
Binary files /dev/null and b/versions/4.0/en/editor/publish/mac/images/build-open-path-mac.png differ
diff --git a/versions/4.0/en/editor/publish/mac/images/build-options-mac.png b/versions/4.0/en/editor/publish/mac/images/build-options-mac.png
new file mode 100644
index 0000000000..751908d1eb
Binary files /dev/null and b/versions/4.0/en/editor/publish/mac/images/build-options-mac.png differ
diff --git a/versions/4.0/en/editor/publish/mac/images/build-panel-mac.png b/versions/4.0/en/editor/publish/mac/images/build-panel-mac.png
new file mode 100644
index 0000000000..85e69f6810
Binary files /dev/null and b/versions/4.0/en/editor/publish/mac/images/build-panel-mac.png differ
diff --git a/versions/4.0/en/editor/publish/mac/images/project-build-menu.png b/versions/4.0/en/editor/publish/mac/images/project-build-menu.png
new file mode 100644
index 0000000000..d5cec7521f
Binary files /dev/null and b/versions/4.0/en/editor/publish/mac/images/project-build-menu.png differ
diff --git a/versions/4.0/en/editor/publish/mac/images/run-mac-800to400.png b/versions/4.0/en/editor/publish/mac/images/run-mac-800to400.png
new file mode 100644
index 0000000000..1c047e2bb6
Binary files /dev/null and b/versions/4.0/en/editor/publish/mac/images/run-mac-800to400.png differ
diff --git a/versions/4.0/en/editor/publish/mac/images/run-mac.png b/versions/4.0/en/editor/publish/mac/images/run-mac.png
new file mode 100644
index 0000000000..831e2e222e
Binary files /dev/null and b/versions/4.0/en/editor/publish/mac/images/run-mac.png differ
diff --git a/versions/4.0/en/editor/publish/mac/images/xcode-folder-mac.png b/versions/4.0/en/editor/publish/mac/images/xcode-folder-mac.png
new file mode 100644
index 0000000000..0afdda5796
Binary files /dev/null and b/versions/4.0/en/editor/publish/mac/images/xcode-folder-mac.png differ
diff --git a/versions/4.0/en/editor/publish/mac/images/xcode-showcase-mac.png b/versions/4.0/en/editor/publish/mac/images/xcode-showcase-mac.png
new file mode 100644
index 0000000000..8f2b05b756
Binary files /dev/null and b/versions/4.0/en/editor/publish/mac/images/xcode-showcase-mac.png differ
diff --git a/versions/4.0/en/editor/publish/mac/index.md b/versions/4.0/en/editor/publish/mac/index.md
new file mode 100644
index 0000000000..d5b60f09a2
--- /dev/null
+++ b/versions/4.0/en/editor/publish/mac/index.md
@@ -0,0 +1,21 @@
+# Publishing macOS Apps
+
+Cocos Creator supports publishing macOS Apps, but it requires at least one macOS device and one Apple developer account.
+
+## Content
+
+- [macOS Publishing Example](./build-example-mac.md)
+- [Build Options - macOS](build-options-mac.md)
+- [JavaScript and iOS/macOS Communication with Reflection](../../../advanced-topics/oc-reflection.md)
+- [JavaScript and Objective-C Communication using JsbBridge](../../../advanced-topics/js-oc-bridge.md)
+- [Features and System Versions](../../../advanced-topics/supported-versions.md)
+
+## Read More
+
+- [Setting up Native Development Environment](../setup-native-development.md)
+- [Build Panel](../build-panel.md)
+- [General Build Panel](../build-options.md)
+- [General Native Build Options](../native-options.md)
+- [Debugging JavaScript on Native Platforms](../debug-jsb.md)
+- [Build Process and FAQ](../build-guide.md)
+- [Native Platform Secondary Development Guide](../../../advanced-topics/native-secondary-development.md)
diff --git a/versions/4.0/en/editor/publish/native-options.md b/versions/4.0/en/editor/publish/native-options.md
new file mode 100644
index 0000000000..f4140f17f0
--- /dev/null
+++ b/versions/4.0/en/editor/publish/native-options.md
@@ -0,0 +1,125 @@
+# Publishing to Native Platforms
+
+To access the **Build** panel, go to the top menu bar and select **Project -> Build**.
+
+Cocos Creator currently supports deployment to native platforms including **Android**, **iOS**, **Mac** and **Windows**. Options for publishing to **iOS**, **Mac**, and **Windows** are only accessible when using their corresponding operating systems.
+
+
+
+## General Native Build Options
+
+
+
+### Encrypt JS
+
+Once enabled, scripts in the project will be encrypted and encapsulated in a .jsc file which can be found in the `assets` folder of the project directory. The original script files will be stored in the `script-backup` folder for debugging purposes and will not be added to the release package.
+
+**JS Encryption Key**: Value will be used as the encryption key for script encryption and will be generated randomly at the project’s creation.
+
+**Zip compression**: If enabled, scripts will be compressed, reducing package size.
+
+
+
+### Native Engine
+
+Users may choose Cocos Creator’s built-in native engine or their custom typescript engine to deploy to native platforms. Click **Edit** to open the **Preferences** panel and enter the custom engine directory under the **[Engine Manager](../preferences/index.md#engine-manager)** tab.
+
+### Job System
+
+Job System is managed by the internal mechanisms and does not require manual modifications. Should such need emerges, please take note:
+
+1. TBB / TaskFlow gives varying performances depending on the execution environment and project specifications, thus should be selected accordingly.
+2. Cocos Creator supports specific versions of TBB / TaskFlow for deployment. For more information, please see below in section **Compatibility**.
+
+### Automatically Execute Next Step
+
+At the bottom right of the **Build** panel, there are three buttons: **Build**, **Make**, and **Run**. By default, you need to click the corresponding button to perform the respective action.
+
+If you want, you can click the **Link** button between two buttons, and it will turn into an **Arrow**. This means that the next step pointed to by the arrow will be automatically executed after the completion of the previous step. Clicking the arrow again will restore it to its previous state.
+
+## Other Build Options
+
+To publish to native platforms, you need to install and configure some necessary environments. For more details, please refer to [Setting up Native Development Environment](setup-native-development.md).
+
+To view the common options for all platforms, please refer to [General Build Options](build-options.md).
+
+To view platform-specific build options, please refer to:
+
+[Build Options - Android](./android/build-options-android.md)
+[Build Options - iOS](./ios/build-options-ios.md)
+[Build Options - Windows](./windows/build-options-windows.md)
+[Build Options - macOS](./mac/build-options-mac.md)
+
+## Start the Build Process
+
+With the builder properties set, click the **Build** button at the bottom right corner of the **Build** panel to start the build process.
+
+While building is in progress, a blue progress bar will be displayed on the Build Tasks page in the Build panel. If the build is successfully done, the progress bar will reach 100% and turn green.
+
+
+
+### Native Project Directory
+
+The native project built by Cocos Creator includes the native common directory, native platform directory, and native project directory. For more details, please refer to the [Native Platform Secondary Development Guide](../../advanced-topics/native-secondary-development.md).
+
+## Compile and Run
+
+In Cocos Creator, you can compile and run your project through the buttons on the **Build** panel. You can also open the project in the corresponding IDE for each platform, such as Xcode for iOS and macOS, Android Studio for Android, or Visual Studio for Windows. This allows you to perform further compilation, running, debugging, and publishing tasks.
+
+### Via Cocos Creator
+
+After the build process is completed, click the **Make** button to start compiling, which will prompt the following message:
+
+`make package YourProjectBuildPath success!`
+
+> **Note**: When building targeting Android platform, it is needed to open the built project in Android Studio, download and install the missing modules and plug-ins as prompted first, then return to Cocos Creator and repeat the operations above.
+
+After the "Make" process is complete, click the **Run** button next to it. Some unfinished compilation may still be ongoing at this point. Please wait patiently or check the progress through the log file. After compilation is done, users will get:
+
+- Mac / Windows: Preview will be executed on desktop.
+- Android: Preview can be executed on a USB-connected device provided the device has USB debugging enabled.
+- iOS: Preview will be executed via a simulator, but it is recommended to execute on a device via Xcode.
+
+### Via IDE
+
+Users can access the build directory with the **folder** button at the lower left corner of each **build task** listed in the **Build** panel. Under `proj` folder in the build directory is a project file that can be opened with IDEs.
+
+Open the project in the IDEs of their respective platform (Xcode for iOS, Android Studio for Android, Visual Studio for Windows, etc.) where users may continue with regular operations such as compilation, preview and release.
+
+- **Android**
+
+ 
+
+- **Windows**
+
+ 
+
+- **iOS** and **Mac**
+
+ 
+
+> **Note**: It is not advisable to do secondary development in IDEs at this point as they will be overridden if the project is rebuilt by Cocos Creator.
+
+To learn more about debugging in IDEs, please refer to [Debugging JavaScript on Native Platforms](debug-jsb.md).
+
+## Considerations
+
+1. When running a debug build on MIUI 10, system may prompt the message "Detected problems with API compatibility." This issue will not emerge with release builds.
+
+2. When deploying a project to iOS without WebView functionalities incorporated, please be sure to disable the WebView module in Cocos Creator at **Project -> Project Settings -> Feature Cropping**. This will noticeably increase the success rate of the project passing iOS App Store’s automatic submission review. If the project requires WebView or related third-party SDKs incorporated to function properly, it is likely to be flagged by the submission review system, in which case it is advisable to contact Apple for an appeal.
+
+3. When building for Android, compilation output of Cocos Creator and Android Studio may differ in the following ways:
+
+ - After the **Make** process is executed in Cocos Creator, the `build` folder will be generated in the release directory, and the .apk package will be generated in the `build\app\publish\` folder of the build directory.
+
+ - After the project is compiled in Android Studio, the .apk package will be generated in the `proj\app\build\outputs\apk` folder.
+
+4. Projects targeting Android and Android Instant are built with the same template. Build output can be found in the `build\android\proj` folder. Regarding this folder, please take note:
+
+ - Code intended for the Android platform should be stored in the `app\src` folder. Third-party libraries should be stored separately in the `app\libs` folder. If these folders do not exist in the build directory, users can create them manually.
+
+ - Code intended for the Android Instant should be stored in the `instantapp\src` folder. Third-party libraries should be stored separately in the `instantapp\libs` folder. If these folders do not exist in the build directory, users can create them manually.
+
+ - Code and libraries shared by Android and Android Instant should be stored in the `src` and `libs` folders respectively. If these folders do not exist in the build directory, users can create them manually.
+
+ When compiling for Android by clicking the **Make** button in the **Build** panel, `assembleRelease/Debug` will be executed by default. Similarly, `instantapp:assembleRelease/Debug` will be executed by default when compiling for Android Instant.
diff --git a/versions/4.0/en/editor/publish/publish-alipay-mini-game.md b/versions/4.0/en/editor/publish/publish-alipay-mini-game.md
new file mode 100644
index 0000000000..f05f3ff8de
--- /dev/null
+++ b/versions/4.0/en/editor/publish/publish-alipay-mini-game.md
@@ -0,0 +1,49 @@
+# Publish to Alipay Mini Game
+
+## Environment Configuration
+
+- Download [Alipay Mini Program Studio](https://render.alipay.com/p/f/fd-jwq8nu2a/pages/home/index.html) to the desktop and install it.
+
+- Download [Alipay](https://mobile.alipay.com/index.htm) and install it on your mobile device.
+
+- The minimum version supported of the Alipay client on Android is 10.3.70 and on iOS is 10.3.70.
+
+## Publishing Process
+
+Use Cocos Creator to open the project to be published, select **Alipay Mini Game** in **Platform** of the **Build** panel, and then click **Build**.
+
+
+
+Please refer to the [build options](build-options.md) documentation for general build options settings. The rules for filling out build options related to Alipay Mini Game are as follows:
+
+| Build Option | Description | Field Name (for command-line publishing) |
+| :-- | :-- | :-- |
+| Start Scene Asset Bundle | When checked, the first scene and its related dependencies will be built into the built-in Asset Bundle - [start-scene](../../asset/bundle.md#the-built-in-asset-bundle) under the release package directory `assets` to improve the speed of loading assets for the start scene. | `startSceneAssetBundle` |
+| Orientation | Optional values include `landscape` and `portrait`. | `deviceOrientation` |
+| Resource Server Address | Used to fill in the address of the remote server where the resource is stored. Developers need to manually upload the remote folder in the release package directory to the filled in resource server address after the build. For details, please refer to the [Uploading Resources to Remote Servers](../../asset/cache-manager.md) documentation | `remoteUrl` |
+| Polyfills | Build polyfills that support some new features, mainly when packaging scripts. Currently only **Async Functions** are supported, more features will be opened later. | `polyfills` |
+
+After the build is finished, click the folder icon button in the bottom left corner of **Build Task**, you can see that the project folder `alipay-mini-game` is created in the `build` directory of the project, which already contains the configuration file `game.json` for the Alipay Mini Game environment.
+
+
+
+Use **Alipay Mini Program Studio** to open the `alipay-mini-game` folder generated by the build to open the Alipay Mini Game project and preview/debug the game content.
+
+
+
+## Resource management for Alipay Mini Game environment
+
+Alipay Mini Game are similar to WeChat Mini Game in that there is a package size limit, and additional resources over **4MB** must be downloaded via network requests. When the package size is too large, configure the **Resource Server Address** option in the **Build** panel to upload the resources to a remote server, please refer to the [Upload Resources to Remote Server](../../asset/cache-manager.md) documentation.
+
+After the game starts, the engine will automatically download resources from the remote server address. Once the resources are downloaded, the engine's cache manager will record the save paths of these resources. This information is used to automatically delete some cached game resources when the cache space is insufficient. Please refer to [Cache Manager](../../asset/cache-manager.md) for more details.
+
+## Restrictions for Alipay Mini Game
+
+The following modules are still not supported:
+
+- WebView
+- VideoPlayer
+
+## Documentation
+
+Since Alipay Mini Game related documentation is currently only available internally, developers can directly contact the members of Alipay integration group if needed.
diff --git a/versions/4.0/en/editor/publish/publish-alipay-mini-game/build.png b/versions/4.0/en/editor/publish/publish-alipay-mini-game/build.png
new file mode 100644
index 0000000000..f049bc5d2b
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-alipay-mini-game/build.png differ
diff --git a/versions/4.0/en/editor/publish/publish-alipay-mini-game/build_option.png b/versions/4.0/en/editor/publish/publish-alipay-mini-game/build_option.png
new file mode 100644
index 0000000000..c8446c9d70
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-alipay-mini-game/build_option.png differ
diff --git a/versions/4.0/en/editor/publish/publish-alipay-mini-game/preview.png b/versions/4.0/en/editor/publish/publish-alipay-mini-game/preview.png
new file mode 100644
index 0000000000..993bd1334b
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-alipay-mini-game/preview.png differ
diff --git a/versions/4.0/en/editor/publish/publish-baidu-mini-game.md b/versions/4.0/en/editor/publish/publish-baidu-mini-game.md
new file mode 100644
index 0000000000..7478bd5531
--- /dev/null
+++ b/versions/4.0/en/editor/publish/publish-baidu-mini-game.md
@@ -0,0 +1,97 @@
+# Publish to Baidu Mini Games
+
+> **Note**:
+> 1. As of November 30, 2022, the publishing and building of Baidu mini-games will no longer be supported as the relevant contract has expired.
+>
+> 2. some platforms only have Chinese documentation available when visiting the platform's website. It may be necessary to use Google Translate in-order to review the documentation.
+
+**Cocos Creator** officially supports the release of games to the **Baidu Mini Games**.
+
+The runtime environment of the Baidu Mini Game is an extension of the **Baidu Smart Mini Program**. This provides a WebGL interface encapsulation based on the mini program environment. This greatly improves the rendering capabilities and performance. However, since these interfaces are encapsulated by the Baidu team, they are not equivalent to the browser environment.
+
+On the engine side, in order to make the developers' workload as easy as possible, our main tasks for developers include the following:
+
+- The engine framework adapts to the Baidu Mini Game API, pure game logic level, developers do not need any additional modifications.
+- The **Cocos Creator** editor provides a fast packaging process, released directly as a **Baidu Mini Game**, and automatically evokes the Baidu DevTools.
+- Automatically load remote assets, cache assets, and cache asset version control.
+
+Please refer to the [Baidu Mini Game Developer Documentation [cn]](https://smartprogram.baidu.com/docs/game/) documentation to review the game submission, the review, and the release process for a Baidu Mini Game.
+
+## Publish Baidu Mini Games with Cocos Creator
+
+### Prerequisites
+
+- Download and install **Baidu DevTools** in the [Baidu DevTools [cn]](https://smartprogram.baidu.com/docs/game/tutorials/howto/dev/) documentation.
+- Download and install the **Baidu App** in the app store of your phone.
+- Log in to the [Baidu Smart Mini Program Platform [cn]](https://smartprogram.baidu.com/developer/index.html) and find **App ID**.
+
+ 
+
+### Release process
+
+1. Select the **Baidu Mini Game** in the **Platform** of the **Build** panel, fill in the **appid**, and then click **Build**.
+
+ 
+
+2. After a build is completed, a `baidu-mini-game` folder will be generated in the project's **build** directory (the name of the folder is based on the **Build Task Name**), which already contains the configuration files `game.json` and `project.swan.json` of the Baidu Mini Games environment.
+
+ 
+
+3. Use the **Baidu DevTools** to open the `baidu-mini-game` folder to preview and debug the game. Please refer to the Baidu DevTools documentation for details. About how to use Baidu DevTools, please refer to [Baidu DevTools Documentation](https://smartprogram.baidu.com/docs/game/tutorials/howto/dev/) for details.
+
+ 
+
+ > **Note**: when previewing and debugging, if a prompt appears stating: `The current version of the developer tool can't publish mini program, please update to the latest devtools`. This means the **appid** filled in the **Build** panel is the **appid** of the **Baidu Smart Mini Program**, not the **appid** of the **Baidu Mini Game**, please re-apply for the **appid** of the **Baidu Mini Game**.
+
+## asset Management for Baidu Mini Game Environment
+
+**Baidu Mini Game** is similar to **WeChat Mini Game**. There are restrictions on the package size. Assets more than **4MB** must be downloaded via a network request.
+
+It is recommended to only save script files in the mini-game packages, while other assets are uploaded to the remote server, and downloaded from the remote server as needed. The download, cache, and version management of remote assets, **Cocos Creator** has already done it for you. The specific implementation logic is similar to the WeChat Mini Game. Please refer to the [asset Management for WeChat Mini Game Environment](./publish-wechatgame.md) documentation for details.
+
+When the **MD5 Cache** feature of the engine is enabled, the URL of the file will change as the content of the file changes. When the game releases a new version, the assets of the old version will naturally become invalid in the cache, and only the new assets can be requested from the server, which achieves the effect of version control.
+
+Specifically, developers need to do the following:
+
+1. When building, check the **MD5 Cache** in the **Build** panel.
+2. Set **Remote server address** in the **Build** panel and then click **Build**.
+3. After the build is complete, upload the `build/baidu-mini-game/res` folder to the server.
+4. Delete the `res` folder under the local release package directory.
+
+> **Note**: when Baidu loads the assets on the remote server on the physical device, it only supports access via HTTPS, so the asset file must be placed on HTTPS, otherwise the loading of the asset will fail.
+> **Note**: if the cache asset exceeds the environment limit of Baidu, you need to manually clear the asset. Use the `remoteDownloader.cleanAllCaches()` and `remoteDownloader.cleanOldCaches()` interfaces to clear the cache in Baidu mini game. The former will clear all cache assets in the cache directory, please use it with caution. The latter will clear the cache assets that are not used in the current application in the cache directory.
+
+## Baidu Mini Game Subpackage Loading
+
+The subpackage loading method of **Baidu Mini Game** is similar to WeChat, with the following package restrictions:
+
+- The size of all subpackages of the entire Mini Game can not exceed **8MB**.
+- The size of a single subpackage/main package can not exceed **4MB**.
+
+Please refer to the [Mini Game Subpackage](subpackage.md) documentation for details.
+
+## Platform SDK Access
+
+In addition to pure game content, the **Baidu Mini Game** environment also provides a very powerful native SDK interface. These interfaces only exist in **Baidu Mini Game** environment, equivalent to the third-party SDK interface of other platforms. The porting of such SDK interfaces still needs to be handled by developers at this stage. Here are some of the powerful SDK capabilities offered by **Baidu Mini Game**:
+
+1. User interface: login, authorization, user information, etc.
+2. Baidu cashier payment
+3. Forwarding information
+4. File upload and download
+5. Other: images, locations, ads, device information, etc.
+
+## Baidu Mini Games known issues
+
+Currently, the adaptation work of Baidu Mini Game is not completely finished, and the following components are not supported for the time being:
+
+- VideoPlayer
+- WebView
+
+If needed, you can directly call Baidu's [API [cn]](https://smartprogram.baidu.com/docs/game/api/openApi/authorize/) as needed.
+
+## Reference documentation
+
+- [Baidu Mini Game Registration Guide [cn]](https://smartprogram.baidu.com/docs/game/)
+- [Baidu DevTools documentation [cn]](https://smartprogram.baidu.com/docs/game/tutorials/howto/dev/)
+- [Baidu Mini Game API documentation [cn]](https://smartprogram.baidu.com/docs/game/api/openApi/authorize/)
+- [Baidu Mini Game Subpackage Loading [cn]](https://smartprogram.baidu.com/docs/game/tutorials/subpackages/sub/)
diff --git a/versions/4.0/en/editor/publish/publish-baidugame/appid.png b/versions/4.0/en/editor/publish/publish-baidugame/appid.png
new file mode 100644
index 0000000000..513e32cf6f
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-baidugame/appid.png differ
diff --git a/versions/4.0/en/editor/publish/publish-baidugame/build.png b/versions/4.0/en/editor/publish/publish-baidugame/build.png
new file mode 100644
index 0000000000..027d437075
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-baidugame/build.png differ
diff --git a/versions/4.0/en/editor/publish/publish-baidugame/game-json.png b/versions/4.0/en/editor/publish/publish-baidugame/game-json.png
new file mode 100644
index 0000000000..8581558bb6
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-baidugame/game-json.png differ
diff --git a/versions/4.0/en/editor/publish/publish-baidugame/maintest-build.png b/versions/4.0/en/editor/publish/publish-baidugame/maintest-build.png
new file mode 100644
index 0000000000..8f54aabd5a
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-baidugame/maintest-build.png differ
diff --git a/versions/4.0/en/editor/publish/publish-baidugame/open-data-project-build.png b/versions/4.0/en/editor/publish/publish-baidugame/open-data-project-build.png
new file mode 100644
index 0000000000..732fc1895c
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-baidugame/open-data-project-build.png differ
diff --git a/versions/4.0/en/editor/publish/publish-baidugame/open-data-project-package.png b/versions/4.0/en/editor/publish/publish-baidugame/open-data-project-package.png
new file mode 100644
index 0000000000..1a8d821791
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-baidugame/open-data-project-package.png differ
diff --git a/versions/4.0/en/editor/publish/publish-baidugame/open-data-project-preview.png b/versions/4.0/en/editor/publish/publish-baidugame/open-data-project-preview.png
new file mode 100644
index 0000000000..c5d8590dba
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-baidugame/open-data-project-preview.png differ
diff --git a/versions/4.0/en/editor/publish/publish-baidugame/package.png b/versions/4.0/en/editor/publish/publish-baidugame/package.png
new file mode 100644
index 0000000000..b1055fe429
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-baidugame/package.png differ
diff --git a/versions/4.0/en/editor/publish/publish-baidugame/preview.png b/versions/4.0/en/editor/publish/publish-baidugame/preview.png
new file mode 100644
index 0000000000..89a6a30cd7
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-baidugame/preview.png differ
diff --git a/versions/4.0/en/editor/publish/publish-baidugame/subcontext.png b/versions/4.0/en/editor/publish/publish-baidugame/subcontext.png
new file mode 100644
index 0000000000..0c2b1bc11b
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-baidugame/subcontext.png differ
diff --git a/versions/4.0/en/editor/publish/publish-bytedance-mini-game.md b/versions/4.0/en/editor/publish/publish-bytedance-mini-game.md
new file mode 100644
index 0000000000..7168163675
--- /dev/null
+++ b/versions/4.0/en/editor/publish/publish-bytedance-mini-game.md
@@ -0,0 +1,134 @@
+# Publish to Douyin Mini Games
+
+> **Note**: some platforms only have Chinese documentation available when visiting the platform's website. It may be necessary to use Google Translate in-order to review the documentation.
+
+**Douyin Mini Games** are developed based on Douyin full products, which do not require users to download. This is a brand-new game type that can be played on tap.
+
+The game submission, review and release process of a mini-game needs to comply with the requirements and standard processes of the Douyin official specification. For specific information, please refer to the links at the end of this document.
+
+## Preparation
+
+1. Download the [Douyin DevTools [cn]](https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/developer-instrument/developer-instrument-update-and-download) and install it..
+
+## Reference Links
+
+- [ByteDance Mini Game Integration Guide](https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/guide/minigame/introduction/)
+- [ByteDance Mini Game Developer Documentation](https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/guide/bytedance-mini-game)
+- [ByteDance Mini Game API Documentation](https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/api/overview)
+- [ByteDance Developer Tools Download](https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/developer-instrument/developer-instrument-update-and-download)
+- [ByteDance Developer Tools Documentation](https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/dev-tools/developer-instrument/development-assistance/mini-app-developer-instrument)
+
+2. Refer to the [Douyin Mini Game Access Guide [cn]](https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/guide/minigame/introduction) to register, login and apply for mini games on the [Douyin Developer Platform [cn]](https://microapp.bytedance.com).
+
+3. After the application is approved, find the appid in **Development Management -> Development Settings** of the developer platform.
+
+ 
+
+## Publishing Process
+
+1. Use Cocos Creator to open the project to be published, open the **Build** panel from **Menu Bar -> Project**, select **Douyin Mini Game** in **Platform**, fill in the **appid**, and click **Build**.
+
+ 
+
+ Click on the **Douyin Mini Game** below to expand the build options configuration of Douyin Mini Game:
+
+ 
+
+ For the general build options settings, please refer to [General Build Options](build-options.md) for details. The Douyin Mini Games specific build options are shown below, please refer to the **Build Options** section below for the filling rules.
+
+2. After the relevant parameters of the **Build** panel are set, click **Build** button. When the build is complete, click the folder icon button below the corresponding build task to open the build release path, notice that a directory `bytedance-mini-game` (with the same name as the Build Task Name) is generated in the default release path `build` directory, which already contains the configuration files `game.json` and `project.config.json` of the ByteDance Mini Games environment.
+
+ 
+
+3. Use the **Douyin DevTools** to open the `bytedance-mini-game` folder generated by the build, open the Douyin game project and preview the debugging game content. Please refer to the [Introduction to Douyin DevTools [cn]](https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/developer-instrument/development-assistance/mini-app-developer-instrument) for details on how to use the developer tools.
+
+ 
+
+### Build Options
+
+| Options | Description | Field name (for publishing with command line) |
+| :-- | :-- | :-- |
+| **Start Scene Asset Bundle** | If set, the start scene and its related dependent resources are built into the built-in Asset Bundle — [start-scene](../../asset/bundle.md#%E5%86%85%E7%BD%AE-asset-bundle) to speed up the resource loading of the start scene. | `startSceneAssetBundle` |
+| **Orientation** | Device orientation, it will be written to `game.json` file. | `orientation` |
+| **AppID** | The appid of the Douyin Mini Games, it will be written to `project.config.json` file. | `appid` |
+| **Remote server address** | This option is used to fill in the address of the remote server where the resources are stored. Developers need to manually upload the `remote` folder from the release package directory to the filled resource server after build. | `remoteServerAddress` |
+| **Open data context root** | For access to Open Data Context, please refer to the [Open Data Context](./build-open-data-context.md) documentation for details. | `buildOpenDataContextTemplate` |
+| **Native PhysX Physics System**| This option is used to set whether to use the PhysX physics system, please see the **Native Physics** section below for more details. | - |
+
+## Native Physics
+
+The Douyin platform has always been committed to providing developers with the more powerful performance and basic capabilities. TikTok will provide PhysX native physics interfaces for Douyin mini games in v16.3 and later versions.
+
+Cocos Creator and the Douyin platform have conducted in-depth collaboration, with the experimental feature in **v3.2** to support the use of PhysX physics capabilities provided by the Douyin platform in Douyin Mini Games, optimizing the performance of physics calculations, and having a nearly 100% performance improvement compared to Bullet physics:
+
+
+
+The prerequisite for using native physics is to set **Physics System** to **PhysX** in **Project -> Project Settings -> Feature Cropping** in the Creator main menu bar. Then open the **Build** panel with the **Platform** option set to **Douyin Mini Game**, and see the native physics related configuration options as follows:
+
+
+
+| Options | Description | Field name (for publishing with command line) |
+| :-- | :-- | :-- |
+| **Not to pack the built-in PhysX library**| If checked, the built-in PhysX library files will not be packaged when building, which helps to reduce the package size, but does not support PhysX running on some application platforms of Douyin, such as TikTok (iOS version) and DevTools. If unchecked, Creator supports PhysX running on the full application platform of Douyin. | `physX.notPackPhysXLibs` |
+| **Multithreading mode**| If checked, multithreading mode is enabled. | `physX.multiThread` |
+| **Number of sub-threads** | The number of sub-threads when multithreading mode is enabled. | `physX.subThreadCount` |
+| **Tolerance of errors** | If this option is enabled, the precision will be lower when using multithreading than single threading. | `physX.epsilon` |
+
+## Subpackage Loading
+
+The Douyin Mini Game requires a specific version to support the subpackage feature, and the version requirements for the Douyin product are as follows:
+
+| Product | Android | iOS |
+| :-- | :--- | :--- |
+| TikTok | v13.6.0 | v13.7.0 |
+| TouTiao | v7.9.9 | v7.9.8 |
+
+For Douyin DevTools, please use **v2.0.6** or above, but below **v3.0.0**. After updating the DevTools, don't forget to modify the **Debug Base library** to **1.88.0** or above in the Douyin DevTools.
+
+> **Note**: if the product version does not support subpackage loading, the engine will load the subpackage as a normal asset bundle.
+
+### Ordinary game packages
+
+In the scenario of not configuring sub-packaging, the total size of code packages allowed to be uploaded for each mini-game is capped at 20MB.
+
+### Packages after packetization
+
+For games with subpackaging configured, the default limit is:
+
+- The size of the whole game package (the entire directory of the game package) should not exceed 20MB.
+- The size of a single main package should not exceed 4MB.
+- The size of a single sub-package should not exceed 20MB.
+
+For details, please refer to the [Douyin Subpackage Loading Official Documentation [cn]](https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/framework/subpackages/introduction/)
+
+## Asset Management for Douyin Mini Game Environment
+
+In a **Douyin Mini Game** environment, asset management is the most special part. It differs from the browser in the following four points:
+
+1. The size of the **Douyin Mini Game** package cannot exceed **4MB**, including all the code and assets. Additional assets must be downloaded via web request.
+
+2. For files downloaded from a remote server, the **Douyin Mini Game** environment does not have the browser's caching and outdated update mechanism.
+
+3. For the assets in the **Douyin Mini Game** package, they are not loaded on demand in the mini game environment, but rather all the assets in the package are loaded at once, and then the game page is launched.
+
+4. You cannot download script files from a remote server.
+
+This brings up two key issues, home page loading speed and remote asset caching and version management. For the home page loading speed, we recommend that developers only save the script file in the **Douyin Mini Game** package, and all other assets are downloaded from the remote server. As for downloading, caching and version management of remote assets, Cocos Creator has done the job for developers.
+
+Specifically, developers need to do the following:
+
+1. When building, enable the **MD5 Cache** in the **Build** config panel.
+2. Set the **Remote service address**, and then click **Build**.
+3. When the build is complete, upload the **res** folder in the mini game release package to the server.
+4. Delete the **res** folder inside the local release package.
+5. For the test phase, you may not be able to deploy to the official server, you need to use the local server to test, then open the details page in the WeChat DevTools, check the `Does not verify valid domain names, web-view (business domain names), TLS versions and HTTPS certificates` option in the **Local Settings**.
+
+## Reference documentation
+
+> **Note**: some platforms only have Chinese documentation available when visiting the platforms website. It may be necessary to use Google Translate in-order to review the documentation.
+
+- [ByteDance Mini Game Integration Guide](https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/guide/minigame/introduction/)
+- [ByteDance Mini Game Developer Documentation](https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/guide/bytedance-mini-game)
+- [ByteDance Mini Game API Documentation](https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/api/overview)
+- [ByteDance Developer Tools Download](https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/developer-instrument/developer-instrument-update-and-download)
+- [ByteDance Developer Tools Documentation](https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/dev-tools/developer-instrument/development-assistance/mini-app-developer-instrument)
diff --git a/versions/4.0/en/editor/publish/publish-bytedance-mini-game/appid.png b/versions/4.0/en/editor/publish/publish-bytedance-mini-game/appid.png
new file mode 100644
index 0000000000..fce04c9524
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-bytedance-mini-game/appid.png differ
diff --git a/versions/4.0/en/editor/publish/publish-bytedance-mini-game/build-options.png b/versions/4.0/en/editor/publish/publish-bytedance-mini-game/build-options.png
new file mode 100644
index 0000000000..10449da610
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-bytedance-mini-game/build-options.png differ
diff --git a/versions/4.0/en/editor/publish/publish-bytedance-mini-game/build.png b/versions/4.0/en/editor/publish/publish-bytedance-mini-game/build.png
new file mode 100644
index 0000000000..4076798011
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-bytedance-mini-game/build.png differ
diff --git a/versions/4.0/en/editor/publish/publish-bytedance-mini-game/package.png b/versions/4.0/en/editor/publish/publish-bytedance-mini-game/package.png
new file mode 100644
index 0000000000..20c2f02073
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-bytedance-mini-game/package.png differ
diff --git a/versions/4.0/en/editor/publish/publish-bytedance-mini-game/performance.png b/versions/4.0/en/editor/publish/publish-bytedance-mini-game/performance.png
new file mode 100644
index 0000000000..19bcbba796
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-bytedance-mini-game/performance.png differ
diff --git a/versions/4.0/en/editor/publish/publish-bytedance-mini-game/physx-options.png b/versions/4.0/en/editor/publish/publish-bytedance-mini-game/physx-options.png
new file mode 100644
index 0000000000..8e1770e9cf
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-bytedance-mini-game/physx-options.png differ
diff --git a/versions/4.0/en/editor/publish/publish-bytedance-mini-game/tool.jpg b/versions/4.0/en/editor/publish/publish-bytedance-mini-game/tool.jpg
new file mode 100644
index 0000000000..021c50c3f4
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-bytedance-mini-game/tool.jpg differ
diff --git a/versions/4.0/en/editor/publish/publish-fb-instant-games.md b/versions/4.0/en/editor/publish/publish-fb-instant-games.md
new file mode 100644
index 0000000000..426ae6a349
--- /dev/null
+++ b/versions/4.0/en/editor/publish/publish-fb-instant-games.md
@@ -0,0 +1,161 @@
+# Publish to Facebook Instant Games
+
+The essential difference between Facebook Instant Games and WeChat mini-games is that Facebook Instant Games runs on a pure HTML5 environment. So it can run not only on cell phones but also on desktop browsers, making development and debugging much easier.
+
+**Currently Cocos Creator does the work for users including:**
+
+- Integration with Facebook Instant Games SDK and automatic initialization, allowing users to call the relevant APIs directly
+- One-click packaging process in the Cocos Creator build panel to package games directly to Facebook Instant Games specifications
+
+**What the user needs to do:**
+
+- Call the Facebook Instant Games SDK to access platform-related features
+- Upload the packaged version of Cocos Creator to Facebook
+
+## Publishing process
+
+- Build the game using Cocos Creator
+- Upload to Facebook backend
+- Test the game
+- Share your game in Facebook
+
+## Build the game with Cocos Creator
+
+1. Open the project to be published using Cocos Creator and open the **Build** panel from the **Menu bar -> Projects**. Select **Facebook Instant Games** from the **Platform** in the **Build** panel.
+
+ 
+
+ Please refer to [Build Options](build-options.md) for general build options, Facebook Instant Games-specific build options are listed below, please refer to the **Build Options** section below for more information.
+
+ 
+
+2. Once the build options in the **Build** panel are set, click **Build** button.
+ When the build is complete, click the folder icon button in the bottom left corner of **build task** to open the project release package, you can see that the `fb-instant-games` (whichever is the name of the specific build task) folder has been created in the default release path `build` directory, which already contains the zip file of the Facebook Instant Games environment `fb -instant-games.zip`.
+
+ 
+
+### Build options
+
+Build options are common across platforms, please refer to [Build Options](build-options.md) for details. Next, let's look at the build options specific to the Facebook Instant Games platform.
+
+| Build options | Description | Field name (for command line publishing) |
+| :--- | :--- | :--- |
+| Device orientation | Options include **Landscape**, **Portrait** | `orientation` |
+| vConsole | Insert the vConsole debugging plugin. vConsole is similar to a mini version of DevTools and is used to assist in debugging. | `embedWebDebugger` |
+
+### Upload to Facebook
+
+Create a new app in Facebook backend, add **small games** in **Add products**, set the game category, and save the changes. (For details, please refer to [Set up the app](https://developers.facebook.com/docs/games/instant-games/getting-started/quickstart?locale=zh_CN#app-setup))
+
+Click the **Small Games -> Web Hosting** tab on the left side of the app panel, click **Upload Versions**, and upload the `.zip` file from the `fb-instant-games` directory to the Facebook hosting service.
+
+
+
+When the version status changes to "Standby", click the "★" button to push the build to the "Production" environment.
+
+
+
+### III. Testing the game
+
+#### Enable the https-enabled web server locally
+
+- First, open a command line window, go to the `fb-instant-games` directory, and install the http-server package via npm: ###
+
+ ```bash
+ cd fb-instant-games
+ npm install -g http-server
+ ```
+
+- Next, create the private key and certificate via openssl.
+
+ ```bash
+ openssl genrsa 2048 > key.pem
+ openssl req -x509 -days 1000 -new -key key.pem -out cert.pem
+ ```
+
+- When the private key and certificate are ready, the Web service can be started locally via SSL: the
+
+ ```bash
+ http-server --ssl -c-1 -p 8080 -a 127.0.0.1
+ ```
+
+- Open [https://localhost:8080](https://localhost:8080) with a browser and skip the security warning displayed by the browser. This step is only for the browser to whitelist the above private key and certificate. If the private key and certificate are subsequently regenerated, you need to open it again to confirm it once. It is not yet possible to preview the game directly at this step, because previewing the game requires initializing the Facebook Instant Games SDK, which needs to be done in the following way.
+
+#### Preview games under Facebook domain
+
+To use all the features of the Facebook Instant Games SDK, you need to open [https://www.facebook.com/embed/instantgames/YOUR_GAME_ID/player?game_url=https:// localhost:8080](https://www.facebook.com/embed/instantgames/YOUR_GAME_ID/player?game_url=https://localhost:8080) and be careful to replace the link `YOUR_ GAME_ID` in the link and replace it with the application number you created in the Facebook backend.
+
+Then you can see the game running successfully.
+
+
+
+### IV. Share your game in Facebook
+
+Click the **Games** tab in the application panel, select **Details**, and pull down the **Details** page to the bottom to see the section shown below, select **Share Game** to share the game directly to the Facebook dynamic message.
+
+
+
+For details, please refer to [Test, Publish and Share Trivia Games](https://developers.facebook.com/docs/games/instant-games/test-publish-share?locale=zh_CN).
+
+> **NOTE**: There are several restrictions on Facebook hosting, the most important of which are.
+>
+> 1. server-side logic (e.g. php) is not supported
+> 2. no more than 500 files per application upload
+
+## Customizing Instant Games
+
+Developers can create the [build-templates/fb-instant-games](custom-project-build-template.md) directory under the Creator project folder to customize them according to their needs, and then copy the published files into that directory to customize them: ##
+
+
+
+- `fbapp-config.json`: this is the configuration for the whole package, go to [official introduction](https://developers.facebook.com/docs/games/instant-games/bundle-config)
+- `index.html`: Here you can modify the introduced Facebook Instant Games SDK version
+- `index.js`: Here you can modify the SDK initialization and progress bar
+
+## Creating DOM Elements in the Game
+Please refer to the example code below to create Dom elements in a Facebook Instant Game and display them on the game screen.
+
+```javascript
+var buttonDiv = document.createElement("div");
+var button = document.createElement("button");
+
+const frameSize = screen.windowSize;
+const imageWidth = 195, imageHeight = 57;
+
+button.style.position = "absolute";
+button.style.left = `${frameSize.width / 2 - imageWidth / 2}px`;
+button.style.top = `${frameSize.height / 2 - imageHeight / 2}px`;
+
+//load image from resources bundle
+resources.load("btn_play", Texture2D, (error, res)=>{
+ if (!error) {
+ button.style.backgroundImage = `url(${res.nativeUrl})`;
+ button.style.backgroundRepeat = "no-repeat";
+ button.style.backgroundPosition = "center";
+ button.style.width = res.width + "px";
+ button.style.height = res.height + "px";
+ button.style.backgroundColor = "transparent";
+ button.style.borderColor = "transparent";
+ button.onclick = (()=>{
+ //DO SOMETHING
+ });
+ buttonDiv.appendChild(button);
+ var body = document.body;
+ body.insertBefore(buttonDiv, body.lastChild);
+ }
+});
+```
+
+Result when running:
+
+
+
+## SDK description
+
+The Creator is integrated with the Instant Games SDK provided by Facebook and is automatically initialized when the game is loaded (`initializeAsync` and `startGameAsync`). Users can access it directly through the `FBInstant` module, see [Instant Games SDK](https://developers.facebook.com/docs/games/instant-games/sdk) for instructions.
+In addition, Facebook also provides a Facebook SDK for JavaScript to access Facebook's social features, which can be accessed through the `FB` module. However, this SDK Creator is not integrated and needs to be introduced manually by the user, see [official documentation](https://developers.facebook.com/docs/javascript).
+
+## Reference links
+
+- [Facebook Backend](https://developers.facebook.com/)
+- [Facebook Instant Games documentation](https://developers.facebook.com/docs/games/instant-games)
diff --git a/versions/4.0/en/editor/publish/publish-fb-instant-games/build-options.png b/versions/4.0/en/editor/publish/publish-fb-instant-games/build-options.png
new file mode 100644
index 0000000000..7f7a9fabf8
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-fb-instant-games/build-options.png differ
diff --git a/versions/4.0/en/editor/publish/publish-fb-instant-games/build.png b/versions/4.0/en/editor/publish/publish-fb-instant-games/build.png
new file mode 100644
index 0000000000..7a6cc23c07
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-fb-instant-games/build.png differ
diff --git a/versions/4.0/en/editor/publish/publish-fb-instant-games/file.png b/versions/4.0/en/editor/publish/publish-fb-instant-games/file.png
new file mode 100644
index 0000000000..81880f764a
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-fb-instant-games/file.png differ
diff --git a/versions/4.0/en/editor/publish/publish-fb-instant-games/game.png b/versions/4.0/en/editor/publish/publish-fb-instant-games/game.png
new file mode 100644
index 0000000000..ed6def3ea7
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-fb-instant-games/game.png differ
diff --git a/versions/4.0/en/editor/publish/publish-fb-instant-games/package.png b/versions/4.0/en/editor/publish/publish-fb-instant-games/package.png
new file mode 100644
index 0000000000..ffd5762aea
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-fb-instant-games/package.png differ
diff --git a/versions/4.0/en/editor/publish/publish-fb-instant-games/push.png b/versions/4.0/en/editor/publish/publish-fb-instant-games/push.png
new file mode 100644
index 0000000000..1af0b924dd
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-fb-instant-games/push.png differ
diff --git a/versions/4.0/en/editor/publish/publish-fb-instant-games/share.png b/versions/4.0/en/editor/publish/publish-fb-instant-games/share.png
new file mode 100644
index 0000000000..682b8f73b2
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-fb-instant-games/share.png differ
diff --git a/versions/4.0/en/editor/publish/publish-fb-instant-games/upload.png b/versions/4.0/en/editor/publish/publish-fb-instant-games/upload.png
new file mode 100644
index 0000000000..9b5ac56d75
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-fb-instant-games/upload.png differ
diff --git a/versions/4.0/en/editor/publish/publish-honor-mini-game.md b/versions/4.0/en/editor/publish/publish-honor-mini-game.md
new file mode 100644
index 0000000000..246fd760be
--- /dev/null
+++ b/versions/4.0/en/editor/publish/publish-honor-mini-game.md
@@ -0,0 +1,92 @@
+# Publish to Honor Mini Games
+
+Starting from Cocos Creator v3.8.6, games can be published to **Honor Mini Games**.
+
+## Preparation Work
+
+- Refer [Honor Mini Games Integration Guide](https://developer.honor.com/cn/docs/game_center/guides/miniGame/miniGameGuidelines), complete the developer registration process and app creation on the Honor Open Platform.
+
+- Download [Honor Quick Game APP](https://developer.honor.com/cn/docs/game_center/guides/miniGame/miniGameGuidelines#开发+调试指引) and install it on your honor mobile device.
+
+## Build Options
+
+Open the project you want to publish with Cocos Creator, and from the Menu Bar -> Project, open the Build and Publish panel, select Honor Mini Games as the Publish Platform.
+
+
+
+General build options can be set according to [General Build Options](build-options.md). The specific build options for Honor Mini Games are as follows:
+
+
+
+| Name | Optional | Description | Field name |
+| :-- | :-- | :-- | :-- |
+| **Game Package Name** | required | such as `com.example.demo` | `package` |
+| **Desktop Icon** | required | Click the **search icon** button at the back of the input box to select the icon you want. When building, the **Desktop Icon** will be built into the Honor Mini Game project. It is suggested to use `PNG` images for the **Desktop Icon**. | `icon` |
+| **Game Version Name** | required | **Game Version Name** is the real version, such as: **1.0.0**. | `versionName` |
+| **Game Version Number** | required | **Game Version Number** is different from the **Game Version Name**, and the **Game Version Number** is mainly used to distinguish the version update. Each time when you submit audit, the game version number is at least 1 higher than the value of the last submitted audit. It must not be equal to or less than the value of the last submitted audit, and it is recommended that the **Game Version Number** be recursively incremented by 1 each time when the audit is submitted. | `versionCode` |
+| **Supported Minimum Platform Version Number** | required | For compatibility checks to prevent incompatibilities from arising when running on lower version platforms after going live. | `minPlatformVersion` |
+| **Screen orientation** | - | Device direction, it will be written in `manifest.json`.| `orientation` |
+| **Use debug keystore** | - | true | When you check **Use Debug Keystore**, it means that the rpk package built with the certificate that comes with Creator is used by default, and it is only used for **debugging**. when the rpk package is to be used to submit an audit, do not check the **Use Debug Keystore** to build it.| `useDebugKey` |
+| **Key certification path** | - | - | The key store certificate, the quick game on the Huawei App Market, must be signed with the release version certificate, and the certificate fingerprint must be configured in the background of the Huawei Developers Alliance. For details, please refer to the following **Generate Signature File** | `privatePemPath`, `certificatePemPath` |
+
+### Generate signature file
+
+If you don't check the **Keystore**, you need to configure the signature files **certificate.pem path** and **private.pem path**, where you build a rpk package that you can **publish directly**. The developer can configure two signature files by using the **search icon** button to the right of the input box.
+
+There are two ways to generate a signature files:
+
+- Generated by the **New** button after the **certificate.pem path** in the **Build** panel.
+
+- Generated by the command line.
+
+ The developer needs to generate the signature file **private.pem**, **certificate.pem** through tools such as **openssl**.
+
+ ```bash
+ # Generate a signature file with the openssl command tool
+ openssl req -newkey rsa:2048 -nodes -keyout private.pem -x509 -days 3650 -out certificate.pem
+ ```
+
+ > **Note**: **openssl** can be used directly in the terminal in Linux or Mac environment, and in the Windows environment you need to install `openssl` and configure system environment variables. Restart Creator after the configuration is complete.
+
+### Building
+
+After setting the build options in the **Build and Publish** panel, click the **Build and Generate** button.
+
+After completion, click the folder icon button at the bottom left of **Build Task** to open the project's published package. You can see that a `honor-mini-game` folder (subject to the specific build task name) is generated in the default publish path build directory. This folder is the exported Honor Quick Game project directory and rpk, and the rpk package is in the `build/honor-mini-game/dist` directory.
+
+
+
+If you need to modify the generated rpk package, after making changes, click the **Generate** button at the bottom right of **Build Task** to regenerate the rpk package without rebuilding.
+
+## Run the rpk
+
+There are two ways to run rpk on your phone:
+
+- **Method One**
+
+ Click the **Run** button in the **Build and Publish** panel and wait for the QR code interface to generate:
+
+ 
+
+ Then open the **Quick App** that was installed before on your Android device. Click the **Scan code install** button to scan the QR Code to open the **rpk**.
+
+ 
+
+- **Method Two**
+
+ Copy the generated mini game **rpk** file (located in the `dist` directory) to the internal storage directory of the mobile phone.
+
+ Open the **Quick App** that has been installed before on the Android device, click **Local Install**, then find the **rpk** file from the internal storage directory of your mobile phone and select **Open**.
+
+ 
+
+## Honor Mini Game Environment Resource Management
+
+Similar to WeChat Mini Games, Honor Mini Games also have package size limitations. The main package size limit for Honor Mini Games is **5MB**, and any content exceeding this limit must be downloaded via network requests. When the package size is too large, you can configure the **Remote Server Address** option in the **Build and Publish** panel to upload low-priority resources to a remote server. For more details, please refer to [Uploading Resources to Remote Server](../../asset/cache-manager.md).
+
+After the game starts, the engine will automatically download resources from the remote server address. Once the resources are downloaded, the engine's cache manager will record the save paths of these resources. This information is used to automatically delete some cached game resources when the cache space is insufficient. Please refer to [Cache Manager](../../asset/cache-manager.md) for more details.
+
+## Reference documentation
+
+- [Honor Mini Games Integration Guide](https://developer.honor.com/cn/docs/game_center/guides/miniGame/miniGameGuidelines)
+- [Honor Quick Game APP](https://developer.honor.com/cn/docs/game_center/guides/miniGame/miniGameGuidelines#开发+调试指引)
diff --git a/versions/4.0/en/editor/publish/publish-honor-mini-game/build-option.png b/versions/4.0/en/editor/publish/publish-honor-mini-game/build-option.png
new file mode 100644
index 0000000000..b9fbb3da37
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-honor-mini-game/build-option.png differ
diff --git a/versions/4.0/en/editor/publish/publish-honor-mini-game/build.png b/versions/4.0/en/editor/publish/publish-honor-mini-game/build.png
new file mode 100644
index 0000000000..29314f9428
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-honor-mini-game/build.png differ
diff --git a/versions/4.0/en/editor/publish/publish-honor-mini-game/honor-instant_native_install2.png b/versions/4.0/en/editor/publish/publish-honor-mini-game/honor-instant_native_install2.png
new file mode 100644
index 0000000000..d36a540955
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-honor-mini-game/honor-instant_native_install2.png differ
diff --git a/versions/4.0/en/editor/publish/publish-honor-mini-game/honor-instant_scan_install1.png b/versions/4.0/en/editor/publish/publish-honor-mini-game/honor-instant_scan_install1.png
new file mode 100644
index 0000000000..138de3dd5e
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-honor-mini-game/honor-instant_scan_install1.png differ
diff --git a/versions/4.0/en/editor/publish/publish-honor-mini-game/package.png b/versions/4.0/en/editor/publish/publish-honor-mini-game/package.png
new file mode 100644
index 0000000000..52b7f9d16e
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-honor-mini-game/package.png differ
diff --git a/versions/4.0/en/editor/publish/publish-honor-mini-game/qr_code.png b/versions/4.0/en/editor/publish/publish-honor-mini-game/qr_code.png
new file mode 100644
index 0000000000..c8e9af64bc
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-honor-mini-game/qr_code.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-agc.md b/versions/4.0/en/editor/publish/publish-huawei-agc.md
new file mode 100644
index 0000000000..64e8823d44
--- /dev/null
+++ b/versions/4.0/en/editor/publish/publish-huawei-agc.md
@@ -0,0 +1,92 @@
+# Publish to HUAWEI AppGallery Connect
+
+Cocos Creator supports publishing games to HUAWEI AppGallery Connect, which helps developers access to HUAWEI AppGallery.
+
+## Preparation
+
+- Login to the [AppGallery Connect](https://developer.huawei.com/consumer/en/service/josp/agc/index.html), it is necessary to complete the [Developer Registration](https://developer.huawei.com/consumer/en/doc/start/10104) before [creating an app](https://developer.huawei.com/consumer/en/doc/distribution/app/agc-create_app). When creating an app, select **APK** for the **Package type**.
+
+ 
+
+- Access the required HUAWEI AppGallery Connect related services via the Cocos Service panel. Currently the SDK only supports the Android platform, please refer to the [HUAWEI HMS Core](https://service.cocos.com/document/en/sdkhub-plugins/sdkhub-hms.html) documentation for the detailed operation steps.
+
+## Publishing Process
+
+Use Cocos Creator to open the project that needs to be published. Open the **Build** panel from the **Menu bar -> Project**, select **HUAWEI AppGallery Connect** in the **Platform** dropdown of the **Build** panel.
+
+
+
+For the settings of the general options, please refer to the [Build Options](build-options.md) documentation.
+
+- **agconnect-services Config**: used to configure Huawei parameter file `agconnect-services.json`. Please refer to the [Configs HUAWEI Parameter File](https://service.cocos.com/document/en/sdkhub-plugins/sdkhub-hms.html#configs-huawei-config-file) for the specific configuration method.
+
+- **Cocos SDKHub Config Set**: this option is used to help the game quickly integrate the channel SDK. Please select the SDKHub service that you have previously enabled in the Cocos Services panel.
+
+ 
+
+### Build and Compile
+
+After the relevant options of the **Build** panel are set, click **Build**.
+After the build is complete, click the folder icon button in the bottom left corner of the **Build Task** to open the release package directory. You can see that the `huawei-agc` folder is generated under the default release path `build` directory, which has been automatically integrated with HUAWEI AppGallery Connect related services.
+
+Then click **Make**, or use [Android Studio](native-options.md#make-and-run) to open the project to compile. After compiling, HUAWEI AppGallery Connect APK will be generated in the release package directory.
+
+
+
+### Upload the APK to AppGallery Connect
+
+There are two ways to upload the APK to AppGallery Connect.
+
+#### 1. Upload by the Build panel
+
+Creator supports uploading the APK generated by building and compiling directly to the AppGallery Connect backend.
+Click the **Upload** button in the bottom right of the **Build Task** panel to open the **Upload** panel, then fill in the relevant information.
+
+
+
+- APP ID: fill in the APP ID for your app. Login to the AppGallery Connect and click **My apps -> App information** to get the APP ID.
+
+- Version: fill in as required.
+
+- APK Path: select the APK generated after compilation.
+
+- Login Type: includes both **OAuth** and **API Client**.
+
+ - **OAuth**
+
+ The OAuth login type only requires you follow the prompts to login to your HUAWEI account (Need to have sufficient [permissions](https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-Guides/agcapi-getstarted-0000001111845114#section797720532313)) when you click **Confirm**, then check the box of the required permissions, the window will automatically close and the APK will be uploaded automatically.
+
+ 
+
+ - **API Client**
+
+ - If the API Client login type is used for the first time, you need to login to AppGallery Connect to get the relevant configuration information.
+
+ 
+
+ - Select **Users and permission -> Connect API -> Create** to create an API client, and select [Roles and Permissions](https://developer.huawei.com/consumer/en/doc/distribution/app/agc-help-rolepermission-0000001155345429) as needed, then click **Confirm**.
+
+ 
+
+ - Fill the **Client ID** and **Key** of the API client into the corresponding input boxes in the **Upload** panel of Creator.
+
+ - Click **Confirm** when you are done configuring.
+
+ Detailed descriptions of the two login types can be found in the [AppGallery Connect API Getting Started](https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-Guides/agcapi-getstarted) documentation.
+
+#### 2. Upload by AppGallery Connect
+
+Sign in to AppGallery Connect, click **My apps** and select the app. Then switch to the **Distribute** column at the top left, click on **Version information -> Draft** in the left column, find the **Upload APK package**, click on **Software packages**, and then click on **Upload**.
+
+### Submit Your App for Review
+
+1. Sign in to AppGallery Connect, click **My apps** and select the app. Then switch to the **Distribute** column at the top left, click on **Version information -> Draft** in the left column, find the **Upload APK package**, click on **Software packages**, and then click on **Select**.
+
+ 
+
+2. For other configuration information, please refer to the [Releasing an App](https://developer.huawei.com/consumer/en/doc/distribution/app/agc-release_app) documentation. After completing and confirming all of the information is in order, click the **Submit** button at the top right of the page. HUAWEI AppGallery will complete the review in 3~5 working days.
+
+## Related Reference Links
+
+- [AppGallery Connect](https://developer.huawei.com/consumer/en/service/josp/agc/index.html)
+- [AppGallery Connect Operation Guide](https://developer.huawei.com/consumer/en/doc/distribution/app/agc-create_app)
diff --git a/versions/4.0/en/editor/publish/publish-huawei-agc/agc-builder.png b/versions/4.0/en/editor/publish/publish-huawei-agc/agc-builder.png
new file mode 100644
index 0000000000..823ba820b0
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-agc/agc-builder.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-agc/agc-upload-panel.png b/versions/4.0/en/editor/publish/publish-huawei-agc/agc-upload-panel.png
new file mode 100644
index 0000000000..da5cc56f4e
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-agc/agc-upload-panel.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-agc/agc-upload.png b/versions/4.0/en/editor/publish/publish-huawei-agc/agc-upload.png
new file mode 100644
index 0000000000..9bf5a6d6b9
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-agc/agc-upload.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-agc/apk-list.png b/versions/4.0/en/editor/publish/publish-huawei-agc/apk-list.png
new file mode 100644
index 0000000000..5718919a17
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-agc/apk-list.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-agc/apk.png b/versions/4.0/en/editor/publish/publish-huawei-agc/apk.png
new file mode 100644
index 0000000000..1ea9419243
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-agc/apk.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-agc/app-info.png b/versions/4.0/en/editor/publish/publish-huawei-agc/app-info.png
new file mode 100644
index 0000000000..3a6eb809a6
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-agc/app-info.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-agc/create-api-key.png b/versions/4.0/en/editor/publish/publish-huawei-agc/create-api-key.png
new file mode 100644
index 0000000000..fa51c93448
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-agc/create-api-key.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-agc/sdkhub.png b/versions/4.0/en/editor/publish/publish-huawei-agc/sdkhub.png
new file mode 100644
index 0000000000..91f41db797
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-agc/sdkhub.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-agc/upload-api.png b/versions/4.0/en/editor/publish/publish-huawei-agc/upload-api.png
new file mode 100644
index 0000000000..8399dacf27
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-agc/upload-api.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-agc/upload-oauth.png b/versions/4.0/en/editor/publish/publish-huawei-agc/upload-oauth.png
new file mode 100644
index 0000000000..7cbacf2b99
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-agc/upload-oauth.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-ohos.md b/versions/4.0/en/editor/publish/publish-huawei-ohos.md
new file mode 100644
index 0000000000..aa60d44289
--- /dev/null
+++ b/versions/4.0/en/editor/publish/publish-huawei-ohos.md
@@ -0,0 +1,145 @@
+# Publish for the Huawei HarmonyOS
+
+Starting with v3.2, Cocos Creator supports packaging games as Huawei **HarmonyOS** (`.hap`) applications.
+
+## Preparations
+
+- Enter [AppGallery Connect website](https://developer.huawei.com/consumer/en/service/josp/agc/index.html#/) to register for a [HUAWEI ID](https://developer.huawei.com/consumer/en/doc/start/registration-and-verification-0000001053628148).
+
+- After logging in, select [Create Project](https://developer.huawei.com/consumer/en/doc/distribution/app/agc-harmonyapp-createproject) and [Add HarmonyOS App](https://developer.huawei.com/consumer/en/doc/distribution/app/agc-harmonyapp-createharmonyapp), select the **Platform** as **HarmonyOS**.
+
+ 
+
+ > **Note**: the **Package name** needs to be consistent with the **Game Package Name** in the **Build** panel of Cocos Creator.
+
+- Download and install [HUAWEI DevEco Studio](https://developer.harmonyos.com/en/develop/deveco-studio#download). After the installation is complete [Configure Development Environment](https://developer.harmonyos.com/en/docs/documentation/doc-guides/environment_config-0000001052902427), download the HarmonyOS SDK, please check **Java** and **Native** for the SDK packages in the **SDK Platforms** page.
+
+ 
+
+ Remember the directory indicated by **HarmonyOS SDK Location** shown at the top of the window, fill in the path of this SDK in the **Preferences** panel of Cocos Creator later.
+
+## Release process
+
+### Building with Cocos Creator
+
+1. Use Cocos Creator to open the project, click **Cocos Creator/File -> Preferences -> External Programs** in the upper menu bar, configure **HarmonyOS NDK** and **HarmonyOS SDK** path:
+
+ 
+
+2. Open the **Build** panel from **Project -> Build** in the menu bar. Select **HarmonyOS** in **Platform** in the **Build** panel, and configure [Build Options](./native-options.md#build-options) as needed. Next, click the **Build** button at the bottom right.
+
+ 
+
+ > **Notes**:
+ >
+ > 1. **Game Package Name** in the expanded option of **HarmonyOS** needs to be consistent with the **Package name** when adding the HarmonyOS application in the AppGallery Connect.
+ > 2. We deprecated the **Render BackEnd** in the expanded option of **HarmonyOS** since v3.4.2 due to **HarmonyOS** offering full support to GLES3.
+
+3. Open the project directory after the build is complete, notice that the `ohos` folder is generated under the `native\engine` directory, which contains the HarmonyOS project generated by the build.
+
+ 
+
+ > **Note**: currently, HarmonyOS does not support multi-directory builds, so the generated HarmonyOS project is in the `native\engine` directory, unlike other platforms that generate in the `build` directory of the project.
+
+ Next, open the `ohos` folder with HUAWEI DevEco Studio to perform further compilation, as described below.
+
+### Compile and run through HUAWEI DevEco Studio
+
+1. Open HUAWEI DevEco Studio, click **Open Project** and select the HarmonyOS project (`ohos` folder) generated after the build in the previous step.
+
+ 
+
+2. Prepare the signature file. For the method of obtaining the signature file, please refer to the contents of the **Signature File** section below.
+
+3. Configure the signature file. Click **File -> Project Structure** in the DevEco Studio menu bar, then select **Modules -> entry -> Signing Configs** and configure the signature information. For details, please refer to the [Configure Signature Information](https://developer.harmonyos.com/en/docs/documentation/doc-guides/ide_debug_device-0000001053822404#EN-US_TOPIC_0000001154985555__section19238119191816) documentation.
+
+ 
+
+ Then proceed to configure the signature information in **Project -> Signing Configs**.
+
+ After setting and saving, the configured signature information can be viewed in the project directory in the `native\engine\ohos\entry\build.gradle` file in the project directory.
+
+ Depending on the build type (Debug/Release) and whether the generated `.hap` contains signature information, the developer can configure in combination as needed, please refer to the [Building and Creating HAPs](https://developer.harmonyos.com/en/docs/documentation/doc-guides/build_hap-0000001053342418) documentation for details.
+
+ 
+
+4. Then click on the **Build -> Build Hap(s)/APP(s) -> Build Hap(s)** in the menu bar to execute the compilation process and generate the `.hap` file.
+
+ 
+
+ After compiling, the `.hap` file with signature information is generated in the `native\engine\ohos\build\outputs\hap` directory of the project directory.
+
+ 
+
+ All `.hap` files with/without signature information are generated in the `native\engine\ohos\entry\build\outputs\hap` directory of the project directory.
+
+ 
+
+5. Connect Huawei devices with HarmonyOS system using USB, then click **Run -> Run ‘entry’** in the menu bar or click the Run button above to run the HarmonyOS app to your device. Please refer to the [Running Your App](https://developer.harmonyos.com/en/docs/documentation/doc-guides/run_phone_tablat-0000001064774652) documentation for details.
+
+ 
+
+ > **Note**: if the app icon is not found when running on the device, check if there is an `installationFree` field with `true` in the `native\engine\ohos\entry\src\main\config.json` file in the project directory, change it to `false`.
+
+6. If need to upload and publish HarmonyOS apps to Huawei AppGallery Connect, please refer to the official [Release HarmonyOS Application Guide](https://developer.huawei.com/consumer/en/doc/distribution/app/agc-harmonyapp-releaseharmonyapp) documentation for the specific process.
+
+### Signature file
+
+HarmonyOS applications use digital certificates (`.cer` files) and HarmonyAppProvision files (`.p7b` files) to ensure the integrity of the application. First, use **DevEco Studio** to generate a key and certificate request file, and then use the certificate request file to apply for a digital certificate and profile file for publishing/debugging in AppGallery Connect.
+
+#### Generate key and certificate request file
+
+In **DevEco Studio**, click **Build -> Generate Key and CSR** in the upper menu bar to generate a key (`.p12` file), and then generate a certificate request file (`.csr`). For details, please refer to the [Generating a Key Store and CSR](https://developer.harmonyos.com/en/docs/documentation/doc-guides/publish_app-0000001053223745#EN-US_TOPIC_0000001154985553__section7209054153620) documentation.
+
+#### Generate and download a digital certificate (`.cer` file)
+
+- Visit the [AppGallery Connect website](https://developer.huawei.com/consumer/en/service/josp/agc/index.html), select **Users and permissions -> Certificate management**, click the **New certificate** button in the upper right corner.
+
+ 
+
+- Enter the required certificate information in the New certificate dialog box that is displayed. **Certificate type** Choose **Release certificate**/**Debug certificate** as required. The certificate request file is the `.csr` file generated in **DevEco Studio** in the previous step.
+
+ 
+
+ - **Certificate name**: Enter up to 100 characters.
+ - **Certificate type**: Select **Release certificate**/**Debug certificate** as required.
+ - **CSR certificate request file**: Select the `.csr` file generated in **DevEco Studio** in the previous step.
+
+- After filling in the information, click **Submit**, a release/debugging certificate (`.cer` file) will be generated, and click the **Download** button behind the certificate to download it to the local.
+
+For more information, please refer to the [Apply for Digital Certificate](https://developer.huawei.com/consumer/en/doc/distribution/app/agc-harmonyapp-debugharmonyapp#h1-1598336089667) documentation.
+
+#### Generate and download HarmonyAppProvision Profile file (`.p7b` file)
+
+- Enter [AppGallery Connect website](https://developer.huawei.com/consumer/en/service/josp/agc/index.html), select **My Project**, select the HarmonyOS project and application created before.
+
+- Click the **HarmonyOS app services -> HAP Provision Profile management** item on the left, and then click the **Add** button at the top right of the page to create a `.p7b` file.
+
+ 
+
+- Enter the required information in the HarmonyAppProvision information dialog box that is displayed.
+
+ 
+
+ - **HarmonyAppProvision file**: Enter the file name, which contains up to 100 characters.
+ - **Type**: Select **Release** or **certificate** as required.
+ - **Certificate**: Select the `.cer` file generated in the previous step.
+ - **Device**: Please refer to the [Registering Debugging Devices](https://developer.huawei.com/consumer/en/doc/distribution/app/agc-harmonyapp-debugharmonyapp#h1-1598520099105) documentation for configuration. It is not necessary to configure this item when the **Type** is set to **Release**.
+
+- After setting, click **Submit** to download the generated `.p7b` file to the local.
+
+For more information, please refer to the [Application Profile](https://developer.huawei.com/consumer/en/doc/distribution/app/agc-harmonyapp-debugharmonyapp#h1-1598336409517) documentation.
+
+## Known issues
+
+- WebView does not support `touch` events, touch is not responsive.
+- VideoPlayer does not support dragging video when playing remote video.
+- EditBox is not zoomed out when full screen, and does not re-layout after keyboard retraction.
+- Gravity/acceleration sensor delay around 500ms, poor followability.
+
+## Reference documentation
+
+- [AppGallery Connect Website](https://developer.huawei.com/consumer/en/service/josp/agc/index.html#/)
+- [HUAWEI DevEco Studio User Guide](https://developer.harmonyos.com/en/docs/documentation/doc-guides/tools_overview-0000001053582387)
+- [Debugging the HarmonyOS App](https://developer.harmonyos.com/en/docs/documentation/doc-guides/ide_debug_device-0000001053822404)
+- [Releasing the HarmonyOS App](https://developer.harmonyos.com/en/docs/documentation/doc-guides/publish_app-0000001053223745)
diff --git a/versions/4.0/en/editor/publish/publish-huawei-ohos/app-info.png b/versions/4.0/en/editor/publish/publish-huawei-ohos/app-info.png
new file mode 100644
index 0000000000..acf87c90c5
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-ohos/app-info.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-ohos/build-hap.png b/versions/4.0/en/editor/publish/publish-huawei-ohos/build-hap.png
new file mode 100644
index 0000000000..d052e7a13e
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-ohos/build-hap.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-ohos/build-variants.png b/versions/4.0/en/editor/publish/publish-huawei-ohos/build-variants.png
new file mode 100644
index 0000000000..d061788cbd
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-ohos/build-variants.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-ohos/build.png b/versions/4.0/en/editor/publish/publish-huawei-ohos/build.png
new file mode 100644
index 0000000000..de2251f352
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-ohos/build.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-ohos/cer-file.png b/versions/4.0/en/editor/publish/publish-huawei-ohos/cer-file.png
new file mode 100644
index 0000000000..1799a245d0
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-ohos/cer-file.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-ohos/debug-output.png b/versions/4.0/en/editor/publish/publish-huawei-ohos/debug-output.png
new file mode 100644
index 0000000000..bf8a94b6a8
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-ohos/debug-output.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-ohos/dev-setting.png b/versions/4.0/en/editor/publish/publish-huawei-ohos/dev-setting.png
new file mode 100644
index 0000000000..8f1e26a010
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-ohos/dev-setting.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-ohos/new-cer-file.png b/versions/4.0/en/editor/publish/publish-huawei-ohos/new-cer-file.png
new file mode 100644
index 0000000000..94aa6b632c
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-ohos/new-cer-file.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-ohos/new-provision-profile.png b/versions/4.0/en/editor/publish/publish-huawei-ohos/new-provision-profile.png
new file mode 100644
index 0000000000..a507302b25
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-ohos/new-provision-profile.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-ohos/open-project.png b/versions/4.0/en/editor/publish/publish-huawei-ohos/open-project.png
new file mode 100644
index 0000000000..32625f32f3
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-ohos/open-project.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-ohos/output.png b/versions/4.0/en/editor/publish/publish-huawei-ohos/output.png
new file mode 100644
index 0000000000..032c121905
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-ohos/output.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-ohos/package-ohos.png b/versions/4.0/en/editor/publish/publish-huawei-ohos/package-ohos.png
new file mode 100644
index 0000000000..99a0833314
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-ohos/package-ohos.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-ohos/preferences.png b/versions/4.0/en/editor/publish/publish-huawei-ohos/preferences.png
new file mode 100644
index 0000000000..7ff73f0f8a
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-ohos/preferences.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-ohos/provision-profile.png b/versions/4.0/en/editor/publish/publish-huawei-ohos/provision-profile.png
new file mode 100644
index 0000000000..ce496aaf1e
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-ohos/provision-profile.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-ohos/run-project.png b/versions/4.0/en/editor/publish/publish-huawei-ohos/run-project.png
new file mode 100644
index 0000000000..f7904309d7
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-ohos/run-project.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-ohos/sign-configs-debug.png b/versions/4.0/en/editor/publish/publish-huawei-ohos/sign-configs-debug.png
new file mode 100644
index 0000000000..fb6f817556
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-ohos/sign-configs-debug.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-ohos/sign-configs.png b/versions/4.0/en/editor/publish/publish-huawei-ohos/sign-configs.png
new file mode 100644
index 0000000000..dfd3f7fe15
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-ohos/sign-configs.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-quick-game.md b/versions/4.0/en/editor/publish/publish-huawei-quick-game.md
new file mode 100644
index 0000000000..ebe92bd05b
--- /dev/null
+++ b/versions/4.0/en/editor/publish/publish-huawei-quick-game.md
@@ -0,0 +1,116 @@
+# Publish to Huawei Quick Games
+
+> **Note**: some platforms only have Chinese documentation available when visiting the platform's website. It may be necessary to use Google Translate in-order to review the documentation.
+
+__Cocos Creator__ officially supports the release of games to the **Huawei Quick Games**.
+
+## Environment Configuration
+
+- Download the [Huawei Quick APP Loader](https://developer.huawei.com/consumer/en/doc/Tools-Library/quickapp-ide-download-0000001101172926#section9347192715112) and install it on your Android device (Android Phone 6.0 or above is recommended)
+
+- Install [nodejs-8.1.4](https://nodejs.org/en/download/) or above, globally.
+
+## Release Process
+
+1. Use **Cocos Creator 3.0** to open the project that needs to be released. Select **Huawei Quick Game** in the **Platform** dropdown of the **Build** panel.
+
+ 
+
+ Click on the **huawei-quick-game** below to expand the parameter configuration of **Huawei Quick Game**.
+
+ 
+
+The specific filling rules for the relevant parameter configuration are as follows:
+
+- **Game Package Name**
+
+ **Game Package Name** is filled in according to the developer's needs. It's required.
+
+- **Desktop Icon**
+
+ **Desktop Icon** is required. Click the **search icon** button at the back of the input box to select the icon you want. When building, the **Desktop Icon** will be built into the **Huawei Quick Game** project. It is suggested that the **Desktop Icon** is a `.png` image.
+
+- **Game Version Name**
+
+ This item is required. **Game Version Name** is the real version, such as: 1.0.0.
+
+- **Game Version Number**
+
+ This item is required. **Game Version Number** is different from the **Game Version Name**, and the **Game Version Number** is mainly used to distinguish the version update. Each time when you submit audit, the game version number is at least 1 higher than the value of the last submitted audit. It must not be equal to or less than the value of the last submitted audit, and it is recommended that the **Game Version Number** be recursively incremented by 1 each time when the audit is submitted
+
+ > **Note**: the **Game Version Number** must be a positive integer.
+
+- **Supported Minimum Platform Version Number**
+
+ This item is required. According to the requirements of Huawei Quick Games, this value must be greater than or equal to **1035**.
+
+- **Custom manifest file path (optional)**
+
+ This is an optional item, which is the expansion function of Huawei Quick Game. When used, you need to select a `JSON` file, and the data type in the file is required to be in `JSON` format.
+
+ > **Note**: the `JSON` data is not available when the key value are `package`, `appType`, `name`, `versionName`, `versionCode`, `icon`, `minPlatformVersion`, `config`, `display`, otherwise it will be overwritten by data such as **Game Package Name**, **Game Name**, **Desktop Icon**, **Game Version Name**, **Game Version Number** during the build.
+
+- **Small Packet Mode**
+
+ This item is optional. The in-package volume of the mini-game contains code and assets that cannot exceed 10M, and assets can be loaded via network requests. **Small Packet Mode** is to help developers keep the script files in the mini game package, other assets are uploaded to the remote server, and downloaded from the remote server as needed. Cocos Creator has already helped the developer with the download, cache, and version management of remote assets. The developer needs to do is the following steps:
+
+ 1. When building, check the **Small Packet Mode** and fill in the **Small Packet Mode Server Path**.
+
+ 2. **First game asset package into the game package**, this item is optional.
+
+ In the Small Packet Mode, due to too many assets on the launch scene, downloading and loading assets for a long time may result in a short black screen when entering the game for the first time. If **First game asset package into the game package** is checked, you can reduce the black screen time when you first enter the game. However, it should be noted that the `res/import` asset does not support split asset downloading at this time, and the entire `import` directory is also packaged into the first package.
+
+ Developers can choose whether to check this item according to their needs. Then click on **Build**.
+
+ 3. After the build is complete, click the **Open** button after the **Build Path** to upload the `res` directory under the release path to the small packet mode server. For example, if the default release path is `build`, the **Build Task Name** is `huawei-quick-game`, you need to upload the `/build/huawei-quick-game/res` directory.
+
+ At this point, the `res` directory will no longer be included in the built-up **rpk**, and the assets in the `res` directory will be downloaded from the filled **Small Packet Mode Server Path** through the network request.
+
+- **Keystore**
+
+ When you check the **Keystore**, the default is to build the **rpk** package with a certificate that comes with Creator. This certificate is used only for **debugging**.
+
+ > **Note**: when the **rpk** package is to be used to submit an audit, do not check the **Keystore** to build it.
+
+ If you don't check the **Keystore**, you need to configure the signature files **certificate.pem path** and **private.pem path**, where you build a **rpk** package that you can **publish directly**. The user can configure two signature files by using the **search icon** button to the right of the input box.
+
+ There are two ways to generate a signature files:
+
+ - Generated by the **New** button after the **certificate.pem path** in the **Build** panel.
+
+ - Generated by the command line.
+
+ The user needs to generate the signature file **private.pem**, **certificate.pem** through tools such as **openssl**.
+
+ ```bash
+ # Generate a signature file with the openssl command tool
+ openssl req -newkey rsa:2048 -nodes -keyout private.pem -x509 -days 3650 -out certificate.pem
+ ```
+
+ > **Note**: **openssl** can be used directly in the terminal in Linux or Mac environment, and in the Windows environment you need to install `openssl` and configure system environment variables. Restart **Cocos Creator** after the configuration is complete.
+
+**2. Build**
+
+After the relevant parameters of the **Build** panel are set, click **Build**. When the build is complete, click the **folder icon** button below the corresponding build task to open the build release path, you can see that a directory with the same name as the **Build Task Name** is generated in the default release path `build` directory, which is the exported Huawei Quick Game project directory and **rpk**, **rpk** package are in the `dist` directory.
+
+
+
+**3. Run the built rpk to the phone**
+
+Copy the **rpk** package generated by the build to the internal storage directory of the Android device. Open the **Huawei Quick APP Loader** that has been installed before, clicking the back button on the Android device will bring up a list, select the **Local Install**, select the path of place **rpk**, and then run the **rpk** on the Android device.
+
+**4. Subpackage rpk**
+
+Subpackage **rpk** can be used according to your needs.
+
+Subpackage loading, which is, splitting the game content into several packages according to certain rules, only downloading the necessary packages when starting up for the first time. This necessary package is called **main package**. The developer can trigger in the main package to download other sub-packages, which can effectively reduce the time spent on the first boot.
+
+To use this function, set the [Bundle Configuration](subpackage.md) in **Cocos Creator**, and the package will be automatically subpackaged when the setting is completed.
+
+After the build is complete, the generated subpackages and main package are merged into one **rpk**, which is in the `build/huawei-quick-game/dist` directory.
+
+> **Note**: currently, Huawei Quick Game does not support downloading multiple subpackages at the same time, please download them in order if you need to download multiple subpackages.
+
+## Reference documentation
+
+[Huawei Quick Game Development Guide](https://developer.huawei.com/consumer/en/doc/quickApp-Guides/quickgame-dev-runtimegame-guide-0000001159778255)
diff --git a/versions/4.0/en/editor/publish/publish-huawei-quick-game/build_options.png b/versions/4.0/en/editor/publish/publish-huawei-quick-game/build_options.png
new file mode 100644
index 0000000000..65a08f4d71
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-quick-game/build_options.png differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-quick-game/huawei_options.jpg b/versions/4.0/en/editor/publish/publish-huawei-quick-game/huawei_options.jpg
new file mode 100644
index 0000000000..5a9c45b64c
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-quick-game/huawei_options.jpg differ
diff --git a/versions/4.0/en/editor/publish/publish-huawei-quick-game/package.png b/versions/4.0/en/editor/publish/publish-huawei-quick-game/package.png
new file mode 100644
index 0000000000..4b0014268b
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-huawei-quick-game/package.png differ
diff --git a/versions/4.0/en/editor/publish/publish-in-command-line.md b/versions/4.0/en/editor/publish/publish-in-command-line.md
new file mode 100644
index 0000000000..94a63f7f73
--- /dev/null
+++ b/versions/4.0/en/editor/publish/publish-in-command-line.md
@@ -0,0 +1,121 @@
+# Publish from the Command Line
+
+Publish a project from the command line can help us build an auto-publish routine that allows modifying command line parameters to achieve different goals.
+
+## Command Reference
+
+**For example**: Building Web Desktop with debug mode enabled:
+
+- Mac
+
+ ```bash
+ /Applications/CocosCreator/Creator/3.0.0/CocosCreator.app/Contents/MacOS/CocosCreator --project projectPath --build "platform=web-desktop;debug=true"
+ ```
+
+- Windows
+
+ ```bash
+ ...\CocosCreator.exe --project projectPath --build "platform=web-desktop;debug=true"
+ ```
+
+Currently, when using the command line to build, except for the required build options, if no parameter values are uploaded, the default values are used to build. Please refer to the description below and the platform's build options description for specific default values.
+
+## Exit Codes
+
+- **32** Build failed —— Invalid build parameters.
+- **34** Build failed —— Some unexpected errors occurred during the build process, please refer to the build log for details.
+- **36** Build success.
+
+## Publish Parameters
+
+- `--project`: Required, specify the project path.
+- `--engine`: Optional, specify custom engine path.
+
+- `--build`: Specify the parameters to be used when building the project.
+
+ When parameters are not specified after `--build`, then the parameters used in the **Build** panel, such as platforms, templates, and so on, will be used as default parameters. When additional parameter settings are specified, the default parameters will be overwritten with the specified parameters. The available parameters are:
+
+ - `configPath`: Parameter file path. If define `configPath`, then Cocos Creator will load this file as a build parameter in the `JSON` file format. This parameter can be modified by yourself or exported directly from the **Build** panel.
+ - `stage` - Specify the build mode, default is 'build', options are 'make' | 'build'.
+ - `logDest`: Specify the log output path.
+ - `includedModules`: Customize the engine packaged modules, only the required modules are packaged. The corresponding field of each module can be found in the `features` field in [this file](https://github.com/cocos/cocos4/blob/3d/cc.config.json) of engine repository.
+ - `outputName`: The name of the release folder generated after the build.
+ - `name`: Game name.
+ - `platform`: Required, the platform needs to be built.
+ - `buildPath`: Specify the directory where the build release package is generated, the default is the `build` directory under the project directory. Either an absolute path or a path relative to the project (e.g.: `project://release`) can be used. Starting with v3.4.2, relative paths like `../` are supported.
+ - `startScene`: The UUID of the main scene (the participating scene will use the build option parameters in the **Build** panel from the last build), and the first scene from the **Included Scenes** will be used if not specified.
+ - `scenes`: Information about the scenes involved in the build, which defaults to all scenes when not specified.
+ - `debug`: Whether or not debug mode, the default is `false`.
+ - `replaceSplashScreen`: Whether to replace the splash screen, the default is `false`.
+ - `md5Cache`: Enabled or disabled the MD5 Cache, the default is `false`.
+ - `mainBundleCompressionType`: Main bundle compression type. For specific option values, please refer to the document [Asset Bundle — compression type](../../asset/bundle.md##compression-type).
+ - `mainBundleIsRemote`: Configure the main package as a remote package.
+ - `packages`: The build configuration parameters supported by each plugin. What needs to be stored is the serialized string for the data object. For details, please refer to the following.
+
+Each platform's build will be embedded in the **Build** panel as a separate plugin, so each platform's build options are in different locations. The build parameters are configured in the `packages` field, for example, to specify the build options for WeChat Mini Game, the configuration is as follows:
+
+```bash
+{
+ taskName: 'wechatgame',
+ packages: {
+ wechatgame: {
+ appid: '*****',
+ }
+ }
+}
+```
+
+After the build plugin system is opened to the public, the configuration parameters of other plugins are embedded in the **Build** panel in the same way. **Please refer to the documentation of each platform for the specific parameter fields of each platform**, it is better to use the **Export** function of the **Build** panel to get the configuration parameters. Currently it is still compatible with the old version of the parameters to build, but the compatibility process will be gradually removed later, so please upgrade the configuration parameters as soon as possible.
+
+## Bundle Build via Command Line
+
+1. Open the Bundle Build panel and configure the options. After configuring, export the configuration (since 3.8.2).
+ 
+ The exported configuration is as follows:
+
+ ```json
+ {
+ "buildTaskIds": [
+ "1699344873959"
+ ],
+ "dest": "project://build/build-bundle",
+ "id": "buildBundle",
+ "bundleConfigs": [
+ {
+ "root": "db://assets/resources",
+ "output": true
+ }
+ ],
+ "taskName": "build bundle db://assets/resources"
+ }
+
+ ```
+
+2. Execute the following command in the command line:
+
+- Mac
+
+ ```bash
+ /Applications/CocosCreator/Creator/3.0.0/CocosCreator.app/Contents/MacOS/CocosCreator --project projectPath
+ --build "stage=bundle;configPath=./bundle-build-config.json;"
+ ```
+
+- Windows
+
+ ```bash
+ ...\CocosCreator.exe --project projectPath --build "stage=bundle;configPath=./bundle-build-config.json;"
+ ```
+
+The command line publish of the Bundle is similar to the ordinary command line build, but the `stage` parameter needs to be specified as `bundle`, and the configuration exported on the Bundle Build Panel should be specified as the `configPath` parameter.
+
+3. Execute "Build script only" on the command line:
+- Mac && Windows
+ ```bash
+ --build "buildScriptsOnly=true"
+ ```
+
+## Publish using Jenkins
+
+**Cocos Creator** still needs the GUI environment when running from the command line. If the Jenkins server can not run **Cocos Creator** from the command line, a solution is running Jenkins in agent mode, so it can interact with the operating systems window server. For more details please review this [Stack Overflow post](https://stackoverflow.com/questions/13966595/build-unity-project-with-jenkins-failed).
+
+If the Jenkins server can not compile under Windows, specify a local user for the Jenkins service in the Windows **Control Panel -> Administrative Tools -> Services**, and then restart the computer. You don't need to set up a master-slave mode separately.
diff --git a/versions/4.0/en/editor/publish/publish-mini-game.md b/versions/4.0/en/editor/publish/publish-mini-game.md
new file mode 100644
index 0000000000..97f8c582f8
--- /dev/null
+++ b/versions/4.0/en/editor/publish/publish-mini-game.md
@@ -0,0 +1,16 @@
+# Publish to Mini Game Platforms
+
+- [Publish to HUAWEI AppGallery Connect](publish-huawei-agc.md)
+- [Publish to Alipay Mini Game](publish-alipay-mini-game.md)
+- [Publish to Taobao Mini Game](publish-taobao-mini-game.md)
+- [Publish to Douyin Mini Game](publish-bytedance-mini-game.md)
+- [Publish to Huawei Quick Game](publish-huawei-quick-game.md)
+- [Publish to OPPO Mini Game](publish-oppo-mini-game.md)
+- [Publish to vivo Mini Game](publish-vivo-mini-game.md)
+- [Publish to Honor Mini Game](publish-honor-mini-game.md)
+- [Publish to Baidu Mini Game](publish-baidu-mini-game.md)
+- [Publish to WeChat Mini Game](publish-wechatgame.md)
+ - [WeChat Engine Plugin](wechatgame-plugin.md)
+ - [Access to WeChat PC Mini Game](publish-pc-wechatgame.md)
+- [Access to Open Data Context](build-open-data-context.md)
+- [Mini Game Subpackage](subpackage.md)
diff --git a/versions/4.0/en/editor/publish/publish-native-index.md b/versions/4.0/en/editor/publish/publish-native-index.md
new file mode 100644
index 0000000000..8119237581
--- /dev/null
+++ b/versions/4.0/en/editor/publish/publish-native-index.md
@@ -0,0 +1,21 @@
+# Fundamentals for Publishing to Native Platforms
+
+Cocos Creator supports publishing to native applications on multiple platforms:
+- [Publishing iOS Apps](./ios/index.md)
+- [Publishing Android Apps](./android/index.md)
+- [Publishing HUAWEI Harmony Apps](./publish-huawei-ohos.md)
+- [Publishing macOS Desktop Apps](./mac/index.md)
+- [Publishing Windows Desktop Apps](./windows/index.md)
+
+The following are some common knowledge points related to publishing to native platforms:
+- [About the Build Panel](build-panel.md)
+- [General Build Options](build-options.md)
+- [General Native Build Options](native-options.md)
+- [Debugging JavaScript on Native Platforms](debug-jsb.md)
+- [Build Process and FAQ](build-guide.md)
+
+If you want to publish to [Mini Game](./publish-mini-game.md) and [Web](./publish-web.md) platforms, please refer to the corresponding documentation.
+
+If you want to perform custom development on native platforms, please refer to the [Native Development](../../native/overview.md).
+
+If you want to customize the engine, please refer to the [Engine Customization Workflow](../../../zh/advanced-topics/engine-customization.md).
diff --git a/versions/4.0/en/editor/publish/publish-native/android-options.png b/versions/4.0/en/editor/publish/publish-native/android-options.png
new file mode 100644
index 0000000000..a429379f98
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-native/android-options.png differ
diff --git a/versions/4.0/en/editor/publish/publish-native/android-studio.png b/versions/4.0/en/editor/publish/publish-native/android-studio.png
new file mode 100644
index 0000000000..1916313261
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-native/android-studio.png differ
diff --git a/versions/4.0/en/editor/publish/publish-native/build-progress-windows.png b/versions/4.0/en/editor/publish/publish-native/build-progress-windows.png
new file mode 100644
index 0000000000..cbe07db4b5
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-native/build-progress-windows.png differ
diff --git a/versions/4.0/en/editor/publish/publish-native/cocos-console-log.png b/versions/4.0/en/editor/publish/publish-native/cocos-console-log.png
new file mode 100644
index 0000000000..0aaa10ec77
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-native/cocos-console-log.png differ
diff --git a/versions/4.0/en/editor/publish/publish-native/encrypt-js.png b/versions/4.0/en/editor/publish/publish-native/encrypt-js.png
new file mode 100644
index 0000000000..ef3cfbea4a
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-native/encrypt-js.png differ
diff --git a/versions/4.0/en/editor/publish/publish-native/gpg-input-sdk-keys.png b/versions/4.0/en/editor/publish/publish-native/gpg-input-sdk-keys.png
new file mode 100644
index 0000000000..14a0370fef
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-native/gpg-input-sdk-keys.png differ
diff --git a/versions/4.0/en/editor/publish/publish-native/ios-options.png b/versions/4.0/en/editor/publish/publish-native/ios-options.png
new file mode 100644
index 0000000000..1a3368fa05
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-native/ios-options.png differ
diff --git a/versions/4.0/en/editor/publish/publish-native/ios-xcode.png b/versions/4.0/en/editor/publish/publish-native/ios-xcode.png
new file mode 100644
index 0000000000..b447d27cbc
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-native/ios-xcode.png differ
diff --git a/versions/4.0/en/editor/publish/publish-native/mac-options.png b/versions/4.0/en/editor/publish/publish-native/mac-options.png
new file mode 100644
index 0000000000..faa8dd4386
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-native/mac-options.png differ
diff --git a/versions/4.0/en/editor/publish/publish-native/modify_abi.png b/versions/4.0/en/editor/publish/publish-native/modify_abi.png
new file mode 100644
index 0000000000..3cbe4c3419
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-native/modify_abi.png differ
diff --git a/versions/4.0/en/editor/publish/publish-native/native-build-buttons.png b/versions/4.0/en/editor/publish/publish-native/native-build-buttons.png
new file mode 100644
index 0000000000..fbdea7ef80
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-native/native-build-buttons.png differ
diff --git a/versions/4.0/en/editor/publish/publish-native/native-common.png b/versions/4.0/en/editor/publish/publish-native/native-common.png
new file mode 100644
index 0000000000..8da739db02
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-native/native-common.png differ
diff --git a/versions/4.0/en/editor/publish/publish-native/native-directory.png b/versions/4.0/en/editor/publish/publish-native/native-directory.png
new file mode 100644
index 0000000000..3e0ac88bdb
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-native/native-directory.png differ
diff --git a/versions/4.0/en/editor/publish/publish-native/native-options.png b/versions/4.0/en/editor/publish/publish-native/native-options.png
new file mode 100644
index 0000000000..44d552ff0a
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-native/native-options.png differ
diff --git a/versions/4.0/en/editor/publish/publish-native/native-platform.png b/versions/4.0/en/editor/publish/publish-native/native-platform.png
new file mode 100644
index 0000000000..80c20c5ec5
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-native/native-platform.png differ
diff --git a/versions/4.0/en/editor/publish/publish-native/native.png b/versions/4.0/en/editor/publish/publish-native/native.png
new file mode 100644
index 0000000000..1798ef85e5
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-native/native.png differ
diff --git a/versions/4.0/en/editor/publish/publish-native/sdk-android-instant.png b/versions/4.0/en/editor/publish/publish-native/sdk-android-instant.png
new file mode 100644
index 0000000000..50b1fb5d62
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-native/sdk-android-instant.png differ
diff --git a/versions/4.0/en/editor/publish/publish-native/windows-options.png b/versions/4.0/en/editor/publish/publish-native/windows-options.png
new file mode 100644
index 0000000000..667fad34d7
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-native/windows-options.png differ
diff --git a/versions/4.0/en/editor/publish/publish-native/windows-vs.png b/versions/4.0/en/editor/publish/publish-native/windows-vs.png
new file mode 100644
index 0000000000..8d6f2fce38
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-native/windows-vs.png differ
diff --git a/versions/4.0/en/editor/publish/publish-oppo-mini-game.md b/versions/4.0/en/editor/publish/publish-oppo-mini-game.md
new file mode 100644
index 0000000000..f0ba8e75ef
--- /dev/null
+++ b/versions/4.0/en/editor/publish/publish-oppo-mini-game.md
@@ -0,0 +1,123 @@
+# Publish to OPPO Mini Games
+
+> **Note**: some platforms only have Chinese documentation available when visiting the platform's website. It may be necessary to use Google Translate in-order to review the documentation.
+
+__Cocos Creator__ officially supports the release of games to the **OPPO Mini Games**.
+
+## Environment Configuration
+
+- Download [OPPO Mini Game Debugger [cn]](https://cdofs.oppomobile.com/cdo-activity/static/201810/26/quickgame/documentation/#/games/use?id=_2-%e5%ae%89%e8%a3%85-runtimeapk-%e5%8c%85%e5%88%b0-oppo-%e6%89%8b%e6%9c%ba%e4%b8%8a) and install it on your OPPO phone (Android 6.0 or above is recommended)
+
+- Install [nodejs-8.1.4](https://nodejs.org/en/download/) or above, globally
+
+## Release Process
+
+1. Use **Cocos Creator 3.0** to open the project that needs to be released. Select **OPPO Mini Game** in the **Platform** dropdown of the **Build** panel.
+
+ 
+
+ Click on the **oppo-mini-game** below to expand the build options configuration of OPPO Mini Game.
+
+ 
+
+For the general build options for each platform, please refer to [General Build Options](build-options.md) for details. OPPO Mini Game related build options filling rules are as follows:
+
+- **Start Scene Asset Bundle**
+
+ This option is optional.
+ If set, the start scene and its related dependent resources are built into the built-in Asset Bundle - [start-scene](../../asset/bundle.md#the-built-in-asset-bundle) to speed up the resource loading of the start scene.
+
+- **Resource Server Address**
+
+ This option is optional and used to fill in the address of the remote server where the resources are stored.
+
+ - If this option is left blank, the `remote` folder in the release package directory will be packaged into the **rpk** package.
+
+ - If this option is filled in, the `remote` folder will not be packaged into the built **rpk** package. You need to manually upload the `remote` folder to the filled in Resource Server Address after build.
+
+ Refer to the Resource Management section at the bottom of the document for more details.
+
+- **Game Package Name**: is filled in according to the user's needs. It's required.
+
+- **Desktop Icon**: is required. Click the **search icon** button at the back of the input box to select the icon you want. When building, the Desktop Icon will be built into the **OPPO Mini Game** project. It is suggested to use **PNG** images for the **Desktop Icon**.
+
+- **Game Version Name**: is required. **Game Version Name** is the real version, such as: 1.0.0.
+
+- **Game Version Number**: is required. **Game Version Number** is different from the **Game Version Name**, and the **Game Version Number** is mainly used to distinguish the version update. Each time when you submit audit, the game version number is at least 1 higher than the value of the last submitted audit. It must not be equal to or less than the value of the last submitted audit, and it is recommended that the **Game Version Number** be recursively incremented by 1 each time when the audit is submitted.
+
+ > **Note**: the **Game Version Number** must be a positive integer.
+
+- **Supported Minimum Platform Version Number**: is required. According to the requirements for OPPO Mini Games, this value must be greater than or equal to **1031**, and **1060** is recommended. Refer to the [Instructions [cn]](https://cdofs.oppomobile.com/cdo-activity/static/201810/26/quickgame/documentation/#/games/use) for details.
+
+- **Screen Orientation**: The screen orientation currently includes **Portrait** and **Landscape**.
+
+- **Seperate Engine**: This feature reduces the size of the first package for each mini-game by sharing the global engine. When enabled, if the engine already has a cache in the phone, the first package download will automatically remove the engine file and load the full version of the engine cached in the phone. If there is no cache in the phone, the full first package will be loaded, and the complete first package will contain the entire engine.
+
+- **Keystore**: when you check the **Keystore**, the default is to build the rpk package with a certificate that comes with Creator, which is used only for **debugging**.
+
+ > **Note**: when the rpk package is to be used to submit an audit, do not check the **Keystore** to build it.
+
+ If you don't check the **Keystore**, you need to configure the signature files **certificate.pem path** and **private.pem path**, where you build a rpk package that you can **publish directly**. The user can configure two signature files by using the **search icon** button to the right of the input box.
+
+ There are two ways to generate a signature files:
+
+ - Generated by the **New** button after the **certificate.pem path** in the **Build** panel.
+
+ - Generated by the command line.
+
+ The user needs to generate the signature file **private.pem**, **certificate.pem** through tools such as **openssl**.
+
+ ```bash
+ # Generate a signature file with the openssl command tool
+ openssl req -newkey rsa:2048 -nodes -keyout private.pem -x509 -days 3650 -out certificate.pem
+ ```
+
+ > **Note**: **openssl** can be used directly in the terminal in **Linux** or **Mac** environment, and in the **Windows** environment you need to install **openssl** and configure system environment variables. Restart **Cocos Creator** after the configuration is complete.
+
+**2. Build**
+
+After the relevant parameters of the **Build** panel are set, click **Build**. When the build is complete, click the **folder icon** button below the corresponding build task to open the build release path, you can see that a directory with the same name as the **Build Task Name** is generated in the default release path `build` directory, which is the exported OPPO Mini Game project directory and **rpk**, **rpk** package is in the `dist` directory.
+
+
+
+**3. Run the built rpk to the phone**
+
+Copy the generated mini-game **rpk** file to the `games` directory on the phone's internal storage. Then open the **Mini Game Debugger** that has been installed before on the OPPO phone, click the **OPPO Mini Game** section, and then find the icon corresponding to the game name. If not found, click on the **More -> Refresh** button in the upper right corner to refresh.
+
+ > **Note**: if the OPPO Mini Game Debugger version is `v3.2.0` and above, copy the mini-game **rpk** file to the `Android/data/com.nearme.instant.platform/files/games` directory on the OPPO phone's internal storage. If there is no `games` directory, create a new one. Please refer to the [Instructions -- New Directory [cn]](https://cdofs.oppomobile.com/cdo-activity/static/201810/26/quickgame/documentation/#/games/use?id=_3-%e6%96%b0%e5%bb%ba%e7%9b%ae%e5%bd%95) for details.
+
+
+
+## Subpackage rpk
+
+Subpackage **rpk** can be used according to your needs.
+
+Subpackage loading, which is, splitting the game content into several packages according to certain rules, only downloading the necessary packages when starting up for the first time. This necessary package is called **main package**, The developer can trigger in the main package to download other sub-packages, which can effectively reduce the time spent on the first boot.
+
+To use this function, set the [Bundle Configuration](subpackage.md) in **Cocos Creator**, and the package will be automatically subpackaged when the setting is completed.
+
+After the build is complete, the subpackage directory is in the `dist` directory. In this case, create a new `subPkg` directory in the internal storage directory of the OPPO phone, and then copy the **.rpk** file in the `dist` directory to the `subPkg` directory.
+
+Then switch to the **Package Load** section of OPPO **Mini Game Debugger**, click **Refresh** at the top right to see the game name of the subpackage, click **Second Open** to use the same as the normal packaged **rpk**.
+
+
+
+Subpackage rpk needs to be copied to the `subPkg` directory of OPPO phone's internal storage, and non-subpackaged rpk needs to be copied to the `games` directory of OPPO phone's internal storage, both of which cannot be mixed.
+
+> **Note**: if the OPPO Mini Game Debugger version is **v3.2.0** and above, copy the mini game subpackaged **rpk** file to the `Android/data/com.nearme.instant.platform/files/subPkg` directory on the OPPO phone's internal storage, or create a new one if there is no `subPkg` directory. The non-subpackaged rpk is copied to the `Android/data/com.nearme.instant.platform/files/games` directory on the OPPO phone's internal storage, and the two cannot be mixed.
+
+For more information, please refer to the [OPPO Mini Game - Subpackage [cn]](https://activity-cdo.heytapimage.com/cdo-activity/static/201810/26/quickgame/documentation/#/subpackage/subpackage) documentation.
+
+## Resource Management for OPPO Mini Game Environment
+
+**OPPO Mini Game** is similar to **WeChat Mini Game**. There are restrictions on the package size. The main package size limit for OPPO Mini Game is **4MB**, more than that must be downloaded via a network request.
+
+After the game starts, the engine will automatically download resources from the remote server address. Once the resources are downloaded, the engine's cache manager will record the save paths of these resources. This information is used to automatically delete some cached game resources when the cache space is insufficient. Please refer to [Cache Manager](../../asset/cache-manager.md) for more details.
+
+## Reference documentation
+
+- [OPPO Developer Guides](https://developers.oppomobile.com/wiki/doc/index#id=88)
+- [OPPO Mini Game Tutorial [cn]](https://activity-cdo.heytapimage.com/cdo-activity/static/201810/26/quickgame/documentation/#/games/quickgame)
+- [OPPO Mini Game API Documentation [cn]](https://activity-cdo.heytapimage.com/cdo-activity/static/201810/26/quickgame/documentation/#/feature/account)
+- [OPPO Mini Game Tool Download [cn]](https://activity-cdo.heytapimage.com/cdo-activity/static/201810/26/quickgame/documentation/#/games/use)
+- [OPPO Mini Game Instructions -- New Directory [cn]](https://activity-cdo.heytapimage.com/cdo-activity/static/201810/26/quickgame/documentation/#/games/use?id=_3-%e6%96%b0%e5%bb%ba%e7%9b%ae%e5%bd%95)
diff --git a/versions/4.0/en/editor/publish/publish-oppo-mini-games/build-option.png b/versions/4.0/en/editor/publish/publish-oppo-mini-games/build-option.png
new file mode 100644
index 0000000000..5a8de90dab
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-oppo-mini-games/build-option.png differ
diff --git a/versions/4.0/en/editor/publish/publish-oppo-mini-games/oppo-build.png b/versions/4.0/en/editor/publish/publish-oppo-mini-games/oppo-build.png
new file mode 100644
index 0000000000..71da63ee91
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-oppo-mini-games/oppo-build.png differ
diff --git a/versions/4.0/en/editor/publish/publish-oppo-mini-games/package.png b/versions/4.0/en/editor/publish/publish-oppo-mini-games/package.png
new file mode 100644
index 0000000000..c12bf91e23
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-oppo-mini-games/package.png differ
diff --git a/versions/4.0/en/editor/publish/publish-oppo-mini-games/rpk_games.jpg b/versions/4.0/en/editor/publish/publish-oppo-mini-games/rpk_games.jpg
new file mode 100644
index 0000000000..b7e9ddb43c
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-oppo-mini-games/rpk_games.jpg differ
diff --git a/versions/4.0/en/editor/publish/publish-oppo-mini-games/run_subpackage.jpg b/versions/4.0/en/editor/publish/publish-oppo-mini-games/run_subpackage.jpg
new file mode 100644
index 0000000000..57888b1756
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-oppo-mini-games/run_subpackage.jpg differ
diff --git a/versions/4.0/en/editor/publish/publish-pc-bytedance.md b/versions/4.0/en/editor/publish/publish-pc-bytedance.md
new file mode 100644
index 0000000000..25363f57ac
--- /dev/null
+++ b/versions/4.0/en/editor/publish/publish-pc-bytedance.md
@@ -0,0 +1,28 @@
+# Access to Douyin PC Mini Games
+
+Douyin PC Mini Games allow you to play Douyin mini-games directly through the Streaming Companion. PC mini-games retain most features available on mobile but currently do not support the following: `keyDown`/`keyUp` keyboard events, screen recording, recording, ads, sharing, favorites, group chat, sidebar, payments, or capabilities that depend heavily on mobile device hardware, such as compass, accelerometer, camera, and microphone.
+
+Cocos Creator supports publishing games to Douyin PC Mini Games. Let’s look at how to publish your game to the Douyin PC mini-game platform through Cocos Creator.
+
+## Using Cocos Creator to Integrate Douyin PC Mini Games
+
+### Preparation
+
+Download and install the latest version of the [Douyin Streaming Companion for PC](https://streamingtool.douyin.com/).
+
+### Publishing Process
+
+1. Follow the process in [Publishing to Douyin Mini Games](./publish-bytedance-mini-game.md) to publish the project to Douyin Mini Games.
+2. Douyin PC Mini Games require code to run in strict mode to ensure proper functionality. Compile the code in strict mode and resolve any issues arising from strict mode to avoid runtime errors.
+3. Ensure the game runs smoothly in the IDE before debugging on the Streaming Companion.
+
+## FAQs
+
+**Q**: Does Douyin PC Mini Games support Mac systems?
+**A**: Not yet.
+
+## Related Links
+
+- [Douyin PC Mini Games Integration Guide](https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/guide/open-ability/pc-game/tutorial)
+- [Douyin PC Download](https://streamingtool.douyin.com/)
+- [Douyin Developer Tools - IDE Download](https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/developer-instrument/developer-instrument-update-and-download)
\ No newline at end of file
diff --git a/versions/4.0/en/editor/publish/publish-pc-wechatgame.md b/versions/4.0/en/editor/publish/publish-pc-wechatgame.md
new file mode 100644
index 0000000000..50a2a32569
--- /dev/null
+++ b/versions/4.0/en/editor/publish/publish-pc-wechatgame.md
@@ -0,0 +1,35 @@
+# Access to WeChat PC Mini Games
+
+> **Note**: some platforms only have Chinese documentation available when visiting the platform's website. It may be necessary to use Google Translate in-order to review the documentation.
+
+WeChat PC Mini Game supports running WeChat mini games in WeChat for PC. The WeChat PC Mini Game will have most of the Mobile capabilities, including but not limited to virtual payment, open data context, touch events, etc. (ads are not currently supported). It also provides keyboard events, mouse events, window customization and other features.
+
+Cocos Creator supports publishing games to WeChat PC Mini Games, and completes the adaptation of mouse and keyboard related interfaces. Let's see how to publish the game to WeChat PC Mini Games by Cocos Creator.
+
+## Use Cocos Creator to Access to WeChat PC Mini Games
+
+### Preparation
+
+Download and install the latest version of [WeChat for PC](https://windows.weixin.qq.com/?lang=en_US) and login to it with the WeChat account bound to the WeChat DevTools.
+
+### Process of Publishing
+
+1. Refer to the process of [Publish to WeChat Mini Games](./publish-wechatgame.md) and publish the game project to the WeChat Mini Game.
+
+2. In the **WeChat DevTools**, click the **Preview** button in the upper toolbar, select the **Automatic Preview** tab, check the **Launch PC for auto preview** option, and then click the **Compile and Remote Debug** button to preview and debug the mini game on the WeChat for PC.
+
+ 
+
+## FAQ
+
+Q: How to distinguish the **Mobile** and **PC** of WeChat through the engine interface?
+A: You can determine by `sys.isMobile` that the PC side returns `false` and the mobile side returns `true`.
+> **Note**: the simulator on the WeChat DevTools simulates a environment on the mobile, so it returns `true`.
+
+Q: Does the WeChat PC Mini Game support Mac?
+A: Yes. WeChat PC Mini Game already support Mac. The publishing process is the same as above.
+
+## Related Reference Links
+
+- [WeChat PC Mini Game Access Guide [cn]](https://developers.weixin.qq.com/minigame/dev/guide/open-ability/pc-game.html)
+- [Download WeChat for PC](https://windows.weixin.qq.com/?lang=en_US)
diff --git a/versions/4.0/en/editor/publish/publish-taobao-mini-game.md b/versions/4.0/en/editor/publish/publish-taobao-mini-game.md
new file mode 100644
index 0000000000..5d6f7a2075
--- /dev/null
+++ b/versions/4.0/en/editor/publish/publish-taobao-mini-game.md
@@ -0,0 +1,81 @@
+# Publish to Taobao Mini Game
+
+## Environment Configuration
+
+- Download [Taobao Mini Game Studio](https://developer.taobao.com/?spm=a219a.15212435.0.0.6a14669aEQ2g6k) to the desktop and install it.
+
+- Download [Taobao](https://market.m.taobao.com/app/fdilab/download-page/main/index.html) and install it on your mobile device.
+
+- The minimum version supported of the Taobao client on Android is 10.22.30 and on iOS is 10.22.30.
+
+## Publishing Process
+
+Use Cocos Creator to open the project to be published, select **Taobao Mini Game** in **Platform** of the **Build** panel, and then click **Build**.
+
+
+
+### Parameter Configuration
+
+The specific filling rules for related parameter configuration are as follows:
+
+- **Main Package Compression Type**
+
+ Set the compression type of the main package. For specific content, please refer to the document [Asset Bundle — Compression Type](../../asset/bundle.md#compression-type).
+
+- **Configure Main Package as Remote Package**
+
+ This is an optional item and needs to be used in conjunction with the option **Resource Server Address**.
+ After checking, the main package will be configured as a remote package and built with its related dependent resources into the built-in Asset Bundle — [main](../../asset/bundle.md#the-built-in-Asset-Bundle) under the release package directory remote.Developers need to upload the entire remote folder to the remote server.
+
+- **Start Scene Asset Bundle**
+
+ This option is optional.
+ If set, the start scene and its related dependent resources are built into the built-in Asset Bundle - [start-scene](../../asset/bundle.md#the-built-in-asset-bundle) to speed up the resource loading of the start scene.
+
+- **Resource Server Address**
+
+ This is an optional item used to fill in the address where resources are stored on a remote server. After building, developers need to manually upload the remote folder under the release package directory to the filled-in resource server address.
+
+- **Separate Engine**
+ This option is optional.
+ After checking, the initial package size of the game can be reduced. You can refer to the document [Usage Instructions](./taobaominigame-plugin.md) for instructions on how to use it. Please select Taobao Mini Game as the building platform.
+
+### Running Preview
+
+- After the build is finished, click the folder icon button in the bottom left corner of **Build Task**, you can see that the project folder `taobao-mini-game` is created in the `build` directory of the project, which already contains the configuration file `game.json` for the Taobao Mini Game environment.
+
+
+
+- Use **Taobao Mini Game Studio** to open the `taobao-mini-game` folder generated by the build to open the Taobao Mini Game project and preview/debug the game content.
+
+
+
+## Resource management for Taobao Mini Game environment
+
+Taobao Mini Game is similar to WeChat Mini Game in that there is a package size limit, and additional resources over **4MB** must be downloaded via network requests. When the package size is too large, configure the **Resource Server Address** option in the **Build** panel to upload the resources to a remote server, please refer to the [Upload Resources to Remote Server](../../asset/cache-manager.md) documentation.
+
+After the game starts, the engine will automatically download resources from the remote server address. Once the resources are downloaded, the engine's cache manager will record the save paths of these resources. This information is used to automatically delete some cached game resources when the cache space is insufficient. Please refer to [Cache Manager](../../asset/cache-manager.md) for more details.
+
+## Restrictions for Taobao Mini Game
+
+Work on adapting the Taobao Mini Game is not completely finished yet, and it is known that the text rendering may not work well on low-end machines. And the following modules are still not supported:
+
+- WebView
+- VideoPlayer
+- Custom Fonts
+
+## Differences Between Taobao and Other Mini Game Platforms
+
+- Access to Global Variables: Accessing global variables in Taobao requires mounting them onto the global object. For example: `$global.my = my;`
+
+- Explanation of 'global-variables.js': The window variable is a reference to the global object, so it is necessary to ensure that variables on the global object already exist for temporary variables to have values. If you are using custom scripts or third-party plugins and encounter situations where global variables are missing, it is typically due to loading timing issues, where the script is used before it is fully loaded.
+
+- The Taobao Mini Game platform currently uses a self-developed JS virtual machine (which may be replaced with v8 in the future). The JS performance of the current platform version is slightly inferior to the mainstream v8 engine, so when publishing games on this platform, special attention needs to be paid to the impact of the game's DrawCall count on performance. The Cocos engine provides a dynamic atlas feature to reduce draw calls generated by the game interface. You can enable the CLEANUP_IMAGE_CACHE option when building for the Taobao Mini Game platform.
+
+- Inconsistencies Among Taobao IDE, Simulator, and Real Device JS Environments: The JavaScript environments in Taobao's IDE, simulator, and real devices are not consistent. If there are no issues on real devices, it is recommended to report the problem directly to the Taobao platform.
+
+- Due to the additional performance overhead in real device debugging mode, it is advisable to use real device preview mode, rather than real device debugging mode, when verifying frame rates.
+
+## References
+
+- [Taobao Document Center - CN](https://miniapp.open.taobao.com/doc.htm?docId=121719&docType=1&tag=game-dev)
\ No newline at end of file
diff --git a/versions/4.0/en/editor/publish/publish-taobao-mini-game/build.png b/versions/4.0/en/editor/publish/publish-taobao-mini-game/build.png
new file mode 100644
index 0000000000..abc43ec3b3
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-taobao-mini-game/build.png differ
diff --git a/versions/4.0/en/editor/publish/publish-taobao-mini-game/build_option.png b/versions/4.0/en/editor/publish/publish-taobao-mini-game/build_option.png
new file mode 100644
index 0000000000..f0474c9a6b
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-taobao-mini-game/build_option.png differ
diff --git a/versions/4.0/en/editor/publish/publish-taobao-mini-game/preview.png b/versions/4.0/en/editor/publish/publish-taobao-mini-game/preview.png
new file mode 100644
index 0000000000..bc3f7aae11
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-taobao-mini-game/preview.png differ
diff --git a/versions/4.0/en/editor/publish/publish-vivo-mini-game.md b/versions/4.0/en/editor/publish/publish-vivo-mini-game.md
new file mode 100644
index 0000000000..875830b4c7
--- /dev/null
+++ b/versions/4.0/en/editor/publish/publish-vivo-mini-game.md
@@ -0,0 +1,120 @@
+# Publish to vivo Mini Games
+
+> **Note**: some platforms only have Chinese documentation available when visiting the platform's website. It may be necessary to use Google Translate in-order to review the documentation.
+
+## Environment Configuration
+
+- Download the [Quick App & vivo Mini Game Debugger](https://minigame.vivo.com.cn/documents/#/lesson/base/environment?id=%E5%AE%89%E8%A3%85vivo%E5%B0%8F%E6%B8%B8%E6%88%8F%E8%B0%83%E8%AF%95%E5%99%A8) and [vivo Mini Game Engine](https://minigame.vivo.com.cn/documents/#/lesson/base/environment?id=%E5%AE%89%E8%A3%85vivo%E5%B0%8F%E6%B8%B8%E6%88%8F%E5%BC%95%E6%93%8E) and install it on your Android device (recommended Android Phone 6.0 or above)
+
+- Install [nodejs-8.9.0](https://nodejs.org/en/download/) or above, globally:
+
+ > **Note**: after installing nodejs, you need to note whether the npm source address is
+
+ ```bash
+ # View current npm source address
+ npm config get registry
+
+ # If not, reset the npm source address
+ npm config set registry https://registry.npmjs.org/
+ ```
+
+- Install `vivo-minigame/cli` globally:
+
+ ```bash
+ npm install -g @vivo-minigame/cli
+ ```
+
+ If `vivo-minigame/cli` installation fails, it may be caused by too low version of **nodejs**. Please check the version of **node** and upgrade.
+
+## Build Options
+
+For some general build options of platforms, please refer to the [General Build Options](build-options.md) documentation for details.
+
+| Name | Optional | Default value | Description | Field name |
+| :-- | :-- | :-- | :-- | :-- |
+| **Start Scene Asset Bundle** | Optional | false | If set, the start scene and its related dependent resources are built into the built-in Asset Bundle — [start-scene](../../asset/bundle.md#the-built-in-asset-bundle) to speed up the resource loading of the start scene. | `startSceneAssetBundle` |
+| **Remote server address** | Optional | Empty | This option is optional and used to fill in the address of the remote server where the resources are stored.If this option is left blank, the `build/vivo-mini-game/remote` folder in the release package directory will be packaged into the rpk package.Refer to the Resource Management section for more details. | `remoteServerAddress` |
+| **Game Package Name** | required | (Project Name) | such as `com.example.demo` | `package` |
+| **Desktop Icon** | required | (Cocos Logo) | Click the **search icon** button at the back of the input box to select the icon you want. When building, the **Desktop Icon** will be built into the vivo Mini Game project. It is suggested to use `PNG` images for the **Desktop Icon**. | `icon` |
+| **Game Version Name** | required | (Cocos version) | **Game Version Name** is the real version, such as: **1.0.0**. | `versionName` |
+| **Game Version Number** | required | 1201 | **Game Version Number** is different from the **Game Version Name**, and the **Game Version Number** is mainly used to distinguish the version update. Each time when you submit audit, the game version number is at least 1 higher than the value of the last submitted audit. It must not be equal to or less than the value of the last submitted audit, and it is recommended that the **Game Version Number** be recursively incremented by 1 each time when the audit is submitted. | `versionCode` |
+| **Supported Minimum Platform Version Number** | required | 1035 | Please refer to [Official Documentation [cn]](https://minigame.vivo.com.cn/documents/#/download/engine?id=%E6%9B%B4%E6%96%B0%E8%AE%B0%E5%BD%95%EF%BC%9A) to check the latest version number of vivo engine. | `minPlatformVersion` |
+| **Orientation** | - | landscape | Device direction, it will be written in `manifest.json`.| `deviceOrientation` |
+| **Separate Engine** | Optional | - | Vivo has added **game engine plugin** feature since platform version number **1063**. This plugin has the official version of the Cocos Creator engine built-in. If the plugin is enabled in the first game the player experiences, all games that also have the plugin enabled do not need to download the Cocos Creator engine again, just use the same version of the engine directly from the public plugin library, or incremental update the engine. Check **Separate Engine** when using, and then build and release normally in the **Build** panel, without additional manual operation. Please refer to the [WeChat Engine Plugin Instructions](./wechatgame-plugin.md) for details. | `separateEngine` |
+| **Use debug keystore** | - | true | When you check **Use Debug Keystore**, it means that the rpk package built with the certificate that comes with Creator is used by default, and it is only used for **debugging**. when the rpk package is to be used to submit an audit, do not check the **Use Debug Keystore** to build it.| `useDebugKey` |
+| **Key certification path** | - | - | The key store certificate, the quick game on the Huawei App Market, must be signed with the release version certificate, and the certificate fingerprint must be configured in the background of the Huawei Developers Alliance. For details, please refer to the following **Generate Signature File** | `privatePemPath`, `certificatePemPath` |
+
+### Generate signature file
+
+If you don't check the **Keystore**, you need to configure the signature files **certificate.pem path** and **private.pem path**, where you build a rpk package that you can **publish directly**. The developer can configure two signature files by using the **search icon** button to the right of the input box.
+
+There are two ways to generate a signature files:
+
+- Generated by the **New** button after the **certificate.pem path** in the **Build** panel.
+
+- Generated by the command line.
+
+ The developer needs to generate the signature file **private.pem**, **certificate.pem** through tools such as **openssl**.
+
+ ```bash
+ # Generate a signature file with the openssl command tool
+ openssl req -newkey rsa:2048 -nodes -keyout private.pem -x509 -days 3650 -out certificate.pem
+ ```
+
+ > **Note**: **openssl** can be used directly in the terminal in Linux or Mac environment, and in the Windows environment you need to install `openssl` and configure system environment variables. Restart Creator after the configuration is complete.
+
+## Run the rpk
+
+
+
+There are three ways to run rpk on your phone:
+
+- **Method One**
+
+ Click the **Run** button at the bottom right of the `vivo-mini-game` build task in the **Build** panel and wait for the QR Code interface to be generated:
+
+ 
+
+ Then open the **Quick App & vivo Mini Game Debugger** that was installed before on your Android device. Click the **Scan code install** button to scan the QR Code to open the **rpk**.
+
+ 
+
+- **Method Two**
+
+ Copy the generated mini game **rpk** file (located in the `dist` directory) to the internal storage directory of the mobile phone.
+
+ Open the **Quick App & vivo Mini Game Debugger** that has been installed before on the Android device, click **Local Install**, then find the **rpk** file from the internal storage directory of your mobile phone and select **Open**.
+
+ 
+
+- **Method Three**
+
+ Specify to the editor installation directory `resources/tools/vivo-pack-tools` in the command line, and execute the command `npm run server` to generate URL and QR code using the vivo Mini Game Packer Commands.
+
+ ```bash
+ # Specify to the editor installation directory.
+ cd F:/CocosCreator/resources/tools/vivo-pack-tools
+
+ # Generate URL and QR code
+ npm run server
+ ```
+
+ Then open the **Quick App & vivo Mini Game Debugger** that was installed before on your Android device.
+
+ Finally, click the **Scan code install** button to copy the URL generated in the first step to the browser, and then directly scan the QR code on the web page to open the **rpk**.
+
+## Subpackage Loading
+
+The subpackage loading of vivo Mini Games is similar to WeChat Mini Games. Please refer to the [Mini Game Subpackage](subpackage.md) documentation for details.
+
+## vivo Mini Game Environment Resource Management
+
+Similar to WeChat Mini Games, Vivo Mini Games also have package size limitations. The main package size limit for Honor Mini Games is **4MB**, and any content exceeding this limit must be downloaded via network requests. When the package size is too large, you can configure the **Remote Server Address** option in the **Build and Publish** panel to upload low-priority resources to a remote server. For more details, please refer to [Uploading Resources to Remote Server](../../asset/cache-manager.md).
+
+After the game starts, the engine will automatically download resources from the remote server address. Once the resources are downloaded, the engine's cache manager will record the save paths of these resources. This information is used to automatically delete some cached game resources when the cache space is insufficient. Please refer to [Cache Manager](../../asset/cache-manager.md) for more details.
+
+## Reference documentation
+
+- [vivo Mini Games Development Documentation [cn]](https://minigame.vivo.com.cn/documents/#/lesson/base/start)
+- [vivo Mini Games API Documentation [cn]](https://minigame.vivo.com.cn/documents/#/api/system/life-cycle)
+- [Quick App & vivo Mini Game Debugger Download [cn]](https://minigame.vivo.com.cn/documents/#/download/debugger)
diff --git a/versions/4.0/en/editor/publish/publish-web.md b/versions/4.0/en/editor/publish/publish-web.md
new file mode 100644
index 0000000000..38d637772d
--- /dev/null
+++ b/versions/4.0/en/editor/publish/publish-web.md
@@ -0,0 +1,85 @@
+# Publish to Web Platforms
+
+Select **Project -> Build** from the main menu, and open the [Build](build-panel.md) panel.
+
+
+
+Cocos Creator provides two web platform page templates. Select **Web Mobile** or **Web Desktop** through the drop-down menu of **Platform**. The main differences between them are:
+
+- **Web Mobile** will fill the entire browser window with the game view by default.
+- **Web Desktop** allows to specify the resolution of a game view when publishing, and the game view will not change with the browser window size afterwards.
+
+## Introduction to Build Options
+
+For the general build options of each platform, please refer to the [General Build Options Introduction](build-options.md) documentation for details.
+
+### Web Desktop
+
+| Build options | Description | Field name (for command line publishing) |
+| :--- | :--- | :--- |
+| Resource Server Address | The server address used to download remote resources. For details, please refer to the content of the **Resource Server Address** section below. | `remoteServerAddress` |
+| WEBGPU | Whether use WebGPU as rendering backend | `WEBGPU` |
+| Preview resolution | Game view resolution, the default is **(1280, 960)** | `resolution` |
+| Polyfills | Build supports polyfills of some new features of scripts. Corresponding processing will be done when scripts are packaged. Developers can choose the polyfills to use according to actual needs. For the time being, only **Async Functions** are supported, and more functions will be opened in the future. | `polyfills` |
+
+### Web Mobile
+
+| Build options | Description | Field name (for command line publishing) |
+| :--- | :--- | :--- |
+| Resource Server Address | The server address used to download remote resources. For details, please refer to the content of the **Resource Server Address** section below. | `remoteServerAddress` |
+| Orientation | Optional values include **Auto**, **Landscape**, **Portrait** | `orientation` |
+| Polyfills | Build supports polyfills of some new features of scripts. Corresponding processing will be done when scripts are packaged. Currently, there are **async Functions** and **coreJs**. Developers can choose the polyfills to use according to actual needs. | `polyfills` |
+| vConsole | Insert the vConsole debugging plug-in. vConsole is similar to the mini version of DevTools for assisting debugging. | `embedWebDebugger` |
+| Preview the QR code | Used to scan and preview, see the introduction below for details |-|
+| Preview URL | Link for preview, see the introduction below for details |-|
+
+- **Resource server address**
+
+ This option is optional and used to fill in the address where the resource is stored on the server.
+
+ - If **do not fill in**, the `remote` folder in the release package directory will be packaged into the built game package.
+ - If **fill in**, it will not be packaged into the game package. Developers need to manually upload the `remote` folder in the release package directory to the resource server address filled in after the build. For details, please refer to [Upload resources to a remote server](../../asset/cache-manager.md).
+
+- **Preview URL**
+
+ The build supports simultaneous previewing of multiple Web projects, so the preview URL to be built is no longer uniform, but each build task will have a separate preview URL, which does not interfere with each other. Click the URL to automatically open the browser for preview. The specific preview URL splicing rule is **${Preview IP address in Preferences panel}:${Editor preview port number}/${Build platform}/${Build task name}/index.html**.
+
+ 
+
+## Build and Preview
+
+After configuring the build options, click the **Build** button to start the web platform version build. A progress bar will appear on the panel. When the progress bar shows **Build success**, the build is complete.
+
+Next, click the **Run** button to open the built game version in the browser for preview and debugging.
+
+
+
+The picture above is the preview of the Web Mobile platform. Notice that the game view occupies the entire browser window, while the game view of Web Desktop has a fixed resolution and will not fill the screen.
+
+### WebGPU Support (Experimental)
+
+[WebGPU](https://www.w3.org/TR/webgpu/) is the next generation GPU API for the web. Cocos Creator supports WebGPU as rendering backend for building Web-Desktop since 3.6.2, just enable `WebGPU` option in the build panel when building Web-Desktop.
+The build process will be a little bit different with `WebGPU` option enabled. Normal builtin server won't work for `WebGPU` package. When building done, you need to locate the package folder by clicking the folder icon in the build panel. Then you can either start an http-server or nginx server to make an accessible address for the supported browsers.
+As WebGPU standard is still a working draft, it's not widely supported on all browsers yet. So please remember to check the compatibility of WebGPU on your browser, see chapter **Browser Compatibility** below for details.
+
+### Browser Compatibility
+
+The desktop browsers tested during the development of Cocos Creator include: **Chrome**, **Firefox** and **QQ Browser**. Other browsers can be used normally as long as the kernel version is high enough. For the browser, please do not enable IE compatibility mode.
+
+Browsers tested on mobile devices include: **Safari (iOS)**, **Chrome (Android)**, **QQ Browser (Android)** and **UC Browser (Android)**.
+
+When you build Web-Desktop platform with `WEBGPU` option enabled, only certain versions of chromium is supported currently.
+Chromium history version is available [here](https://vikyd.github.io/download-chromium-history-version/#/), version 105 and 106 should be well supported by Cocos Creator's WebGPU build, support for later version is comming soon.
+After chromium is opened, visit `chrome://flags` in the address bar, then enable `WebGPU Developer Features` and reopen chromium, then everything is set for you to try your project rendered with WebGPU.
+
+## Retina Settings
+
+Set whether to use high resolution through `view.enableRetina(true)` in the script. Retina display will be turned on by default when it is built on the Web platform. For details, please refer to the [enableRetina](%__APIDOC__%/en/class/View?id=enableRetina) API.
+
+## Publish to Web Server
+
+To publish or share the game on the Internet, just click the **folder icon** button at the bottom left of the **Build Task**, and after opening the release path, follow the name of the current build task to build the corresponding folder in the the entire content is copied to the Web server and can be accessed through the corresponding address.
+
+
+
+Regarding the establishment of the Web server, search for related solutions such as Apache, Nginx, IIS, Express, etc.
diff --git a/versions/4.0/en/editor/publish/publish-web/preview-url.png b/versions/4.0/en/editor/publish/publish-web/preview-url.png
new file mode 100644
index 0000000000..6dbaf408c2
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-web/preview-url.png differ
diff --git a/versions/4.0/en/editor/publish/publish-web/web-folder.png b/versions/4.0/en/editor/publish/publish-web/web-folder.png
new file mode 100644
index 0000000000..3486a1b160
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-web/web-folder.png differ
diff --git a/versions/4.0/en/editor/publish/publish-web/web-mobile.png b/versions/4.0/en/editor/publish/publish-web/web-mobile.png
new file mode 100644
index 0000000000..a67bd441b2
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-web/web-mobile.png differ
diff --git a/versions/4.0/en/editor/publish/publish-web/web.png b/versions/4.0/en/editor/publish/publish-web/web.png
new file mode 100644
index 0000000000..b1ee8469f3
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-web/web.png differ
diff --git a/versions/4.0/en/editor/publish/publish-wechatgame.md b/versions/4.0/en/editor/publish/publish-wechatgame.md
new file mode 100644
index 0000000000..a1e6c09582
--- /dev/null
+++ b/versions/4.0/en/editor/publish/publish-wechatgame.md
@@ -0,0 +1,141 @@
+# Publish to WeChat Mini Games
+
+> **Note**: some platforms only have Chinese documentation available when visiting the platform's website. It may be necessary to use Google Translate in-order to review the documentation.
+
+The runtime environment of the **WeChat Mini Game** is an extension of the **WeChat Mini Program**, providing a WebGL interface encapsulation based on the mini program environment, greatly improving rendering capabilities and performance. However, since these interfaces are encapsulated by the WeChat team, they are not equivalent to the browser environment.
+
+On the engine side, in order to make the developers' workload as easy as possible, our main tasks for developers include the following:
+
+- The engine framework adapts to the WeChat Mini Game API, pure game logic level, developers do not need any additional modifications.
+- The **Cocos Creator** editor provides a fast packaging process, released directly as a **WeChat Mini Game**, and automatically evokes the **WeChat DevTools**.
+- Automatically load remote assets, cache assets, and cache asset version control.
+
+In addition, the game submission, review and release process of the **WeChat Mini Game** is no different from the **WeChat Mini Program**. Please refer to the [WeChat Mini Game Developer](https://developers.weixin.qq.com/minigame/en/dev/guide/) documentation.
+
+## Publish WeChat Mini Games with Cocos Creator
+
+1. Download the **WeChat DevTools** on [WeChat Official Document](https://developers.weixin.qq.com/miniprogram/en/dev/devtools/download.html)
+
+2. Set the **WeChatGame App Path** in **Cocos Creator/File -> Preferences -> [Native Develop](../../editor/preferences/index.md)**.
+
+ 
+
+3. Log in to the WeChat public platform and find the appid
+
+ 
+
+4. Select the **WeChat Game** in the **Platform** of the **Build** panel, fill in the `mini game appid`, and then click **Build**
+
+ 
+
+5. Click **Play** to open the **WeChat DevTools**
+
+ 
+
+ > **Note**: the **WeChat DevTools**, if it has not been run on a Mac before, will show an error that states: `Please ensure that the IDE has been properly installed`. You need to manually open the **WeChat DevTools** once, before you can click **Run**.
+
+6. Preview deployment
+
+ Following this process, a `wechatgame` folder will be generated in the project's **build** directory (the name of the folder is based on the **Build Task Name**), which already contains the configuration files `game.json` and `project.config.json` of the WeChat Mini Games environment.
+
+ 
+
+### Build Options
+
+
+
+| Options | Optional or not | Default | Explanation |
+| :-- | :-- | :-- | :-- |
+| **appid** | Required | `wx6ac3f5090a6b99c5` | The appid of the WeChat Mini Games, it will be written to `project.config.json` file.|
+| **Start Scene Asset Bundle** | Optional | false | If set, the start scene and its related dependent resources are built into the built-in Asset Bundle — [start-scene](../../asset/bundle.md#the-built-in-asset-bundle) to speed up the resource loading of the start scene.|
+| **Open data context root** | Optional | Empty | If an Open Data Context exists, use this root to specify the relative path of the Open Data Context folder in the build directory so that the directory is not overwritten or modified during the build.|
+| **Orientation** | Required | `landscape` | Device orientation, it will be written to `game.json` file.|
+| **Separate Engine** | Optional | Empty | Whether to use WeChat Mini Games engine plugin, please refer to [WeChat Mini Games Engine Plugin Instructions](./wechatgame-plugin.md) for details. |
+| **High Performance Mode** | Whether to use hight performance mode Please refer to [High Performance Mode](https://developers.weixin.qq.com/minigame/dev/guide/performance/perf-high-performance.html) for more details. |
+| **Wasm 3D physics system (based on `ammo.js`)** | Optional | Enabled | This option is used to select whether to enable **Wasm**, which takes effect when using **bullet(ammo.js)** physics. Please refer to the **WebAssembly Support** section below for more details. |
+| **Whether to enabled WebGL2** (Experimental feature) | - | Forced Off | In order to allow WebGL 2.0 to be enabled on WeChat Mini Games in the future, we have added this option in **v3.4.1** to support to enable WebGL 2.0 following the configuration in the **Project Settings** panel, and to turn off to reduce the package by default. If this option is set to **Consistent with project settings** and **WebGL 2.0** is checked in **Project Settings -> Feature Cropping**, it will be successfully enabled in the future if the WeChat environment supports WebGL 2.0. |
+
+## Asset Management for WeChat Mini Game Environment
+
+In a **WeChat Mini Game** environment, asset management is the most special part. It differs from the browser in the following four points:
+
+1. The size of the **WeChat Mini Game** package cannot exceed **4MB**, including all the code and assets. Additional assets must be downloaded via web request.
+
+2. For files downloaded from a remote server, the **WeChat Mini Game** environment does not have the browser's caching and outdated update mechanism.
+
+3. For the assets in the **WeChat Mini Game** package, they are not loaded on demand in the mini game environment, but rather all the assets in the package are loaded at once, and then the game page is launched.
+
+4. You cannot download script files from a remote server.
+
+This brings up two key issues, home page loading speed and remote asset caching and version management. For the home page loading speed, we recommend that developers only save the script file in the **WeChat Mini Game** package, and all other assets are downloaded from the remote server. As for downloading, caching and version management of remote assets, **Cocos Creator** has done the job for developers.
+
+In the **WeChat Mini Game** environment, we provide a `wxDownloader` object, and after setting the `REMOTE_SERVER_ROOT` property to it, the logic of the engine to download assets becomes:
+
+1. Check that assets are in the mini game package.
+2. If not present, query local cache assets.
+3. If no local cache assets are available, download from a remote server.
+4. Download and save them to the mini game application cache in backstage for re-access.
+5. Local cache storage has space limitation, if total space of cache exceeds the limit, there will be no more caching without disturbing game process.
+
+It should be noted that once the cache space is full, all the assets that need to be downloaded cannot be saved, only the temporary files for save download assets can be used, and WeChat will automatically clean up all temporary files after the mini game is exited. So the next time you run the mini game again, those assets are downloaded again and the process keeps looping.
+In addition, the problem of file saving failure due to cache space exceeding the limit does not occur on the **WeChat DevTools**, because the **WeChat DevTools** does not limit the cache size, so testing the cache needs to be done in a real WeChat environment.
+
+At the same time, when the **MD5 Cache** feature of the engine is enabled, the URL of the file will change as the content of the file changes, so that when a new version of the game is released, the assets of the old version will naturally become invalid in the cache, and only the new assets can be requested from the server, which achieves the effect of version control.
+
+Specifically, developers need to do:
+
+1. When building, check the **MD5 Cache** in the **Build** panel.
+2. Set the **Remote service address**, and then click **Build**.
+3. When the build is complete, upload the **res** folder in the mini game release package to the server.
+4. Delete the **res** folder inside the local release package.
+5. For the test phase, you may not be able to deploy to the official server, you need to use the local server to test, then open the details page in the WeChat DevTools, check the `Does not verify valid domain names, web-view (business domain names), TLS versions and HTTPS certificates` option in the **Local Settings**.
+
+ 
+
+> **Note**: if the cache asset exceeds the WeChat environment limit, you need to manually clear the asset. Use `wx.downloader.cleanAllAssets()` and `wx.downloader.cleanOldAssets()` to clear the cache in **WeChat Mini Games**. The former clears all the cache assets in the cache directory, please use it carefully. While the latter clears cache assets that are currently unused in the cache directory in the application.
+
+## WeChat Mini Game Subpackage Loading
+
+To achieve subpackage loading with **WeChat Mini Game**, please refer to [Mini Game Subpackage](subpackage.md) documentation.
+
+## Platform SDK Access
+
+In addition to pure game content, the **WeChat Mini Game** environment actually provides a very powerful native SDK interface, the most important of which are user, social, payment, etc. These interfaces are only available in the **WeChat Mini Game** environment, equivalent to third-party SDK interfaces for other platforms. The porting of such SDK interfaces still needs to be handled by developers at this stage. Here are some of the powerful SDK capabilities provided by WeChat Mini Games:
+
+1. User interface: login, authorization, user information, etc.
+2. WeChat payment
+3. Forward and get forwarding information
+4. File upload and download
+5. Media: pictures, recordings, cameras, etc.
+6. Other: location, device information, scan code, NFC, etc.
+
+## WeChat Mini Games Known issues
+
+Cocos Creator's adaptation of **WeChat Mini Games** has not been completely implemented. The following modules are still not supported:
+
+- VideoPlayer
+- WebView
+
+It is possible to use the missing functionality by calling the **WeChat's** API directly.
+
+## WebAssembly Support
+
+> **Note**: this section has been significantly changed in v3.3.1. For v3.3.0, please switch to the previous version documentation (e.g., v3.2) in the upper right corner of the page to view the content.
+
+As of 3.0, the **Wasm 3D physics system (based on `ammo.js`)** option has been added to the build options of WeChat Mini Game, which takes effect when **Projects -> Project Settings -> Feature Cropping -> 3D -> Physics System** in the editor's main menu is set to **bullet(ammo.js)**.
+
+The **Wasm 3D physics system** option is enabled by default, and the engine will automatically package codes in `wasm` mode when building. If disabled, `js` mode is used.
+
+> **Notes**:
+> 1. The WeChat Mini Games Separation Engine Plugin currently only supports **js** mode.
+> 2. WebAssembly required WeChat v7.0.17 and above.
+> 3. The WeChat WebAssembly debugging base library needs to be v2.12.0 and above.
+
+## Reference documentation
+
+- [WeChat Mini Game Developer Document](https://developers.weixin.qq.com/minigame/en/dev/guide/)
+- [WeChat Public Platform](https://mp.weixin.qq.com/?lang=en_US)
+- [WeChat Mini Game API Documentation](https://developers.weixin.qq.com/minigame/en/dev/api/)
+- [WeChat DevTools](https://developers.weixin.qq.com/miniprogram/en/dev/devtools/devtools.html)
+- [WeChat DevTools Download](https://mp.weixin.qq.com/debug/wxagame/en/dev/devtools/download.html)
+- [WeChat Cache Space Overflow Case](https://github.com/cocos-creator/test-wechat-mini-game)
diff --git a/versions/4.0/en/editor/publish/publish-wechatgame/appid.jpeg b/versions/4.0/en/editor/publish/publish-wechatgame/appid.jpeg
new file mode 100644
index 0000000000..1bd570ccb2
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-wechatgame/appid.jpeg differ
diff --git a/versions/4.0/en/editor/publish/publish-wechatgame/build.png b/versions/4.0/en/editor/publish/publish-wechatgame/build.png
new file mode 100644
index 0000000000..9d7d3fcc98
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-wechatgame/build.png differ
diff --git a/versions/4.0/en/editor/publish/publish-wechatgame/detail.jpeg b/versions/4.0/en/editor/publish/publish-wechatgame/detail.jpeg
new file mode 100644
index 0000000000..6c2584a505
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-wechatgame/detail.jpeg differ
diff --git a/versions/4.0/en/editor/publish/publish-wechatgame/game-json.png b/versions/4.0/en/editor/publish/publish-wechatgame/game-json.png
new file mode 100644
index 0000000000..9e7ed4fa0f
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-wechatgame/game-json.png differ
diff --git a/versions/4.0/en/editor/publish/publish-wechatgame/maintest-build.png b/versions/4.0/en/editor/publish/publish-wechatgame/maintest-build.png
new file mode 100644
index 0000000000..e45b3a3c7c
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-wechatgame/maintest-build.png differ
diff --git a/versions/4.0/en/editor/publish/publish-wechatgame/open-data-project-build.png b/versions/4.0/en/editor/publish/publish-wechatgame/open-data-project-build.png
new file mode 100644
index 0000000000..8b2dd5919b
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-wechatgame/open-data-project-build.png differ
diff --git a/versions/4.0/en/editor/publish/publish-wechatgame/package.jpg b/versions/4.0/en/editor/publish/publish-wechatgame/package.jpg
new file mode 100644
index 0000000000..453c49d44b
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-wechatgame/package.jpg differ
diff --git a/versions/4.0/en/editor/publish/publish-wechatgame/package.png b/versions/4.0/en/editor/publish/publish-wechatgame/package.png
new file mode 100644
index 0000000000..f00dc1df73
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-wechatgame/package.png differ
diff --git a/versions/4.0/en/editor/publish/publish-wechatgame/preference.png b/versions/4.0/en/editor/publish/publish-wechatgame/preference.png
new file mode 100644
index 0000000000..34de48bd65
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-wechatgame/preference.png differ
diff --git a/versions/4.0/en/editor/publish/publish-wechatgame/preview.jpeg b/versions/4.0/en/editor/publish/publish-wechatgame/preview.jpeg
new file mode 100644
index 0000000000..e0875e4e2a
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-wechatgame/preview.jpeg differ
diff --git a/versions/4.0/en/editor/publish/publish-wechatgame/preview.png b/versions/4.0/en/editor/publish/publish-wechatgame/preview.png
new file mode 100644
index 0000000000..7849d2ee83
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-wechatgame/preview.png differ
diff --git a/versions/4.0/en/editor/publish/publish-wechatgame/tool.jpeg b/versions/4.0/en/editor/publish/publish-wechatgame/tool.jpeg
new file mode 100644
index 0000000000..2c710168ee
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-wechatgame/tool.jpeg differ
diff --git a/versions/4.0/en/editor/publish/publish-wechatgame/wechat-build.png b/versions/4.0/en/editor/publish/publish-wechatgame/wechat-build.png
new file mode 100644
index 0000000000..703948657f
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-wechatgame/wechat-build.png differ
diff --git a/versions/4.0/en/editor/publish/publish-wechatgame/wechat-pc.png b/versions/4.0/en/editor/publish/publish-wechatgame/wechat-pc.png
new file mode 100644
index 0000000000..fbe5f592b6
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-wechatgame/wechat-pc.png differ
diff --git a/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/build.jpg b/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/build.jpg
new file mode 100644
index 0000000000..fcbb794a8c
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/build.jpg differ
diff --git a/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/certificate.png b/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/certificate.png
new file mode 100644
index 0000000000..ce93306c86
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/certificate.png differ
diff --git a/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/debug.png b/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/debug.png
new file mode 100644
index 0000000000..7510fe7da3
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/debug.png differ
diff --git a/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/play.png b/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/play.png
new file mode 100644
index 0000000000..bbfdc3a1e5
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/play.png differ
diff --git a/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/play2.png b/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/play2.png
new file mode 100644
index 0000000000..67e219f335
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/play2.png differ
diff --git a/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/rpk.png b/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/rpk.png
new file mode 100644
index 0000000000..0756594ccb
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/rpk.png differ
diff --git a/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/run.jpg b/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/run.jpg
new file mode 100644
index 0000000000..b072797a6d
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/run.jpg differ
diff --git a/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/xiaomi_options.jpg b/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/xiaomi_options.jpg
new file mode 100644
index 0000000000..52b34e9ec6
Binary files /dev/null and b/versions/4.0/en/editor/publish/publish-xiaomi-quick-game/xiaomi_options.jpg differ
diff --git a/versions/4.0/en/editor/publish/setup-native-development.md b/versions/4.0/en/editor/publish/setup-native-development.md
new file mode 100644
index 0000000000..3c1c1a51c7
--- /dev/null
+++ b/versions/4.0/en/editor/publish/setup-native-development.md
@@ -0,0 +1,94 @@
+# Setting Up Native Development Environment
+
+Cocos Creator supports building projects into native application projects that comply with different platform specifications. Before building and publishing native applications, developers need to configure the relevant native development environment.
+
+### Download Java SDK (JDK)
+
+Compiling Android projects requires a complete Java SDK toolkit on your development machine. Please download the appropriate installation package matching your operating system and architecture from:
+
+[JDK Development Kit 17.0.7 downloads](https://www.oracle.com/java/technologies/downloads/#java17)
+
+For Windows systems, after installing JDK, you need to add the `JAVA_HOME` system variable to environment variables. Follow these steps: Right-click My Computer -> Properties -> Advanced system settings -> Environment Variables. Add the variable as shown in the following image (variable value is the JDK installation path), then restart your computer for changes to take effect.
+
+
+
+To verify Java environment configuration, execute the following command in Mac Terminal or Windows Command Prompt. Successful installation will display version information:
+
+```
+java -version
+```
+
+If your system uses JRE, install [JAVA SE Runtime Environment](http://www.oracle.com/technetwork/java/javase/downloads/index.html).
+
+> **Note**: [OpenJDK](https://openjdk.org/) and JDK differ only in open-source licenses, with no fundamental differences in functionality or configuration methods.
+
+## Download Android Studio
+
+Different versions of Cocos Creator engine typically support different Android Studio versions. Users can refer to the following version recommendations and download the corresponding IDE from [Android Studio Archive](https://developer.android.com/studio/archive?hl=zh-cn).
+
+| Cocos Creator Version Range | Recommended Android Studio Version | JDK Version |
+| :-------------------------- | :--------------------------------- | :---------- |
+| v2.4.12+ or v3.8.0+ | 2022.2.1 or 2022.3.1 | JDK 17 |
+| v2.4.11- or v3.0.0-3.7.4 | 2020.3.1 or earlier versions | JDK 11 |
+
+## Download Android SDK and NDK
+
+After installing Android Studio, open SDK Manager following the official documentation: [SDK Manager Guide](https://developer.android.google.cn/studio/intro/update.html#sdk-manager).
+
+1. In SDK Platforms tab, select your desired API Levels. Recommended choices include mainstream API Level 26 (8.0), API Level 28 (9.0), etc.
+ * [Check Android versions corresponding to API Levels](https://developer.android.google.cn/tools/releases/platforms)
+ * [View minimum system versions supported by engine](../../advanced-topics/supported-versions.md)
+2. Remember the **Android SDK Location** path shown in the window, which will be used for configuring SDK and NDK paths in Cocos Creator editor
+3. In SDK Tools tab, check **Show Package Details** to display different tool versions before installation
+4. Under **Android SDK Build-Tools**, select the latest build tools version
+5. Check **Android SDK Platform-Tools** and **CMake**. For Android Support Library installation, refer to [Official Documentation - Support Library Setup](https://developer.android.google.cn/topic/libraries/support-library/setup)
+6. Select desired **NDK** version. Recommended versions: **r21 ~ r23** to avoid compatibility issues. Users with Apple M-series chips are recommended to use the **r24** version.
+7. Click **Apply** to install. You can also manage installed tools here later
+
+ 
+
+## Install Windows & Mac/iOS Development Environments
+
+- Windows requires [Visual Studio 2019/2022 Community Edition](https://www.visualstudio.com/downloads/download-visual-studio-vs). During installation, select **Desktop development with C++** and **Game development with C++** modules.
+- After Visual Studio installation, you can build and publish Windows platform games.
+
+ > **Important**: Do NOT check the **Cocos** option under **Game development with C++** module.
+
+- macOS requires Xcode 14 or later, [Download here](https://apps.apple.com/us/app/xcode/id497799835).
+- After Xcode installation, you can build and publish Mac & iOS platform games.
+
+## Configure Android Build Environment Paths
+
+After setting up native build environment, configure development paths in Cocos Creator editor (skip if not building for Android).
+From main menu: **Cocos Creator -> Preferences**, open **Program Manager** page to configure:
+
+- **Android SDK**: Enter the `Android SDK Location` path (should contain `build-tools`, `platforms` folders)
+- **Android NDK**: Find ndk folder under `Android SDK Location` path. For newer Android Studio versions, this folder contains multiple NDK versions. Enter your downloaded NDK version path in **Android NDK** field
+
+ > **Note**: New Android Studio versions support multiple NDK versions in ndk folder, while older versions store single version in `ndk-bundle`.
+
+ 
+
+> **Note**: These configurations apply during native project building. If configuration fails, manually set these environment variables: `NDK_ROOT`, `ANDROID_SDK_ROOT`.
+
+## Troubleshooting Notes
+
+Based on public beta feedback, here are additional potential issues:
+
+1. Package Name Issues
+
+ Verify **Game Package Name** in Build panel. Refer to [Build Options Documentation](./native-options.md#build-options) for platform-specific naming conventions.
+
+2. Android Runtime Error: `dlopen failed: cannot locate symbol "xxxx" referenced by "libcocos.so"...`
+
+ Verify NDK and Android SDK versions match the target device's Android system architecture. Test with NDK/SDK versions specified in this documentation.
+
+3. JDK Version Compatibility
+
+ When upgrading Android Studio and Gradle, ensure JDK version is upgraded to 17 or specified version to maintain compatibility.
+
+If build failures persist, please submit feedback via [Cocos Forum](https://discuss.cocos2d-x.org/c/33) including:
+- Cocos Creator version
+- Detailed reproduction steps
+- Build log from Build panel
+- Sample project reproducing the issue
diff --git a/versions/4.0/en/editor/publish/setup-native-development/sdk-manager.png b/versions/4.0/en/editor/publish/setup-native-development/sdk-manager.png
new file mode 100644
index 0000000000..4d36367000
Binary files /dev/null and b/versions/4.0/en/editor/publish/setup-native-development/sdk-manager.png differ
diff --git a/versions/4.0/en/editor/publish/setup-native-development/sdk.png b/versions/4.0/en/editor/publish/setup-native-development/sdk.png
new file mode 100644
index 0000000000..cf6e7a3b9d
Binary files /dev/null and b/versions/4.0/en/editor/publish/setup-native-development/sdk.png differ
diff --git a/versions/4.0/en/editor/publish/setup-native-development/windows-java-home.jpg b/versions/4.0/en/editor/publish/setup-native-development/windows-java-home.jpg
new file mode 100644
index 0000000000..0cfdde10d4
Binary files /dev/null and b/versions/4.0/en/editor/publish/setup-native-development/windows-java-home.jpg differ
diff --git a/versions/4.0/en/editor/publish/subpackage.md b/versions/4.0/en/editor/publish/subpackage.md
new file mode 100644
index 0000000000..a7248474a6
--- /dev/null
+++ b/versions/4.0/en/editor/publish/subpackage.md
@@ -0,0 +1,85 @@
+# Mini Game Subpackage
+
+Some mini game platforms support subpackaging to divide resources, scripts and scenes. Including WeChat Mini Game, Baidu Mini Game, Douyin Mini Game, Huawei Quick Game, OPPO Mini Game and vivo Mini Game.
+
+Cocos Creator supports [Asset Bundle](../../asset/bundle.md) starting in v2.4, which allows developers to divide contents that need to be subpackaged into multiple Asset Bundles, and these Asset Bundles will be built into subpackages of the mini game. Only the necessary main packages will be downloaded when you startup the game, and these subpackages will not be loaded, but will be manually loaded by the developer during the game. This effectively reduces the time for the game startup.
+
+## Configuration
+
+The Asset Bundle is configured in **folders**. When we select a folder in the **Assets** panel, the **Inspector** panel will show a **Is Bundle** option, if set, the folder-related configuration options will appear:
+
+
+
+In addition to the general [Asset Bundle Configuration](../../asset/bundle.md#configuration), the main settings to focus on for the mini game subpackage are:
+- Set the **Target Platform** to the mini game platform that you want to subpackage, and set the **Compression Type** to the **Mini Game Subpackage**.
+- The mini game subpackage can only be placed locally and cannot be configured as remote packages, so the **Is Remote Bundle** option cannot be checked.
+
+Once configured, click the **Check** button on the top right and the folder will be configured as a Asset Bundle.
+
+## Build
+
+When building, the **Main Bundle Compression Type** in the **Build** panel should be set to **Mini Game Subpackage**. For detailed instructions, please refer to the [Asset Bundle - Compression Type](../../asset/bundle.md#compression-type) documentation.
+
+After the project is built, this Asset Bundle folder is packaged into the `subpackages` folder in the release package directory of the mini game platform. Each folder contained in this folder is an Asset Bundle.
+
+**For example**, if the `assets/scene` folder in the Hello World project is configured as an Asset Bundle on the WeChat Mini Game, then after the project is built, a `scene` folder is generated in the `subpackages` folder in the release package directory, and the `scene` folder is an Asset Bundle.
+
+
+
+## WeChat Mini Games
+
+When building for the WeChat Mini Game, the configuration of the Asset Bundle will be automatically generated into the `game.json` configuration file of the WeChat Mini Games release package directory according to the rules.
+
+
+
+> **Note**: WeChat Mini Games require a specific version to support the Subpackage feature. WeChat 6.6.7 client, 2.1.0 and above base library support, please update to the latest client version. Developer tools please use version **1.02.1806120** and above. After updating the developer tools, don't forget to modify the version of **Details -> Local Settings -> Debug Base library** to 2.1.0 and above in the WeChat DevTools:
+>
+> 
+
+### Subpackage Load Packet Size Limit
+
+Currently, the size of the WeChat Mini Game subpackage has following restrictions:
+
+- The size of all subpackage of the entire Mini Game can not exceed **30M**.
+- The size of a single subpackage is not limited.
+- The main package size can not exceed **4M**.
+
+Please refer to the [WeChat Mini Game Subpackage Loading](https://developers.weixin.qq.com/minigame/en/dev/guide/base-ability/subPackage/useSubPackage.html) documentation for details.
+
+## ByteDance Mini Game
+
+When building for the ByteDance Mini Game, the configuration of the Asset Bundle will be automatically generated into the `game.json` configuration file of the ByteDance Mini Games release package directory according to the rules.
+
+
+
+For the specific property meanings in game.json, you can refer to the documentation:[ByteDane Mini Game Configurition](https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/framework/mini-game-configuration/).
+
+### Subpackage Limit
+
+Currently, the size of the WeChat Mini Game subpackage has following restrictions:
+
+- The size of all subpackage of the entire Mini Game can not exceed 20MB
+- The main package size can not exceed 4MB
+- The size of a single subpackage can not exceed 20MB
+
+> The ByteDance Mini Game Open Data Context is similar to the subpackage, which can not exceed a size of 4MB.
+
+For more details, pelease refer to:[ByteDance Mini Game Subpackage](https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/framework/subpackages/introduction).
+
+## vivo Mini Games
+
+When building for the vivo Mini Game, the configuration of the Asset Bundle will be automatically generated into the `manifest.json` configuration file in the `vivo-mini-game/src` directory of the vivo Mini Game release package according to the rules.
+
+
+
+> **Notes**:
+> 1. Starting with **1051** version, **Quick App & vivo Mini Game Debugger** supports the subpackage loading of vivo Mini Game. Versions lower than 1051 do not support subpackage loading, but they are also compatible. If a subpackage is configured in the editor's **Properties** panel, it will not affect the normal operation of the game. Please refer to the [vivo Mini Game Subpackage Loading -- Runtime Compatibility [cn]](https://minigame.vivo.com.cn/documents/#/lesson/base/subpackage?id=%e8%bf%90%e8%a1%8c%e6%97%b6%e5%85%bc%e5%ae%b9) documentation for details.
+> 2. Unlike other mini game platforms, the Asset Bundle folder for the vivo Mini Game will be generated in the `src` directory of release package `vivo-mini-game` directory after the project is built.
+>
+> 
+
+### Subpackage Load Packet Size Limit
+
+Currently, the size of the vivo Mini Game subpackage is limited to 20M (4M for main package and 16M for subpackages).
+
+Please refer to the [vivo Mini Game Subpackage Loading [cn]](https://minigame.vivo.com.cn/documents/#/lesson/base/subpackage) documentation for details.
diff --git a/versions/4.0/en/editor/publish/subpackage/devtools-setting.png b/versions/4.0/en/editor/publish/subpackage/devtools-setting.png
new file mode 100644
index 0000000000..cdc27d98d2
Binary files /dev/null and b/versions/4.0/en/editor/publish/subpackage/devtools-setting.png differ
diff --git a/versions/4.0/en/editor/publish/subpackage/profile.png b/versions/4.0/en/editor/publish/subpackage/profile.png
new file mode 100644
index 0000000000..5aea3b02d1
Binary files /dev/null and b/versions/4.0/en/editor/publish/subpackage/profile.png differ
diff --git a/versions/4.0/en/editor/publish/subpackage/subpackage-config.png b/versions/4.0/en/editor/publish/subpackage/subpackage-config.png
new file mode 100644
index 0000000000..d36609025a
Binary files /dev/null and b/versions/4.0/en/editor/publish/subpackage/subpackage-config.png differ
diff --git a/versions/4.0/en/editor/publish/subpackage/subpackage.png b/versions/4.0/en/editor/publish/subpackage/subpackage.png
new file mode 100644
index 0000000000..f86af19eda
Binary files /dev/null and b/versions/4.0/en/editor/publish/subpackage/subpackage.png differ
diff --git a/versions/4.0/en/editor/publish/subpackage/vivo-profile.png b/versions/4.0/en/editor/publish/subpackage/vivo-profile.png
new file mode 100644
index 0000000000..58b5b92a34
Binary files /dev/null and b/versions/4.0/en/editor/publish/subpackage/vivo-profile.png differ
diff --git a/versions/4.0/en/editor/publish/subpackage/vivo-subpackages.png b/versions/4.0/en/editor/publish/subpackage/vivo-subpackages.png
new file mode 100644
index 0000000000..effe4ea371
Binary files /dev/null and b/versions/4.0/en/editor/publish/subpackage/vivo-subpackages.png differ
diff --git a/versions/4.0/en/editor/publish/vivo-mini-game/build_options.jpg b/versions/4.0/en/editor/publish/vivo-mini-game/build_options.jpg
new file mode 100644
index 0000000000..5078eebf95
Binary files /dev/null and b/versions/4.0/en/editor/publish/vivo-mini-game/build_options.jpg differ
diff --git a/versions/4.0/en/editor/publish/vivo-mini-game/play.jpg b/versions/4.0/en/editor/publish/vivo-mini-game/play.jpg
new file mode 100644
index 0000000000..2bf3a964cb
Binary files /dev/null and b/versions/4.0/en/editor/publish/vivo-mini-game/play.jpg differ
diff --git a/versions/4.0/en/editor/publish/vivo-mini-game/rpk.png b/versions/4.0/en/editor/publish/vivo-mini-game/rpk.png
new file mode 100644
index 0000000000..98aafe1ba8
Binary files /dev/null and b/versions/4.0/en/editor/publish/vivo-mini-game/rpk.png differ
diff --git a/versions/4.0/en/editor/publish/vivo-mini-game/vivo-instant_native_install.jpg b/versions/4.0/en/editor/publish/vivo-mini-game/vivo-instant_native_install.jpg
new file mode 100644
index 0000000000..f0a0175bdb
Binary files /dev/null and b/versions/4.0/en/editor/publish/vivo-mini-game/vivo-instant_native_install.jpg differ
diff --git a/versions/4.0/en/editor/publish/vivo-mini-game/vivo-instant_scan_install.jpg b/versions/4.0/en/editor/publish/vivo-mini-game/vivo-instant_scan_install.jpg
new file mode 100644
index 0000000000..729e92eb9c
Binary files /dev/null and b/versions/4.0/en/editor/publish/vivo-mini-game/vivo-instant_scan_install.jpg differ
diff --git a/versions/4.0/en/editor/publish/vivo-mini-game/vivo_options.jpg b/versions/4.0/en/editor/publish/vivo-mini-game/vivo_options.jpg
new file mode 100644
index 0000000000..84728fcacf
Binary files /dev/null and b/versions/4.0/en/editor/publish/vivo-mini-game/vivo_options.jpg differ
diff --git a/versions/4.0/en/editor/publish/wechatgame-plugin.md b/versions/4.0/en/editor/publish/wechatgame-plugin.md
new file mode 100644
index 0000000000..8cb8df12c8
--- /dev/null
+++ b/versions/4.0/en/editor/publish/wechatgame-plugin.md
@@ -0,0 +1,39 @@
+# WeChat Mini Games Engine Plugin Instructions
+
+> **Note**: some platforms only have Chinese documentation available when visiting the platform's website. It may be necessary to use Google Translate in-order to review the documentation.
+
+The **Game Engine Plugin** is a new feature added to **WeChat v7.0.7**, which has the official version of the __Cocos Creator__ engine built in. If the plugin is enabled in the first game the player experiences, all games that also have the plugin enabled do not need to download the __Cocos Creator__ engine again, just use the same version of the engine directly from the public plugin library, or incremental update the engine.
+
+For example, when a player has played an A game developed using __Cocos Creator__ v2.2.0, and the A game already enabled this plugin. Then he played the B Game, also developed by v2.2.0, and would not have needed to re-download the __Cocos Creator__ engine if the B game had also enabled this plugin. Even if the B Game is developed using __Cocos Creator__ v2.2.1, WeChat only needs to incremental update the difference between the two engine versions. This will drastically reduce the download counts of mini games, and improve the startup speed of mini games by 0.5~2s for a better user experience.
+
+## How to use
+
+Simply check the **Separate Engine** option in the **Build** panel, and then build and release as normal, without additional manual operation. (This feature is only available when the built-in engine is used and the build is in non-debug mode.)
+
+
+
+## FAQ
+
+__Q:__ Does the engine plugin feature support engine customization?
+__A:__ Not supported. If the version does not match or the engine customization is enabled during the build, the built package will not actually use the engine plugin feature properly, although the editor will continue to build after an error occurs.
+
+__Q:__ The project enable the engine module clipping, should I need to disable it when using the engine plugin?
+__A:__ No, the project can continue to use the engine module clipping as before. The engine plugin provides a complete engine that is compatible with all clipping settings without affecting the original project package.
+
+__Q:__ After the engine plugin is enabled, will the engine code still be counted into the first package?
+__A:__ According to WeChat's rules, it will still be counted.
+
+__Q:__ After the engine plugin is enabled, can I remove all modules in **Project Setting -> Modules** of editor to reduce the package size?
+__A:__ No, because WeChat only supports engine plugin since v7.0.7, if the engine is clipped randomly, the game may not be able to run on a lower version of WeChat.
+
+__Q:__ When the engine plugin is enabled, prompt "Code package unpacking failed" or "Login user is not the developer of the Mini Program" in the WeChat DevTools, while the physical device previews correctly?
+__A:__ The default appid in the **Build** panel is a common test id, and according to WeChat's rules, you need to fill in the **appid** applied for yourself to test the engine plugin.
+
+__Q:__ When the engine plugin is enabled, prompt "Unauthorized plugin, `Add plugin`" in the WeChat DevTools?
+__A:__ Click the `Add plugin` in the prompt, then select add **CocosCreator** plugin and recompile. If prompt "There are no plugins to add" when you add the plugin, you can select the **Clear Cache -> Clear All** option in the WeChat DevTools and try again.
+
+## Reference documentation
+
+> **Note**: some platforms only have Chinese documentation available when visiting the platforms website. It may be necessary to use Google Translate in-order to review the documentation.
+
+- [WeChat Mini Games Engine Plugin Development Documentation](https://developers.weixin.qq.com/minigame/dev/guide/base-ability/game-engine-plugin.html)
diff --git a/versions/4.0/en/editor/publish/wechatgame-plugin/build-options.png b/versions/4.0/en/editor/publish/wechatgame-plugin/build-options.png
new file mode 100644
index 0000000000..d80679187a
Binary files /dev/null and b/versions/4.0/en/editor/publish/wechatgame-plugin/build-options.png differ
diff --git a/versions/4.0/en/editor/publish/windows/build-example-windows.md b/versions/4.0/en/editor/publish/windows/build-example-windows.md
new file mode 100644
index 0000000000..08d20a3a48
--- /dev/null
+++ b/versions/4.0/en/editor/publish/windows/build-example-windows.md
@@ -0,0 +1,93 @@
+# Windows Publishing Example
+
+This guide demonstrates how to publish a project created with Cocos Creator as a Windows application. Before proceeding, make sure you have the following prerequisites:
+
+- A Windows computer
+- C++ development environment
+
+## Installing C++ Development Environment
+
+First, you need to install [Visual Studio 2019/2022](https://www.visualstudio.com/downloads/download-visual-studio-vs).
+
+During the installation of Visual Studio, make sure to select the modules `Desktop development with C++` and `Game development with C++`.
+
+> **Note**: Within the Game development with C++ module, there is an option for **Cocos**. Please **do not** select this option.
+
+## Publishing Process
+
+### Prepare a Project for Testing
+
+Open an existing project or create a new test project.
+
+### Build
+
+
+
+As shown in the above image, select **Project -> Build** from the top menu of Cocos Creator to open the **Build** panel.
+
+
+
+#### General Options
+
+In the left section of the image above, you can find the common parameters that need to be configured for all platforms supported by Cocos Creator. For more details, refer to [General Build Options](./../build-options.md).
+
+#### Windows-specific Options
+
+Select the platform as **Windows**, and scroll down the panel to see the native and Windows-specific options as shown in the image on the right. For more information, refer to [General Native Build Options](./../native-options.md) and [Build Options - Windows](./build-options-windows.md).
+
+#### Start to Build
+
+Once the configuration is complete, click the **Build** button to generate the Visual Studio `*.sln` project.
+
+After a successful build, you can click the open file button as shown below to open the generated project folder.
+
+
+
+If you haven't changed the build path, you can find the `build/windows/proj` directory located in the project root, which contains the following files:
+
+
+
+### Compile and Run in Visual Studio
+
+Double-click on `build/windows/proj/.sln` to open the project with Visual Studio.
+
+
+
+As shown in the image above, the project includes the `cocos-engine` library and **project code**. Click the compile and run button to start the project.
+
+
+
+> `*.sln` is a Visual Studio project solution file, and it is recommended to open it with Visual Studio. You can also use IDEs such as **Rider** that support `*.sln` files.
+
+### Modifying the Resolution
+
+You can modify the resolution in `native/engine/common/classes/Game.cpp` using the `_windowInfo` property.
+
+The default resolution is set to **800 x 600**. Let's take an example of changing it to **800 x 400**.
+
+```C++
+int Game::init() {
+ _windowInfo.title = GAME_NAME;
+ // configure window size
+ _windowInfo.width = 800;
+ _windowInfo.height = 400;
+}
+```
+
+After making the modification, compile and run again in Visual Studio. The effect will be as shown in the image below:
+
+
+
+## Read More
+
+### Script-Native Communication
+
+Sometimes, projects need to call Windows system functions or, when integrating a third-party SDK, use script code to call its APIs. In such cases, the communication mechanism between the script layer and the native layer is required.
+
+For information on the JS script and C++ communication mechanism, please refer to the [Tutorial: JSB 2.0](../../../advanced-topics/JSB2.0-learning.md)。
+
+### Debugging JavaScript on Native Platforms
+
+Some issues only occur on specific devices and environments. If you can debug the code on the corresponding situation, you can quickly identify the problem and find a solution.
+
+Cocos Creator provides a native debugging mechanism that allows you to easily debug game code on a device. For more details, please refer to [Debugging JavaScript on Native Platforms](./../debug-jsb.md).
diff --git a/versions/4.0/en/editor/publish/windows/build-options-windows.md b/versions/4.0/en/editor/publish/windows/build-options-windows.md
new file mode 100644
index 0000000000..1304e7d296
--- /dev/null
+++ b/versions/4.0/en/editor/publish/windows/build-options-windows.md
@@ -0,0 +1,17 @@
+# Build Options - Windows
+
+The build options for the Windows platform include the **Render BackEnd** and **Target Platform**.
+
+
+
+## Executable Name
+
+This a field used to specify the name of the main executable file of an application. If not provided, the system will generate a default value based on the app name field. The value for this field must adhere to a specific format, containing only numbers, letters, underscores (_) and hyphens (-).
+
+## Render BackEnd
+
+On the Windows platform, Cocos Creator currently supports three render backends: **VULKAN**, **GLES3**, and **GLES2**. By default, **GLES3** is selected. If multiple options are selected, the runtime will choose the appropriate render backend based on the device's capabilities.
+
+## Target Platform
+
+Set the compilation architecture, currently only supporting **x64**, which means the application can only run on **x64** systems.
diff --git a/versions/4.0/en/editor/publish/windows/images/build-open-path-windows.png b/versions/4.0/en/editor/publish/windows/images/build-open-path-windows.png
new file mode 100644
index 0000000000..519ddb02a4
Binary files /dev/null and b/versions/4.0/en/editor/publish/windows/images/build-open-path-windows.png differ
diff --git a/versions/4.0/en/editor/publish/windows/images/build-options-windows.png b/versions/4.0/en/editor/publish/windows/images/build-options-windows.png
new file mode 100644
index 0000000000..06253e18ed
Binary files /dev/null and b/versions/4.0/en/editor/publish/windows/images/build-options-windows.png differ
diff --git a/versions/4.0/en/editor/publish/windows/images/build-panel-windows.png b/versions/4.0/en/editor/publish/windows/images/build-panel-windows.png
new file mode 100644
index 0000000000..aa63b2eda9
Binary files /dev/null and b/versions/4.0/en/editor/publish/windows/images/build-panel-windows.png differ
diff --git a/versions/4.0/en/editor/publish/windows/images/project-build-menu.png b/versions/4.0/en/editor/publish/windows/images/project-build-menu.png
new file mode 100644
index 0000000000..225f5c1c1a
Binary files /dev/null and b/versions/4.0/en/editor/publish/windows/images/project-build-menu.png differ
diff --git a/versions/4.0/en/editor/publish/windows/images/project-folder-windows.png b/versions/4.0/en/editor/publish/windows/images/project-folder-windows.png
new file mode 100644
index 0000000000..d1cdaa85f2
Binary files /dev/null and b/versions/4.0/en/editor/publish/windows/images/project-folder-windows.png differ
diff --git a/versions/4.0/en/editor/publish/windows/images/run-windows-800to400.png b/versions/4.0/en/editor/publish/windows/images/run-windows-800to400.png
new file mode 100644
index 0000000000..352915cb54
Binary files /dev/null and b/versions/4.0/en/editor/publish/windows/images/run-windows-800to400.png differ
diff --git a/versions/4.0/en/editor/publish/windows/images/run-windows.png b/versions/4.0/en/editor/publish/windows/images/run-windows.png
new file mode 100644
index 0000000000..acb3fc3312
Binary files /dev/null and b/versions/4.0/en/editor/publish/windows/images/run-windows.png differ
diff --git a/versions/4.0/en/editor/publish/windows/images/vs-showcase-windows.png b/versions/4.0/en/editor/publish/windows/images/vs-showcase-windows.png
new file mode 100644
index 0000000000..55f9fe6850
Binary files /dev/null and b/versions/4.0/en/editor/publish/windows/images/vs-showcase-windows.png differ
diff --git a/versions/4.0/en/editor/publish/windows/index.md b/versions/4.0/en/editor/publish/windows/index.md
new file mode 100644
index 0000000000..721f66b6d3
--- /dev/null
+++ b/versions/4.0/en/editor/publish/windows/index.md
@@ -0,0 +1,18 @@
+# Publishing Windows Desktop Apps
+
+Cocos Creator supports publishing Windows desktop applications, but it requires at least one device that supports Windows.
+
+## Content
+
+- [Windows Publishing Example](./build-example-windows.md)
+- [Build Options - Windows](build-options-windows.md)
+
+## Read More
+
+- [Setting up Native Development Environment](../setup-native-development.md)
+- [Build Panel](../build-panel.md)
+- [General Build Panel](../build-options.md)
+- [General Native Build Options](../native-options.md)
+- [Debugging JavaScript on Native Platforms](../debug-jsb.md)
+- [Build Process and FAQ](../build-guide.md)
+- [Native Platform Secondary Development Guide](../../../advanced-topics/native-secondary-development.md)
diff --git a/versions/4.0/en/editor/rendering/lod.md b/versions/4.0/en/editor/rendering/lod.md
new file mode 100644
index 0000000000..9b9182da93
--- /dev/null
+++ b/versions/4.0/en/editor/rendering/lod.md
@@ -0,0 +1,139 @@
+# Level Of Details
+
+Level Of Details (LOD) is a common optimization method used in large-scene development, where the core of LOD is to reduce the display details of distant or unimportant objects to improve rendering efficiency.
+
+The common practice of LOD is to use low-poly for some objects that are far away from the screen or unimportant instead.
+
+To enable LOD in the engine, select the **Add Component** button in the **Inspector** panel and select the **LOD Group** component.
+
+
+
+When added, the words **Culled** or **LOD** will be displayed in the scene.
+
+
+
+## Properties
+
+
+
+The properties of the LOD Group component are described as follows.
+
+| Properties | Description |
+| :-- | :-- |
+| **Recalculate Bounds** | Recalculate Bounds When this button is clicked, the model bounds for the entire group are recalculated This button calls the `recalculateBounds` interface to recalculate the bounds, which will also effects the **Object Size** property |
+| **Object Size** | Bounding box size Calculate the bounding box of the object and take the axis with the largest value in X, Y, Z Clicking the **Reset Object Size** button on the right will reset this property to 1
+| **LOD(0 ~ 3)** | LOD. Click the **>** symbol on the left side to expand for configuration, please refer to the figure below for the expanded content. LOD0 indicates the richest display detail LOD2 shows low-poly When the object's screen ratio is less than the **Screen Ratio** value of LOD2, the object will be culled |
+
+Click on any **> LOD(0 ~ 3)** on the **Inspector** panel to expand it and the following image will be displayed.
+
+
+
+Its properties and description are as follows.
+
+| Properties | Description |
+| :-- | :-- |
+| **Screen Ratio(%)** | Screen Ratio [0, 1]。 Developers can enter a custom screen ratio in the back input box, or the screen ratio can be calculated automatically with **Apply Current Screen Ratio** When the screen ratio is lower than the currently configured value, LOD will automatically switch to the next level; if there are no more levels, the object will be culled |
+| **Apply Current Screen Ratio** | Applying the Current Screen Ratio When pressed, the LOD Group component takes the screen ratio of the current display state as the value of **Screen Ratio (%)** |
+| **Mesh Renderers** | Mesh Renderer Please refer to the documentation below for more detailed information |
+| **0 Triangle - 0 Sub Mesh(es)** | This property shows the number of triangulated surfaces configured at the current level and the number of their submeshes
+
+### Mesh Renderer Properties
+
+The mesh renderer can be changed by clicking on the  and  buttons below to add or remove actions.
+
+Once added, the node with the mesh renderer within the hierarchy manager can be configured by dragging and dropping the following.
+
+
+
+## LOD
+
+Mouse over the right side of the LOD to display the mesh information to show the Add or Remove Levels button.
+
+
+
+Clicking on  will add a new LOD to the end of the array.
+
+Clicking on  will delete the LOD currently pointed to by the mouse; after deletion, subsequent LODs are automatically shifted forward.
+
+## Preview
+
+Once you have configured the LOD, you can preview the different levels with the mouse wheel in the scene manager.
+
+
+
+As the mouse scrolling changes, the scene camera will gradually pull away, and the level of the LOD will change, if the screen ratio of the current object is lower than the configured screen ratio of LOD2, the scene management system will cull it. The screen will show the current LOD Group's hierarchy status LOD(0~3) or Culled.
+
+## Use of scripts
+
+The developer can obtain the component via the `getComponent` method.
+
+```ts
+import { _decorator, Component, Node, LODGroup } from 'cc';
+const { ccclass, property, requireComponent } = _decorator;
+
+@ccclass('LOD')
+@requireComponent(LODGroup)
+export class LOD extends Component {
+
+ lodGroup : LODGroup | null = null;
+
+ start() {
+ this.lodGroup = this.node.getComponent(LODGroup);
+ }
+
+ update(deltaTime: number) {
+
+ }
+}
+```
+
+API reference could be found at [LOD Group API](%__APIDOC__%/en/class/LODGroup)
+
+## Art Workflow
+
+In real project development, artists can perform faceting operations in DCC software (Maya, 3D Max, Blender) and export the model.
+
+It is often possible to export multiple models at different levels or add different sub-meshes to the same model to represent different LOD levels.
+
+
+
+### Automatic Matching
+
+The LOD Group component automatically matches child meshes or mesh renderers of models exported via DCC software that have multiple child nodes ending in **_lod+[0,N]**.
+
+#### Example of automatic matching
+
+Make sure you have exported the appropriate model according to the rules above.
+
+Import the prepared FBX or glTF file into the engine's **Asset Manager** at
+
+
+
+In this case, the asset import system automatically recognizes these nodes and enables LOD Groups for automatic matching.
+
+
+
+#### Auto LOD
+
+Since v3.8, we have optimized the LOD when importing models, if the model does not have LOD information, you can find the Model pagination on the **Inspector** panel of the model, find and edit the LOD of the model, check the LOD check box to enable auto LOD.
+
+
+
+Mouse over the hierarchy to click / to increase and decrease the level.
+
+
+
+- Face count(%): the face count ratio, the ratio of the number of triangular faces of the optimized mesh divided by the number of faces of the original mesh. For example, 25% means 75% original faces will be optimized.
+- Screen Ratio: the minimum screen ratio, same as the Screen Ratio property of the LOD component, see above.
+
+Each tier is set up similarly to the LOD component, allowing you to modify the percentage of faces in different tiers.
+
+## Q&A
+
+- Can I add more than one LOD Group?
+
+ Yes. They will work well with each other.
+
+- Can I use LODs within a 2D scene?
+
+ Since LOD Group components only recognize MeshRenderers and 2D or UI components usually don't have MeshRenderers, it doesn't make much sense to do so.
diff --git a/versions/4.0/en/editor/rendering/lod/+.png b/versions/4.0/en/editor/rendering/lod/+.png
new file mode 100644
index 0000000000..eb5321a9ba
Binary files /dev/null and b/versions/4.0/en/editor/rendering/lod/+.png differ
diff --git a/versions/4.0/en/editor/rendering/lod/-.png b/versions/4.0/en/editor/rendering/lod/-.png
new file mode 100644
index 0000000000..197fef21f9
Binary files /dev/null and b/versions/4.0/en/editor/rendering/lod/-.png differ
diff --git a/versions/4.0/en/editor/rendering/lod/add-comp.png b/versions/4.0/en/editor/rendering/lod/add-comp.png
new file mode 100644
index 0000000000..564267d0ad
Binary files /dev/null and b/versions/4.0/en/editor/rendering/lod/add-comp.png differ
diff --git a/versions/4.0/en/editor/rendering/lod/add-remove-level.png b/versions/4.0/en/editor/rendering/lod/add-remove-level.png
new file mode 100644
index 0000000000..bc75de91e0
Binary files /dev/null and b/versions/4.0/en/editor/rendering/lod/add-remove-level.png differ
diff --git a/versions/4.0/en/editor/rendering/lod/auto-match.png b/versions/4.0/en/editor/rendering/lod/auto-match.png
new file mode 100644
index 0000000000..2fc09c02c8
Binary files /dev/null and b/versions/4.0/en/editor/rendering/lod/auto-match.png differ
diff --git a/versions/4.0/en/editor/rendering/lod/dcc-export.png b/versions/4.0/en/editor/rendering/lod/dcc-export.png
new file mode 100644
index 0000000000..ab6024b2f2
Binary files /dev/null and b/versions/4.0/en/editor/rendering/lod/dcc-export.png differ
diff --git a/versions/4.0/en/editor/rendering/lod/drag-mesh.gif b/versions/4.0/en/editor/rendering/lod/drag-mesh.gif
new file mode 100644
index 0000000000..a49516d4ac
Binary files /dev/null and b/versions/4.0/en/editor/rendering/lod/drag-mesh.gif differ
diff --git a/versions/4.0/en/editor/rendering/lod/enabled.png b/versions/4.0/en/editor/rendering/lod/enabled.png
new file mode 100644
index 0000000000..82515eaab9
Binary files /dev/null and b/versions/4.0/en/editor/rendering/lod/enabled.png differ
diff --git a/versions/4.0/en/editor/rendering/lod/hover.png b/versions/4.0/en/editor/rendering/lod/hover.png
new file mode 100644
index 0000000000..66272d83da
Binary files /dev/null and b/versions/4.0/en/editor/rendering/lod/hover.png differ
diff --git a/versions/4.0/en/editor/rendering/lod/import-asset.png b/versions/4.0/en/editor/rendering/lod/import-asset.png
new file mode 100644
index 0000000000..bf1b14fbc0
Binary files /dev/null and b/versions/4.0/en/editor/rendering/lod/import-asset.png differ
diff --git a/versions/4.0/en/editor/rendering/lod/lod0.png b/versions/4.0/en/editor/rendering/lod/lod0.png
new file mode 100644
index 0000000000..135bb35848
Binary files /dev/null and b/versions/4.0/en/editor/rendering/lod/lod0.png differ
diff --git a/versions/4.0/en/editor/rendering/lod/mesh-renderers.png b/versions/4.0/en/editor/rendering/lod/mesh-renderers.png
new file mode 100644
index 0000000000..838b1ce296
Binary files /dev/null and b/versions/4.0/en/editor/rendering/lod/mesh-renderers.png differ
diff --git a/versions/4.0/en/editor/rendering/lod/model.png b/versions/4.0/en/editor/rendering/lod/model.png
new file mode 100644
index 0000000000..06e7a51b1b
Binary files /dev/null and b/versions/4.0/en/editor/rendering/lod/model.png differ
diff --git a/versions/4.0/en/editor/rendering/lod/preview.gif b/versions/4.0/en/editor/rendering/lod/preview.gif
new file mode 100644
index 0000000000..054a1e8d7f
Binary files /dev/null and b/versions/4.0/en/editor/rendering/lod/preview.gif differ
diff --git a/versions/4.0/en/editor/rendering/lod/property.png b/versions/4.0/en/editor/rendering/lod/property.png
new file mode 100644
index 0000000000..0a88e716af
Binary files /dev/null and b/versions/4.0/en/editor/rendering/lod/property.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/2d.png b/versions/4.0/en/editor/scene/bar_img/2d.png
new file mode 100644
index 0000000000..84cc636e1b
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/2d.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/3d.png b/versions/4.0/en/editor/scene/bar_img/3d.png
new file mode 100644
index 0000000000..ee60de495a
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/3d.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/align-bar.png b/versions/4.0/en/editor/scene/bar_img/align-bar.png
new file mode 100644
index 0000000000..66ccd1a4ff
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/align-bar.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/align.png b/versions/4.0/en/editor/scene/bar_img/align.png
new file mode 100644
index 0000000000..b197746bfd
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/align.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/all-use-x.png b/versions/4.0/en/editor/scene/bar_img/all-use-x.png
new file mode 100644
index 0000000000..46094417cf
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/all-use-x.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/anchor-or-center.png b/versions/4.0/en/editor/scene/bar_img/anchor-or-center.png
new file mode 100644
index 0000000000..9903360e0e
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/anchor-or-center.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/center.png b/versions/4.0/en/editor/scene/bar_img/center.png
new file mode 100644
index 0000000000..dd020cc8ec
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/center.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/desig-resolution.png b/versions/4.0/en/editor/scene/bar_img/desig-resolution.png
new file mode 100644
index 0000000000..7ff551fe0e
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/desig-resolution.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/distribute.png b/versions/4.0/en/editor/scene/bar_img/distribute.png
new file mode 100644
index 0000000000..3b3e9fed63
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/distribute.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/increase-snap-config.png b/versions/4.0/en/editor/scene/bar_img/increase-snap-config.png
new file mode 100644
index 0000000000..1b8ce6eb2f
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/increase-snap-config.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/light.png b/versions/4.0/en/editor/scene/bar_img/light.png
new file mode 100644
index 0000000000..b4185acb22
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/light.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/local.png b/versions/4.0/en/editor/scene/bar_img/local.png
new file mode 100644
index 0000000000..f7bb11eb98
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/local.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/moveing.png b/versions/4.0/en/editor/scene/bar_img/moveing.png
new file mode 100644
index 0000000000..02d58a2a35
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/moveing.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/rect.png b/versions/4.0/en/editor/scene/bar_img/rect.png
new file mode 100644
index 0000000000..b9ffec6a63
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/rect.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/rotating.png b/versions/4.0/en/editor/scene/bar_img/rotating.png
new file mode 100644
index 0000000000..0d12b188a9
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/rotating.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/rotation.png b/versions/4.0/en/editor/scene/bar_img/rotation.png
new file mode 100644
index 0000000000..bfb625cf85
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/rotation.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/scale.png b/versions/4.0/en/editor/scene/bar_img/scale.png
new file mode 100644
index 0000000000..779187653b
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/scale.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/scaling.png b/versions/4.0/en/editor/scene/bar_img/scaling.png
new file mode 100644
index 0000000000..658e8f9d7b
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/scaling.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/shaded.png b/versions/4.0/en/editor/scene/bar_img/shaded.png
new file mode 100644
index 0000000000..66248a09fb
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/shaded.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/translate.png b/versions/4.0/en/editor/scene/bar_img/translate.png
new file mode 100644
index 0000000000..d20ca60753
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/translate.png differ
diff --git a/versions/4.0/en/editor/scene/bar_img/world-or-local.png b/versions/4.0/en/editor/scene/bar_img/world-or-local.png
new file mode 100644
index 0000000000..6ebe2b1952
Binary files /dev/null and b/versions/4.0/en/editor/scene/bar_img/world-or-local.png differ
diff --git a/versions/4.0/en/editor/scene/camera-gizmo.md b/versions/4.0/en/editor/scene/camera-gizmo.md
new file mode 100644
index 0000000000..dff9d3c13f
--- /dev/null
+++ b/versions/4.0/en/editor/scene/camera-gizmo.md
@@ -0,0 +1,15 @@
+# Camera Gizmo
+
+**Camera Gizmo** is used to show the clip area of a camera, you can read the [Camera Introduction](../components/camera-component.md) documentation for more information about camera.
+
+## Perspective Camera Gizmo
+
+**Perspective Camera Gizmo** shows the shape of frustum, which is calculate by the distance of the near clip plane, far clip plane and fov. You can edit them by dragging the control quad.
+
+
+
+## Ortho Camera Gizmo
+
+**Ortho Camera Gizmo** shows the shape of box, which is calculated by the distance of the near clip plane, far clip plane and the height of ortho camera. You can edit them by dragging the control quad.
+
+
diff --git a/versions/4.0/en/editor/scene/collider-gizmo.md b/versions/4.0/en/editor/scene/collider-gizmo.md
new file mode 100644
index 0000000000..d90b3939cf
--- /dev/null
+++ b/versions/4.0/en/editor/scene/collider-gizmo.md
@@ -0,0 +1,11 @@
+# Collider Gizmo
+
+Information about colliders for Cocos Creator can be found at: [Colliders](../../physics/physics-collider.md)
+
+The collider gizmo is used to display the position and size of the collider in the editor. Select any node with a collider component in the **Hierarchy** panel to see its gizmo in the scene window:
+
+
+
+For all colliders, the collider can be resized by selecting and dragging these squares with the mouse. The following figure shows how to resize colliders, using the **box collider gizmo** as an example.
+
+
diff --git a/versions/4.0/en/editor/scene/images/auto-snapping.gif b/versions/4.0/en/editor/scene/images/auto-snapping.gif
new file mode 100644
index 0000000000..60bc7c28be
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/auto-snapping.gif differ
diff --git a/versions/4.0/en/editor/scene/images/bar.png b/versions/4.0/en/editor/scene/images/bar.png
new file mode 100644
index 0000000000..3b089be1ef
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/bar.png differ
diff --git a/versions/4.0/en/editor/scene/images/bar2d.png b/versions/4.0/en/editor/scene/images/bar2d.png
new file mode 100644
index 0000000000..572360db6e
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/bar2d.png differ
diff --git a/versions/4.0/en/editor/scene/images/box-collider-gizmo.png b/versions/4.0/en/editor/scene/images/box-collider-gizmo.png
new file mode 100644
index 0000000000..f0e3fc021f
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/box-collider-gizmo.png differ
diff --git a/versions/4.0/en/editor/scene/images/camera-ortho-gizmo.png b/versions/4.0/en/editor/scene/images/camera-ortho-gizmo.png
new file mode 100644
index 0000000000..7b45da27de
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/camera-ortho-gizmo.png differ
diff --git a/versions/4.0/en/editor/scene/images/camera-perspective-gizmo.png b/versions/4.0/en/editor/scene/images/camera-perspective-gizmo.png
new file mode 100644
index 0000000000..3cfed133f5
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/camera-perspective-gizmo.png differ
diff --git a/versions/4.0/en/editor/scene/images/debug-preview.png b/versions/4.0/en/editor/scene/images/debug-preview.png
new file mode 100644
index 0000000000..252f6f32a3
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/debug-preview.png differ
diff --git a/versions/4.0/en/editor/scene/images/edit-collider.gif b/versions/4.0/en/editor/scene/images/edit-collider.gif
new file mode 100644
index 0000000000..4bac5bb1fd
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/edit-collider.gif differ
diff --git a/versions/4.0/en/editor/scene/images/edit-resolution.png b/versions/4.0/en/editor/scene/images/edit-resolution.png
new file mode 100644
index 0000000000..21bfc1daca
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/edit-resolution.png differ
diff --git a/versions/4.0/en/editor/scene/images/enable-snaping-rotating.gif b/versions/4.0/en/editor/scene/images/enable-snaping-rotating.gif
new file mode 100644
index 0000000000..a4580d5321
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/enable-snaping-rotating.gif differ
diff --git a/versions/4.0/en/editor/scene/images/global-rotation.png b/versions/4.0/en/editor/scene/images/global-rotation.png
new file mode 100644
index 0000000000..576a99543d
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/global-rotation.png differ
diff --git a/versions/4.0/en/editor/scene/images/increase-snap-conf.png b/versions/4.0/en/editor/scene/images/increase-snap-conf.png
new file mode 100644
index 0000000000..bed3de572d
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/increase-snap-conf.png differ
diff --git a/versions/4.0/en/editor/scene/images/light-off.png b/versions/4.0/en/editor/scene/images/light-off.png
new file mode 100644
index 0000000000..e6e5f93211
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/light-off.png differ
diff --git a/versions/4.0/en/editor/scene/images/light-on.png b/versions/4.0/en/editor/scene/images/light-on.png
new file mode 100644
index 0000000000..f87cfb06e4
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/light-on.png differ
diff --git a/versions/4.0/en/editor/scene/images/local-rotation.png b/versions/4.0/en/editor/scene/images/local-rotation.png
new file mode 100644
index 0000000000..66d69c05f0
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/local-rotation.png differ
diff --git a/versions/4.0/en/editor/scene/images/multiple-select.gif b/versions/4.0/en/editor/scene/images/multiple-select.gif
new file mode 100644
index 0000000000..7f9642f752
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/multiple-select.gif differ
diff --git a/versions/4.0/en/editor/scene/images/particle-box-gizmo.png b/versions/4.0/en/editor/scene/images/particle-box-gizmo.png
new file mode 100644
index 0000000000..94832637c9
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/particle-box-gizmo.png differ
diff --git a/versions/4.0/en/editor/scene/images/particle-circle-gizmo.png b/versions/4.0/en/editor/scene/images/particle-circle-gizmo.png
new file mode 100644
index 0000000000..3a39cd2ab0
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/particle-circle-gizmo.png differ
diff --git a/versions/4.0/en/editor/scene/images/particle-cone-gizmo.png b/versions/4.0/en/editor/scene/images/particle-cone-gizmo.png
new file mode 100644
index 0000000000..86fa6f8650
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/particle-cone-gizmo.png differ
diff --git a/versions/4.0/en/editor/scene/images/particle-hemisphere-gizmo.png b/versions/4.0/en/editor/scene/images/particle-hemisphere-gizmo.png
new file mode 100644
index 0000000000..bf106f3dd4
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/particle-hemisphere-gizmo.png differ
diff --git a/versions/4.0/en/editor/scene/images/particle-sphere-gizmo.png b/versions/4.0/en/editor/scene/images/particle-sphere-gizmo.png
new file mode 100644
index 0000000000..7f86d8ed2e
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/particle-sphere-gizmo.png differ
diff --git a/versions/4.0/en/editor/scene/images/position-gizmo.png b/versions/4.0/en/editor/scene/images/position-gizmo.png
new file mode 100644
index 0000000000..c9f0b9d98f
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/position-gizmo.png differ
diff --git a/versions/4.0/en/editor/scene/images/rect-gizmo.png b/versions/4.0/en/editor/scene/images/rect-gizmo.png
new file mode 100644
index 0000000000..8b23b7c45f
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/rect-gizmo.png differ
diff --git a/versions/4.0/en/editor/scene/images/rect-tool-snap-config.png b/versions/4.0/en/editor/scene/images/rect-tool-snap-config.png
new file mode 100644
index 0000000000..83d1192eae
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/rect-tool-snap-config.png differ
diff --git a/versions/4.0/en/editor/scene/images/reference.png b/versions/4.0/en/editor/scene/images/reference.png
new file mode 100644
index 0000000000..b0da445ca9
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/reference.png differ
diff --git a/versions/4.0/en/editor/scene/images/remove-light.png b/versions/4.0/en/editor/scene/images/remove-light.png
new file mode 100644
index 0000000000..e75dc8473c
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/remove-light.png differ
diff --git a/versions/4.0/en/editor/scene/images/rotation-gizmo.png b/versions/4.0/en/editor/scene/images/rotation-gizmo.png
new file mode 100644
index 0000000000..87ccdda345
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/rotation-gizmo.png differ
diff --git a/versions/4.0/en/editor/scene/images/rotation.png b/versions/4.0/en/editor/scene/images/rotation.png
new file mode 100644
index 0000000000..7573ea4848
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/rotation.png differ
diff --git a/versions/4.0/en/editor/scene/images/scale-gizmo.png b/versions/4.0/en/editor/scene/images/scale-gizmo.png
new file mode 100644
index 0000000000..3e3086d9c0
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/scale-gizmo.png differ
diff --git a/versions/4.0/en/editor/scene/images/scene-camera.png b/versions/4.0/en/editor/scene/images/scene-camera.png
new file mode 100644
index 0000000000..aec1780690
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/scene-camera.png differ
diff --git a/versions/4.0/en/editor/scene/images/scene-gizmo.png b/versions/4.0/en/editor/scene/images/scene-gizmo.png
new file mode 100644
index 0000000000..a02467b623
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/scene-gizmo.png differ
diff --git a/versions/4.0/en/editor/scene/images/scene-grid.png b/versions/4.0/en/editor/scene/images/scene-grid.png
new file mode 100644
index 0000000000..96a5af68d9
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/scene-grid.png differ
diff --git a/versions/4.0/en/editor/scene/images/scene-light.png b/versions/4.0/en/editor/scene/images/scene-light.png
new file mode 100644
index 0000000000..c88b9f2b5b
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/scene-light.png differ
diff --git a/versions/4.0/en/editor/scene/images/scene-reference.png b/versions/4.0/en/editor/scene/images/scene-reference.png
new file mode 100644
index 0000000000..01d84a02bf
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/scene-reference.png differ
diff --git a/versions/4.0/en/editor/scene/images/scene-resolution.png b/versions/4.0/en/editor/scene/images/scene-resolution.png
new file mode 100644
index 0000000000..b09b353749
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/scene-resolution.png differ
diff --git a/versions/4.0/en/editor/scene/images/scene.png b/versions/4.0/en/editor/scene/images/scene.png
new file mode 100644
index 0000000000..46d8f00f7e
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/scene.png differ
diff --git a/versions/4.0/en/editor/scene/images/set-camera.png b/versions/4.0/en/editor/scene/images/set-camera.png
new file mode 100644
index 0000000000..9c1badaa89
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/set-camera.png differ
diff --git a/versions/4.0/en/editor/scene/images/shaded-config.png b/versions/4.0/en/editor/scene/images/shaded-config.png
new file mode 100644
index 0000000000..2d9d9abe61
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/shaded-config.png differ
diff --git a/versions/4.0/en/editor/scene/images/shaded-debug1.png b/versions/4.0/en/editor/scene/images/shaded-debug1.png
new file mode 100644
index 0000000000..4df41fbf90
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/shaded-debug1.png differ
diff --git a/versions/4.0/en/editor/scene/images/shaded-debug2.png b/versions/4.0/en/editor/scene/images/shaded-debug2.png
new file mode 100644
index 0000000000..752d63b8a4
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/shaded-debug2.png differ
diff --git a/versions/4.0/en/editor/scene/images/shaded-debug3.png b/versions/4.0/en/editor/scene/images/shaded-debug3.png
new file mode 100644
index 0000000000..e725095e97
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/shaded-debug3.png differ
diff --git a/versions/4.0/en/editor/scene/images/snaping-surface.gif b/versions/4.0/en/editor/scene/images/snaping-surface.gif
new file mode 100644
index 0000000000..4cc2d61a29
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/snaping-surface.gif differ
diff --git a/versions/4.0/en/editor/scene/images/sphere-collider-gizmo.png b/versions/4.0/en/editor/scene/images/sphere-collider-gizmo.png
new file mode 100644
index 0000000000..5c86b3a974
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/sphere-collider-gizmo.png differ
diff --git a/versions/4.0/en/editor/scene/images/transform-bar.png b/versions/4.0/en/editor/scene/images/transform-bar.png
new file mode 100644
index 0000000000..52ad594a66
Binary files /dev/null and b/versions/4.0/en/editor/scene/images/transform-bar.png differ
diff --git a/versions/4.0/en/editor/scene/index.md b/versions/4.0/en/editor/scene/index.md
new file mode 100644
index 0000000000..04e35727d3
--- /dev/null
+++ b/versions/4.0/en/editor/scene/index.md
@@ -0,0 +1,314 @@
+# Scene Panel
+
+
+
+The **Scene** panel is the central work area for content creation, used for selecting and placing scene images, characters, effects, UI, and other game elements. This workspace allows to select and modify the position, rotation, and scaling of nodes with the **Transform Gizmos**, and get a WYSIWYG scene preview.
+
+## Menu Bar Introduction
+
+The menu bar at the top of the scene panel is slightly different after switching between 3D and 2D views, see below.
+
+- 3D:
+
+ 
+
+- 2D:
+
+ 
+
+## View Introduction
+
+The **Scene** panel includes two views, **3D** and **2D**. The 3D view is used for 3D scene editing, while the 2D view is mainly used for editing 2D elements such as UI nodes, etc. The scene view can be switched via the **3D/2D** button in the toolbar at the top left of the editor.
+
+-  Indicates that the current view is **3D** view mode, when the view's camera is of perspective type. Click on it to go to **2D** view.
+-  Indicates that the current view mode is **2D**, and the view camera is of orthogonal type at this time, which will return to **3D** view when clicked again.
+
+### 3D view
+
+In the 3D view, you can move and position the view of the **Scene** panel by the following actions:
+- Left mouse button + Alt: rotates the view centered on its center point.
+- Middle mouse button: pans the view.
+- Spacebar + mouse/touchpad drag: pans the view.
+- Mouse wheel: zoom the view centered on the view center point.
+- Right mouse button + WASD: camera roaming.
+- **F** Shortcut: focus the camera on the currently selected node.
+
+### 2D view
+
+In 2D view, the view of the **Scene** panel can be moved and positioned by the following actions:
+- Middle mouse button: pans the view.
+- Mouse wheel: zooms the view centered on the current mouse hover position.
+- Right mouse button: pans the view.
+- **F** Shortcut: focus the camera on the currently selected node.
+
+## Transform Tools
+
+
+
+The above tools are the transform tools group, responsible for node **moving, scaling, rotating, attaching, anchoring/centering, local/world coordinate system**, etc.
+
+-  Switch the moving gizmo in the current scene to **Move Gizmo**, the shortcut key is W
+
+ When selecting any node, notice a movement control handle consisting of red, green, and blue arrows and red, green, and blue squares in the center of the node in the **Scene** panel.
+
+ The **control handles** are controllers that can be interacted with by the mouse in a particular editing state in the **Scene** panel. These controllers are only used to assist in editing and will not be displayed while the game is running.
+
+ 
+
+ When the Move Gizmo is active:
+ - Holding the red/green/blue arrows and dragging the mouse will move the node in the X, Y and Z directions respectively.
+ - Holding the red/green/blue square and dragging the mouse will move the node in the Y-Z plane, X-Z plane, X-Y plane, respectively.
+
+-  Switch the gizmo tool in the current scene to **Rotate Gizmo**, the shortcut key is E
+
+ The handle of the Rotate Gizmo consists of three orthogonal red, green and blue circles (in 2D view it consists of an arrow and a circle). When you drag the mouse on any of the red/green/blue circles, the nodes will rotate around the X, Y and Z axes respectively.
+
+ 
+
+ When the mouse hovers over any circle, the circle will be displayed in yellow, click on it to select it, and a yellow arrow will be displayed to indicate which axis the current node is rotated by. Drag any point on the circle to rotate the node, and before releasing the mouse, notice the rotation angle on the control handle.
+
+ 
+
+-  Switch the transform gizmo in the current scene to **Scale Gizmo**, the shortcut key is R
+
+ The scale gizmo consists of three axes with red, green and blue squares at the head and a gray square at the center. When the mouse is hovered over any of the squares, it appears yellow and can be selected and dragged by clicking on.
+
+ - Holding the red/green/blue square and dragging the mouse will scale the node in the X, Y and Z axis directions respectively.
+ - Dragging the mouse on a gray square will scale the node in X, Y, and Z directions at the same time.
+
+ 
+
+-  Switch the transform tool in the current scene to **Rect Gizmo** with the shortcut key T.
+
+ The Rect Gizmo consists of four vertex control points, four edge control points, and one center control point which is only valid for UI Components.
+
+ 
+
+ When the Rect Gizmo is active:
+ - Dragging either vertex control point of the control handle can modify both the `Position` property of the UI node and the `ContentSize` property in the UITransform component while keeping the position of the diagonal vertices unchanged.
+ - Dragging either side of the control handle modifies both the `Position` (`X` or `Y` property) of the UI node and the `ContentSize` property (`width` or `height` property) of the UITransform component, while keeping the position of the opposite side unchanged.
+ - Dragging the center control point of a control handle allows to modify both the `Position` property of the UI node and the `AnchorPoint` property of the UITransform component while keeping the size of the UI node unchanged.
+
+ In the layout of UI elements, it is often necessary to use the **Rect Gizmo** to directly control the position and length of the node's four edges precisely. For image elements where the original image aspect ratio must be maintained, the Rect Gizmo is not usually used to resize.
+
+-  **Incremental snap tool**, click this button and **Incremental snap configuration** will appear, please refer to **Incrase Snap Configuration** section below for details.
+-  The transform gizmo control point is used to set the position of the gizmo and to control the orientation of the handles.
+
+ -  Pivot: the transform gizmo will be displayed in the location of the 2D object **AnchorPoint** or in the 3D object's **world coordinate system**.
+ -  Center: the transform gizmo will be displayed at the center of the node. If multiple nodes are selected at the same time, the center of all nodes will be displayed.
+-  Toggle transformation tool gizmo is **local** coordinate system or **world** coordinate system.
+
+ -  Local: the control handle of the transform gizmo is based on the direction of rotation of the node, as follows:
+
+ 
+
+ -  Global: the direction of the control handles in the transform gizmo is based on the world coordinate system, and is not affected by the node rotation, as follows:
+
+ 
+
+## Increment Snap Configuration
+
+The incremental snap tool mainly consists of **Increment Snap Configuration** and **Rect Tool Snap Configuration**.
+
+### Increment Snap Configuration
+
+The increment snapping feature can be used to manipulate nodes in a set step size when using the move/rotate/scale transform tools in the scene editor. The increment snapping feature can be triggered in the following two ways:
+
+1. Press and hold the Ctrl/Command key while using transform tools to trigger the increment snapping feature.
+2. In the increment snapping configuration panel, use the button to enable the automatic snapping feature of corresponding transform tools. See below for details.
+
+Click on the fifth **Increment Snapping configuration** button in the toolbar in the upper left corner of the editor's main window, the increment snapping configuration panel will pop up, which can be used to set the step size of corresponding transform tools, and enable the auto snapping feature:
+
+
+
+| Button | Description |
+| :-- | :-- |
+| | This button is used to set whether to enable the automatic snapping when using the **Move Transform Tool**. X, Y, and Z are used to set the move steps on the X, Y, and Z axes respectively, and the default X, Y, and Z values are the same for X, or you can click the  button to set the step size for each axis separately. |
+| | This button is used to set whether to enable automatic snapping when using the **Rotation Transform Tool**. The box on the right side is used to set the rotation step, the default is 1. |
+| | This button is used to set whether to enable automatic snapping when using the **Scale Transform Tool**. The box on the right side is used to set the rotation step, the default is 1. Please note that the scale snap is a factor not an absolute value |
+
+
+
+### Rect Tool Snap Configuration
+
+
+
+When using the **Rect Tool Snap Configuration**, the Smart Alignment feature is enabled by default. When dragging UI elements around the scene and encountering elements that can be aligned, the alignment reference line will be displayed and automatically attached to the reference line position.
+
+
+
+| Option | Description |
+| :-- | :-- |
+| Enable auto snap | Check this option to enable the Smart Alignment feature, which is enabled by default. |
+| Snap threshold | Set the threshold value for adsorption detection (world space unit). |
+
+## Alignment and Distribution
+
+This tool is unique to the 2D view and is used for 2D/UI multi-node alignment and distribution functions.
+
+
+
+- Alignment: Align selected nodes, at least two nodes need to be selected for the alignment to take effect
+
+ 
+
+ In order from left to right, the menus are as follows:
+
+ - Align Top
+ - Align Vertical Center
+ - Align Bottom
+ - Align Left
+ - Align Horizontal Center
+ - Align Right
+
+ The handling process of alignment is as follows: After selecting one or more nodes, the AABB for all selected nodes will be calculated via current **un-parent** nodes(This means if there is a parent-child relationship in the selected nodes, then only the parent node will be taken into consideration), and when clicking the Align Bottom button, all nodes will be put at the bottom of the AABB, and when clicking the Align Left button, all nodes will be put to the left side of the AABB.
+
+- Distribution: Used to evenly distribute multiple selected nodes, at least three nodes are required for this to take effect
+
+ 
+
+ The buttons in order from left to right are as follows:
+
+ - Distribute Top
+ - Distribute Vertical Center
+ - Distribute Bottom
+ - Distribute Left
+ - Distribute Horizontal Center
+ - Distribute Right
+
+## Adsorption operation
+
+In the 3D view, objects in the scene can be edited more accurately through adsorption. Two new adsorption modes have been added to the engine **Vertex Adsorption** and **Surface Adsorption**.
+
+- **Vertex Adsorption**: The main purpose of vertex adsorption is to align more precisely through a vertex on one object to a certain vertex on another object. The shortcut is v
+- **Surface Adsorption**: for objects with colliding bodies, surface adsorption will adsorb to the surface of the colliding body; and for objects without colliding bodies, it will adsorb to the surface of the object. The shortcut isCtrl/Command + Shift
+
+Operation process.
+- Select the model model you want to move in **Hierarchy** panel
+- Press the corresponding shortcut key in the scene, a white control block will appear below the model
+- Hold down the left mouse button and drag the control block to move the model
+- Move the mouse, during the movement, the object will move depending on the type of adsorption operation
+- Release the left mouse button to determine the position of the object
+
+
+
+## Shaded Mode
+
+ It is mainly used to configure the way the scene is drawn. Clicking on it will display the shading configuration window.
+
+
+
+Supports both basic shading mode and **Rendering Debug**.
+
+By default, the base shading mode mode is used. To debug the scene, slide the mouse over the **Rendering Debug** menu (currently only the [Surface Shader](../../shader/surface-shader.md#Debug%20View)) is supported) to select a different debugging mode.
+
+
+
+To demonstrate the use of **Rendering Debug** using **World Normal** as an example.
+
+
+
+- Select the engine's built-in Surfaces/standard shader in the **Shader** property of the Material **Property Inspector**.
+- Select the item to be debugged in the **Rendering Debug** drop-down menu
+- Observe whether the rendering results in the view are as expected
+
+## Render output target resolution setting
+
+ The rendering output target resolution of the scene camera can be selected as needed, which will affect the viewing range of the scene camera and facilitate a similar display to the resolution selected in the final preview.
+
+
+
+The resolution can be added/modified/deleted in the [Device Manager](../preferences/index.md#Device%20Manager) of **Preferences** in the top menu bar to add/modify/delete resolutions.
+
+The resolution can also be edited by scrolling down to the bottom:
+
+
+
+## Scene lighting settings
+
+ The button is mainly used to set whether to use the scene lights when doing scene editing, the default is to use.
+
+If the button is shown in blue, it means that the scene lights are used and the scene will be illuminated with the lights added in the scene, as follows:
+
+
+
+When there are no lights added to the scene, the scene is completely black, making it inconvenient to edit.
+
+
+
+At this point, the button can be switched to black, indicating that no scene lights are used and the editor will automatically create a hidden directional light aligned with the scene camera view to illuminate the scene, as shown in the following figure.
+
+
+
+## View Camera
+
+Click on the  button in the right corner to set the properties of the scene camera (not the user-created camera).
+
+
+
+| Options | Description |
+| :-- | :-- |
+| Fov | Field of view of the camera |
+| Far | The far clipping distance of the camera, should be as small as possible within acceptable range |
+| Near | The near clipping distance of the camera, should be as large as possible within acceptable range |
+| Color | The Clear Color of the camera |
+| Wheel Speed | Set the speed at which the scene camera moves back and forth when the mouse wheel is scrolled |
+| Wander Speed | Set the movement speed of the scene camera when wandering |
+| Wander Acceleration |Set whether to enable acceleration when the camera wanders (new in v3.3) If this is checked, acceleration is enabled and the camera will move faster and faster If this is unchecked, the camera will move at a constant speed. |
+
+For the description of camera viewing range, please refer to [Camera component](../components/camera-component.md)。
+
+## Reference Image
+
+Click the  button in the top right corner of the **Scene Editor** to open the **Reference Image** panel, which is mainly used as a cross-reference for developers when stitching together UI in the **Scene Editor**.
+
+
+
+| Options | Description |
+| :-- | :-- |
+| Add | Add a UI reference image, multiple reference images can be added. |
+| Delete | Deletes the UI reference image in the currently selected box. |
+| Position X | The selected UI reference image is displayed in the X-axis position of the scene. |
+| Position Y | The selected UI reference image is displayed on the Y-axis of the scene |
+| Scale X | Scale on X-axis of the selected UI reference image |
+| Scale Y | Scale on Y-axis of the selected UI reference image |
+| Opacity | The transparency of the selected UI reference image in the scene |
+
+### Grid Configuration
+
+The grid in the scene is an important reference for the position of the scene elements when we place them, and can be set via the button at the top right of the **Scene Editor** at.
+
+
+
+| Options | Function Description |
+| :-- | :-- |
+| 3D Icons | Whether the scene is 3D icon enabled or not, the input box after it is used to set the size of the icon Gizmo, the value range is 0 ~ 8. If you check this box to enable 3D icons, the icon Gizmo in the **Scene Editor** will be a 3D slice with a near-large and far-small effect. If this item is unchecked, the icon Gizmo will be displayed as a fixed size image. |
+| Show Grid | Whether to show the grid in **Scene Editor**, the color setting box behind is used to set the color of the grid. |
+
+## Scene Gizmo
+
+Scene Gizmo is in the upper right corner of the scene view, it shows the viewing direction of the current scene camera, and you can quickly switch between different viewing angles by clicking it.
+
+
+
+- Click on the 6 directional axes to quickly switch to the top, bottom, left, right, front, and back angles to view the scene.
+- Click the center cube to switch between orthogonal view and perspective view.
+
+### Select node
+
+Click the left mouse button in the scene view to select the node where the object is located. Selecting the node is a prerequisite for using transform gizmos to set the node position, rotation, scaling, etc.
+
+### Multiple selection operation
+
+Pressing the left mouse button and dragging the mouse within the scene will simultaneously review all the nodes within the current box selection range, and through the transform gizmos, you can batch transform the selected nodes.
+
+
+
+### Gizmo operation introduction
+
+The core function of **Scene** panel is to edit and arrange the visible elements in the scene in a WYSIWYG way. **Gizmos** are mainly used to assist in the visual editing of the scene.
+
+- [Toolbar](../toolbar/index.md)
+- [Camera Gizmo](./camera-gizmo.md)
+- [Collider Gizmo](./collider-gizmo.md)
+- [Particle System Gizmo](./particle-system-gizmo.md)
diff --git a/versions/4.0/en/editor/scene/particle-system-gizmo.md b/versions/4.0/en/editor/scene/particle-system-gizmo.md
new file mode 100644
index 0000000000..af9a7bd6ac
--- /dev/null
+++ b/versions/4.0/en/editor/scene/particle-system-gizmo.md
@@ -0,0 +1,33 @@
+# Particle System Gizmo
+
+Particle System Gizmo is used for the visualization of the [ShapeModule](../../particle-system/emitter.md) of particle system.
+
+## Box
+
+`Box Gizmo` shows the length, width, height of box, you can edit them by dragging the control quad.
+
+
+
+## Sphere
+
+`Sphere Gizmo` shows the size of sphere, you can edit the radius of sphere by dragging the control quad.
+
+
+
+## Hemisphere
+
+`Hemisphere Gizmo` shows the size of hemisphere, you can edit the radius of sphere by dragging the control quad.
+
+
+
+## Circle
+
+`Circle Gizmo` shows the size of circle, you can edit the radius of circle by dragging the control quad.
+
+
+
+## Cone
+
+`Cone Gizmo` shows the shape of cone, you can edit the radius,angle,height of cone by dragging the control quad.
+
+
diff --git a/versions/4.0/en/editor/terrain/images/create-terrain-asset.png b/versions/4.0/en/editor/terrain/images/create-terrain-asset.png
new file mode 100644
index 0000000000..376f68b679
Binary files /dev/null and b/versions/4.0/en/editor/terrain/images/create-terrain-asset.png differ
diff --git a/versions/4.0/en/editor/terrain/images/create-terrain.png b/versions/4.0/en/editor/terrain/images/create-terrain.png
new file mode 100644
index 0000000000..4f699e65ce
Binary files /dev/null and b/versions/4.0/en/editor/terrain/images/create-terrain.png differ
diff --git a/versions/4.0/en/editor/terrain/images/terrain-inspector.png b/versions/4.0/en/editor/terrain/images/terrain-inspector.png
new file mode 100644
index 0000000000..c89c89be7a
Binary files /dev/null and b/versions/4.0/en/editor/terrain/images/terrain-inspector.png differ
diff --git a/versions/4.0/en/editor/terrain/images/terrain-layer.png b/versions/4.0/en/editor/terrain/images/terrain-layer.png
new file mode 100644
index 0000000000..b156f9e1fc
Binary files /dev/null and b/versions/4.0/en/editor/terrain/images/terrain-layer.png differ
diff --git a/versions/4.0/en/editor/terrain/images/terrain-manage.png b/versions/4.0/en/editor/terrain/images/terrain-manage.png
new file mode 100644
index 0000000000..afda42b5d4
Binary files /dev/null and b/versions/4.0/en/editor/terrain/images/terrain-manage.png differ
diff --git a/versions/4.0/en/editor/terrain/images/terrain-paint.png b/versions/4.0/en/editor/terrain/images/terrain-paint.png
new file mode 100644
index 0000000000..a180a19ecf
Binary files /dev/null and b/versions/4.0/en/editor/terrain/images/terrain-paint.png differ
diff --git a/versions/4.0/en/editor/terrain/images/terrain-panel.png b/versions/4.0/en/editor/terrain/images/terrain-panel.png
new file mode 100644
index 0000000000..671051da6c
Binary files /dev/null and b/versions/4.0/en/editor/terrain/images/terrain-panel.png differ
diff --git a/versions/4.0/en/editor/terrain/images/terrain-sculpt.png b/versions/4.0/en/editor/terrain/images/terrain-sculpt.png
new file mode 100644
index 0000000000..8943a65e92
Binary files /dev/null and b/versions/4.0/en/editor/terrain/images/terrain-sculpt.png differ
diff --git a/versions/4.0/en/editor/terrain/images/terrain-select.png b/versions/4.0/en/editor/terrain/images/terrain-select.png
new file mode 100644
index 0000000000..d68bdbf9ab
Binary files /dev/null and b/versions/4.0/en/editor/terrain/images/terrain-select.png differ
diff --git a/versions/4.0/en/editor/terrain/images/terrain.png b/versions/4.0/en/editor/terrain/images/terrain.png
new file mode 100644
index 0000000000..2ad48159d0
Binary files /dev/null and b/versions/4.0/en/editor/terrain/images/terrain.png differ
diff --git a/versions/4.0/en/editor/terrain/index.md b/versions/4.0/en/editor/terrain/index.md
new file mode 100644
index 0000000000..c2f9a68074
--- /dev/null
+++ b/versions/4.0/en/editor/terrain/index.md
@@ -0,0 +1,129 @@
+# Terrain System
+
+The **terrain system** is an efficient tool for creating mountainous landscapes. Users can use various tools to sculpt out basins, mountains, valleys, plains and other landforms.
+
+
+
+## Creating Terrain Objects and Assets
+
+To create a new terrain in the project, users need to create a terrain object in the scene in conjunction with a terrain asset in the project directory:
+
+1. Right click anywhere in the **Hierarchy** panel and select **Create -> Terrain**. This will create a new terrain object in the current scene. Terrain objects can be moved but is prohibited from rotating and scaling.
+
+ 
+
+2. Right click anywhere in the **Assets** panel and select **Create -> Terrain**. This will create a new terrain asset in the project directory. Terrain objects require terrain assets in conjunction to work properly.
+
+ 
+
+## Configuring Terrain Properties
+
+Select the terrain object in the **Hierarchy** panel. Drag and drop the terrain asset from the **Assets** panel in the `Asset` property of the terrain component (`cc.Terrain`) or click the arrow button behind the `Asset` property and select the terrain asset from the drop-down menu.
+
+The terrain component includes properties as follows:
+
+
+
+| Property | Description |
+| :----- | :---- |
+| Asset | Specify terrain asset |
+| Effect Asset | Specify a shader to render terrain, e.g. `builtin-standard.effect` |
+| Receive Shadow | Allow shadows to be casted on the terrain object |
+| Use Normal Map | Allow terrain to be rendered with normal maps |
+| Use PBR | Allow terrain to be rendered using PBR maps |
+| Lod Enable | Enable LODs for the terrain mesh to improve rendering performance |
+| Lod Bias | Specify the distance at which the LOD level is switched |
+
+## Terrain Editing Tools
+
+With the terrain asset specified in the `Asset` property, users now have access to the terrain editing panel in lower right corner of the **Scene** panel, as well as terrain editing tools on the upper left corner of the **Scene** panel.
+
+Terrain editing panel includes properties brush size and intensity, terrain material and layers, etc. which can be accessed via **Manage**, **Sculpt**, **Paint** and **Select** tabs.
+
+
+
+Terrain editing tools can be found at the upper left corner of the **Scene** panel:
+- **Manage** tool: Switch to Manage tab in terrain editing panel.
+- **Paint Bulge** tool: Switch to the bulge brush. This is equivalent to selecting **Bulge** in the `BrushMode` property under Sculpt tab in the terrain editing panel. With the bulge brush, users may sculpt bumps in the terrain mesh.
+- **Paint Sunken** tool: Switch to the sunken brush. This is equivalent to selecting **Sunken** in the `BrushMode` property under Sculpt tab in the terrain editing panel. With the bulge brush, users may sculpt recesses in the terrain mesh.
+- **Paint Smooth** tool: Switch to the smooth brush. This is equivalent to selecting **Smooth** in the `BrushMode` property under Sculpt tab in the terrain editing panel. With the smooth brush, users may smooth out the excessive bumpiness of the terrain mesh by averaging the vertices heights.
+- **Paint** tool: Switch to the material painting brush. This is equivalent to selecting the **Paint** tab in the terrain editing panel. With the paint brush, users may no longer sculpt structures on the terrain mesh. Instead the brush allows users to paint a layer of texture on top of the existing texture layer of the terrain mesh.
+- **Select** tool: Switch to the selection tool. This is equivalent to selecting the **Select** tab in the terrain editing panel. With the selection tool, users may gain more information including texture layers and height alphas by selecting a tile in the terrain object.
+
+### Working with Terrain: Manage
+
+The **Manage** tab includes properties to adjust the overall size, density and texel density of the terrain object. A terrain object consists of multiple instances of an editable surface known as a tile block, which is 32 by 32 meters by default (with **TileSize** being equal to 1.) A terrain object requires at least one tile block.
+
+
+
+| Parameter | Description |
+| :--- | :-- |
+| Tile Size | Scalar for a single tile. By default, a tile block is 32 by 32 meters. This property scales the tile block linearly, which means the final size of a tile block is **32 * Tile Size** square meters. |
+| Weight Map Size | Resolution of the weight map which produces the bumps and recesses in the terrain mesh. Higher resolution yields more detailed structures in the terrain mesh. |
+| Light Map Size | Resolution of the light map |
+| Block Count | Number of tile blocks in the current terrain object |
+
+### Working with Terrain: Sculpt
+
+Users may create the structure of the terrain object by sculpting bumps and recesses in the terrain mesh.
+
+
+
+| Parameter | Description |
+| :--- | :--- |
+| Brush Size | Size of the active brush |
+| Brush Strength | Intensity of the active brush |
+| Brush Mode | Active mode of the brush, including **Bulge**, **Sunken**, **Smooth**, **Flatten**, **Set Height** |
+| Brush Height | Height of the brush, only availabe with **Set Height** mode |
+| Brush | Stencil of the brush, requires a texture map with alpha channel as stencil |
+| Brush Rotation | The brush rotation |
+
+| Brush mode | Description |
+| :--- | :--- |
+| Bulge | Sculpt bumps in the terrain mesh |
+| Sunken | Sculpt recesses in the terrain mesh |
+| Smooth | Smooth out terrain bumpiness by averaging vertices heights |
+| Flatten | Flatten terrain by resetting vertices heights to the same value |
+| Set Height | Used in conjunction with the **Brush Height** property to reset vertices heights to a certain value |
+
+While a brush tool is activated, use **LMB** to sculpt or paint on the terrain mesh. Hold **Shift** to temporarily switch from **Bulge** mode to **Sunken** mode when **Bulge** brush is activated, or vice versa when **Sunken** brush is activated.
+
+### Working with Terrain: Paint
+
+With the **Paint** tool, users may paint textures on the terrain mesh. **Paint** tool includes properties as follows:
+
+
+
+| Parameter | Description |
+| :--- | :--- |
+| Terrain Layer | Texture layers for the current terrain object, see below in section **Layer editing**. |
+| Brush Size | Size of the active brush |
+| Brush Strength | Intensity of the active brush |
+| Brush Falloff | Hardness of the active brush **0.0** indicates full hardness. **1.0** indicates full feathering. |
+| Brush | Stencil of the brush, requires a texture map with alpha channel as stencil |
+
+#### Painting with Layers
+
+
+
+Users may paint multiple layers of texture on the terrain mesh. Click the **+** or **-** button at the top right of the terrain editing panel to **add** or **delete** layers (up to **4** layers are supported.) Once a Layer is selected, use the **Paint** tool to paint on the corresponding layer.
+
+| Parameter | Description |
+| :--- | :--- |
+| Terrain Layer | Texture layers for the current terrain object |
+| Normal Map | Assign a normal texture to the selected layer. For this property to take effect, the **Use Normal Map** property in the terrain component must be enabled. |
+| Metallic | Set the metallic value of the selected layer |
+| Roughness | Set the roughness value of the selected layer |
+| Tile Size | Scalar for a single tile. This will only take effect regarding texture projection. Users may use a smaller tile scale compared to that in terms of the terrain construction (**Tile Size** under **Manage** tab) to achieve higher texel density. |
+
+### Working with Terrain: Select
+
+When switching to the **Select** tab and selecting a terrain block in the **Scene** panel, information about the current terrain block will be displayed.
+
+
+
+| Parameter | Description |
+| :--- | :--- |
+| Index | Index of the selected block (in x and y axis.) |
+| Layers | Texture layers being applied to the selected block |
+| Weight | Weight maps of the selected block |
diff --git a/versions/4.0/en/editor/toolbar/img/2d3d.png b/versions/4.0/en/editor/toolbar/img/2d3d.png
new file mode 100644
index 0000000000..d98908f33d
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/2d3d.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/browse.png b/versions/4.0/en/editor/toolbar/img/browse.png
new file mode 100644
index 0000000000..dfe05fd423
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/browse.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/build.png b/versions/4.0/en/editor/toolbar/img/build.png
new file mode 100644
index 0000000000..d15ed5a884
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/build.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/gizmo_position.png b/versions/4.0/en/editor/toolbar/img/gizmo_position.png
new file mode 100644
index 0000000000..ec87099ade
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/gizmo_position.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/open_project.png b/versions/4.0/en/editor/toolbar/img/open_project.png
new file mode 100644
index 0000000000..e7b10a9c2b
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/open_project.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/position-snap.png b/versions/4.0/en/editor/toolbar/img/position-snap.png
new file mode 100644
index 0000000000..2c4706faae
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/position-snap.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/position-snap1.png b/versions/4.0/en/editor/toolbar/img/position-snap1.png
new file mode 100644
index 0000000000..874772802d
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/position-snap1.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/position-tool.png b/versions/4.0/en/editor/toolbar/img/position-tool.png
new file mode 100644
index 0000000000..d7fa645952
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/position-tool.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/preview-bar.png b/versions/4.0/en/editor/toolbar/img/preview-bar.png
new file mode 100644
index 0000000000..601f124d7b
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/preview-bar.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/preview.png b/versions/4.0/en/editor/toolbar/img/preview.png
new file mode 100644
index 0000000000..30d7b78dcb
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/preview.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/preview_url.png b/versions/4.0/en/editor/toolbar/img/preview_url.png
new file mode 100644
index 0000000000..50d9aa5b56
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/preview_url.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/rect-tool-config.png b/versions/4.0/en/editor/toolbar/img/rect-tool-config.png
new file mode 100644
index 0000000000..367c4391a5
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/rect-tool-config.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/rect-tool.png b/versions/4.0/en/editor/toolbar/img/rect-tool.png
new file mode 100644
index 0000000000..4031c6a011
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/rect-tool.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/rotation-snap.png b/versions/4.0/en/editor/toolbar/img/rotation-snap.png
new file mode 100644
index 0000000000..223f24c4c8
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/rotation-snap.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/rotation-tool.png b/versions/4.0/en/editor/toolbar/img/rotation-tool.png
new file mode 100644
index 0000000000..d7451f3e70
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/rotation-tool.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/scale-snap.png b/versions/4.0/en/editor/toolbar/img/scale-snap.png
new file mode 100644
index 0000000000..ac32b83238
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/scale-snap.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/scale-tool.png b/versions/4.0/en/editor/toolbar/img/scale-tool.png
new file mode 100644
index 0000000000..7ad09bed53
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/scale-tool.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/small.png b/versions/4.0/en/editor/toolbar/img/small.png
new file mode 100644
index 0000000000..787e94d176
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/small.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/smallSecretary.png b/versions/4.0/en/editor/toolbar/img/smallSecretary.png
new file mode 100644
index 0000000000..567fd61c35
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/smallSecretary.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/toolbarEdit.png b/versions/4.0/en/editor/toolbar/img/toolbarEdit.png
new file mode 100644
index 0000000000..705e65a603
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/toolbarEdit.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/transform-snap-config.png b/versions/4.0/en/editor/toolbar/img/transform-snap-config.png
new file mode 100644
index 0000000000..112131acc6
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/transform-snap-config.png differ
diff --git a/versions/4.0/en/editor/toolbar/img/transform_tool.png b/versions/4.0/en/editor/toolbar/img/transform_tool.png
new file mode 100644
index 0000000000..2ef8d1f61b
Binary files /dev/null and b/versions/4.0/en/editor/toolbar/img/transform_tool.png differ
diff --git a/versions/4.0/en/editor/toolbar/index.md b/versions/4.0/en/editor/toolbar/index.md
new file mode 100644
index 0000000000..61e90fd92c
--- /dev/null
+++ b/versions/4.0/en/editor/toolbar/index.md
@@ -0,0 +1,28 @@
+# Toolbar
+
+The **Toolbar** is located directly above the main editor window and contains seven groups of control buttons or messages that are used to provide editing functionality for specific panels or to facilitate our implementation of development workflows.
+
+
+
+## Preview
+
+
+
+Multiple preview types are allowed before the preview section, including **in-editor**, **browser** and **emulator**, please refer to [Project Preview & Debugging](../preview/index.md).
+
+## Build
+
+ Click the build button to build the project, please refer to [Cross-Platform Game Publishing](../publish/index.md) for more information.
+
+## Mobile Preview Address
+
+
+
+This shows the LAN address of the desktop computer running Cocos Creator. Mobile devices connected to the same LAN can access this address to preview and debug the game. Hovering over the LAN address will bring up a QR code, which can also be accessed by scanning the QR code to preview and debug the game.
+
+## Open the Project/App Directory
+
+
+
+- **Project**: opens the folder where the project is located
+- **App**: opens the installation path of the program
diff --git a/versions/4.0/en/engine/event/bubble-event.png b/versions/4.0/en/engine/event/bubble-event.png
new file mode 100644
index 0000000000..66c998144a
Binary files /dev/null and b/versions/4.0/en/engine/event/bubble-event.png differ
diff --git a/versions/4.0/en/engine/event/event-api.md b/versions/4.0/en/engine/event/event-api.md
new file mode 100644
index 0000000000..ae87765116
--- /dev/null
+++ b/versions/4.0/en/engine/event/event-api.md
@@ -0,0 +1,61 @@
+# Global and Node Touch and Mouse Events API
+
+## Mouse Event API
+
+| Function Name | Return value type | Meaning |
+|:--------------|:------------------|:----------------------------------------------------------------------------------------|
+| __getScrollY__ | Number | Get the scrolling distance of the mouse wheel on the y-axis, valid only when scrolling. |
+| __getButton__ | Number | __EventMouse.BUTTON_LEFT__ or __EventMouse.BUTTON_RIGHT__ or __EventMouse.BUTTON_MIDDLE__. |
+
+### Global Mouse Events API
+
+| Function Name | Return value type | Meaning |
+|:--------------------|:------------------|:------------------------------------------------------------------------------------------------------------------------------------|
+| __getLocation__ | Vec2 | Get the mouse position, which contains the x and y properties. |
+| __getLocationX__ | Number | Get the mouse position on x-axis. |
+| __getLocationY__ | Number | Get the mouse position on y-axis. |
+| __getPreviousLocation__ | Vec2 | Get the position of the last triggered mouse event, which contains the x and y properties. |
+| __getDelta__ | Vec2 | Get the distance the mouse has moved relative to the lower-left corner since the last event, which contains the x and y properties. |
+| __getDeltaX__ | Number | Get the x-axis distance the mouse has moved relative to the lower-left corner since the last event. |
+| __getDeltaY__ | Number | Get the y-axis distance the mouse has moved relative to the lower-left corner since the last event. |
+
+### Node Mouse Events API
+
+| Function Name | Return value type | Meaning |
+|:-----------------------|:-------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------|
+| __getUILocation__ | Vec2 | Get the current mouse position relative to the lower-left corner of the UI window, which contains the x and y properties. |
+| __getUILocationX__ | Number | Get the position of the touch point on the x-axis relative to the lower-left corner of the UI window. |
+| __getUILocationY__ | Number | Get the current mouse position on y-axis relative to the lower-left corner of the UI window. |
+| __getUIPreviousLocation__ | Vec2 | Get the previous mouse position relative to the lower-left corner of the UI window, which contains the x and y properties. |
+| __getUIDelta__ | Vec2 | Get the distance the mouse has moved relative to the lower-left corner of the UI window since the last event, which contains the x and y properties. |
+| __getUIDeltaX__ | Number | Get the x-axis distance the mouse has moved relative to the lower-left corner of the UI window since the last event. |
+| __getUIDeltaY__ | Number | Get the y-axis distance the mouse has moved relative to the lower-left corner of the UI window since the last event. |
+
+## Touch Events API
+
+| API Name | Type | Meaning |
+|:----------|:--------|:---------------------------------------------------------------------|
+| __touch__ | Touch | The touch point related to the current event. |
+| __getID__ | Number | Get the ID of the touch point, which is used for multi-touch logic. |
+
+### Global Touch Events API
+
+| Function Name | Return value type | Meaning |
+|:---------------------|:-------------------|:-------------------------------------------------------------------------------------------------------------------------------------|
+| __getLocation__ | Vec2 | Get the mouse position, which contains the x and y properties. |
+| __getLocationX__ | Number | Get the position of the touch point on the x-axis. |
+| __getLocationY__ | Number | Get the position of the touch point on the y-axis. |
+| __getStartLocation__ | Vec2 | Get the initial position of the touch point, which contains the x and y properties. |
+| __getPreviousLocation__ | Vec2 | Get the position of the last triggered touch point event, which contains the x and y properties. |
+| __getDelta__ | Vec2 | Get the distance the mouse has moved relative to the lower-left corner since the last event, which contains the x and y properties. |
+
+### Node Touch Events API
+
+| Function Name | Return value type | Meaning |
+|:-----------------------|:-------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------|
+| __getUILocation__ | Vec2 | Get the current mouse position relative to the lower-left corner of the UI window, which contains the x and y properties. |
+| __getUILocationX__ | Number | Get the current mouse position on x-axis relative to the lower-left corner of the UI window. |
+| __getUILocationY__ | Number | Get the current mouse position on y-axis relative to the lower-left corner of the UI window. |
+| __getUIStartLocation__ | Vec2 | Get the position of the initial touch point relative to the lower-left corner of the UI window, which contains the x and y properties. |
+| __getUIPreviousLocation__ | Vec2 | Get the position of the last touch point relative to the lower-left corner of the UI window, which contains the x and y properties. |
+| __getUIDelta__ | Vec2 | Get the distance the mouse has moved relative to the lower-left corner of the UI window since the last event, which contains the x and y properties. |
diff --git a/versions/4.0/en/engine/event/event-emit.md b/versions/4.0/en/engine/event/event-emit.md
new file mode 100644
index 0000000000..92c6ec0fea
--- /dev/null
+++ b/versions/4.0/en/engine/event/event-emit.md
@@ -0,0 +1,119 @@
+# Event Listening and Emitting
+
+Cocos Creator provides the `EventTarget` class to suport the listening and emitting of custom event. Before using it, it needs to be imported from the `'cc'` module and an `EventTarget` object needs to be instantiated.
+
+```ts
+import { EventTarget } from 'cc';
+const eventTarget = new EventTarget();
+```
+
+> __Note__: although the `Node` object also implements some `EventTarget` interfaces, it is no longer recommended to continue using the `Node` object to listen to and emit custom events. Because this is not efficient enough, and we also hope that `Node` object only listens to events related to `Node`.
+
+## Event Listening
+
+Listen to events can be registered by the interface `this.node.on()`. The methods are as follows:
+
+```ts
+// This event listener is triggered every time and needs to be unregistered manually.
+eventTarget.on(type, func, target?);
+```
+
+The `type` is the event registration string. `func` is the callback to listen to when the event is executed. And `target` is the event receive object. If `target` is not set, then `this` in the callback refers to the object that is currently executing the callback.
+
+The event listener interface `on` can pass to the third parameter target to bind the caller of the response function. Calling the following two methods would have the same effect:
+
+```ts
+// Using Function Binding
+eventTarget.on(Node.EventType.MOUSE_DOWN, function ( event ) {
+ this.enabled = false;
+}.bind(this));
+
+// Using the third parameter
+eventTarget.on(Node.EventType.MOUSE_DOWN, (event) => {
+ this.enabled = false;
+}, this);
+```
+
+Besides listening with `on`, the `once` interface can also be used. The `once` listener will shut the event being listened to after the listener function responds.
+
+## Canceling listeners
+
+We can shut the corresponding event listener using `off` when we don't care about a certain event anymore.
+
+The `off` method can be used in two ways
+
+```ts
+// Cancel all registered events of this type on the object.
+eventTarget.off(type);
+// Cancels events on objects with this type of callback designation target.
+eventTarget.off(type, func, target);
+```
+
+One thing to note is that the parameter of `off` must be in one-to-one correspondence with the parameter of `on` in order to cancel it.
+
+Example:
+
+```ts
+import { _decorator, Component, EventTarget } from 'cc';
+const { ccclass } = _decorator;
+const eventTarget = new EventTarget();
+
+@ccclass("Example")
+export class Example extends Component {
+ onEnable () {
+ eventTarget.on('foobar', this._sayHello, this);
+ }
+
+ onDisable () {
+ eventTarget.off('foobar', this._sayHello, this);
+ }
+
+ _sayHello () {
+ console.log('Hello World');
+ }
+}
+```
+
+## Event Emitting
+
+Events are emitted through the `eventTarget.emit()` interface, as follows:
+
+```ts
+// At most 5 args could be emit.
+eventTarget.emit(type, ...args);
+```
+
+## Explanation for event parameters
+
+When emitting events, we can pass our event parameters starting with the second argument of the `emit` function. Also, the corresponding event parameters can be fetched in the callback registered in `on`.
+
+```ts
+import { _decorator, Component, EventTarget } from 'cc';
+const { ccclass } = _decorator;
+const eventTarget = new EventTarget();
+
+@ccclass("Example")
+export class Example extends Component {
+ onLoad () {
+ eventTarget.on('foo', (arg1, arg2, arg3) => {
+ console.log(arg1, arg2, arg3); // print 1, 2, 3
+ });
+ }
+
+ start () {
+ let arg1 = 1, arg2 = 2, arg3 = 3;
+ // At most 5 args could be emit.
+ eventTarget.emit('foo', arg1, arg2, arg3);
+ }
+}
+```
+
+> __Note__: only up to 5 event parameters can be passed here for the performance of the underlying event distribution. Therefore, care should be taken to control the number of parameters passed when passing a parameter.
+
+## System built-in events
+
+Above are the general rules for listening to and emitting events. __Cocos Creator__ has some built-in system events. Please refer to the following documents:
+
+- [Input Event System](event-input.md)
+
+- [Node Event System](event-node.md)
diff --git a/versions/4.0/en/engine/event/event-input.md b/versions/4.0/en/engine/event/event-input.md
new file mode 100644
index 0000000000..b5b3dbf46c
--- /dev/null
+++ b/versions/4.0/en/engine/event/event-input.md
@@ -0,0 +1,242 @@
+# Input Event System
+
+As mentioned in the previous document, `EventTarget` supports a complete set of event listening and emitting mechanisms. In Cocos Creator v3.4.0, `input` object is supported, which implements the event registering interface of `EventTarget`, and can register global system input events through this object. The original `systemEvent` object has been deprecated since v3.4.0 and will be gradually removed in the future, we recommend using the `input` object as a replacement.
+
+The differences between `systemEvent` and `input` are as follows:
+
+- **Differences in type definitions**
+
+ - The declaration of touch event callback in `systemEvent` is `(touch: Touch, event: EventTouch) => void`
+
+ - The declaration of touch event callback in `input` is `(event: EventTouch) => void`
+
+- **Differences in priority**
+
+ - The event listener of `systemEvent` will be intercepted by the event listener of the node.
+
+ - `input` objects have higher priority than nodes and will not be intercepted.
+
+ > __Note__: we lowered the priority of `input` in **v3.4.1**, so there is no difference in priority between the two objects since v3.4.1.
+
+---
+
+In this section, the handling of global input events in Cocos Creator will be introduced.
+
+**Global input events** are irrelevant with the node hierarchy, so they are dispatched globally by `input`, currently supported:
+
+- Mouse
+- Touch
+- Keyboard
+- DeviceMotion
+
+## How to define the input events
+
+Use `input.on(type, callback, target)` to register global input event listeners. Event types included:
+
+| Input Event | `type` |
+| :----- | :---------- |
+| Mouse Event | `Input.EventType.MOUSE_DOWN` `Input.EventType.MOUSE_MOVE` `Input.EventType.MOUSE_UP` `Input.EventType.MOUSE_WHEEL` |
+| Touch Event | `Input.EventType.TOUCH_START` `Input.EventType.TOUCH_MOVE` `Input.EventType.TOUCH_END` `Input.EventType.TOUCH_CANCEL` |
+| Keyboard Event | `Input.EventType.KEY_DOWN` (keyboard pressed) `Input.EventType.KEY_PRESSING` (keyboard continuously pressed) `Input.EventType.KEY_UP` (keyboard release) |
+| DeviceMotion Event | `Input.EventType.DEVICEMOTION` |
+
+### Pointer Events
+
+Pointer events include mouse and touch events.
+
+- Event listener types
+
+ - Mouse event listening
+
+ - `Input.EventType.MOUSE_DOWN`
+
+ - `Input.EventType.MOUSE_MOVE`
+
+ - `Input.EventType.MOUSE_UP`
+
+ - `Input.EventType.MOUSE_WHEEL`
+
+ - Touch event listening
+
+ - `Input.EventType.TOUCH_START`
+
+ - `Input.EventType.TOUCH_MOVE`
+
+ - `Input.EventType.TOUCH_CANCEL`
+
+ - `Input.EventType.TOUCH_END`
+
+- Callback function after event triggering
+
+ - Custom callback function: `callback(event);`
+
+- Callback parameter
+
+ - [EventMouse](%__APIDOC__%/en/class/EventMouse) or [EventTouch](__APIDOC__/en/class/EventTouch)
+
+Examples of the use of pointer events are as follows:
+
+```ts
+import { _decorator, Component, input, Input, EventTouch } from 'cc';
+const { ccclass } = _decorator;
+
+@ccclass("Example")
+export class Example extends Component {
+ onLoad () {
+ input.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
+ }
+
+ onDestroy () {
+ input.off(Input.EventType.TOUCH_START, this.onTouchStart, this);
+ }
+
+ onTouchStart(event: EventTouch) {
+ console.log(event.getLocation()); // location on screen space
+ console.log(event.getUILocation()); // location on UI space
+ }
+}
+```
+
+### Keyboard events
+
+- Event listener types
+
+ - `Input.EventType.KEY_DOWN`
+
+ - `Input.EventType.KEY_PRESSING`
+
+ - `Input.EventType.KEY_UP`
+
+- Callback function after event triggering
+
+ - Custom Function: `callback(event);`
+
+- Callback parameter
+
+ - [EventKeyboard](%__APIDOC__%/en/class/EventKeyboard)
+
+Examples of the use of keyboard events are as follows:
+
+```ts
+import { _decorator, Component, input, Input, EventKeyboard, KeyCode } from 'cc';
+const { ccclass } = _decorator;
+
+@ccclass("Example")
+export class Example extends Component {
+ onLoad () {
+ input.on(Input.EventType.KEY_DOWN, this.onKeyDown, this);
+ input.on(Input.EventType.KEY_UP, this.onKeyUp, this);
+ }
+
+ onDestroy () {
+ input.off(Input.EventType.KEY_DOWN, this.onKeyDown, this);
+ input.off(Input.EventType.KEY_UP, this.onKeyUp, this);
+ }
+
+ onKeyDown (event: EventKeyboard) {
+ switch(event.keyCode) {
+ case KeyCode.KEY_A:
+ console.log('Press a key');
+ break;
+ }
+ }
+
+ onKeyUp (event: EventKeyboard) {
+ switch(event.keyCode) {
+ case KeyCode.KEY_A:
+ console.log('Release a key');
+ break;
+ }
+ }
+}
+```
+
+### Device Motion
+
+- Event listener type
+
+ - `Input.EventType.DEVICEMOTION`
+
+- Callback function after event triggering
+
+ - Custom callback function: `callback(event);`
+
+- Callback parameter
+
+ - [EventAcceleration](%__APIDOC__%/en/class/EventAcceleration)
+
+Examples of the use of DeviceMotion events are as follows:
+
+```ts
+import { _decorator, Component, input, Input, log } from 'cc';
+const { ccclass } = _decorator;
+
+@ccclass("Example")
+export class Example extends Component {
+ onLoad () {
+ input.setAccelerometerEnabled(true);
+ input.on(Input.EventType.DEVICEMOTION, this.onDeviceMotionEvent, this);
+ }
+
+ onDestroy () {
+ input.off(Input.EventType.DEVICEMOTION, this.onDeviceMotionEvent, this);
+ }
+
+ onDeviceMotionEvent (event: EventAcceleration) {
+ log(event.acc.x + " " + event.acc.y);
+ }
+}
+```
+
+The specific usage can be found in the example [event](https://github.com/cocos/cocos-test-projects/tree/v3.8/assets/cases/event), which contains the implementation of keyboard, accelerometer, single-touch, multi-touch and other functions.
+
+## Touch detection for 3D objects
+
+The touch detection for 3D objects and 2D UI nodes is different:
+
+- 2D UI nodes only need the size information provided by the `UITransform` component and the position information of the node to do the touch detection. For details, please refer to [Node Event System](event-node.md).
+
+- The touch detection for 3D objects needs to be implemented by ray cast. The specific method is to generate a ray from the rendering camera of the 3D object to the screen coordinates of the touch point to determine whether the ray hits the object that was detected. The specific code implementation is as follows:
+
+ ```ts
+ import { _decorator, Component, Node, Camera, geometry, input, Input, EventTouch, PhysicsSystem } from 'cc';
+ const { ccclass, property } = _decorator;
+
+ @ccclass("Example")
+ export class Example extends Component {
+
+ // Specify the camera rendering the target node.
+ @property(Camera)
+ readonly cameraCom!: Camera;
+
+ @property(Node)
+ public targetNode!: Node
+
+ private _ray: geometry.Ray = new geometry.Ray();
+
+ onEnable () {
+ input.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
+ }
+
+ onDisable () {
+ input.off(Input.EventType.TOUCH_START, this.onTouchStart, this);
+ }
+
+ onTouchStart(event: EventTouch) {
+ const touch = event.touch!;
+ this.cameraCom.screenPointToRay(touch.getLocationX(), touch.getLocationY(), this._ray);
+ if (PhysicsSystem.instance.raycast(this._ray)) {
+ const raycastResults = PhysicsSystem.instance.raycastResults;
+ for (let i = 0; i < raycastResults.length; i++) {
+ const item = raycastResults[i];
+ if (item.collider.node == this.targetNode) {
+ console.log('raycast hit the target node !');
+ break;
+ }
+ }
+ } else {
+ console.log('raycast does not hit the target node !');
+ }
+ }
+ }
+ ```
diff --git a/versions/4.0/en/engine/event/event-node.md b/versions/4.0/en/engine/event/event-node.md
new file mode 100644
index 0000000000..44c34d7907
--- /dev/null
+++ b/versions/4.0/en/engine/event/event-node.md
@@ -0,0 +1,245 @@
+# Node Event System
+
+As mentioned in the previous document, the `input` object supports the global [input event system](event-input.md), and the `Node` also implements the event listening interface of the `EventTarget`. On this basis, the basic node-related system events are provided. This document will introduce how to use these events.
+
+This document focuses on the mouse and touch events associated with the UI node tree, which are triggered directly on the UI-related nodes and are therefore called node events, and are used as follows:
+
+```ts
+node.on(Node.EventType.MOUSE_DOWN, (event) => {
+ console.log('Mouse down');
+}, this);
+```
+
+> __Note__: it is no longer recommended to directly use the event name string to register event listeners. Like the example above, please do not use `node.on('mouse-down', callback, target)` to register event listeners.
+
+The touch event listener on the node depends on the `UITransform` component, which is only applicable to 2D UI nodes. To implement the touch detection of 3D objects, refer to the [Touch Detection of 3D Objects](event-input.md#touch-detection-for-3D-objects) documentation.
+
+## Mouse event types and event objects
+
+__Mouse events__ will only be triggered on desktop platforms, the event types the system provides are as follows:
+
+| Enum Value Definition | Timing of Event Triggering |
+|:-------------------------------|:-----------------------------|
+| __Node.EventType.MOUSE_DOWN__ | When a button on the mouse is pressed in the target node area |
+| __Node.EventType.MOUSE_ENTER__ | When the cursor enters the target node area, whether or not the button is pressed |
+| __Node.EventType.MOUSE_MOVE__ | When the cursor is moved in the target node area, whether or not the button is pressed |
+| __Node.EventType.MOUSE_LEAVE__ | When the cursor is moved out of the target node area, whether or not the button is pressed |
+| __Node.EventType.MOUSE_UP__ | When a button on the mouse is released |
+| __Node.EventType.MOUSE_WHEEL__ | When the mouse wheel is scrolled |
+
+The important APIs of mouse events (`Event.EventMouse`) are described in the [Mouse Events API](event-api.md#Mouse-Event-API) (`Event` standard events API excluded).
+
+## Touch event types and event objects
+
+__Touch events__ can be triggered on both mobile platforms and desktop platforms. Developers can better debug on the desktop platform, by simply listening to touch events and responding to both mobile touch events and desktop mouse events at the same time. The types of touch events provided by the system are as follows:
+
+| Enum Value Definition | Timing of Event Triggering |
+|:--------------------------------|:---------------------------|
+| __Node.EventType.TOUCH_START__ | When one or more touch points are placed in the target node area |
+| __Node.EventType.TOUCH_MOVE__ | When one or more touch points are moved along the screen |
+| __Node.EventType.TOUCH_END__ | When one or more touch points are removed from the screen in the target node area |
+| __Node.EventType.TOUCH_CANCEL__ | When one or more touch points are removed from the screen outside the target node area |
+
+The important APIs of a touch event (`Event.EventTouch`) are described in the [Mouse Events API](event-api.md#Touch-Event-API) (`Event` standard event API excluded).
+
+> __Note__: touch events support multi-touch, each touch spot will send one event to the event listener.
+
+## Node Event Dispatching
+
+The `dispatchEvent` interface is supported on `Node`. Events dispatched by this interface would enter the event delivery stage. The event dispatching system of Cocos Creator is based on the implementation of [event bubbling and capture on Web standard](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_bubbling_and_capture). After the event is dispatched, it will go through the following three stages:
+- __Capturing phase__: the event is passed from the scene root node to the child nodes step by step, until it reaches the target node or the event propagation is stopped in the event callback
+- __Target phase__: the event is triggered on the target node
+- __Bubbling phase__: the event is bubbled from the target node to the parent node level by level, until the root node is reached or the event propagation is stopped in the event callback
+
+When calling `node.dispatchEvent()`, it means that `node` is the target node mentioned above. In the process of event delivery, call `event.propagationStopped = true` to stop the event propagation.
+
+In v3.0, the `Event.EventCustom` class was removed. To dispatch custom events, a custom event class that inherits from the `Event` class needs to be implemented first. For example:
+
+```ts
+// Import "Event" from 'cc' module
+import { Event } from 'cc';
+
+class MyEvent extends Event {
+ constructor(name: string, bubbles?: boolean, detail?: any){
+ super(name, bubbles);
+ this.detail = detail;
+ }
+ public detail: any = null; // Custom property
+}
+```
+
+
+
+Take the above picture as an example, this picture shows the propagation sequence of events in the **target** and **bubbling** phases. When we dispatch the event `“foobar”` from node c, if both node a and b listen to the event `“foobar”`, the event will pass to node b and a from c. For example:
+
+```ts
+// In the component script of node c
+this.node.dispatchEvent( new MyEvent('foobar', true, 'detail info') );
+```
+
+To stop the event propagation after node b intercepts the event, call `event.propagationStopped = true` to do this. Detailed methods are as follows:
+
+```ts
+// In the component script of node b
+this.node.on('foobar', (event: MyEvent) => {
+ event.propagationStopped = true;
+});
+```
+
+> __Note__: to dispatch a custom event, do not use `Event` directly because it's an abstract class.
+
+If you wish to register the event in the capturing phase, you can pass a fourth parameter to the `on` interface as follows:
+
+```ts
+// in the component script of node a
+this.node.on('foobar', callback, target, true);
+```
+
+## Event Objects
+
+In the callback of the event listener, the developer will receive an event object event of the `Event` type. `propagationStopped` is the standard API of Event, other important API include:
+
+| API Name | Type | Meaning |
+|:-----------|:-------|:---------|
+| __type__ | String | The event type (event name). |
+| __target__ | Node | The original target that received the event. |
+| __currentTarget__ | Node | The current object that received the event. The current target of the event during the bubbling phase may be different from the original target. |
+| __getType__ | Function | Get the event type. |
+| __propagationStopped__ | Boolean | Whether or not stop the bubbling phase. The parent node of the current target no longer receives the corresponding event. |
+| __propagationImmediateStopped__ | Boolean | Whether or not stop passing the current event immediately. The current target no longer receives the event either. |
+
+## Touch event propagation
+
+As mentioned above, touch events registered on the `Node` are dispatched internally by the engine through the `dispatchEvent` interface. Below introduces the propagation sequence of touch events in the **target** and **bubbling** phases.
+
+### Touch event bubbling
+
+Touch events support the event bubbling on the node tree, take the pictures below as an example:
+
+
+
+In the scene shown in the picture, suppose node A has a child node B which has a child node C. The developer sets the touch event listeners for all these three nodes (each node has a touch event listener in examples below by default).
+
+When the mouse or finger was applied in the node C region, the event will be triggered at node C first and the node C listener will receive the event (this is the target phase). Then the node C will pass this event to its parent node, so the node B listener will receive this event. Similarly the node B will also pass the event to its parent node A. This is a basic event bubbling phase.
+
+> __Note__: it needs to be emphasized that there is no hit test in parent nodes in the bubbling phase, which means that nodes A and B can receive touch events even though the touch location is out of their node area.
+
+The bubbling phase of touch events is no different than the general events. Calling `event.propagationStopped = true` can force stopping the bubbling phase.
+
+### Ownership of touch points among brother nodes
+
+Suppose the node B and C in the picture above are brother nodes, while C partly covers over B. Now if C receives a touch event, it is announced that the touch point belongs to C, which means that the brother node B won't receive the touch event any more, even though the touch location is also inside its node area. The touch point belongs to the top one among brother nodes.
+
+At the same time, if C has a parent node, it will also pass the touch event to its parent node through the event bubble mechanism.
+
+In v3.4.0, the ability of event penetrating dispatch is supported. In this example, if the event needs to be dispatched to node B, the event can be prevented from being swallowed by node C by calling `event.preventSwallow = true`.
+
+> __Note__: Can prevent swallowing touch end event only if prevent swallowing corresponding touch start event. Penetrating dispatch reduces the efficiency of event dispatch, please use it with caution.
+
+### Point of Contact Attribution for Different Canvas
+
+Contact interception between different Canvas is determined by priority. In the scene in the figure below, Canvas 1-5 in the node tree corresponds to priority 1-5 of the image display. It can be seen that even though Canvas nodes 3, 4, and 5 are arranged in scrambled order, the order of response of the contacts is still __Canvas5 -> Canvas4 -> Canvas3 -> Canvas2 -> Canvas1__, according to the priority relationship on the Canvas. The sorting between Canvas is done in the order of the node tree only if the priority is the same.
+
+
+
+### Register touch or mouse events in the capturing phase
+
+Sometimes, it is necessary to dispatch touch or mouse events to parent node event listeners before dispatching to any child nodes beneath it in hierarchy, like the design of __ScrollView__ component.
+
+Event bubbling cannot meet all demands. When this happens, register the parent node event listeners in the capturing phase. To achieve this goal, passing in `true` as the `useCapture` parameter (a fourth parameter) when registering touch or mouse event on the node. For example:
+
+```ts
+this.node.on(Node.EventType.TOUCH_START, this.onTouchStartCallback, this, true);
+```
+
+When the node fires the `Node.EventType.TOUCH_START` event, the `Node.EventType.TOUCH_START` event will be first dispatched to all the parent node event listeners registered in the capturing phase, then dispatched to the node itself, and finally comes the event bubbling phase.
+
+Only touch or mouse events can be registered in the capturing phase, while the other events can't be.
+
+### Event Interception
+
+Normal events are dispensed as described above. However, if the node has components such as `Button`, `Toggle` or `BlockInputEvents` on it, it will stop event bubbling.
+
+Look at the picture below. There are two buttons, priority 1 for Canvas0 and priority 2 for Canvas1. Click on the intersection of the two buttons, which is the blue area in the picture, it appears that button priority 2 received the contact event successfully, while button priority 1 did not. That's because according to the event reception rules above, button priority 2 receives contact events first and intercepts them (`event.propagationStopped = true`) to prevent event penetration. If the node is a non-button node, events can also be intercepted by adding the `BlockInputEvents` component to prevent penetration.
+
+> **Note**: buttons priority 1 and priority 2 are under Canvas 0 and Canvas 1 nodes respectively, the two buttons are not brother nodes.
+
+
+
+## Example for touch events
+
+Using the example below, summarizing touch events is easy. There are four nodes A, B, C and D in the picture above, where A and B are brother nodes. The specific hierarchical relationship should be like this:
+
+
+
+1. If one touch is applied in the overlapping area between A and B, now B won't receive the touch event, so that propagating order of the touch event should be __A -> C -> D__.
+2. If the touch location is in node B (the visible green area), the order should be __B -> C -> D__.
+3. If the touch location is in node C, the order should be __C -> D__.
+4. As a precondition to the second case, register touch events on C D node in the capturing phase, then the order should be __D -> C -> B__.
+
+## Other events of Node
+
+All built-in `Node` events can get event names from `Node.EventType`.
+
+### 3D Node Events
+
+| Enum Value Definition | Timing of Event Triggering |
+| :------------- | :---------- |
+| __TRANSFORM_CHANGED__ | When a transform property is modified, an enum value `TransformBit` is assigned that defines the modified transform based on the enum value. |
+
+Definition of Transformation Enum Values:
+
+| Enum Value Definition | Transformations |
+|:---------------------------|:-----------------------------------------------|
+| __TransformBit.NONE__ | The properties remain unchanged. |
+| __TransformBit.POSITION__ | The node position changes. |
+| __TransformBit.ROTATION__ | The node rotation changes. |
+| __TransformBit.SCALE__ | The node scale changes. |
+| __TransformBit.RS__ | The node rotation and scale change. |
+| __TransformBit.TRS__ | The node position, rotation and scale change. |
+
+### 2D Node Events
+
+| Enum Value Definition | Timing of Event Triggering |
+|:---------------------------|:-------------------------------------------------------------------------------------------------------------------------|
+| __SIZE_CHANGED__ | When the width/height property is modified. The width/height property is located on the `UITransform` component. |
+| __ANCHOR_CHANGED__ | When the X/Y properties of the anchor is modified. The width/height property is located on the `UITransform` component. |
+| __COLOR_CHANGED__ | When the color property is modified. The width/height property is located on the `UITransform` component. |
+| **CHILD_ADDED** | When adding child node |
+| **CHILD_REMOVED** | When removing child node |
+| **PARENT_CHANGED** | When the parent node changes |
+| **SIBLING_ORDER_CHANGED** | When the sibling order changes |
+| **SCENE_CHANGED_FOR_PERSISTS** | When the scene changes where the persist node is |
+| **NODE_DESTROYED** | When destroying node |
+| **LAYER_CHANGED** | When `layer` property changes |
+| **ACTIVE_IN_HIERARCHY_CHANGED** | When `activeInHierarchy` property changes |
+
+## Multi-touch event
+
+The engine has a multi-touch event blocking switch. Multi-touch events are enabled by default. For projects that do not require multi-touch, you can disable allowing multi-touch with the following code:
+
+```ts
+macro.ENABLE_MULTI_TOUCH = false;
+```
+
+Alternatively, it can be configured via __Project -> Project Settings -> Macro Config__. Just uncheck the **ENABLE_MULTI_TOUCH** property.
+
+## Pause or resume node system events
+
+Pause node system events
+
+```ts
+// Pause all node system events registered on the current node. Node system events include Touch and Mouse Events.
+// If a parameter true is passed, the API will pause node system events on this node and all its children.
+// Example
+this.node.pauseSystemEvents();
+```
+
+Resume node system events
+
+```ts
+// Resume all node system events registered on the current node. Node system events include Touch and Mouse Events.
+// If a parameter true is passed, the API will resume node system events on this node and all its children.
+// Example
+this.node.resumeSystemEvents();
+```
diff --git a/versions/4.0/en/engine/event/event-screen.md b/versions/4.0/en/engine/event/event-screen.md
new file mode 100644
index 0000000000..89eae921f2
--- /dev/null
+++ b/versions/4.0/en/engine/event/event-screen.md
@@ -0,0 +1,55 @@
+# Screen Event System in Cocos Creator
+
+## Introduction
+
+As discussed earlier, `EventTarget` provides functionalities for event listening and emitting. Cocos Creator v3.8.0 introduces the `screen` object, which implements the `EventTarget` interface. This object allows registering global system screen events.
+
+## Supported Events
+
+Here's a table outlining the currently supported global screen events:
+
+| Event Name | Description | Supported Platforms | Supported Version |
+|----------------------------|-------------------------------------------------|--------------------------|-------------------|
+| `window-resize` | Listens for window size changes. | Web, Native, MiniGame | 3.8.0 |
+| `orientation-change` | Listens for screen orientation changes. | Web, Native | 3.8.3 |
+| `fullscreen-change` | Listens for full screen changes. | Web | 3.8.0 |
+
+## Event Usage Example
+
+```typescript
+import { _decorator, Component, screen, macro } from 'cc';
+const { ccclass } = _decorator;
+
+@ccclass("Example")
+export class Example extends Component {
+ onLoad() {
+ // Register event listeners with the screen object
+ screen.on('window-resize', this.onWindowResize, this);
+ screen.on('orientation-change', this.onOrientationChange, this);
+ screen.on('fullscreen-change', this.onFullScreenChange, this);
+ }
+
+ onDestroy() {
+ // Unregister event listeners when the component is destroyed
+ screen.off('window-resize', this.onWindowResize, this);
+ screen.off('orientation-change', this.onOrientationChange, this);
+ screen.off('fullscreen-change', this.onFullScreenChange, this);
+ }
+
+ onWindowResize(width: number, height: number) {
+ console.log("Window resized:", width, height);
+ }
+
+ onOrientationChange(orientation: number) {
+ if (orientation === macro.ORIENTATION_LANDSCAPE_LEFT || orientation === macro.ORIENTATION_LANDSCAPE_RIGHT) {
+ console.log("Orientation changed to landscape:", orientation);
+ } else {
+ console.log("Orientation changed to portrait:", orientation);
+ }
+ }
+
+ onFullScreenChange(width: number, height: number) {
+ console.log("Fullscreen change:", width, height);
+ }
+}
+```
diff --git a/versions/4.0/en/engine/event/events-block.png b/versions/4.0/en/engine/event/events-block.png
new file mode 100644
index 0000000000..9fb6664e4e
Binary files /dev/null and b/versions/4.0/en/engine/event/events-block.png differ
diff --git a/versions/4.0/en/engine/event/example.png b/versions/4.0/en/engine/event/example.png
new file mode 100644
index 0000000000..d38c8f2985
Binary files /dev/null and b/versions/4.0/en/engine/event/example.png differ
diff --git a/versions/4.0/en/engine/event/index.md b/versions/4.0/en/engine/event/index.md
new file mode 100644
index 0000000000..fa3d7c8c24
--- /dev/null
+++ b/versions/4.0/en/engine/event/index.md
@@ -0,0 +1,13 @@
+# Event System
+
+The event system is a common feature that needs to be involved in interaction during game development. The event system can be used not only to send input actions (e.g. keyboard, mouse, touch) to the application in the form of events, but also to respond to things that happen during the game that require the attention of other objects in the form of events. For example, opening the checkout or reward screen after a game victory.
+
+## Use of Events
+
+Events need to be registered to get listened to. Learn about event listening and emitting through the [Event Listening and Emitting](event-emit.md) documentation.
+
+On the basis of event listening and emitting, Cocos Creator supports many built-in event systems, including:
+
+- [Input Event System](event-input.md)
+- [Node Event System](event-node.md)
+- [Screen Event System](event-screen.md)
diff --git a/versions/4.0/en/engine/event/multi-canvas.png b/versions/4.0/en/engine/event/multi-canvas.png
new file mode 100644
index 0000000000..3004dd4647
Binary files /dev/null and b/versions/4.0/en/engine/event/multi-canvas.png differ
diff --git a/versions/4.0/en/engine/event/propagation.png b/versions/4.0/en/engine/event/propagation.png
new file mode 100644
index 0000000000..4c3cd1170f
Binary files /dev/null and b/versions/4.0/en/engine/event/propagation.png differ
diff --git a/versions/4.0/en/engine/renderable/create-model.png b/versions/4.0/en/engine/renderable/create-model.png
new file mode 100644
index 0000000000..86412ef46a
Binary files /dev/null and b/versions/4.0/en/engine/renderable/create-model.png differ
diff --git a/versions/4.0/en/engine/renderable/mesh-renderer/view-model.gif b/versions/4.0/en/engine/renderable/mesh-renderer/view-model.gif
new file mode 100644
index 0000000000..75bb20c8a8
Binary files /dev/null and b/versions/4.0/en/engine/renderable/mesh-renderer/view-model.gif differ
diff --git a/versions/4.0/en/engine/renderable/meshrenderer-properties.png b/versions/4.0/en/engine/renderable/meshrenderer-properties.png
new file mode 100644
index 0000000000..c62a5ad74f
Binary files /dev/null and b/versions/4.0/en/engine/renderable/meshrenderer-properties.png differ
diff --git a/versions/4.0/en/engine/renderable/model-component.md b/versions/4.0/en/engine/renderable/model-component.md
new file mode 100644
index 0000000000..e8c561f745
--- /dev/null
+++ b/versions/4.0/en/engine/renderable/model-component.md
@@ -0,0 +1,89 @@
+# MeshRenderer Component Reference
+
+The __MeshRenderer__ component is used to display a static 3D model. Set the model mesh with the `Mesh` property, and change the appearance of the model with the `Materials` property.
+
+Click **Add Component -> Mesh -> MeshRenderer** in the **Inspector** panel to add the MeshRenderer component.
+
+
+
+## MeshRenderer Properties
+
+| Property | Description
+| :--- | :---
+| **Materials** | The material used to render the model, one material corresponds to one sub-mesh in the mesh.
+| **LightmapSettings** | For baking Lightmap, please refer to [Lightmapping](../../concepts/scene/light/lightmap.md) for details.
+| **ShadowCastingMode** | Specifies whether the current model will cast shadows, which needs to [enable shadow effect](../../concepts/scene/light/shadow.md#enable-shadow-effect) in the scene first
+| **ReceiveShadow** | Specifies whether the current model will receive and display shadow effects generated by other objects, which needs to [enable shadow effect](../../concepts/scene/light/shadow.md#enable-shadow-effect) in the scene first. This property takes effect only when the shadow type is __ShadowMap__.
+| **Mesh** | 3D model assets for rendering.
+
+The component interfaces for the common model are described in [MeshRenderer API](%__APIDOC__%/en/class/MeshRenderer).
+
+The component interfaces for the skinning model are described in [SkinnedMeshRenderer API](%__APIDOC__%/en/class/SkinnedMeshRenderer).
+
+### Mesh Assets
+
+Mesh assets are necessary for rendering meshes. Currently, meshes are mainly generated automatically by Creator when [importing models](../../asset/model/mesh.md) into Creator.
+
+A Mesh asset contains a set of vertices and multiple sets of indices. The index points to the vertex in the vertex array, and every three sets of indices form a triangle. A mesh is composed of multiple triangles and is the most basic graphical element in the 3D world. Multiple triangles are stitched together to form a complex polygon, and multiple polygons are stitched together to form a 3D model.
+
+Creator provides several simple static 3D models with basic models such as the cube, cylinder, etc. Developers can create a few in the **Hierarchy** panel as needed to get a first look.
+
+
+
+## Model Group Rendering
+
+The group rendering function is determined by the [Visibility property](../../editor/components/camera-component.md#set-the-visibility-property) of the camera component and the [Layer property](../../concepts/scene/node-component.md#set-the-layer-property-of-the-node) of the node. Users can set the `Visibility` value through code to complete the group rendering. All nodes belong to the `DEFAULT` layer by default and are visible on all cameras.
+
+## Static Batching
+
+The current static batching scheme is static batching at run time. Static batching can be performed by calling `BatchingUtility.batchStaticModel`. This function receives a node, and then merges all `Mesh` in `MeshRenderer` under that node into one, and hangs it under another node.
+
+After batching, the original transform of `MeshRenderer` cannot be changed, but the transform of the root node after batching can be changed. Only nodes that meet the following conditions can be statically batched:
+
+- The child node can only contain `MeshRenderer`.
+- The vertex data structure of `Mesh` of `MeshRenderer` under child nodes must be consistent.
+- The material of `MeshRenderer` under child nodes must be the same.
+
+## Dynamic Batching
+
+The engine currently provides **instancing batching** .
+
+To turn on batching, simply check the corresponding `USE_INSTANCING` switch in the material used by the model.
+
+> **Note**: the current batching process introduces several limitations:
+>
+> 1. The transparent models in the same batch are not sorted, this may lead to incorrect blending results.
+> 2. The inverse-transpose world matrix is not uploaded into batches, models with non-uniform scale will have inaccurate normals.
+> 3. Only plain models and skinning models under pre-baked skeletal animation are supported. (i.e. real-time skeletal animations, 2D objects, UIs and particles do not support dynamic batching)
+
+### Instancing Batching
+
+The batch through **instancing** is suitable for drawing a large number of dynamic models with the same vertex data. When enabled, drawing will be grouped according to the material and vertex data, and the instanced attributes information will be organized in each group, and then complete the drawing at one time.
+
+> **Note**: for the support and related settings of the skinning model, refer to the [Skeletal Animation Component](../../animation/skeletal-animation.md#AboutDynamic-Instancing) documentation.
+
+In addition, inside each group, the instanced attributes supports custom additional instanced attributes, which can pass more per-instance data between different instances (such as the difference in appearance of a diffuse color between different characters, or the influence of wind in a large grass field). This requires the support of custom effects. For more detailed instructions, please refer to the [Syntax Guide](../../material-system/effect-syntax.md#Custom-Instanced-Properties) documentation.
+
+### VB-merging Batching
+
+VB-merging batching will do some operations such as merging vertices per frame introduce a portion of CPU overhead, which is particularly expensive in JavaScript. Abuse without rigorous testing can cause performance degradation, **This feature has been removed in 3.6.2, so please use Instancing or static batching as a preference instead.**
+
+In addition, it is necessary to remind that the number of draw calls is not is not the only performance metric[^2]. Optimal performance is often the result of CPU and GPU load balancing, so when using batch functions, be sure to do more tests to identify performance bottlenecks and do targeted optimization.
+
+## Batch Best Practices
+
+Generally speaking, the priority of the batch system is: **static batching** -> **instancing batching**.
+
+The material must be insured that it is consistent, under this premise:
+
+- If you are certain that certain models will remain completely static during the game cycle, use **static batching**.
+- If there are a large number of the same model repeated drawing, there is only a relatively controllable small difference between each other, use **instancing batching**.
+
+## Preview Model
+
+The model can be observed in the scene view when the mouse hovers over the drop-down mesh in the **Mesh** property.
+
+
+
+[^1]: Currently use uniforms to upload the batched world transformation matrix, taking into account the WebGL standard uniform quantity limit, the current batch draws up to 10 models, so for a large number of same For the material model, the number of drawcalls is expected to be reduced by up to 10 times after enabling __VB-merging batching__.
+[^2]: There have been many discussions in the industry on the topic of batching and performance, you can refer to this [nVidia slide](https://www.nvidia.com/docs/IO/8228/BatchBatchBatch.pdf).
diff --git a/versions/4.0/en/engine/rendering/sorting-2d.md b/versions/4.0/en/engine/rendering/sorting-2d.md
new file mode 100644
index 0000000000..fd793f8c23
--- /dev/null
+++ b/versions/4.0/en/engine/rendering/sorting-2d.md
@@ -0,0 +1,76 @@
+# 2D Rendering Sorting Component
+
+The Sorting2D component allows customizing the rendering order of 2D objects without affecting the original node hierarchy. It can help solve the issue of increased DrawCalls caused by adjacent render objects using different materials.
+
+
+
+## Sorting2D Properties
+
+| Property | Description |
+| :-------------- | :----------- |
+| sortingLayer | Sets the sorting layer for render objects. [**Modify project's sorting layer configuration**](../../editor/project/index.md#sorting-layers). Lower layers are rendered first. Default layer is "Default". |
+| sortingOrder | Sets the order of render objects within the same sorting layer. Objects with lower values are rendered first. If values are equal, nodes with lower hierarchy are rendered first. |
+
+**Note**: When recursively collecting render elements from a 2D node tree encounters a Mask renderer, it will use custom sorting rules to render the recorded 2D UI, reset the render state, recollect render elements, and continue using custom sorting rules for the remaining 2D UI after collection is complete.
+
+## Optimization Example
+
+1. Configure sorting layers in your project
+
+ 
+
+2. Enable the `2D Rendering Sorting` module in `Project Settings -> Feature Cropping`
+
+ 
+
+3. Add Sorting2D component to 2D UI nodes and set sorting layers and orders.
+
+ 
+
+4. Build the project, run and observe optimization results
+
+ * Before optimization
+ 
+
+ * After optimization
+ 
+
+## Modifying Sorting2D Component's Layer and Order in Code
+
+```typescript
+import { _decorator, Component, find, Node, settings, Sorting2D } from 'cc';
+const { ccclass, property } = _decorator;
+
+const sortingLayers = settings.querySettings("engine", "sortingLayers");
+const default_layer = sortingLayers[0].value;
+const autoAtlas_1_layer = sortingLayers[1].value;
+const autoAtlas_2_layer = sortingLayers[2].value;
+const autoAtlas_1_1_layer = sortingLayers[3].value;
+const label_layer = sortingLayers[4].value;
+
+@ccclass('NewComponent')
+export class NewComponent extends Component {
+
+ start() {
+ var testNode = find("Canvas/test");
+ if (testNode) {
+ this.changeUISortingLayer(testNode, autoAtlas_1_layer, 0);
+ }
+ }
+
+ changeUISortingLayer(sortingNode: Node, sortingLayer: number, sortingOrder?: number) {
+ if (sortingNode.getComponent(Sorting2D)) {
+ sortingNode.getComponent(Sorting2D).sortingLayer = sortingLayer;
+ if (sortingOrder !== undefined) {
+ sortingNode.getComponent(Sorting2D).sortingOrder = sortingOrder;
+ }
+ }
+ }
+}
+```
+
+## API Reference and Examples
+
+[Sorting2D API](https://docs.cocos.com/creator/4.0/api/en/class/Sorting2D)
+
+[Sorting2D Demo](https://github.com/cocos/cocos-test-projects/tree/v3.8.7/assets/cases/ui/other/sorting2D)
diff --git a/versions/4.0/en/engine/rendering/sorting-2d/sorting2D-addComponent.jpg b/versions/4.0/en/engine/rendering/sorting-2d/sorting2D-addComponent.jpg
new file mode 100644
index 0000000000..ef526b5489
Binary files /dev/null and b/versions/4.0/en/engine/rendering/sorting-2d/sorting2D-addComponent.jpg differ
diff --git a/versions/4.0/en/engine/rendering/sorting-2d/sorting2D-layers.jpg b/versions/4.0/en/engine/rendering/sorting-2d/sorting2D-layers.jpg
new file mode 100644
index 0000000000..ab084987b0
Binary files /dev/null and b/versions/4.0/en/engine/rendering/sorting-2d/sorting2D-layers.jpg differ
diff --git a/versions/4.0/en/engine/rendering/sorting-2d/sorting2D-open.jpg b/versions/4.0/en/engine/rendering/sorting-2d/sorting2D-open.jpg
new file mode 100644
index 0000000000..d9749f485e
Binary files /dev/null and b/versions/4.0/en/engine/rendering/sorting-2d/sorting2D-open.jpg differ
diff --git a/versions/4.0/en/engine/rendering/sorting-2d/sorting2D-setProperty.jpg b/versions/4.0/en/engine/rendering/sorting-2d/sorting2D-setProperty.jpg
new file mode 100644
index 0000000000..9413e9f38a
Binary files /dev/null and b/versions/4.0/en/engine/rendering/sorting-2d/sorting2D-setProperty.jpg differ
diff --git a/versions/4.0/en/engine/rendering/sorting.md b/versions/4.0/en/engine/rendering/sorting.md
new file mode 100644
index 0000000000..57d6314edb
--- /dev/null
+++ b/versions/4.0/en/engine/rendering/sorting.md
@@ -0,0 +1,87 @@
+# 3D Sorting
+
+For most rendering cases, the default sorting is sufficient. But in practice, due to the special nature of translucent objects, we may need to sort these objects manually. For this case, the **Sorting** component can be used.
+
+Click the **Add Component** button inside the **Inspector** panel and select **Sorting** to add it.
+
+
+
+> **Note**: This component is only available for nodes holding **MeshRenderer** and **SpriteRenderer** components.
+
+## Properties
+
+| Properties | Decription |
+| :-- | :-- |
+| **Sorting Layer** | Select **Sort Layers** Select different sort layers by using the drop down box, these layers need to be set within **Project Settings** -> **Sort Layers** before they can be selected  |
+| **Sorting Order** | Sorting priority within the same layer |
+
+## Example
+
+- Add Sorting Layer 1 to **Project Settings** -> **Sorting Layer**.
+
+ 
+
+- Build the following scene as shown in the example.
+
+ 
+
+- The cube and sphere materials require the option of using the translucent render queue.
+
+ 
+
+ Adds the Sorting component and leaves the properties as default.
+
+- The image needs to use the **SpriteRenderer** component (note that it is not a Sprite component), the shader needs to use the **builtin-sprite-renderer**, and the Sorting component needs to be added, keeping the properties defaulted to.
+
+ 
+
+At this point it can be observed that the nodes are sorted in the default order.
+
+### Sorting Layer Example
+
+The Sorting Layer of the SpriteRenderer node is adjusted as follows.
+
+
+
+Since the custom level is higher than the level default for cubes and spheres, the result can be observed in the following figure.
+
+
+
+### Sorting Order Example
+
+The Sorting Order property allows you to adjust the priority of rendering objects within the same sorting layer.
+
+The scene is similar to the example above, but with the Sorting Order property within the Sorting component of the cube adjusted to 1.
+
+
+
+At this point, the cube is prioritized over the sphere within the rendering queue, so you can observe the result in the following figure.
+
+
+
+## Code Example
+
+The following code demonstrates how to modify the Sorting Order and Sorting Layer at runtime.
+
+```ts
+import { _decorator, Component, Sorting, SortingLayers } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass('SortingSample')
+export class SortingSample extends Component {
+
+ @property(Sorting)
+ sorting:Sorting | null = null;
+
+ start() {
+ this.sorting.sortingLayer = SortingLayers.getLayerIndexByName("Sorting Layer 1");
+ this.sorting.sortingOrder = 1;
+ }
+}
+```
+
+**SortingLayers** The names and indexes of sorting layers can be obtained at runtime, but cannot be modified at runtime.
+
+## API
+
+The API for sorting components can be found in [Sorting](%__APIDOC__%/en/class/Sorting) and [SortingLayers](%__APIDOC__%/en/class/SortingLayers) 。
diff --git a/versions/4.0/en/engine/rendering/sorting/default-sort.png b/versions/4.0/en/engine/rendering/sorting/default-sort.png
new file mode 100644
index 0000000000..affb0e08e2
Binary files /dev/null and b/versions/4.0/en/engine/rendering/sorting/default-sort.png differ
diff --git a/versions/4.0/en/engine/rendering/sorting/project-settings.png b/versions/4.0/en/engine/rendering/sorting/project-settings.png
new file mode 100644
index 0000000000..d1d0734fa1
Binary files /dev/null and b/versions/4.0/en/engine/rendering/sorting/project-settings.png differ
diff --git a/versions/4.0/en/engine/rendering/sorting/result-sorting-layer.png b/versions/4.0/en/engine/rendering/sorting/result-sorting-layer.png
new file mode 100644
index 0000000000..747cd800a1
Binary files /dev/null and b/versions/4.0/en/engine/rendering/sorting/result-sorting-layer.png differ
diff --git a/versions/4.0/en/engine/rendering/sorting/sorting-layer.png b/versions/4.0/en/engine/rendering/sorting/sorting-layer.png
new file mode 100644
index 0000000000..cd9572b379
Binary files /dev/null and b/versions/4.0/en/engine/rendering/sorting/sorting-layer.png differ
diff --git a/versions/4.0/en/engine/rendering/sorting/sorting-layer1.png b/versions/4.0/en/engine/rendering/sorting/sorting-layer1.png
new file mode 100644
index 0000000000..b353823258
Binary files /dev/null and b/versions/4.0/en/engine/rendering/sorting/sorting-layer1.png differ
diff --git a/versions/4.0/en/engine/rendering/sorting/sorting-order1-result.png b/versions/4.0/en/engine/rendering/sorting/sorting-order1-result.png
new file mode 100644
index 0000000000..df467f408c
Binary files /dev/null and b/versions/4.0/en/engine/rendering/sorting/sorting-order1-result.png differ
diff --git a/versions/4.0/en/engine/rendering/sorting/sorting-order1.png b/versions/4.0/en/engine/rendering/sorting/sorting-order1.png
new file mode 100644
index 0000000000..d4b871182b
Binary files /dev/null and b/versions/4.0/en/engine/rendering/sorting/sorting-order1.png differ
diff --git a/versions/4.0/en/engine/rendering/sorting/sorting.png b/versions/4.0/en/engine/rendering/sorting/sorting.png
new file mode 100644
index 0000000000..44415270cd
Binary files /dev/null and b/versions/4.0/en/engine/rendering/sorting/sorting.png differ
diff --git a/versions/4.0/en/engine/rendering/sorting/sprite-renderer-layer.png b/versions/4.0/en/engine/rendering/sorting/sprite-renderer-layer.png
new file mode 100644
index 0000000000..0db65490b7
Binary files /dev/null and b/versions/4.0/en/engine/rendering/sorting/sprite-renderer-layer.png differ
diff --git a/versions/4.0/en/engine/rendering/sorting/tech.png b/versions/4.0/en/engine/rendering/sorting/tech.png
new file mode 100644
index 0000000000..dedcfba542
Binary files /dev/null and b/versions/4.0/en/engine/rendering/sorting/tech.png differ
diff --git a/versions/4.0/en/engine/template/native-upgrade-to-v3.5.md b/versions/4.0/en/engine/template/native-upgrade-to-v3.5.md
new file mode 100644
index 0000000000..a7116cac4c
--- /dev/null
+++ b/versions/4.0/en/engine/template/native-upgrade-to-v3.5.md
@@ -0,0 +1,156 @@
+# v3.5 Built project upgrade Guide
+
+Since v3.5, the 'appdelegate' of MAC and windows platforms has been moved into the internal implementation of the engine, and can be compatible with the usage of previous versions by overloading 'appdelegate' `game.cpp` has also been adjusted, and existing projects need to be rebuilt and upgraded.
+
+## Engineering Upgrade
+
+Check whether the native/engine directory exists in the project directory. If it exists, you need to delete the folder and make a backup before deleting it (if this directory exists, it will not be updated automatically when you rebuild); if it does not exist, you can build it directly.
+
+### Custom code migration methods
+
+The code previously added in AppDelegate can be upgraded by customizing the platform and AppDelegate below; the custom game.cpp can be upgraded by replacing the interface.
+
+#### Platform and AppDelegate customization methods
+
+Take **Mac** as an example:
+
+1. Custom AppDelegate(Reference file name: MyAppdelegate.h, MyAppdelegate.mm)
+
+```
+@interface MyAppDelegate : NSObject
+ // Define the methods that need to be rewritten
+ - (void)applicationWillResignActive:(UIApplication *)application;
+@end
+
+@implementation MyAppDelegate
+- (void)applicationWillResignActive:(UIApplication *)application {
+ // Note: Calling methods of the parent class
+ [super applicationWillResignActive:application]
+}
+@end
+```
+
+2. Customized platforms(Reference file name: CustomMacPlatform.h)
+
+```
+#include "platform/BasePlatform.h"
+#include "MyAppDelegate.h"
+
+class CustomMacPlatform : public MacPlatform {
+public:
+ // Rewrite the initialization method of the platform
+ int32_t init() override {
+ // Calling the methods of the parent class
+ return MacPlatform::init();
+ }
+ // Here you enter the message loop of oc until the program exits
+ int32_t run(int argc, const char** argv) {
+ id delegate = [[MyAppDelegate alloc] init];
+ NSApplication.sharedApplication.delegate = delegate;
+ return NSApplicationMain(argc, argv);
+ }
+}
+```
+
+3. Loading custom platforms(Reference file name: main.mm)
+
+```
+#include "CustomMacPlatform.h"
+
+int main(int argc, const char * argv[]) {
+ CustomMacPlatform platform;
+ if (platform.init()) {
+ return -1;
+ }
+ return platform.run(argc, (const char**)argv);
+}
+```
+
+#### game.cpp Migration mode
+
+- Set js encryption secret key: jsb_set_xxtea_key -> Set `_xxteaKey` member variable; ; or call `setXXTeaKey`
+- Setup debugging: jsb_enable_debugger -> Change the value of `_debuggerInfo`, or call `setDebugIpAndPort`
+- Setting exception callbacks: setExceptionCallback -> Override the `handleException` interface
+- Run custom scripts: jsb_run_script -> call `runScript`
+- You can add events to be listened to by using `engine`, -> `getEngine()->addEventCallback(WINDOW_OSEVENT, eventCb);`
+- Customized games `CustomGame`, Need to register to engine `CC_REGISTER_APPLICATION(CustomGame)` for loading
+- `game` Inherited from `cc::BaseGame`, and `cc::BaseGame` inherits from `CocosApplication`,so that partial implementations can be rewritten to add custom logic.
+
+### The modification of Native Files
+
+- Replace the header file path: #include "cocos/platform/Application.h" —> #include "application/ApplicationManager.h"
+- Change of usage: cc::Application::getInstance()->getScheduler() -> CC_CURRENT_ENGINE()->getScheduler()
+- If the code uses custom jsb: `native_ptr_to_seval` changed to `nativevalue_to_se`
+
+### Android
+
+#### JAVA
+
+- Delete `onCreate` in the following files: game/AppActivity.java, game/InstantActivity.java
+
+ ```java
+ // Workaround in https://stackoverflow.com/questions/16283079/re-launch-of-activity-on-home-button-but-only-the-first-time/16447508
+ if (!isTaskRoot()) {
+ // Android launched another instance of the root activity into an existing task
+ // so just quietly finish and go away, dropping the user back into the activity
+ // at the top of the stack (ie: the last state of this task)
+ // Don't need to finish it again since it's finished in super.onCreate .
+ return;
+ }
+ ```
+
+- app/AndroidManifest.xml
+ - delete code in the `application` tag: `android:taskAffinity=""`
+ - add code in the `application` tag: `android:exported="true"`
+
+- app/build.gradle
+ - modify code:
+
+ ```html
+ "${RES_PATH}/assets" -> "${RES_PATH}/data"
+ ```
+
+#### CMakeLists.txt
+
+- android/CMakeLists.txt
+ - LIB_NAME changed to CC_LIB_NAME
+ - PROJ_SOURCES changed to CC_PROJ_SOURCES
+ - add code: set(CC_PROJECT_DIR ${CMAKE_CURRENT_LIST_DIR})
+ - add code: set(CC_COMMON_SOURCES)
+ - add code: set(CC_ALL_SOURCES)
+ - delete code:
+
+ ```cmake
+ ${CMAKE_CURRENT_LIST_DIR}/../common/Classes/Game.h
+ ${CMAKE_CURRENT_LIST_DIR}/../common/Classes/Game.cpp
+
+ add_library(${LIB_NAME} SHARED ${PROJ_SOURCES})
+ target_link_libraries(${LIB_NAME}
+ "-Wl,--whole-archive" cocos2d_jni "-Wl,--no-whole-archive"
+ cocos2d
+ )
+ target_include_directories(${LIB_NAME} PRIVATE
+ ${CMAKE_CURRENT_LIST_DIR}/../common/Classes
+ )
+ ```
+
+ - add code:
+
+ ```cmake
+ cc_android_before_target(${CC_LIB_NAME})
+ add_library(${CC_LIB_NAME} SHARED ${CC_ALL_SOURCES})
+ # Add user dependent library AAA here. target_link_libraries(${CC_LIB_NAME} AAA)
+ # Add user defined file xxx/include here. target_include_directories(${CC_LIB_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../common/Classes/xxx/include)
+ cc_android_after_target(${CC_LIB_NAME})
+ ```
+
+- common/CMakeLists.txt
+ - cocos2d-x-lite/ changed to engine/native/
+ - Add code at the end of the file
+
+ ```cmake
+ list(APPEND CC_COMMON_SOURCES
+ ${CMAKE_CURRENT_LIST_DIR}/Classes/Game.h
+ ${CMAKE_CURRENT_LIST_DIR}/Classes/Game.cpp
+ )
+ ```
diff --git a/versions/4.0/en/engine/template/native-upgrade-to-v3.6.md b/versions/4.0/en/engine/template/native-upgrade-to-v3.6.md
new file mode 100644
index 0000000000..ead16cf613
--- /dev/null
+++ b/versions/4.0/en/engine/template/native-upgrade-to-v3.6.md
@@ -0,0 +1,69 @@
+# v3.5 Built Project Upgrade Guide to v3.6
+
+This article details the considerations for upgrading Cocos Creator native builds from 3.5.0 ~ 3.5.x to 3.6. The changes are only for the native directory under the project.
+
+## Build
+
+Open the old version of the project with the new version of the engine, and then build the target platform after the upgrade is completed. To avoid upgrade failure, please backup the project first, and then follow the steps below to upgrade.
+
+## Android
+
+### File modification
+
+- Delete file: jni/main.cpp
+- android/CMakeLists.txt: delete `${CMAKE_CURRENT_LIST_DIR}/jni/main.cpp`
+
+### Compile changes
+
+To reduce the package size, the default value of `CMAKE_C_FLAGS_RELEASE` and `CMAKE_CXX_FLAGS_RELEASE` compiler parameter `visibility` has been changed from `default` to `hidden`. For this change, if the interface is not found in the release version of `jni`, please check if the interface has the declaration `JNIEXPORT` added. For example.
+
+- Old Code
+
+ ```c++
+ void Java_com_google_android_games_paddleboat_GameControllerManager_onMouseConnected
+ ```
+
+- Modified
+
+ ````c++
+ JNIEXPORT void JNICALL Java_com_google_android_games_paddleboat_GameControllerManager_onMouseConnected
+ ````
+
+## Code modification
+
+- Projects with custom jsb interfaces: code related to `NonRefNativePtrCreatedByCtorMap` must be removed
+
+- Manually written JSB `_finalize` functions should be set to empty, please refer the [Tutorial: JSB 2.0](../../advanced-topics/JSB2.0-learning.md#c++-object-lifecycle-management).
+
+ For example:
+
+ ```c++
+ static bool js_cc_gfx_Size_finalize(se::State& s) // NOLINT(readability-identifier-naming)
+ {
+ auto iter = se::NonRefNativePtrCreatedByCtorMap::find(SE_THIS_OBJECT(s));
+ if (iter != se::NonRefNativePtrCreatedByCtorMap::end())
+ {
+ se::NonRefNativePtrCreatedByCtorMap::erase(iter);
+ auto* cobj = SE_THIS_OBJECT(s);
+ JSB_FREE(cobj);
+ }
+ return true;
+ }
+ SE_BIND_FINALIZE_FUNC(js_cc_gfx_Size_finalize)
+ ```
+ Remove all operations.
+ ```c++
+ static bool js_cc_gfx_Size_finalize(se::State& s) // NOLINT(readability-identifier-naming)
+ {
+ return true;
+ }
+ SE_BIND_FINALIZE_FUNC(js_cc_gfx_Size_finalize)
+ ```
+
+## Scripting Considerations
+
+Since the implementation of Native engines differs slightly from that of non-Native engines, developers must be aware of these differences, which are organized as follows.
+
+- `Readonly`: On Native platforms, properties are fetched as newly created objects in order to reduce memory usage.
+
+ The description of `Readonly` can be found in [Development Notes - ReaOnly](../../scripting/readonly.md#readonly)
diff --git a/versions/4.0/en/geometry-renderer/enable-geometry-renderer.png b/versions/4.0/en/geometry-renderer/enable-geometry-renderer.png
new file mode 100644
index 0000000000..30942212ec
Binary files /dev/null and b/versions/4.0/en/geometry-renderer/enable-geometry-renderer.png differ
diff --git a/versions/4.0/en/geometry-renderer/geometry-renderer-demo.png b/versions/4.0/en/geometry-renderer/geometry-renderer-demo.png
new file mode 100644
index 0000000000..75b9530656
Binary files /dev/null and b/versions/4.0/en/geometry-renderer/geometry-renderer-demo.png differ
diff --git a/versions/4.0/en/geometry-renderer/geometry-renderer-features.png b/versions/4.0/en/geometry-renderer/geometry-renderer-features.png
new file mode 100644
index 0000000000..fc5c233abd
Binary files /dev/null and b/versions/4.0/en/geometry-renderer/geometry-renderer-features.png differ
diff --git a/versions/4.0/en/geometry-renderer/index.md b/versions/4.0/en/geometry-renderer/index.md
new file mode 100644
index 0000000000..b4a6307739
--- /dev/null
+++ b/versions/4.0/en/geometry-renderer/index.md
@@ -0,0 +1,86 @@
+# Geometry Renderer
+
+Geometry renderer is a functional interface provided by the engine for batch rendering of various geometries, mainly used for debugging (such as displaying the enclosing boxes of objects) and the gizmo batch display of Cocos Creator.
+
+The effect of the geometry renderer is shown in the following figure.
+
+
+
+The features of Geometry Renderer is as follows:
+
+
+
+Where.
+- solid: whether to support solid mode, if not, then display wireframe mode
+- depth test: whether to support depth test, if support then the blocked part of the translucent display, not blocked part of the opaque display, if not support then all opaque display
+- lighting: whether to support simple lighting, if not, use no light mode
+- transform: whether support transform, if support, developer can pass in a transform matrix, the transform matrix will act on the geometry of the vertices, convenient to display the geometry of any coordinate space
+
+## API
+
+- Typescript: [geometry-render.ts](https://github.com/cocos/cocos4/blob/v4.0.0/cocos/core/pipeline/geometry-renderer.ts).
+- Native: [GeometryRenderer.h](https://github.com/cocos/cocos4/blob/v4.0.0/native/cocos/renderer/pipeline/GeometryRenderer.h).
+
+### Supported Geometry Types
+
+| Geometry Type | Interface |
+|:--|:--|
+| Dashed Line | addDashedLine |
+| Line | addLine |
+| Triangle | addTriangle |
+| Quad | addQuad |
+| BoundingBox | addBoundingBox |
+| Cross | addCross |
+| Frustum | addFrustum |
+| Capsule | addCapsule |
+| Cylinder | addCylinder |
+| Cone | addCone |
+| Circle | addCircle |
+| Arc | addArc |
+| Polygon | addPolygon |
+| Disc | addDisc |
+| Sector | addSector |
+| Sphere | addSphere |
+| Torus | addTorus |
+| Octahedron | addOctahedron |
+| Bezier curves | addBezier |
+| Spline curves with three modes: Folded segments, Multi-segment Bessel curves, Catmull-Rom curves | addSpline |
+| Mesh | addMesh |
+| Index Based Mesh | addIndexedMesh |
+
+### Example
+
+Since the vertex cache is cleared after rendering these geometries per frame, it is necessary to add geometries to the geometry renderer object (located in the camera) per frame in functions like update.
+
+To use this feature you need to enable **Geometry Renderer** in **Project Settings** -> **Feature Cropping**.
+
+
+
+> **Note**: Please make sure your project is 3D based.
+
+The code example is as follows:
+
+```ts
+import { _decorator, Component, Camera, Color } from 'cc';
+const { ccclass, property, executeInEditMode} = _decorator;
+
+@ccclass('Geometry')
+@executeInEditMode(true)
+export class Geometry extends Component {
+
+ @property(Camera)
+ mainCamera:Camera = null;
+
+ start() {
+ this.mainCamera?.camera.initGeometryRenderer();
+ }
+
+ update(deltaTime: number) {
+ this.mainCamera?.camera?.geometryRenderer?.addCircle(this.node.worldPosition, 1, Color.GREEN, 20);
+ }
+}
+```
+
+The result is as follows:
+
+
diff --git a/versions/4.0/en/geometry-renderer/result.png b/versions/4.0/en/geometry-renderer/result.png
new file mode 100644
index 0000000000..9e4deb3dd0
Binary files /dev/null and b/versions/4.0/en/geometry-renderer/result.png differ
diff --git a/versions/4.0/en/getting-started/attention/index.md b/versions/4.0/en/getting-started/attention/index.md
new file mode 100644
index 0000000000..790b1b8899
--- /dev/null
+++ b/versions/4.0/en/getting-started/attention/index.md
@@ -0,0 +1,11 @@
+## Precautions
+
+### Syntax format
+
+__Cocos Creator 3.0__ and __Cocos Creator v2.x__ use a different syntax format.
+
+__Cocos Creator 3.0__ has full support for __ES6__ and __TypeScript__. Therefore, __Cocos Creator 3.0__ only supports __ES6__ and __TypeScript__ `classes`. In addition, we also support __TypeScript__ syntax hints.
+
+__Cocos Creator__ supports only __ES5__ `classes`.
+
+__Please keep this precaution in mind.__
diff --git a/versions/4.0/en/getting-started/dashboard/index.md b/versions/4.0/en/getting-started/dashboard/index.md
new file mode 100644
index 0000000000..124fb43eb1
--- /dev/null
+++ b/versions/4.0/en/getting-started/dashboard/index.md
@@ -0,0 +1,94 @@
+# Using Cocos Dashboard
+
+Upon launching the Cocos Dashboard and logging in with your Cocos Developer account, the Dashboard interface opens. Dashboard allows downloading the engine, creating a new project, opening an existing project, or getting help information.
+
+
+
+The left navigation menu bar includes: **Home**, **Projects**, **Installs**, **Store**, **Community**, **Learn**, **Settings**, and **Account**. See below for specific instructions.
+
+## Home
+
+The home page contains the Cocos product news, editor version news, and user's recently opened projects. Here you can quickly open projects, create new projects, install editors, get the latest editor version, etc.
+
+
+
+It mainly consists of the following three parts:
+
+- Carousels: shows the latest Cocos product news.
+- Recently Projects: Shows recently opened projects, double-click to open a project; the **New Project** button on the top right quickly opens the New Project page to create a project, and the **View More** button takes you to the project list page.
+- Editors: Shows released products of Cocos, where you can quickly install editor versions, create new projects, and get the latest released editor versions.
+
+## Projects
+
+The Projects page shows all created/imported projects, **double click** opens the project. The list is empty when you run Cocos Dashboard for the first time, and you can create/import a new project in the top right.
+
+
+
+- **1**: Search for projects directly by project name.
+- **2**: Sorts projects in forward/reverse order according to the most recent open time.
+- **3**: Select another version of the editor that has been successfully installed to open the project.
+- **4**: Operation menu, which can also be opened by right-clicking. Support **Open (project)**, **Show in Finder/Explorer**, **Remove from list**, **Select the icon of the project**, **Rename the project**, **Set the description of the project**:
+ - **Select the icon of the project**: Customize the project cover image, currently supports four formats: BMP, PNG, GIF and JPG.
+ - **Rename the project**: Renaming the project name will also rename the project folder.
+ - **Set the description of project**: Can be used to note descriptive information related to the project.
+
+### New Project
+
+Creator provides a number of project templates, including basic architectures for different types of games, as well as sample resources and scripts for learning to help developers get into creative work faster. As Cocos Creator becomes more complete, we will continue to add more project templates.
+
+Click **Templates** and **Examples** in the upper left to switch the project type. **Editor Version** is used to select the editor version for creating the project, and the drop-down box includes all successfully installed versions.
+
+
+
+Check any of the project templates and at the bottom of the page you can see **Project Name** and **Location**:
+
+- **Name**: The project name can only contain **a-z**, **A-Z**, **0-9** as well as **_** and **-**.
+- **Location**: Click the icon behind the Project Path input box to select the project's storage path, or you can manually enter it in the input box.
+
+Once everything is set up, click the **Create and Open** button to finish creating the project; the Dashboard window will be hidden and the newly created project will open in the main Cocos Creator editor window.
+
+## Installs
+
+The Installs page displays the successfully installed product editor, and you can import/install the editor version by clicking the button on the top right.
+
+
+
+> **Note**: When Cocos Dashboard is first run, this list is empty. Click the two buttons in the top right corner to import existing Creator editors locally or download and install them directly.
+
+- **Locate**: Used to add locally existing editors, supports dragging and dropping locally existing Creator editors directly from the operating system's file manager into the version list.
+- **Install Editor**: Clicking on this button opens the Install Editor page, showing all installed and uninstalled versions of the editor, which can be downloaded and installed as needed.
+
+ 
+
+## Store
+
+Cocos game development resource center, you can browse, download and install official or third-party extensions, source code, resources and so on, specific instructions can refer to the [Cocos Store](https://store.cocos.com/document/en/).
+
+
+
+## Community
+
+This tab is used to post official announcements or events of Cocos Creator, including the **News** and **Update** modules.
+
+
+
+## Learn
+
+The Learn page collects official tutorial resources from Cocos, as well as editor's choice and forum Pinned Topics.
+
+
+
+## Account
+
+Displays information about the currently logged in account, the ability to go to the account center, and logging out.
+
+
+
+Developers can also visit the official Cocos website for tutorials and other information by clicking the icon below:
+
+- [Twitter](https://twitter.com/CocosEngine)
+- [Facebook](https://www.facebook.com/CocosEngine)
+- [Forum](https://discuss.cocos2d-x.org/c/33)
+- [Discord](https://discord.com/invite/pVqab4K)
+- [YouTube](https://www.youtube.com/cocosengine)
+- [GitHub](https://github.com/cocos/cocos4/)
diff --git a/versions/4.0/en/getting-started/dashboard/index/account.png b/versions/4.0/en/getting-started/dashboard/index/account.png
new file mode 100644
index 0000000000..50f92e2c03
Binary files /dev/null and b/versions/4.0/en/getting-started/dashboard/index/account.png differ
diff --git a/versions/4.0/en/getting-started/dashboard/index/add-project.png b/versions/4.0/en/getting-started/dashboard/index/add-project.png
new file mode 100644
index 0000000000..8ab0e3edde
Binary files /dev/null and b/versions/4.0/en/getting-started/dashboard/index/add-project.png differ
diff --git a/versions/4.0/en/getting-started/dashboard/index/community.png b/versions/4.0/en/getting-started/dashboard/index/community.png
new file mode 100644
index 0000000000..ad9686643d
Binary files /dev/null and b/versions/4.0/en/getting-started/dashboard/index/community.png differ
diff --git a/versions/4.0/en/getting-started/dashboard/index/download.png b/versions/4.0/en/getting-started/dashboard/index/download.png
new file mode 100644
index 0000000000..19849483d4
Binary files /dev/null and b/versions/4.0/en/getting-started/dashboard/index/download.png differ
diff --git a/versions/4.0/en/getting-started/dashboard/index/home.png b/versions/4.0/en/getting-started/dashboard/index/home.png
new file mode 100644
index 0000000000..47f9fd587d
Binary files /dev/null and b/versions/4.0/en/getting-started/dashboard/index/home.png differ
diff --git a/versions/4.0/en/getting-started/dashboard/index/home1.png b/versions/4.0/en/getting-started/dashboard/index/home1.png
new file mode 100644
index 0000000000..26c8c3b62a
Binary files /dev/null and b/versions/4.0/en/getting-started/dashboard/index/home1.png differ
diff --git a/versions/4.0/en/getting-started/dashboard/index/installs.png b/versions/4.0/en/getting-started/dashboard/index/installs.png
new file mode 100644
index 0000000000..9fa220c6d6
Binary files /dev/null and b/versions/4.0/en/getting-started/dashboard/index/installs.png differ
diff --git a/versions/4.0/en/getting-started/dashboard/index/learn.png b/versions/4.0/en/getting-started/dashboard/index/learn.png
new file mode 100644
index 0000000000..10c1baa49b
Binary files /dev/null and b/versions/4.0/en/getting-started/dashboard/index/learn.png differ
diff --git a/versions/4.0/en/getting-started/dashboard/index/project.png b/versions/4.0/en/getting-started/dashboard/index/project.png
new file mode 100644
index 0000000000..2beeae0f8a
Binary files /dev/null and b/versions/4.0/en/getting-started/dashboard/index/project.png differ
diff --git a/versions/4.0/en/getting-started/dashboard/index/store.png b/versions/4.0/en/getting-started/dashboard/index/store.png
new file mode 100644
index 0000000000..2fb9e56eb1
Binary files /dev/null and b/versions/4.0/en/getting-started/dashboard/index/store.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/40-on-y.png b/versions/4.0/en/getting-started/first-game-2d/images/40-on-y.png
new file mode 100644
index 0000000000..1527286f03
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/40-on-y.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/add-animation.png b/versions/4.0/en/getting-started/first-game-2d/images/add-animation.png
new file mode 100644
index 0000000000..b9a85fb04e
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/add-animation.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/add-keyframes.gif b/versions/4.0/en/getting-started/first-game-2d/images/add-keyframes.gif
new file mode 100644
index 0000000000..959649c47d
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/add-keyframes.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/add-player-controller.gif b/versions/4.0/en/getting-started/first-game-2d/images/add-player-controller.gif
new file mode 100644
index 0000000000..44566e934b
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/add-player-controller.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/add-position-track.png b/versions/4.0/en/getting-started/first-game-2d/images/add-position-track.png
new file mode 100644
index 0000000000..9d3c20c6dc
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/add-position-track.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/after-layer-setting.gif b/versions/4.0/en/getting-started/first-game-2d/images/after-layer-setting.gif
new file mode 100644
index 0000000000..04814334f5
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/after-layer-setting.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/assign-body-anim.gif b/versions/4.0/en/getting-started/first-game-2d/images/assign-body-anim.gif
new file mode 100644
index 0000000000..04e0bc4040
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/assign-body-anim.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/assign-box-prefab.gif b/versions/4.0/en/getting-started/first-game-2d/images/assign-box-prefab.gif
new file mode 100644
index 0000000000..89467804fb
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/assign-box-prefab.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/assign-clip.gif b/versions/4.0/en/getting-started/first-game-2d/images/assign-clip.gif
new file mode 100644
index 0000000000..ec4eaf5721
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/assign-clip.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/bind-manager.png b/versions/4.0/en/getting-started/first-game-2d/images/bind-manager.png
new file mode 100644
index 0000000000..c1346f519e
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/bind-manager.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/box-layer.png b/versions/4.0/en/getting-started/first-game-2d/images/box-layer.png
new file mode 100644
index 0000000000..4e33b59b69
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/box-layer.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/cavans-camera.png b/versions/4.0/en/getting-started/first-game-2d/images/cavans-camera.png
new file mode 100644
index 0000000000..38c451d8b8
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/cavans-camera.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/click-event.gif b/versions/4.0/en/getting-started/first-game-2d/images/click-event.gif
new file mode 100644
index 0000000000..dfa7beb7d9
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/click-event.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/click-event.gif.gif b/versions/4.0/en/getting-started/first-game-2d/images/click-event.gif.gif
new file mode 100644
index 0000000000..f2dbd6faae
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/click-event.gif.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/create-2d-empty.png b/versions/4.0/en/getting-started/first-game-2d/images/create-2d-empty.png
new file mode 100644
index 0000000000..5fd75021d1
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/create-2d-empty.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/create-bg.gif b/versions/4.0/en/getting-started/first-game-2d/images/create-bg.gif
new file mode 100644
index 0000000000..224aeeda9e
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/create-bg.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/create-body.gif b/versions/4.0/en/getting-started/first-game-2d/images/create-body.gif
new file mode 100644
index 0000000000..ef9fcbd914
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/create-body.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/create-box-prefab.gif b/versions/4.0/en/getting-started/first-game-2d/images/create-box-prefab.gif
new file mode 100644
index 0000000000..b9219f67c4
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/create-box-prefab.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/create-box.png b/versions/4.0/en/getting-started/first-game-2d/images/create-box.png
new file mode 100644
index 0000000000..e5c77f69a1
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/create-box.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/create-clip-onestep.gif b/versions/4.0/en/getting-started/first-game-2d/images/create-clip-onestep.gif
new file mode 100644
index 0000000000..3dab75afff
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/create-clip-onestep.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/create-fist-script.png b/versions/4.0/en/getting-started/first-game-2d/images/create-fist-script.png
new file mode 100644
index 0000000000..017cad1339
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/create-fist-script.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/create-game-manager.png b/versions/4.0/en/getting-started/first-game-2d/images/create-game-manager.png
new file mode 100644
index 0000000000..cf4bc1bab1
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/create-game-manager.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/create-player.gif b/versions/4.0/en/getting-started/first-game-2d/images/create-player.gif
new file mode 100644
index 0000000000..1e093cf010
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/create-player.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/create-scripts.gif b/versions/4.0/en/getting-started/first-game-2d/images/create-scripts.gif
new file mode 100644
index 0000000000..bc4388c7c0
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/create-scripts.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/create-sprite.gif b/versions/4.0/en/getting-started/first-game-2d/images/create-sprite.gif
new file mode 100644
index 0000000000..d2a1169d39
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/create-sprite.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/create-sprite.png b/versions/4.0/en/getting-started/first-game-2d/images/create-sprite.png
new file mode 100644
index 0000000000..556d5e9b98
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/create-sprite.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/create-start-menu.png b/versions/4.0/en/getting-started/first-game-2d/images/create-start-menu.png
new file mode 100644
index 0000000000..223d097f78
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/create-start-menu.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/create-tip.png b/versions/4.0/en/getting-started/first-game-2d/images/create-tip.png
new file mode 100644
index 0000000000..6fe17d3f8d
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/create-tip.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/create-title.png b/versions/4.0/en/getting-started/first-game-2d/images/create-title.png
new file mode 100644
index 0000000000..f92e851d1e
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/create-title.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/create-twostep.gif b/versions/4.0/en/getting-started/first-game-2d/images/create-twostep.gif
new file mode 100644
index 0000000000..8ef64b1d2b
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/create-twostep.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/create-ui-canvas.png b/versions/4.0/en/getting-started/first-game-2d/images/create-ui-canvas.png
new file mode 100644
index 0000000000..253fdb4094
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/create-ui-canvas.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/download-editor.png b/versions/4.0/en/getting-started/first-game-2d/images/download-editor.png
new file mode 100644
index 0000000000..da4b9b54ac
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/download-editor.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/enter-anim-editing-mode.png b/versions/4.0/en/getting-started/first-game-2d/images/enter-anim-editing-mode.png
new file mode 100644
index 0000000000..d883e38f51
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/enter-anim-editing-mode.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/gen-road.png b/versions/4.0/en/getting-started/first-game-2d/images/gen-road.png
new file mode 100644
index 0000000000..ffb0698839
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/gen-road.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/jumptime-with-duration.gif b/versions/4.0/en/getting-started/first-game-2d/images/jumptime-with-duration.gif
new file mode 100644
index 0000000000..daac617871
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/jumptime-with-duration.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/layer-default.png b/versions/4.0/en/getting-started/first-game-2d/images/layer-default.png
new file mode 100644
index 0000000000..3309f5e20e
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/layer-default.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/layer-error.png b/versions/4.0/en/getting-started/first-game-2d/images/layer-error.png
new file mode 100644
index 0000000000..030f6d4113
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/layer-error.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/preview-anim.gif b/versions/4.0/en/getting-started/first-game-2d/images/preview-anim.gif
new file mode 100644
index 0000000000..638dfae475
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/preview-anim.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/preview-menu.png b/versions/4.0/en/getting-started/first-game-2d/images/preview-menu.png
new file mode 100644
index 0000000000..720237c7ea
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/preview-menu.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/preview-oneStep.gif b/versions/4.0/en/getting-started/first-game-2d/images/preview-oneStep.gif
new file mode 100644
index 0000000000..7b0d6242f6
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/preview-oneStep.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/projects.png b/versions/4.0/en/getting-started/first-game-2d/images/projects.png
new file mode 100644
index 0000000000..67d24d345e
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/projects.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/save-prefab.png b/versions/4.0/en/getting-started/first-game-2d/images/save-prefab.png
new file mode 100644
index 0000000000..96a1aa8e7b
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/save-prefab.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/save-scene.png b/versions/4.0/en/getting-started/first-game-2d/images/save-scene.png
new file mode 100644
index 0000000000..13cc9541a1
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/save-scene.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/saved-scene.png b/versions/4.0/en/getting-started/first-game-2d/images/saved-scene.png
new file mode 100644
index 0000000000..046f908f42
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/saved-scene.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/scene-dir.png b/versions/4.0/en/getting-started/first-game-2d/images/scene-dir.png
new file mode 100644
index 0000000000..2adf590e57
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/scene-dir.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/scene.png b/versions/4.0/en/getting-started/first-game-2d/images/scene.png
new file mode 100644
index 0000000000..25ae7f80b0
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/scene.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/scroll.gif b/versions/4.0/en/getting-started/first-game-2d/images/scroll.gif
new file mode 100644
index 0000000000..4fae1fe790
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/scroll.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/setup-scroll.gif b/versions/4.0/en/getting-started/first-game-2d/images/setup-scroll.gif
new file mode 100644
index 0000000000..37db457cca
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/setup-scroll.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/start-game-without-result.gif b/versions/4.0/en/getting-started/first-game-2d/images/start-game-without-result.gif
new file mode 100644
index 0000000000..4d504eb771
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/start-game-without-result.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/step.png b/versions/4.0/en/getting-started/first-game-2d/images/step.png
new file mode 100644
index 0000000000..e027d29b62
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/step.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/to-red.png b/versions/4.0/en/getting-started/first-game-2d/images/to-red.png
new file mode 100644
index 0000000000..fd01b478b1
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/to-red.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/ui-canvas.png b/versions/4.0/en/getting-started/first-game-2d/images/ui-canvas.png
new file mode 100644
index 0000000000..c58ab38791
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/ui-canvas.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/uicanvas-camera.png b/versions/4.0/en/getting-started/first-game-2d/images/uicanvas-camera.png
new file mode 100644
index 0000000000..2fdb71eff7
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/uicanvas-camera.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/with-scale.gif b/versions/4.0/en/getting-started/first-game-2d/images/with-scale.gif
new file mode 100644
index 0000000000..ed7408564d
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/with-scale.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/images/without-scale.gif b/versions/4.0/en/getting-started/first-game-2d/images/without-scale.gif
new file mode 100644
index 0000000000..e0935b59f1
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/images/without-scale.gif differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/index.md b/versions/4.0/en/getting-started/first-game-2d/index.md
new file mode 100644
index 0000000000..b5be8f9301
--- /dev/null
+++ b/versions/4.0/en/getting-started/first-game-2d/index.md
@@ -0,0 +1,1679 @@
+# Quick Start: Making Your First 2D Game
+
+Platform jumping games are a very common and popular game genre, ranging from simple games on the original NES console to large-scale games made with complex 3D technology on modern gaming platforms. You can always find platform jumping games.
+
+In this section, we will demonstrate how to use the 2D features provided by Cocos Creator to create a simple platform jumping game.
+
+## Environment Setup
+
+### Download Cocos Dashboard
+
+Visit the [Cocos Creator official website](https://www.cocos.com/creator-download) to download the latest version of Cocos Dashboard, which allows for unified management of the Cocos Creator versions and your projects. After installing, open the Cocos Dashboard.
+
+
+
+### Install Cocos Creator
+
+
+
+In the **Editor** tab, click on the Install button for the desired version to install the editor, Cocos Creator.
+
+> We usually recommend using the latest version of Cocos Creator to get started. it will obtain more features and support.
+
+### Create Project
+
+In the **Project** tab, find the **Create** button, select **Empty(2D)**.
+
+
+
+Next, just enter your project name in the highlighted field shown in the image above.
+
+For example, you could input: cocos-tutorial-mind-your-step-2d.
+
+Let's make a game that is similar to the one in [Quick Start: Making Your First 3D Game](../first-game/index.md).
+
+If you haven't read [Quick Start: Making Your First 3D Game](../first-game/index.md) yet, that's okay. In this section, we'll assume you haven't used Cocos Creator before, and we'll start from scratch!
+
+Without further ado, let's get started.
+
+## Create the Character
+
+In a 2D game, all visible objects are made of images, including the character.
+
+To keep things simple, we'll be using the images that come bundled with Cocos Creator to create our game. These images can be found in `internal/default_ui/`.
+
+In Cocos Creator, we use a `Sprite` node ( a node with a Sprite component ) to show an image.
+
+To create a new node of type Sprite, right-click in the Hierarchy panel, select "Create", and then choose "2D -> Sprite" from the pop-up menu.
+
+Right-click in the Hierarchy and select "Create" from the pop-up menu, and we can see different types of nodes. Here, we select "2D -> Sprite" to create a new `Sprite` node.
+
+
+
+Next, we find the `internal/default_ui/default_btn_normal` and assign it to the `Sprite Frame` property of the `Sprite` node we just created.
+
+
+
+Next, create an `Empty` node and name it "Player":
+
+
+
+If you didn't name the node when you created it, there are two ways to change its name:
+
+- In the **Inspector** panel, find the name and rename it
+- In the **Hierarchy**, select the node then press `F2`
+
+We can adjust the parent-child relationship of nodes by dragging and dropping them in the Hierarchy. Here, drag the `Sprite` node onto the `Player` node to make it a child, then rename the `Sprite` node to "Body".
+
+
+
+> **Note**:
+> - The hierarchy relationship determines the rendering order. if may cause the node to not be visible when the order is wrong.
+> - 2D/UI elements must be under a `Canvas` node in order to be visible.
+> - The layer of 2D/UI elements must be set to `UI_2D`
+
+Next, Let's adjust the position's Y of the `Body` node to 40:
+
+
+
+Finally, let's adjust the color of the `Body`.
+
+In the Inspector panel, find the `Color` property and expand it, then set the color to red.
+
+
+
+## The First Script
+
+Scripts, also known as code, are used to implement game logic, such as character movement, jumping, and other gameplay mechanics.
+
+Cocos Creator uses TypeScript as its scripting programming language. It has simple and easy-to-learn syntax, a large user base, and widespread applications. You can encounter it in web development, app development, game development, etc.
+
+Creating a script component in Cocos Creator is very simple. All you need to do is right-click in the Assets Manager window, and select "Create -> TypeScript -> NewComponent" option.
+
+
+
+For ease of management, it is often recommended to create a folder named `Script` to put all of your scripts in.
+
+Next, right-click on the `Scripts` folder, and create a new script component named `PlayerController` to control the player.
+
+
+
+The engine will generate the following code for the script component that we just created.
+
+```ts
+import { _decorator, Component, Node } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass('PlayerController')
+export class PlayerController extends Component {
+ start() {
+
+ }
+
+ update(deltaTime: number) {
+
+ }
+}
+```
+
+**Note** Cocos Creator uses a Node + Component architecture, meaning that a component must be attached to a node in order to function. Scripts in Cocos Creator are also designed as components.
+
+So, let's drag the `PlayerController` script onto the Inspector of Player node.
+
+
+
+You should see that a `PlayerController` component has been added to the Player node.
+
+> **Note**: You can also click on the **Add Component** button to add different types of components.
+
+## Map
+
+A map in a game is an area where your character can move around and interact within a game.
+
+As mentioned before, all visible objects in 2D games are made up of images. The map is no exception.
+
+Just like the steps we used to create the `Body` node, we will now create an object called `Box` which will be used to construct the map.
+
+- Right-click in the Hierarchy
+- Create a `Sprite` node by selecting "Create -> 2D Objects -> Sprite" through the pop-up menu.
+- Name it as "Box"
+- Select the "Box" node, set its **Sprite Frame** property by using `internal/default_ui/default_btn_normal`
+
+
+
+### Prefab
+
+A prefab is a special type of resource that can save the information of a node as a file. so that it can be reused in other situations.
+
+In Cocos Creator, creating a prefab is quite simple. We just need to drag the node into the Assets Manager window, a *.prefab file will be automatically generated.
+
+Now, let's create a folder named Prefab in the Assets Manager window, which will be used to organize all prefabs together.
+
+Then, find the Box node and drag it to the Prefab folder, a prefab file named "Box" will be generated.
+
+The box node in the hierarchy can be deleted, because it won't be used when the game is running. Instead, we will create nodes in the script using Box.prefab to build the game map during gameplay.
+
+
+
+> **Tips:** Generally, We will use different folders to manage different types of resources. It's a good habit to keep your project well-organized.
+
+### Scene
+
+In the game engine, a scene is used to manage all game objects. It contains characters, maps, gameplay, UI. you name it in a game.
+
+A game can be divided into different scenes based on its functionalities. Such as the loading-scene, start-menu-scene, gameplay-scene, etc.
+
+A game requires at least one scene to start.
+
+So, in Cocos Creator, an unsaved empty scene will be opened by default, just like the one we are currently editing.
+
+To ensure that we can find this scene the next time we open Cocos Creator, we need to save it.
+
+First, let's create a folder named "Scene" to save our scenes in the Assets Manager window.
+
+
+
+Then, press the Ctrl + S shortcut key.
+
+Since it is the first time we are saving this scene, the scene-saving window will pop up.
+
+We choose the "Scene" folder that we just created as the location, and name it "game.scene". Click save.
+
+
+
+Now the scene is saved. We can see a scene resource file named "game" under the assets/Scene folder in the Assets Manager window.
+
+
+
+The scene now can be observed as below, the red block represents the player, and the white represents the ground.
+
+
+
+> Don't forget to press Ctrl + S shortcut key to save your scene when there are changes to the scene. Avoid losing work progress due to unexpected events such as power outages.
+
+## Make the character move
+
+We have created the "Player" node before, but it can not move.
+
+Next, we will add code and animations to control its movement and make it move.
+
+### PlayerController
+
+The player should have the following behaviors:
+
+- it starts jumping when the mouse is clicked.
+- When it has been jumping for a certain amount of time, the jumping ends.
+
+To achieve the above goals, we need to add some methods in the `PlayerController` component.
+
+- Listen for mouse-click events
+
+ ```ts
+ onMouseUp(event: EventMouse) {}
+ ```
+
+- Jump according to the given steps
+
+ ```ts
+ jumpByStep(step: number) {}
+ ```
+
+- Calculate the position of the player
+
+ ```ts
+ update (deltaTime: number) {}
+ ```
+
+Next, let's complete these methods.
+
+#### Listen for mouse-click events
+
+Cocos Creator supports various common control devices, such as the mouse, keyboard, touchpad, and gamepad. You can easily access the relevant content through `Input` class.
+
+For ease of use, Cocos Creator provides a global instance object `input` for the `Input` class.
+
+> **Note** It's easy to confuse, `input` is the instance, and `Input` is the class.
+
+To make the `onMouseUp` method be called by the engine when the mouse is clicked, we need to add the following code to the `start` method.
+
+```ts
+start () {
+ input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+}
+```
+
+The `onMouseUp` method has an `event` parameter of type `EventMouse`.
+
+Through the `event.getButton()` method, we can get which button of the mouse is clicked.
+
+Add the following code to the `onMouseUp` method:
+
+```ts
+onMouseUp(event: EventMouse) {
+ if (event.getButton() === EventMouse.BUTTON_LEFT) {
+ this.jumpByStep(1);
+ } else if (event.getButton() === EventMouse.BUTTON_RIGHT) {
+ this.jumpByStep(2);
+ }
+}
+```
+
+In the `EventMouse` class, there are three values have been defined:
+- public static BUTTON_LEFT = 0;
+- public static BUTTON_MIDDLE = 1;
+- public static BUTTON_RIGHT = 2;
+
+The code has implemented that:
+- When the left mouse button is clicked, the player jumps forward one step.
+- When the right mouse button is clicked, the player jumps forward two steps.
+
+#### Move the player
+
+In our game, the player moves horizontally to the right, so we need to use a simple physics formula as below:
+
+```txt
+P_1 = P_0 + v*t
+```
+
+Where `P_1` is the final position, `P_0` is the original position, v is the speed of the object, and t is the unit time.
+
+> Final Position = Original Position + Speed * deltaTime
+
+The `update` function in the PlayerController component will be automatically called by the game engine. And also pass in a `deltaTime` parameter.
+
+```ts
+update (deltaTime: number) {}
+```
+
+The times that `update` will be called per second is determined by the frame rate (also known as FPS) when the game running.
+
+For example, if a game is running at 30 FPS, the `deltaTime` will be 1.0 / 30.0 = 0.03333333... second.
+
+In game development, we use `deltaTime` as the `t` in the physics formula to ensure consistent movement results at any frame rate.
+
+Here, let's add some properties needed for calculating player movement `PlayerController` component.
+
+```ts
+//used to judge if the player is jumping.
+private _startJump: boolean = false;
+
+//the number of steps will the player jump, should be 1 or 2. determined by which mouse button is clicked.
+private _jumpStep: number = 0;
+
+//the time it takes for the player to jump once.
+private _jumpTime: number = 0.1;
+
+//the time that the player's current jump action has taken, should be set to 0 each time the player jumps, when it reaches the value of `_jumpTime`, the jump action is completed.
+private _curJumpTime: number = 0;
+
+// The player's current vertical speed, used to calculate the Y value of position when jumping.
+private _curJumpSpeed: number = 0;
+
+// The current position of the player, used as the original position in the physics formula.
+private _curPos: Vec3 = new Vec3();
+
+//movement calculated by deltaTime.
+private _deltaPos: Vec3 = new Vec3(0, 0, 0);
+
+// store the final position of the player, when the player's jumping action ends, it will be used directly to avoid cumulative errors.
+private _targetPos: Vec3 = new Vec3();
+```
+
+Now, what we need to do next is very simple:
+
+- Calculating the data needed for player movement in the `jumpByStep` method.
+- Processing player movement in the `update` method.
+
+In the `jumpByStep` method, we add the following code:
+
+```ts
+jumpByStep(step: number) {
+ if (this._startJump) {
+ //if the player is jumping, do nothing.
+ return;
+ }
+ //mark player is jumping.
+ this._startJump = true;
+ //record the number of steps the jumping action will take.
+ this._jumpStep = step;
+ //set to 0 when a new jumping action starts
+ this._curJumpTime = 0;
+ //because the player will finish the jumping action in the fixed duration(_jumpTime), so it needs to calculate jump speed here.
+ this._curJumpSpeed = this._jumpStep / this._jumpTime;
+ //copy the current position of the node which will be used when calculating the movement.
+ this.node.getPosition(this._curPos);
+ //calculate the final position of the node which will be used when the jumping action ends.
+ Vec3.add(this._targetPos, this._curPos, new Vec3(this._jumpStep, 0, 0));
+}
+```
+
+`Vec3` is the vector class in Cocos Creator, the name is short for `Vector3`, which has 3 components, x,y,z. all vector operations are placed in `Vec3` class. Such as `Vec3.add`, `Vec3.subtract` etc.
+
+In Cocos Creator, 2D games also use `Vec3` as the property type for position, scale, and rotation. Just ignore the irrelevant components, e.g. the z component in position.
+
+Next, let's calculate the movement of the player while jumping.
+
+In this game, the player only moves when jumping, and keeps still when not jumping.
+
+Let's add the following code to the `update` method in `PlayerController`.
+
+```ts
+update (deltaTime: number) {
+ //we only do something when the player is jumping.
+ if (this._startJump) {
+ //accumulate the jumping time.
+ this._curJumpTime += deltaTime;
+ //check if it reaches the jump time.
+ if (this._curJumpTime > this._jumpTime) {
+ // When the jump ends, set the player's position to the target position.
+ this.node.setPosition(this._targetPos);
+ //clear jump state
+ this._startJump = false;
+ } else {
+ //if it still needs to move.
+ // copy the position of the node.
+ this.node.getPosition(this._curPos);
+ //calculate the offset x by using deltaTime and jumping speed.
+ this._deltaPos.x = this._curJumpSpeed * deltaTime;
+ //calculate the final pos by adding deltaPos to the original position
+ Vec3.add(this._curPos, this._curPos, this._deltaPos);
+ //update the position of the player.
+ this.node.setPosition(this._curPos);
+ }
+ }
+}
+```
+
+Now, click the **Preview** button at the top of Cocos Creator.
+
+
+
+The **Player** will move by clicking the mouse buttons.
+
+
+
+As you can see, the player only moves a little each time you click the mouse button.
+
+This is because we use `pixels/s` as the unit of speed for the Player.
+
+```ts
+this._curJumpSpeed = this._jumpStep / this._jumpTime;
+```
+
+The above code indicates that the player will only move one pixel per step.
+
+In fact, we want the Player to move a certain distance per step.
+
+To fix this, we need to add a constant to express the step size.
+
+Below, the `BLOCK_SIZE` is used for this purpose.
+
+```ts
+import { _decorator, Component, Node } from 'cc';
+const { ccclass, property } = _decorator;
+
+//
+export const BLOCK_SIZE = 40;
+
+@ccclass('PlayerController')
+export class PlayerController extends Component {
+ //...
+}
+```
+
+As you can see, in TypeScript:
+- A constant can be defined outside of the class and exported separately.
+- Values declared as const cannot be modified and are often used for fixed configurations.
+
+Next, find the code line in `jumpByStep` method:
+
+```ts
+this._curJumpSpeed = this._jumpStep / this._jumpTime;
+```
+
+Change it to:
+
+```ts
+this._curJumpSpeed = this._jumpStep * BLOCK_SIZE/ this._jumpTime;
+```
+
+Here is the updated `jumpByStep`:
+
+```ts
+jumpByStep(step: number) {
+ if (this._startJump) {
+ return;
+ }
+ this._startJump = true;
+ this._jumpStep = step;
+ this._curJumpTime = 0;
+
+ this._curJumpSpeed = this._jumpStep * BLOCK_SIZE/ this._jumpTime;
+
+ this.node.getPosition(this._curPos);
+ Vec3.add(this._targetPos, this._curPos, new Vec3(this._jumpStep* BLOCK_SIZE, 0, 0));
+}
+```
+
+Restart the game, and you can see that the distance of the player's movement is as expected now.
+
+
+
+At this moment, the code of `PlayerController` is as follows.
+
+```ts
+import { _decorator, Component, Vec3, EventMouse, input, Input } from "cc";
+const { ccclass, property } = _decorator;
+
+export const BLOCK_SIZE = 40;
+
+@ccclass("PlayerController")
+export class PlayerController extends Component {
+
+ private _startJump: boolean = false;
+ private _jumpStep: number = 0;
+ private _curJumpTime: number = 0;
+ private _jumpTime: number = 0.3;
+ private _curJumpSpeed: number = 0;
+ private _curPos: Vec3 = new Vec3();
+ private _deltaPos: Vec3 = new Vec3(0, 0, 0);
+ private _targetPos: Vec3 = new Vec3();
+
+ start () {
+ input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ }
+
+ reset() {
+ }
+
+ onMouseUp(event: EventMouse) {
+ if (event.getButton() === 0) {
+ this.jumpByStep(1);
+ } else if (event.getButton() === 2) {
+ this.jumpByStep(2);
+ }
+
+ }
+
+ jumpByStep(step: number) {
+ if (this._startJump) {
+ return;
+ }
+ this._startJump = true;
+ this._jumpStep = step;
+ this._curJumpTime = 0;
+
+ this._curJumpSpeed = this._jumpStep * BLOCK_SIZE/ this._jumpTime;
+ this.node.getPosition(this._curPos);
+ Vec3.add(this._targetPos, this._curPos, new Vec3(this._jumpStep* BLOCK_SIZE, 0, 0));
+ }
+
+ update (deltaTime: number) {
+ if (this._startJump) {
+ this._curJumpTime += deltaTime;
+ if (this._curJumpTime > this._jumpTime) {
+ // end
+ this.node.setPosition(this._targetPos);
+ this._startJump = false;
+ } else {
+ // tween
+ this.node.getPosition(this._curPos);
+ this._deltaPos.x = this._curJumpSpeed * deltaTime;
+ Vec3.add(this._curPos, this._curPos, this._deltaPos);
+ this.node.setPosition(this._curPos);
+ }
+ }
+ }
+}
+```
+
+### Player Animation
+
+For 2D game development, Cocos Creator supports various types of animation, including keyframe animation, Spine, DragonBones, and Live2D.
+
+In this tutorial, the jump animation of the Player is very simple and it is enough to use keyframe animation.
+
+Using Cocos Creator's built-in animation editor, it's easy to make it.
+
+Let's take a step-by-step approach to creating it.
+
+First, let's add the Animation component to the Body node of the Player.
+
+
+
+In the Assets Manager window, create a new folder named "Animation", Inside that folder, create a new AnimationClip named "oneStep".
+
+
+
+In the Hierarchy, select the "Body" node and drag "oneStep" from the Animation folder onto the "Clips" property in the Inspector panel.
+
+
+
+In the editor console area, switch to the "Animation" tab and click the "Enter animation editing mode" button:
+
+
+
+In the animation editor, we add a track for the node's position property.
+
+
+
+After adding the track, we can set the indicator of the current frame to a certain frame and then change the position of the node, the current frame will be set to be a keyframe automatically.
+
+> Both modify the value on the Inspector panel and dragging the node in the scene can change the position of a node.
+
+
+
+Finally, we have the following keyframes:
+
+- 0 frame:set position to x = 0, y = 40
+- 10 frame: set position to x = 0, y = 120
+- 20 frame: set position to x = 0, y = 40
+
+> Don't forget to click the **Save** button to save it.
+
+You can click the **Play** button to preview the animation clip.
+
+
+
+Follow the steps of making `oneStep` animation, and make another one: `twoStep`.
+
+
+
+After completing the animation creation, click the **Close** button to exit the Animation editing mode.
+
+### Play animations in code
+
+Next, let's add some code lines into PlayerController to play the animation we've just made.
+
+Playing an animation using TypeScript in Cocos Creator is quite simple:
+
+```ts
+animation.play(animName);
+```
+
+- animation is the Animation component on Body node.
+- play is the method of Animation component to play animation
+- animName is the name of an animation file that you want to play
+
+> In Cocos Creator, we must ensure the animation which will be played is included in the clips of the node's Animation component,
+
+Add the following code at the beginning of the PlayerController class:
+
+```ts
+@ccclass("PlayerController")
+export class PlayerController extends Component {
+ @property(Animation)
+ BodyAnim:Animation = null;
+ //...
+}
+```
+
+> **Note**:The TypeScript and Cocos Creator both have an Animation class, please make sure the `Animation` is included in the code line `import { ..., Animation,... } from "cc" `. Otherwise, the code will use the `Animation` from TypeScript, and unpredictable errors may occur.
+
+Here we added a property named `BodyAnim` and added `@property` above it. This syntax is called: [Decorator](../../scripting/decorator.md). The `@property` decorator allows the editor to be aware of the type of `BodyAnim` and display the exported properties of the Animation component on the Inspector panel.
+
+To make sure there is a code line in your PlayerController file as below, or the code will fail to compile.
+
+```ts
+const { ccclass, property } = _decorator;
+```
+
+Here `_decorator` is a class containing all of the decorators that can be used in Cocos Creator, it should be imported from namespace cc before using it.
+
+The related code lines are as follows:
+
+```ts
+import { _decorator, Component, Vec3, EventMouse, input, Input, Animation } from "cc";
+const { ccclass, property } = _decorator;
+
+```
+
+In `jumpByStep` method, we add to the following code lines:
+
+```ts
+if (this.BodyAnim) {
+ if (step === 1) {
+ this.BodyAnim.play('oneStep');
+ } else if (step === 2) {
+ this.BodyAnim.play('twoStep');
+ }
+}
+```
+
+Now, the `jumpByStep` method is like this:
+
+```ts
+jumpByStep(step: number) {
+ if (this._startJump) {
+ return;
+ }
+ this._startJump = true;
+ this._jumpStep = step;
+ this._curJumpTime = 0;
+ this._curJumpSpeed = this._jumpStep * BLOCK_SIZE/ this._jumpTime;
+ this.node.getPosition(this._curPos);
+ Vec3.add(this._targetPos, this._curPos, new Vec3(this._jumpStep* BLOCK_SIZE, 0, 0));
+
+ //the code can explain itself
+ if (this.BodyAnim) {
+ if (step === 1) {
+ this.BodyAnim.play('oneStep');
+ } else if (step === 2) {
+ this.BodyAnim.play('twoStep');
+ }
+ }
+}
+```
+
+Back to the Cocos Creator, select **Player** node, and then drag the **Body** node on the `BodyAnim` property.
+
+
+
+The engine will automatically get the Animation component on the Body node and assign it to `BodyAnim`. As a result, the `PlayerController`'s `BodyAnim` property references the `Animation` component of **Body** node.
+
+Hit **Play** button at the top of Cocos Creator to preview, you can see the **Player** jumps while clicking the mouse buttons.
+
+
+
+Because of using the unified.
+
+Here we use a unified jumpTime value, `jumpTime = 0.1`, But since the duration of the two animations is not the same, you can find it a little weird when animations are played.
+
+To solve this, it's better to use the real duration of the animations as the value of `jumpTime`.
+
+```ts
+// Get jump time from animation duration.
+const clipName = step == 1? 'oneStep' : 'twoStep';
+const state = this.BodyAnim.getState(clipName);
+this._jumpTime = state.duration;
+```
+
+
+
+## GameManager
+
+In game development, we can manually place nodes using Box.prefab to build the map, but the map will be fixed. To make the map change whenever the game starts and provide some surprises for the players, we can randomly build the map in code.
+
+Now, let's create a new TypeScript component called `GameManger` in the Assets Manager window to achieve this.
+
+> **Note**:If you forget to rename the script or input the wrong name you don't want to use when creating a script component, The best way to fix it is to delete it and create a new one.
+> **Note**:If you modify the name of a script, the content in the script file will not change accordingly.
+
+After creating the `GameManger` script component, let's create a new node named **GameManager**, then attach `GameManager` to it.
+
+> **Note** Generally, we can attach the `GameManager` script component to any node in the scene, but for keeping the project structure well-organized, we usually create a node with the same name and attach the `GameManager` to it. This rule applies to all XXXManager script components.
+
+
+
+To build the map, we will use the `Box.prefab` to create the nodes.
+
+So, the first thing we need to do is to add a property to the `GameManager` class for referencing the `Box.prefab`.
+
+Now, the content of the `GameManager` class is as follows:
+
+```ts
+import { _decorator, Component, Prefab } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass('GameManager')
+export class GameManager extends Component {
+
+ @property({type: Prefab})
+ public boxPrefab: Prefab|null = null;
+
+ start(){}
+
+ update(dt: number): void {
+
+ }
+}
+```
+
+Go back to the Cocos Creator, select the **GameManager** node, and drag `Box` prefab onto the `boxPrefab` property of **GameManager** node.
+
+
+
+The map in this game is made up of two types of blocks. the two types of blocks alternate to form the map.
+
+- None: an empty block, if the Player steps on a block of this type, the game is over.
+- Stone: The Player can stand on.
+
+To make the code more understandable, we often use `enum` to define the types of objects.
+
+We define an enum named `BlockType` which has two elements as below.
+
+```ts
+enum BlockType{
+ BT_NONE,
+ BT_STONE,
+};
+```
+
+ > In TypeScript, if the first element of an enum hasn't been given a value, it will take 0 as default. Here, `BT_NONE = 0`, `BT_STONE = 1`.
+
+In the following code, you can see how we use it.
+
+We put it above the definition of GameManager class, and without giving it an `export`. As a result, it only can be used in this single file.
+
+Next, it is needed to determine where to place a new block. We add a property named `roadLength` to record the length of the road made up of the blocks.
+
+To manage all the types of blocks we have created, we add the private property `_road` of type Array to store the generated block types.
+
+Now, the code of the `GameManager` is as follows:
+
+```ts
+import { _decorator, CCInteger, Component, Prefab } from 'cc';
+const { ccclass, property } = _decorator;
+
+enum BlockType{
+ BT_NONE,
+ BT_STONE,
+};
+
+@ccclass('GameManager')
+export class GameManager extends Component {
+
+ @property({type: Prefab})
+ public boxPrefab: Prefab|null = null;
+ @property({type: CCInteger})
+ public roadLength: number = 50;
+ private _road: BlockType[] = [];
+
+ start() {
+
+ }
+}
+```
+
+The flow of constructing the map is as follows:
+
+- Clear all data when the game starts
+- The type of the first block is always `BlockType.BT_STONE` to prevent the Player from falling off.
+- The type of a block after a block with the type of `BlockType.BT_NONE` should always be `BlockType.BT_STONE`.
+
+Next, let's add the following method to `GameManger`.
+
+- Method to generate the map:
+
+ ```ts
+ generateRoad() {
+
+ this.node.removeAllChildren();
+
+ this._road = [];
+ // startPos
+ this._road.push(BlockType.BT_STONE);
+
+ for (let i = 1; i < this.roadLength; i++) {
+ if (this._road[i - 1] === BlockType.BT_NONE) {
+ this._road.push(BlockType.BT_STONE);
+ } else {
+ this._road.push(Math.floor(Math.random() * 2));
+ }
+ }
+
+ for (let j = 0; j < this._road.length; j++) {
+ let block: Node | null = this.spawnBlockByType(this._road[j]);
+ if (block) {
+ this.node.addChild(block);
+ block.setPosition(j * BLOCK_SIZE, 0, 0);
+ }
+ }
+ }
+ ```
+
+ >`Math.floor`: rounds down and returns the largest integer less than or equal to a given number. refer to [Math.floor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor) for more detail.
+ >`Math.random`:returns a floating-point in a range of [0.0,1.0), refer to [Math.random](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random) for more detail.
+
+ Obviously, the code `Math.floor(Math.random() * 2)` will only produce two integer numbers, 0 or 1, which are exactly correspond to the value of `BT_NONE` and `BT_STONE` declared in the `BlockType` enum.
+
+- Create a new block by the given type:
+
+ ```ts
+ spawnBlockByType(type: BlockType) {
+ if (!this.boxPrefab) {
+ return null;
+ }
+
+ let block: Node|null = null;
+ switch(type) {
+ case BlockType.BT_STONE:
+ block = instantiate(this.boxPrefab);
+ break;
+ }
+
+ return block;
+ }
+ ```
+
+ If the given type is `BT_STONE`, we create a new block from `boxPrefab` using `instantiate` method.
+
+ If the given type is `BT_NONE`, we just do nothing.
+
+ > `instantiate`: is a built-in method provided by Cocos Creator, it is used for making a copy of an existing node and creating a new instance for a prefab.
+
+Let's call `generateRoad` in the `start` method of `GameManager`:
+
+```ts
+start() {
+ this.generateRoad()
+}
+```
+
+You can see the generated map when running the game.
+
+
+
+## Camera Follow
+
+In a game that has a movable player, we often let the camera follow the player. As a result, you can see the screen scrolling when the player is moving.
+
+It's very simple to achieve it in Cocos Creator. Just make the following changes.
+
+1. Select the Canvas node, and uncheck the **Align Canvas With Screen** property of cc.Canvas component on the Inspector panel.
+
+2. Drag the Camera node on the Player node, and make it a child node.
+
+
+
+Now, run the game, and you can see the camera is following the player.
+
+
+
+## UI layout
+
+UI ( User Interface ) is a very important part of most games. it displays information about the game and allows users to interact with the game systems.
+
+As we mentioned before, In Cocos Creator, all 2D elements should be put directly or indirectly under the Canvas node, or they will not be rendered.
+
+In Cocos Creator, UI is a special collection of 2D elements, they are text, buttons, toggles, etc.
+
+As 2D elements, they also need to be put under the Canvas node.
+
+As we know, UI elements are always fixed on the screen, so we need a fixed camera to render them.
+
+In the previous section, the camera of the Canvas has been changed to follow our Player, it is no longer suitable for UI rendering.
+
+Thus, we need to create a new Canvas for UI.
+
+### UICanvas
+
+In the Hierarchy, right lick the scene root and select "Create -> UI Component -> Canvas" in the pop-up menu.
+
+
+
+Name it "UICanvas".
+
+
+
+Create an empty node named **StartMenu** under the UICanvas.
+
+Then, create a button node under the **StartMenu** node, you can find there is a node named 'Label' under the button node. Select it and set the String property to 'Play'.
+
+Now, we have made a 'Play' button.
+
+
+
+### Background & Text
+
+Next, let's add a background and text to tell users how to play this game.
+
+Create a Sprite node under the 'StartMenu' node and name it 'Bg'.
+
+Assign `internal/default_ui/default_panel` to the `Sprite Frame` property of 'Bg' node.
+
+Set the value of `Type` property to `SLICED`.
+
+Set the `Content Size` of `UITransform` to a certain value (e.g. 400,250) .
+
+
+
+Create a new Label node named 'Title' under the 'StartMenu' node, and set the properties as below:
+- position: 0,80
+- cc.Label Color: black
+- cc.Label String: Mind Your Step 2D
+- cc.Label Font Size:40
+
+
+
+Continue creating some `Label` nodes to describe the gameplay. Name them 'Tip'.
+
+
+
+Create a `Label` node **under UICanvas**, and name it 'Step', to show how many steps the player has taken.
+
+
+
+Now, we have completed the UI layout, let's write some code to finish the game logic.
+
+## Game state
+
+There are 3 states in most games.
+- **INIT**: game is ready to start
+- **PLAYING**: game is playing
+- **END**: game is over, will restart or exit
+
+We can define these states using an enum type as below:
+
+```ts
+enum GameState{
+ GS_INIT,
+ GS_PLAYING,
+ GS_END,
+};
+```
+
+For better readability, let's put it after the `BlockType` enum.
+
+Let's add a `setCurState` method to `GameManger`, which will be used to control the state of the game.
+
+The code is as follows.
+
+```ts
+setCurState (value: GameState) {
+ switch(value) {
+ case GameState.GS_INIT:
+ break;
+ case GameState.GS_PLAYING:
+ break;
+ case GameState.GS_END:
+ break;
+ }
+}
+```
+
+Add a new method named `init` to initialize game data.
+
+```ts
+init() {
+ //to do something
+}
+```
+
+Then, call it in `setCurState` when the game state is set to `GameState.GS_INIT`.
+
+```ts
+setCurState (value: GameState) {
+ switch(value) {
+ case GameState.GS_INIT:
+ this.init();
+ break;
+ case GameState.GS_PLAYING:
+ break;
+ case GameState.GS_END:
+ break;
+ }
+}
+```
+
+As designed, the **Player** only can be controlled by users when the game is running.
+
+So, we make a small change to the input event listener in the `PlayerController`.
+
+The input event is no longer listening in the `start` method, instead, we create a new method named `setInputActive` to handle it. the `setInputActive` method will be called when needed.
+
+```ts
+start () {
+
+}
+
+setInputActive(active: boolean) {
+ if (active) {
+ input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ } else {
+ input.off(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ }
+}
+```
+
+Here, the code of `GameManager` is like this:
+
+```ts
+import { _decorator, CCInteger, Component, instantiate, Node, Prefab } from 'cc';
+import { BLOCK_SIZE, PlayerController } from './PlayerController';
+const { ccclass, property } = _decorator;
+
+enum BlockType{
+ BT_NONE,
+ BT_STONE,
+};
+
+enum GameState{
+ GS_INIT,
+ GS_PLAYING,
+ GS_END,
+};
+
+@ccclass('GameManager')
+export class GameManager extends Component {
+
+ @property({type: Prefab})
+ public boxPrefab: Prefab|null = null;
+ @property({type: CCInteger})
+ public roadLength: number = 50;
+ private _road: BlockType[] = [];
+
+ start() {
+ }
+
+ init() {
+ }
+
+ setCurState (value: GameState) {
+ switch(value) {
+ case GameState.GS_INIT:
+ this.init();
+ break;
+ case GameState.GS_PLAYING:
+
+ break;
+ case GameState.GS_END:
+ break;
+ }
+ }
+
+ generateRoad() {
+
+ this.node.removeAllChildren();
+
+ this._road = [];
+ // startPos
+ this._road.push(BlockType.BT_STONE);
+
+ for (let i = 1; i < this.roadLength; i++) {
+ if (this._road[i - 1] === BlockType.BT_NONE) {
+ this._road.push(BlockType.BT_STONE);
+ } else {
+ this._road.push(Math.floor(Math.random() * 2));
+ }
+ }
+
+ for (let j = 0; j < this._road.length; j++) {
+ let block: Node | null = this.spawnBlockByType(this._road[j]);
+ if (block) {
+ this.node.addChild(block);
+ block.setPosition(j * BLOCK_SIZE, 0, 0);
+ }
+ }
+ }
+
+ spawnBlockByType(type: BlockType) {
+ if (!this.boxPrefab) {
+ return null;
+ }
+
+ let block: Node|null = null;
+ switch(type) {
+ case BlockType.BT_STONE:
+ block = instantiate(this.boxPrefab);
+ break;
+ }
+
+ return block;
+ }
+}
+```
+
+Next, let's add the logic code.
+
+### Game Start
+
+This is not a state, but we must start from here. When the game is launched, the `start` method of `GameManager` will be called.
+
+We call `setCurState` here to initialize the game.
+
+```ts
+ start(){
+ this.setCurState(GameState.GS_INIT);
+ }
+```
+
+### GS_INIT
+
+In this game state, we should initialize the map, reset the position of the player, show the game UI, etc.
+
+So, we need to add the needed properties to `GameManager.
+
+```ts
+// References to the startMenu node.
+@property({ type: Node })
+public startMenu: Node | null = null;
+
+//references to player
+@property({ type: PlayerController })
+public playerCtrl: PlayerController | null = null;
+
+//references to UICanvas/Steps node.
+@property({type: Label})
+public stepsLabel: Label|null = null;
+```
+
+In the `init` method, we add code lines as below:
+
+```ts
+init() {
+ //show the start menu
+ if (this.startMenu) {
+ this.startMenu.active = true;
+ }
+
+ //generate the map
+ this.generateRoad();
+
+
+ if (this.playerCtrl) {
+
+ //disable input
+ this.playerCtrl.setInputActive(false);
+
+ //reset player data.
+ this.playerCtrl.node.setPosition(Vec3.ZERO);
+ this.playerCtrl.reset();
+ }
+}
+```
+
+### Handle Button Click Event
+
+Next, let's implement when users click the 'Play' button on the UI, the game starts playing.
+
+Add a new method named `onStartButtonClicked` to the `GameManager` class, which is used to handle the click event of 'Play' button on the 'startMenu` node.
+
+In `onStartButtonClicked`, we just call `setCurState` to set the game state to `GameState.GS_PLAYING`.
+
+```ts
+onStartButtonClicked() {
+ this.setCurState(GameState.GS_PLAYING);
+}
+```
+
+Go back to Cocos Creator, and select the `UICanvas/StartMenu/Button` node.
+
+On the Inspector panel, type `1` into the input box after `Click Events` property.
+
+Then drag the `GameManager` node to the first slot, select `GameManager` for the second slot, and choose `onStartButtonClicked` for the third slot.
+
+
+
+### GS_PLAYING
+
+After users click the 'Play' button, the game is going to this state. We need to:
+
+- Hide the StartMenu
+- Reset the number of steps
+- Enable user input
+
+The related code in `setCurState` method is as below:
+
+```ts
+setCurState(value: GameState) {
+ switch (value) {
+ //...
+ case GameState.GS_PLAYING:
+ if (this.startMenu) {
+ this.startMenu.active = false;
+ }
+
+ //reset steps counter to 0
+ if (this.stepsLabel) {
+ this.stepsLabel.string = '0';
+ }
+
+ //enable user input after 0.1 second.
+ setTimeout(() => {
+ if (this.playerCtrl) {
+ this.playerCtrl.setInputActive(true);
+ }
+ }, 0.1);
+ break;
+ //...
+ }
+}
+```
+
+### GS_END
+
+We do nothing for now. you can add anything you want to make the game perfect.
+
+### Bind properties
+
+Go back to Cocos Creator, and drag the corresponding node to each property for `GameManager`.
+
+
+
+Look! We can play it now.
+> #### Note: If you find that the UI appears duplicated after running the game, please refer to the `Layers & Visibility` section of this article to resolve the issue.
+
+
+
+## Game Over
+
+Next, let's handle the situation when the player steps on an empty block.
+
+### Handle jump end
+
+Add a new property called `_curMoveIndex` to `PlayerController`, which is used to record how many steps the player has taken.
+
+```ts
+private _curMoveIndex: number = 0;
+```
+
+Set it to 0 in the `reset` method.
+
+```ts
+reset() {
+ this._curMoveIndex = 0;
+ this.node.getPosition(this._curPos);
+ this._targetPos.set(0,0,0);
+}
+```
+
+In the `jumpByStep` method, increase it by `step`.
+
+```ts
+jumpByStep(step: number) {
+ if (this._startJump) {
+ return;
+ }
+ this._startJump = true;
+ this._jumpStep = step;
+ this._curJumpTime = 0;
+ this._curJumpSpeed = this._jumpStep * BLOCK_SIZE/ this._jumpTime;
+ this.getPosition(this._curPos);
+ Vec3.add(this._targetPos, this._curPos, new Vec3(this._jumpStep* BLOCK_SIZE, 0, 0));
+
+ if (this.BodyAnim) {
+ if (step === 1) {
+ this.BodyAnim.play('oneStep');
+ } else if (step === 2) {
+ this.BodyAnim.play('twoStep');
+ }
+ }
+
+ this._curMoveIndex += step;
+}
+```
+
+Add `onOnceJumpEnd` to `PlayerController` to emit an 'JumpEnd' event and pass in `_curMoveIndex` as a parameter.
+
+```ts
+onOnceJumpEnd() {
+ this.node.emit('JumpEnd', this._curMoveIndex);
+}
+```
+
+Call `onOnceJumpEnd` in the `update` of `PlayerController` when the jump action is over.
+
+```ts
+update (deltaTime: number) {
+ if (this._startJump) {
+ this._curJumpTime += deltaTime;
+ if (this._curJumpTime > this._jumpTime) {
+ // end
+ this.node.setPosition(this._targetPos);
+ this._startJump = false;
+ this.onOnceJumpEnd();
+ } else {
+ // tween
+ this.node.getPosition(this._curPos);
+ this._deltaPos.x = this._curJumpSpeed * deltaTime;
+ Vec3.add(this._curPos, this._curPos, this._deltaPos);
+ this.node.setPosition(this._curPos);
+ }
+ }
+}
+```
+
+Go back to `GameManager` and add the following code.
+
+- Add `onPlayerJumpEnd` method to handle the jump end event.
+
+ ```ts
+ onPlayerJumpEnd(moveIndex: number) {
+
+ }
+ ```
+
+- Listen 'JumpEnd' event in the `start` method.
+
+ ```ts
+ start() {
+ this.setCurState(GameState.GS_INIT);
+ this.playerCtrl?.node.on('JumpEnd', this.onPlayerJumpEnd, this);
+ }
+ ```
+
+ > In Cocos Creator, an event dispatched through the `emit` of a node can only be listened to by using its `on`.
+
+- Add `checkResult` to check the type of block the player steps on.
+
+ ```ts
+ checkResult(moveIndex: number) {
+ if (moveIndex < this.roadLength) {
+ if (this._road[moveIndex] == BlockType.BT_NONE) { //steps on empty block, reset to init.
+ this.setCurState(GameState.GS_INIT);
+ }
+ } else { //out of map, reset to init.
+ this.setCurState(GameState.GS_INIT);
+ }
+ }
+ ```
+
+- Finish the `onPlayerJumpEnd` method.
+
+ ```ts
+ onPlayerJumpEnd(moveIndex: number) {
+ //update steps label.
+ if (this.stepsLabel) {
+ this.stepsLabel.string = '' + (moveIndex >= this.roadLength ? this.roadLength : moveIndex);
+ }
+ this.checkResult(moveIndex);
+ }
+ ```
+
+## Layers & Visibility
+
+When playing the game, you may notice the overlapping graphics, this is because the both cameras ( Canvas/Camera, UICanvas/Camera) are rendering all objects.
+
+
+
+In Cocos Creator, a node can only be put in one of the layers, a camera can choose which layers will be rendered by itself.
+
+To solve this problem, we need to allocate the role of the layers and the visibility of cameras.
+
+In this game, we have two types of objects.
+- Scene Object: player, blocks
+- UI Object: windows, buttons, labels
+
+So, we just need to put all of the scene objects to `DEFAULT` layer and put all of the UI objects to `UI_2D` layer.
+
+Then, we need to change a little about the visibility of cameras to let the `Canvas/Camera` only render the objects in `DEFAULT` layer, the `UICanvas/Camera` only render the object in `UI_2D` layer, and everything will be ok.
+
+It's so clear, now, let's do it.
+
+## DEFAULT
+
+- Set the layer of Canvas **and all its children** to `DEFAULT`:
+
+ 
+
+- Set the layer of `Box.prefab` to `DEFAULT`:
+
+ 
+
+ Double-click the left mouse button on the prefab file to enter the prefab editing mode, don't forget to hit the 'Save' button after finishing the modification.
+
+ 
+
+- Set the **Visibility** of `Canvas/Player/Camera` as follows:
+
+ 
+
+## UI_2D
+
+- Set the **Visibility** of `UICanvas/Camera` as follows:
+
+ 
+
+ Since the default layer for 2D nodes is `UI_2D`, we don't need to set the layer for nodes under `UICanvas`.
+
+Play the game again, everything is ok now.
+
+
+
+## Summary
+
+Here we come to the end of this tutorial, hope it has been helpful to you.
+
+In the future, you can add more gameplay and features based on this game, such as replacing the Player with an animation role, adding a beautiful background image, adding rhythmic background music and sounds, etc.
+
+If you have any questions, please refer to [Get Help and Support](../support.md).
+
+## Full Source Code
+
+PlayerController.ts:
+
+```ts
+import { _decorator, Component, Vec3, EventMouse, input, Input, Animation } from "cc";
+const { ccclass, property } = _decorator;
+
+export const BLOCK_SIZE = 40;
+
+@ccclass("PlayerController")
+export class PlayerController extends Component {
+
+ @property(Animation)
+ BodyAnim:Animation = null;
+
+ private _startJump: boolean = false;
+ private _jumpStep: number = 0;
+ private _curJumpTime: number = 0;
+ private _jumpTime: number = 0.1;
+ private _curJumpSpeed: number = 0;
+ private _curPos: Vec3 = new Vec3();
+ private _deltaPos: Vec3 = new Vec3(0, 0, 0);
+ private _targetPos: Vec3 = new Vec3();
+ private _curMoveIndex: number = 0;
+ start () {
+ //input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ }
+
+ setInputActive(active: boolean) {
+ if (active) {
+ input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ } else {
+ input.off(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ }
+ }
+
+ reset() {
+ this._curMoveIndex = 0;
+ this.node.getPosition(this._curPos);
+ this._targetPos.set(0,0,0);
+ }
+
+ onMouseUp(event: EventMouse) {
+ if (event.getButton() === 0) {
+ this.jumpByStep(1);
+ } else if (event.getButton() === 2) {
+ this.jumpByStep(2);
+ }
+
+ }
+
+ jumpByStep(step: number) {
+ if (this._startJump) {
+ return;
+ }
+ this._startJump = true;
+ this._jumpStep = step;
+ this._curJumpTime = 0;
+
+ // get jump time from animation duration.
+ const clipName = step == 1? 'oneStep' : 'twoStep';
+ const state = this.BodyAnim.getState(clipName);
+ this._jumpTime = state.duration;
+
+
+ this._curJumpSpeed = this._jumpStep * BLOCK_SIZE/ this._jumpTime;
+ this.node.getPosition(this._curPos);
+ Vec3.add(this._targetPos, this._curPos, new Vec3(this._jumpStep* BLOCK_SIZE, 0, 0));
+
+ if (this.BodyAnim) {
+ if (step === 1) {
+ this.BodyAnim.play('oneStep');
+ } else if (step === 2) {
+ this.BodyAnim.play('twoStep');
+ }
+ }
+
+ this._curMoveIndex += step;
+ }
+
+
+ onOnceJumpEnd() {
+ this.node.emit('JumpEnd', this._curMoveIndex);
+ }
+
+ update (deltaTime: number) {
+ if (this._startJump) {
+ this._curJumpTime += deltaTime;
+ if (this._curJumpTime > this._jumpTime) {
+ // end
+ this.node.setPosition(this._targetPos);
+ this._startJump = false;
+ this.onOnceJumpEnd();
+ } else {
+ // tween
+ this.node.getPosition(this._curPos);
+ this._deltaPos.x = this._curJumpSpeed * deltaTime;
+ Vec3.add(this._curPos, this._curPos, this._deltaPos);
+ this.node.setPosition(this._curPos);
+ }
+ }
+ }
+}
+```
+
+GameManager.ts:
+
+```ts
+import { _decorator, CCInteger, Component, instantiate, Label, Node, Prefab, Vec3 } from 'cc';
+import { BLOCK_SIZE, PlayerController } from './PlayerController';
+const { ccclass, property } = _decorator;
+
+enum BlockType {
+ BT_NONE,
+ BT_STONE,
+};
+
+enum GameState {
+ GS_INIT,
+ GS_PLAYING,
+ GS_END,
+};
+
+@ccclass('GameManager')
+export class GameManager extends Component {
+
+ @property({ type: Prefab })
+ public boxPrefab: Prefab | null = null;
+ @property({ type: CCInteger })
+ public roadLength: number = 50;
+ private _road: BlockType[] = [];
+
+ @property({ type: Node })
+ public startMenu: Node | null = null;
+ @property({ type: PlayerController })
+ public playerCtrl: PlayerController | null = null;
+ @property({type: Label})
+ public stepsLabel: Label|null = null;
+
+ start() {
+ this.setCurState(GameState.GS_INIT);
+ this.playerCtrl?.node.on('JumpEnd', this.onPlayerJumpEnd, this);
+ }
+
+ init() {
+ if (this.startMenu) {
+ this.startMenu.active = true;
+ }
+
+ this.generateRoad();
+
+ if (this.playerCtrl) {
+ this.playerCtrl.setInputActive(false);
+ this.playerCtrl.node.setPosition(Vec3.ZERO);
+ this.playerCtrl.reset();
+ }
+ }
+
+ setCurState(value: GameState) {
+ switch (value) {
+ case GameState.GS_INIT:
+ this.init();
+ break;
+ case GameState.GS_PLAYING:
+ if (this.startMenu) {
+ this.startMenu.active = false;
+ }
+
+ if (this.stepsLabel) {
+ this.stepsLabel.string = '0';
+ }
+
+ setTimeout(() => {
+ if (this.playerCtrl) {
+ this.playerCtrl.setInputActive(true);
+ }
+ }, 0.1);
+ break;
+ case GameState.GS_END:
+ break;
+ }
+ }
+
+ generateRoad() {
+
+ this.node.removeAllChildren();
+
+ this._road = [];
+ // startPos
+ this._road.push(BlockType.BT_STONE);
+
+ for (let i = 1; i < this.roadLength; i++) {
+ if (this._road[i - 1] === BlockType.BT_NONE) {
+ this._road.push(BlockType.BT_STONE);
+ } else {
+ this._road.push(Math.floor(Math.random() * 2));
+ }
+ }
+
+ for (let j = 0; j < this._road.length; j++) {
+ let block: Node | null = this.spawnBlockByType(this._road[j]);
+ if (block) {
+ this.node.addChild(block);
+ block.setPosition(j * BLOCK_SIZE, 0, 0);
+ }
+ }
+ }
+
+ spawnBlockByType(type: BlockType) {
+ if (!this.boxPrefab) {
+ return null;
+ }
+
+ let block: Node | null = null;
+ switch (type) {
+ case BlockType.BT_STONE:
+ block = instantiate(this.boxPrefab);
+ break;
+ }
+
+ return block;
+ }
+
+ onStartButtonClicked() {
+ this.setCurState(GameState.GS_PLAYING);
+ }
+
+ checkResult(moveIndex: number) {
+ if (moveIndex < this.roadLength) {
+ if (this._road[moveIndex] == BlockType.BT_NONE) {
+ this.setCurState(GameState.GS_INIT);
+ }
+ } else {
+ this.setCurState(GameState.GS_INIT);
+ }
+ }
+
+ onPlayerJumpEnd(moveIndex: number) {
+ if (this.stepsLabel) {
+ this.stepsLabel.string = '' + (moveIndex >= this.roadLength ? this.roadLength : moveIndex);
+ }
+ this.checkResult(moveIndex);
+ }
+
+}
+
+```
diff --git a/versions/4.0/en/getting-started/first-game-2d/touch.md b/versions/4.0/en/getting-started/first-game-2d/touch.md
new file mode 100644
index 0000000000..f3117b260a
--- /dev/null
+++ b/versions/4.0/en/getting-started/first-game-2d/touch.md
@@ -0,0 +1,203 @@
+# Handle Touch Events
+
+If we want our game to run on mobile devices, we need to handle touch events instead of mouse-clicked events, since the latter are only fired on PCs.
+
+In Cocos Creator, we can handle touch events from the screen by listening to `Input.EventType.TOUCH_START` event.
+
+There are two ways can be used.
+
+- handle all touch events from the screen using`input.on`
+- listen to touch events that occur within the content size of a node by using the `node.on` method
+
+We partition the screen into two sides, when users touch the left side, the player moves one step, when they touch the right side, the player moves two steps. It's better to use `node.on` in this situation.
+
+Next, let's take a look at how to accomplish it.
+
+Under the `UICanvas` node, create two nodes and name them `LeftTouch` and `RightTouch`.
+
+
+
+Set their positions and content size as shown below.
+
+
+
+
+
+Back to `PlayerController`, add the following properties for referencing the touch nodes.
+
+```ts
+@property(Node)
+leftTouch: Node = null;
+
+@property(Node)
+rightTouch: Node = null;
+```
+
+Select the `Player` node and then drag the nodes created before onto the corresponding properties added above.
+
+
+
+In `PlayerController`, add the following code.
+
+- Listen touch events:
+
+ ```ts
+ setInputActive(active: boolean) {
+ if (active) {
+ //for pc
+ input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ //for mobile
+ this.leftTouch.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
+ this.rightTouch.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
+ } else {
+ //for pc
+ input.off(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ //for mobile
+ this.leftTouch.off(Input.EventType.TOUCH_START, this.onTouchStart, this);
+ this.rightTouch.off(Input.EventType.TOUCH_START, this.onTouchStart, this);
+ }
+ }
+ ```
+
+- Add the method for handling touch events
+
+ ```ts
+ onTouchStart(event: EventTouch) {
+ const target = event.target as Node;
+ if (target?.name == 'LeftTouch') {
+ this.jumpByStep(1);
+ } else {
+ this.jumpByStep(2);
+ }
+ }
+ ```
+
+ `target` is of type `any`, so we need to use `as` to convert it into the `Node` type.
+
+ After obtaining the touched target node, we can determine whether it is touching on the left or right side based on its name.
+
+Now, you can run the game on your phone by using the browser to scan the QR code on the Cocos Creator operation bar shown as below.
+
+> **Note**: your computer running Cocos Creator and your mobile devices must be connected to the same LAN.
+
+
+
+The complete code of `PlayerController` is shown below.
+
+```ts
+import { _decorator, Component, Vec3, EventMouse, input, Input, Animation, EventTouch, Node } from "cc";
+const { ccclass, property } = _decorator;
+
+export const BLOCK_SIZE = 40;
+
+@ccclass("PlayerController")
+export class PlayerController extends Component {
+
+ @property(Animation)
+ BodyAnim: Animation = null;
+
+ private _startJump: boolean = false;
+ private _jumpStep: number = 0;
+ private _curJumpTime: number = 0;
+ private _jumpTime: number = 0.3;
+ private _curJumpSpeed: number = 0;
+ private _curPos: Vec3 = new Vec3();
+ private _deltaPos: Vec3 = new Vec3(0, 0, 0);
+ private _targetPos: Vec3 = new Vec3();
+ private _curMoveIndex = 0;
+
+ @property(Node)
+ leftTouch: Node = null;
+
+ @property(Node)
+ rightTouch: Node = null;
+
+ start() {
+ //input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ }
+
+ setInputActive(active: boolean) {
+ if (active) {
+ input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ this.leftTouch.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
+ this.rightTouch.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
+ } else {
+ input.off(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ this.leftTouch.off(Input.EventType.TOUCH_START, this.onTouchStart, this);
+ this.rightTouch.off(Input.EventType.TOUCH_START, this.onTouchStart, this);
+ }
+ }
+
+ reset() {
+ this._curMoveIndex = 0;
+ }
+
+ onTouchStart(event: EventTouch) {
+ const target = event.target as Node;
+ if (target?.name == 'LeftTouch') {
+ this.jumpByStep(1);
+ } else {
+ this.jumpByStep(2);
+ }
+ }
+
+ onMouseUp(event: EventMouse) {
+ if (event.getButton() === 0) {
+ this.jumpByStep(1);
+ } else if (event.getButton() === 2) {
+ this.jumpByStep(2);
+ }
+
+ }
+
+ jumpByStep(step: number) {
+ if (this._startJump) {
+ return;
+ }
+ this._startJump = true;
+ this._jumpStep = step;
+ this._curJumpTime = 0;
+
+ const clipName = step == 1 ? 'oneStep' : 'twoStep';
+ const state = this.BodyAnim.getState(clipName);
+ this._jumpTime = state.duration;
+
+ this._curJumpSpeed = this._jumpStep * BLOCK_SIZE / this._jumpTime;
+ this.node.getPosition(this._curPos);
+ Vec3.add(this._targetPos, this._curPos, new Vec3(this._jumpStep * BLOCK_SIZE, 0, 0));
+
+ if (this.BodyAnim) {
+ if (step === 1) {
+ this.BodyAnim.play('oneStep');
+ } else if (step === 2) {
+ this.BodyAnim.play('twoStep');
+ }
+ }
+
+ this._curMoveIndex += step;
+ }
+
+
+ onOnceJumpEnd() {
+ this.node.emit('JumpEnd', this._curMoveIndex);
+ }
+
+ update(deltaTime: number) {
+ if (this._startJump) {
+ this._curJumpTime += deltaTime;
+ if (this._curJumpTime > this._jumpTime) {
+ // end
+ this.node.setPosition(this._targetPos);
+ this._startJump = false;
+ this.onOnceJumpEnd();
+ } else {
+ // tween
+ this.node.getPosition(this._curPos);
+ this._deltaPos.x = this._curJumpSpeed * deltaTime;
+ Vec3.add(this._curPos, this._curPos, this._deltaPos);
+ this.node.setPosition(this._curPos);
+ }
+ }
+ }
+}
+```
diff --git a/versions/4.0/en/getting-started/first-game-2d/touch/config-touch-nodes.png b/versions/4.0/en/getting-started/first-game-2d/touch/config-touch-nodes.png
new file mode 100644
index 0000000000..e17e6da77b
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/touch/config-touch-nodes.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/touch/create-touch.png b/versions/4.0/en/getting-started/first-game-2d/touch/create-touch.png
new file mode 100644
index 0000000000..00ea30da62
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/touch/create-touch.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/touch/left-touch.png b/versions/4.0/en/getting-started/first-game-2d/touch/left-touch.png
new file mode 100644
index 0000000000..95eb7743dc
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/touch/left-touch.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/touch/qr-code.png b/versions/4.0/en/getting-started/first-game-2d/touch/qr-code.png
new file mode 100644
index 0000000000..94ea7d80f3
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/touch/qr-code.png differ
diff --git a/versions/4.0/en/getting-started/first-game-2d/touch/right-touch.png b/versions/4.0/en/getting-started/first-game-2d/touch/right-touch.png
new file mode 100644
index 0000000000..88c7515a77
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game-2d/touch/right-touch.png differ
diff --git a/versions/4.0/en/getting-started/first-game/advance.md b/versions/4.0/en/getting-started/first-game/advance.md
new file mode 100644
index 0000000000..18f38f934c
--- /dev/null
+++ b/versions/4.0/en/getting-started/first-game/advance.md
@@ -0,0 +1,448 @@
+# Advanced: Add Light, Shadow and Skeleton Animation
+
+In this section, we will show you how to use third-part assets such as animation, etc to complete the game prototype we have made in [Quick Start: Make Your First 3D Game](index.md)
+
+## Lighting and Shadows
+
+Lighting and shadows are important rendering features that describe the game. With light sources and shadows, we can simulate a more realistic game world, providing better immersion and empathy.
+
+Next, we add a simple shadow to the character.
+
+### Turn on shadows
+
+1. Click the top `Scene` node in the **Hierarchy** panel, then in the **Inspector** panel check Enabled in `shadows` and modify the **Distance** and **Normal** properties to:
+
+ 
+
+2. Click on the Body node under the Player node and set **ShadowCastingMode** to **ON** in the `cc.MeshRenderer` component.
+
+ 
+
+At this point, you will see a shadow sheet in the **Scene Editor**. The preview will show that the shadow is not visible because it is directly behind the model, covered by the capsule.
+
+
+
+### Adjusting lighting
+
+By default, a **Main Light** node with `cc.DirectionalLight` component is added when creating a new scene. So to make the shadows appear in a different position, we can adjust the direction of this light. Click in the **Hierarchy** panel to select the **Main Light** node and adjust the `Rotation` property to (-10, 17, 0).
+
+
+
+The shadow effect can be seen by clicking on the preview at
+
+
+
+## Adding a protagonist model
+
+### Importing model resources
+
+Importing models, materials, animations and other resources from the original sources is not the focus of this basic tutorial, so we will directly use the resources that have been imported into the project. Put **project** ([GitHub](https://github.com/cocos-creator/tutorial-mind-your-step-3d) in the assets directory and copy the cocos folder to the assets directory of your own project.
+
+### Adding to the scene
+
+A Prefab named Cocos is already included in the Cocos file. Drag it to the Body node under the Player node in the **Hierarchy** panel as a child node of the Body node.
+
+
+
+Also, remove the original capsule model from the **Inspector** panel:
+
+
+
+You can add a Spotlight under the Cocos node to highlight its shiny head.
+
+
+
+### Add jump animation
+
+Now the preview shows that the main character will have a standby animation initially, but it will look very inconsistent to use this standby animation when jumping, so we can change it to a jump animation during jumping. Add a variable to the `PlayerController.ts` class that references the model animation:
+
+```ts
+@property({type: SkeletalAnimation})
+public CocosAnim: SkeletalAnimation|null = null;
+```
+
+Also, since we have changed the protagonist from a capsule body to a character model, we can discard the animation previously created for the capsule body and comment on the relevant code as follows:
+
+```ts
+// @property({type: Animation})
+// public BodyAnim: Animation|null = null;
+
+jumpByStep(step: number) {
+ // ...
+ // if (this.BodyAnim) {
+ // if (step === 1) {
+ // this.BodyAnim.play('oneStep');
+ // } else if (step === 2) {
+ // this.BodyAnim.play('twoStep');
+ // }
+ // }
+}
+```
+
+Then in the **Hierarchy** panel drag and drop the Cocos node into the `CocosAnim` property box of the Player node:
+
+
+
+Play the jump animation in the `jumpByStep` function of the `PlayerController` script:
+
+```ts
+jumpByStep(step: number) {
+ if (this._startJump) {
+ return;
+ }
+ this._startJump = true;
+ this._jumpStep = step;
+ this._curJumpTime = 0;
+ this._curJumpSpeed = this._jumpStep / this._jumpTime;
+ this.node.getPosition(this._curPos);
+ Vec3.add(this._targetPos, this._curPos, new Vec3(this._jumpStep, 0, 0));
+
+ if (this.CocosAnim) {
+ this.CocosAnim.getState('cocos_anim_jump').speed = 3.5; // Jump animation time is relatively long, here to speed up the playback
+ this.CocosAnim.play('cocos_anim_jump'); // Play jump animation
+ }
+
+ // if (this.BodyAnim) {
+ // if (step === 1) {
+ // this.BodyAnim.play('oneStep');
+ // } else if (step === 2) {
+ // this.BodyAnim.play('twoStep');
+ // }
+ // }
+
+ this._curMoveIndex += step;
+}
+```
+
+Here `_jumpStep` time is 0.3 seconds, if the animation length and `_jumpStep` don't match, it may cause the following problem:
+
+- The animation transition is not smooth when the animation is not finished yet
+- or the animation is finished but the jump time is not yet up, resulting in slippage
+
+One way to handle this is to recalculate the speed of the animation directly from the length of the animation clip and `_jumpStep` instead of using a constant: `_jumpStep`:
+
+```ts
+var state = this.CocosAnim.getState('cocos_anim_jump');
+state.speed = state.duration/this._jumpTime;
+```
+
+Developers can try it themselves, or manually modify `_jumpStep` and `speed` to the right values to control the game's pace.
+
+In the `OnceJumpEnd` function of the `PlayerController` script, make the main character standby and play the standby animation.
+
+```ts
+onOnceJumpEnd() {
+ if (this.CocosAnim) {
+ this.CocosAnim.play('cocos_anim_idle');
+ }
+ this.node.emit('JumpEnd', this._curMoveIndex);
+}
+```
+
+> **Note**: `onOnceJumpEnd` will be triggered when the jump is completed, see the `update` function in `PlayerController.ts` for details.
+>
+The preview effect is as follows:
+
+
+
+## Final Code
+
+**PlayerController.ts**
+
+```ts
+import { _decorator, Component, Vec3, input, Input, EventMouse, Animation, SkeletalAnimation } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass("PlayerController")
+export class PlayerController extends Component {
+
+ @property({type: Animation})
+ public BodyAnim: Animation|null = null;
+ @property({type: SkeletalAnimation})
+ public CocosAnim: SkeletalAnimation|null = null;
+
+ // for fake tween
+ private _startJump: boolean = false;
+ private _jumpStep: number = 0;
+ private _curJumpTime: number = 0;
+ private _jumpTime: number = 0.3;
+ private _curJumpSpeed: number = 0;
+ private _curPos: Vec3 = new Vec3();
+ private _deltaPos: Vec3 = new Vec3(0, 0, 0);
+ private _targetPos: Vec3 = new Vec3();
+ private _curMoveIndex = 0;
+
+ start () {
+ }
+
+ reset() {
+ this._curMoveIndex = 0;
+ }
+
+ setInputActive(active: boolean) {
+ if (active) {
+ input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ } else {
+ input.off(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ }
+ }
+
+ onMouseUp(event: EventMouse) {
+ if (event.getButton() === 0) {
+ this.jumpByStep(1);
+ } else if (event.getButton() === 2) {
+ this.jumpByStep(2);
+ }
+
+ }
+
+ jumpByStep(step: number) {
+ if (this._startJump) {
+ return;
+ }
+ this._startJump = true;
+ this._jumpStep = step;
+ this._curJumpTime = 0;
+ this._curJumpSpeed = this._jumpStep / this._jumpTime;
+ this.node.getPosition(this._curPos);
+ Vec3.add(this._targetPos, this._curPos, new Vec3(this._jumpStep, 0, 0));
+
+ if (this.CocosAnim) {
+ this.CocosAnim.getState('cocos_anim_jump').speed = 3.5; // Jump animation time is relatively long, here to speed up the playback
+ this.CocosAnim.play('cocos_anim_jump'); // Play jump animation
+ }
+
+ // if (this.BodyAnim) {
+ // if (step === 1) {
+ // this.BodyAnim.play('oneStep');
+ // } else if (step === 2) {
+ // this.BodyAnim.play('twoStep');
+ // }
+ // }
+
+ this._curMoveIndex += step;
+ }
+
+ onOnceJumpEnd() {
+ if (this.CocosAnim) {
+ this.CocosAnim.play('cocos_anim_idle');
+ }
+
+ this.node.emit('JumpEnd', this._curMoveIndex);
+ }
+
+ update (deltaTime: number) {
+ if (this._startJump) {
+ this._curJumpTime += deltaTime;
+ if (this._curJumpTime > this._jumpTime) {
+ // end
+ this.node.setPosition(this._targetPos);
+ this._startJump = false;
+ this.onOnceJumpEnd();
+ } else {
+ // tween
+ this.node.getPosition(this._curPos);
+ this._deltaPos.x = this._curJumpSpeed * deltaTime;
+ Vec3.add(this._curPos, this._curPos, this._deltaPos);
+ this.node.setPosition(this._curPos);
+ }
+ }
+ }
+}
+```
+
+**GameManager.ts**
+
+```ts
+import { _decorator, Component, Prefab, instantiate, Node, Label, CCInteger, Vec3 } from 'cc';
+import { PlayerController } from "./PlayerController";
+const { ccclass, property } = _decorator;
+
+// The runway type, pit (BT_NONE) or solid road (BT_STONE)
+enum BlockType{
+ BT_NONE,
+ BT_STONE,
+};
+
+enum GameState{
+ GS_INIT,
+ GS_PLAYING,
+ GS_END,
+};
+
+@ccclass("GameManager")
+export class GameManager extends Component {
+
+ // The runway prefab
+ @property({type: Prefab})
+ public cubePrfb: Prefab | null = null;
+ // Length of the road
+ @property({type: CCInteger})
+ public roadLength: Number = 50;
+ private _road: BlockType[] = [];
+ // Node of the start menu
+ @property({type: Node})
+ public startMenu: Node | null = null;
+ // The reference of the PlayerController instance on the Player node
+ @property({type: PlayerController})
+ public playerCtrl: PlayerController | null = null;
+ // Label to display the step
+ @property({type: Label})
+ public stepsLabel: Label | null = null!;
+
+ start () {
+ this.curState = GameState.GS_INIT;
+ this.playerCtrl?.node.on('JumpEnd', this.onPlayerJumpEnd, this);
+ }
+
+ init() {
+ // Active the start menu
+ if (this.startMenu) {
+ this.startMenu.active = true;
+ }
+ // Generate the runway
+ this.generateRoad();
+ if(this.playerCtrl){
+ // Disable user input
+ this.playerCtrl.setInputActive(false);
+ // Reset the player's position
+ this.playerCtrl.node.setPosition(Vec3.ZERO);
+ // Reset the steps
+ this.playerCtrl.reset();
+ }
+ }
+
+ set curState (value: GameState) {
+ switch(value) {
+ case GameState.GS_INIT:
+ this.init();
+ break;
+ case GameState.GS_PLAYING:
+ if (this.startMenu) {
+ this.startMenu.active = false;
+ }
+
+ if (this.stepsLabel) {
+ this.stepsLabel.string = '0'; // Reset the number of steps to 0
+ }
+ // What happens is that the character already starts moving at the moment the game starts
+ // Therefore, a delay is needed here
+ setTimeout(() => {
+ if (this.playerCtrl) {
+ this.playerCtrl.setInputActive(true);
+ }
+ }, 0.1);
+ break;
+ case GameState.GS_END:
+ break;
+ }
+ }
+
+ generateRoad() {
+ // Prevent the track from being the old track when the game is restarted
+ // Therefore, the old track needs to be removed and the old track data cleared
+ this.node.removeAllChildren();
+ this._road = [];
+ // Make sure that the character is standing on the real road when the game is running
+ this._road.push(BlockType.BT_STONE);
+
+ // Determine the type of track for each frame
+ for (let i = 1; i < this.roadLength; i++) {
+ // If the last track is a pit, then this frame must not be a pit
+ if (this._road[i-1] === BlockType.BT_NONE) {
+ this._road.push(BlockType.BT_STONE);
+ } else {
+ this._road.push(Math.floor(Math.random() * 2));
+ }
+ }
+
+ // Generate tracks based on track type
+ let linkedBlocks = 0;
+ for (let j = 0; j < this._road.length; j++) {
+ if(this._road[j]) {
+ ++linkedBlocks;
+ }
+ if(this._road[j] == 0) {
+ if(linkedBlocks > 0) {
+ this.spawnBlockByCount(j - 1, linkedBlocks);
+ linkedBlocks = 0;
+ }
+ }
+ if(this._road.length == j + 1) {
+ if(linkedBlocks > 0) {
+ this.spawnBlockByCount(j, linkedBlocks);
+ linkedBlocks = 0;
+ }
+ }
+ }
+ }
+
+ spawnBlockByCount(lastPos: number, count: number) {
+ let block: Node|null = this.spawnBlockByType(BlockType.BT_STONE);
+ if(block) {
+ this.node.addChild(block);
+ block?.setScale(count, 1, 1);
+ block?.setPosition(lastPos - (count - 1) * 0.5, -1.5, 0);
+ }
+ }
+ spawnBlockByType(type: BlockType) {
+ if (!this.cubePrfb) {
+ return null;
+ }
+
+ let block: Node|null = null;
+ switch(type) {
+ case BlockType.BT_STONE:
+ block = instantiate(this.cubePrfb);
+ break;
+ }
+
+ return block;
+ }
+
+ onStartButtonClicked() {
+ // To start the game by clicking the Play button
+ this.curState = GameState.GS_PLAYING;
+ }
+
+ checkResult(moveIndex: number) {
+ if (moveIndex < this.roadLength) {
+ // Jumped on the pit
+ if (this._road[moveIndex] == BlockType.BT_NONE) {
+ this.curState = GameState.GS_INIT;
+ }
+ } else { // Jumped over the maximum length
+ this.curState = GameState.GS_INIT;
+ }
+ }
+
+ onPlayerJumpEnd(moveIndex: number) {
+ if (this.stepsLabel) {
+ // Because in the last step there may be a jump with a large pace, but at this time, whether the jump is a large pace or a small pace should not increase the score more
+ this.stepsLabel.string = '' + (moveIndex >= this.roadLength ? this.roadLength : moveIndex);
+ }
+ // Check the type of the currently falling road and get the result
+ this.checkResult(moveIndex);
+ }
+
+ // update (deltaTime: number) {
+ // // Your update function goes here.
+ // }
+}
+```
+
+## Conclusion
+
+Congratulations on completing your first game made with Cocos Creator! You can download the full project at [GitHub - Mind-Your-Step-3D](https://github.com/cocos-creator/tutorial-mind-your-step-3d). We hope this quick start tutorial will help you understand the basic concepts and workflow of the Cocos Creator game development process. If you are not interested in writing and learning to script, you can also copy the script directly from the finished project.
+
+Next, you can continue to improve all aspects of the game, here are some recommended improvements:
+- Add difficulty to the game, when the character stays in the same place for 1 second it is considered a failure
+- Change the runway to infinite, dynamically delete the runway that has been run and extend the runway behind.
+- Add game sound effects
+- Add an end menu for the game, count the number of jumps and the time spent by the player
+- Replace characters and runways with more beautiful resources
+- Add some pickup items to guide the player to "make mistakes"
+- Add some particle effects, such as trailing when the character is moving, dust when it hits the ground
+- Add two buttons for touchscreen devices instead of left and right mouse buttons
+
+In addition, if you want to publish your finished game to the server and share it with your friends, you can read the [Cross-Platform Game Publishing](../../editor/publish/index.md) section.
diff --git a/versions/4.0/en/getting-started/first-game/images/2d-view.png b/versions/4.0/en/getting-started/first-game/images/2d-view.png
new file mode 100644
index 0000000000..d07cb8ce34
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/2d-view.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/add-animation-from-assets.gif b/versions/4.0/en/getting-started/first-game/images/add-animation-from-assets.gif
new file mode 100644
index 0000000000..bc1cd0836e
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/add-animation-from-assets.gif differ
diff --git a/versions/4.0/en/getting-started/first-game/images/add-animation.gif b/versions/4.0/en/getting-started/first-game/images/add-animation.gif
new file mode 100644
index 0000000000..b360b5b13e
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/add-animation.gif differ
diff --git a/versions/4.0/en/getting-started/first-game/images/add-cocos-prefab.png b/versions/4.0/en/getting-started/first-game/images/add-cocos-prefab.png
new file mode 100644
index 0000000000..87619e8ff1
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/add-cocos-prefab.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/add-ground-base.png b/versions/4.0/en/getting-started/first-game/images/add-ground-base.png
new file mode 100644
index 0000000000..92e74efdf9
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/add-ground-base.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/add-keyframe.gif b/versions/4.0/en/getting-started/first-game/images/add-keyframe.gif
new file mode 100644
index 0000000000..5c2ed5d241
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/add-keyframe.gif differ
diff --git a/versions/4.0/en/getting-started/first-game/images/add-label-title.gif b/versions/4.0/en/getting-started/first-game/images/add-label-title.gif
new file mode 100644
index 0000000000..c13788d4c2
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/add-label-title.gif differ
diff --git a/versions/4.0/en/getting-started/first-game/images/add-player-controller.png b/versions/4.0/en/getting-started/first-game/images/add-player-controller.png
new file mode 100644
index 0000000000..ea9759e4be
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/add-player-controller.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/add-steps-to-game-manager.png b/versions/4.0/en/getting-started/first-game/images/add-steps-to-game-manager.png
new file mode 100644
index 0000000000..57e864dfd9
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/add-steps-to-game-manager.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/assign-cocos-prefab.png b/versions/4.0/en/getting-started/first-game/images/assign-cocos-prefab.png
new file mode 100644
index 0000000000..85c103828f
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/assign-cocos-prefab.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/assign-cube-prefab.png b/versions/4.0/en/getting-started/first-game/images/assign-cube-prefab.png
new file mode 100644
index 0000000000..72068ab151
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/assign-cube-prefab.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/camera-setting.png b/versions/4.0/en/getting-started/first-game/images/camera-setting.png
new file mode 100644
index 0000000000..0f5fc9a5ea
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/camera-setting.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/change-spriteFrame.png b/versions/4.0/en/getting-started/first-game/images/change-spriteFrame.png
new file mode 100644
index 0000000000..4053ba21a0
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/change-spriteFrame.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/cocos-add-light.png b/versions/4.0/en/getting-started/first-game/images/cocos-add-light.png
new file mode 100644
index 0000000000..f0146933bd
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/cocos-add-light.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/cocos-play.gif b/versions/4.0/en/getting-started/first-game/images/cocos-play.gif
new file mode 100644
index 0000000000..0d829a51ca
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/cocos-play.gif differ
diff --git a/versions/4.0/en/getting-started/first-game/images/create-bg-sprite.gif b/versions/4.0/en/getting-started/first-game/images/create-bg-sprite.gif
new file mode 100644
index 0000000000..fcefda381c
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/create-bg-sprite.gif differ
diff --git a/versions/4.0/en/getting-started/first-game/images/create-button.gif b/versions/4.0/en/getting-started/first-game/images/create-button.gif
new file mode 100644
index 0000000000..e41a65d52b
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/create-button.gif differ
diff --git a/versions/4.0/en/getting-started/first-game/images/create-cube-prefab.gif b/versions/4.0/en/getting-started/first-game/images/create-cube-prefab.gif
new file mode 100644
index 0000000000..7c35aa6f71
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/create-cube-prefab.gif differ
diff --git a/versions/4.0/en/getting-started/first-game/images/create-cube.gif b/versions/4.0/en/getting-started/first-game/images/create-cube.gif
new file mode 100644
index 0000000000..f163df010f
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/create-cube.gif differ
diff --git a/versions/4.0/en/getting-started/first-game/images/create-folder.png b/versions/4.0/en/getting-started/first-game/images/create-folder.png
new file mode 100644
index 0000000000..fdfd12e71a
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/create-folder.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/create-player-script.gif b/versions/4.0/en/getting-started/first-game/images/create-player-script.gif
new file mode 100644
index 0000000000..e75ad1abda
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/create-player-script.gif differ
diff --git a/versions/4.0/en/getting-started/first-game/images/create-player-script.png b/versions/4.0/en/getting-started/first-game/images/create-player-script.png
new file mode 100644
index 0000000000..63e9ea4788
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/create-player-script.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/create-player.gif b/versions/4.0/en/getting-started/first-game/images/create-player.gif
new file mode 100644
index 0000000000..0754205ded
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/create-player.gif differ
diff --git a/versions/4.0/en/getting-started/first-game/images/create-player.png b/versions/4.0/en/getting-started/first-game/images/create-player.png
new file mode 100644
index 0000000000..7a4941aacf
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/create-player.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/create-project.png b/versions/4.0/en/getting-started/first-game/images/create-project.png
new file mode 100644
index 0000000000..914b6f9613
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/create-project.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/create-scene.png b/versions/4.0/en/getting-started/first-game/images/create-scene.png
new file mode 100644
index 0000000000..e307de90fc
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/create-scene.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/drag-camera-to-player.gif b/versions/4.0/en/getting-started/first-game/images/drag-camera-to-player.gif
new file mode 100644
index 0000000000..0da4c53eda
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/drag-camera-to-player.gif differ
diff --git a/versions/4.0/en/getting-started/first-game/images/drag-to-animComp.gif b/versions/4.0/en/getting-started/first-game/images/drag-to-animComp.gif
new file mode 100644
index 0000000000..e9696b5f8a
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/drag-to-animComp.gif differ
diff --git a/versions/4.0/en/getting-started/first-game/images/edit-second-clip.png b/versions/4.0/en/getting-started/first-game/images/edit-second-clip.png
new file mode 100644
index 0000000000..19ae8d7339
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/edit-second-clip.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/game-manager-player.png b/versions/4.0/en/getting-started/first-game/images/game-manager-player.png
new file mode 100644
index 0000000000..63390d17fe
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/game-manager-player.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/hierarchy.png b/versions/4.0/en/getting-started/first-game/images/hierarchy.png
new file mode 100644
index 0000000000..8bb03eba5a
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/hierarchy.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/main-light.png b/versions/4.0/en/getting-started/first-game/images/main-light.png
new file mode 100644
index 0000000000..83f594862d
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/main-light.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/main-window.png b/versions/4.0/en/getting-started/first-game/images/main-window.png
new file mode 100644
index 0000000000..c1325dae0c
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/main-window.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/model-shadow.png b/versions/4.0/en/getting-started/first-game/images/model-shadow.png
new file mode 100644
index 0000000000..5810745dfa
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/model-shadow.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/planarShadows.png b/versions/4.0/en/getting-started/first-game/images/planarShadows.png
new file mode 100644
index 0000000000..6e9ee1972a
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/planarShadows.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/play-button-inspector.png b/versions/4.0/en/getting-started/first-game/images/play-button-inspector.png
new file mode 100644
index 0000000000..03028061b3
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/play-button-inspector.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/play.png b/versions/4.0/en/getting-started/first-game/images/play.png
new file mode 100644
index 0000000000..35a468cf9f
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/play.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/player-move.gif b/versions/4.0/en/getting-started/first-game/images/player-move.gif
new file mode 100644
index 0000000000..5d235463ae
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/player-move.gif differ
diff --git a/versions/4.0/en/getting-started/first-game/images/player-shadow-preview.png b/versions/4.0/en/getting-started/first-game/images/player-shadow-preview.png
new file mode 100644
index 0000000000..c7cf7b9491
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/player-shadow-preview.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/player-shadow-scene.png b/versions/4.0/en/getting-started/first-game/images/player-shadow-scene.png
new file mode 100644
index 0000000000..455545762d
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/player-shadow-scene.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/preview-with-jump.gif b/versions/4.0/en/getting-started/first-game/images/preview-with-jump.gif
new file mode 100644
index 0000000000..bc92c7659e
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/preview-with-jump.gif differ
diff --git a/versions/4.0/en/getting-started/first-game/images/remove-capsule.png b/versions/4.0/en/getting-started/first-game/images/remove-capsule.png
new file mode 100644
index 0000000000..659fac63e9
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/remove-capsule.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/start-menu.png b/versions/4.0/en/getting-started/first-game/images/start-menu.png
new file mode 100644
index 0000000000..a010bc532a
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/start-menu.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/steps-label.png b/versions/4.0/en/getting-started/first-game/images/steps-label.png
new file mode 100644
index 0000000000..b629572b20
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/steps-label.png differ
diff --git a/versions/4.0/en/getting-started/first-game/images/title-inspector.png b/versions/4.0/en/getting-started/first-game/images/title-inspector.png
new file mode 100644
index 0000000000..e1f71adac9
Binary files /dev/null and b/versions/4.0/en/getting-started/first-game/images/title-inspector.png differ
diff --git a/versions/4.0/en/getting-started/first-game/index.md b/versions/4.0/en/getting-started/first-game/index.md
new file mode 100644
index 0000000000..c8c63cfdfa
--- /dev/null
+++ b/versions/4.0/en/getting-started/first-game/index.md
@@ -0,0 +1,1163 @@
+# Quick Start: Make Your First 3D Game
+
+In this section, we will introduce you to some of the 3D features in Cocos Creator, and how to use them to make a simple but complete platform jump game.
+
+The following tutorial shows a mini-game named "Mind Your Step". This game tests the user's reaction speed, choosing whether to jump one step or two steps according to the road.
+
+You can experience the finished form of the game at [here](https://gameall3d.github.io/MindYourStep_Tutorial/index.html).
+
+## Add Player
+
+A controllable character is always needed for most games. Here we will make our main character in the game, Miss/Mr. Capsule.
+
+For the sake of convenience in production, let's review a little here how nodes are created within the editor.
+
+
+
+The **Hierarchy** panel will demonstrate all nodes in the scene, and you can create a new node right-clicking on the popup menu of the **Hierarchy** panel.
+
+### Create Player Node
+
+First, you need to create an empty Node named 'Player', and then create another Node named 'Body' to represent the character's model node. To make it simple, we use the built-in capsule model as our main character.
+
+
+
+You may notice that our player is divided into two nodes, the advantage of the division is that when we move the Player node horizontally, this movement will not affect the vertical animation on the Body node(such as jump up and fall). The entire jump animation is combined with horizontal movement and vertical jump-fall animation.
+
+Then place the Player node at (0, 0, 0), so that it can stand on the first block. The effect is as follows:
+
+
+
+### Scripting the Main Character
+
+To make a character move by mouse-events, there is a need to write some custom scripts. Don't worry even if you don't have any programming experience, we will provide all code and all you need to do is copy and paste all those codes to the right place. And of course, we will explain all the code provided to help you get started with Cocos Creator as quick as possible.
+
+#### How to Create Script Components
+
+1. If you haven't created the Scripts folder yet, first right-click on the **assets** folder in **Assets**, select the **Create -> Folder** menu to create a new folder, and rename it with 'Scripts';
+2. Right-click on the Scripts folder, and select **Create -> TypeScript -> NewComponent** on the popup menu to create a new TypeScript component. More references can be found on [official TypeScript](https://www.typescriptlang.org/).
+3. Rename the created component to `PlayerController` and double-click on the script file to open any code editor(such as VSCode).
+
+ 
+
+> **Note**: The script name in Cocos Creator is case-sensitive! If the capitalization is incorrect, you can't use the component based on its name.
+>
+> About renaming: If you enter the name of a component by mistake, you need to change the file name, class name, and decorator name to correct it. Therefore if you do not familiar with the whole operation, consider deleting the file and re-creating it.
+
+#### Writing Script Code
+
+Within the opened `PlayerController` script there is already some pre-set blocks for code, as follows:
+
+```ts
+import { _decorator, Component } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass("PlayerController")
+export class PlayerController extends Component {
+ /* class member could be defined like this */
+ // dummy = '';
+
+ /* use the `property` decorator if you want the member to be serializable */
+ // @property
+ // serializableDummy = 0;
+
+ start () {
+ // Your initialization goes here.
+ }
+
+ // update (deltaTime: number) {
+ // // Your update function goes here.
+ // }
+}
+```
+
+The above code demonstrates the necessary structure of a component(script). Any class that inherits from a `cc.Component` is called a Component and can be attached to any node in a scene to control the behavior of the node, for more details please refer to [Scripting](../../scripting/index.md).
+
+Next, let's refine the `PlayerController` code so that the character can actually move.
+
+#### Listening to the Input
+
+We need to listen to the computer input(mouse, keyboard, or joystick, etc.) to manipulate the character in games, and in Cocos Creator, you can do this by listening to the `input` events.
+
+```ts
+input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+```
+
+The above code demonstrates use how we are listening to the mouse-up event(`MOUSE_UP`) of the Input-System(`input`), and when the mouse-up event is emitted, the `onMouseUp` in this script will be invoked.
+
+Usually, we will put all the initial code in the `start` method of a Component to make sure the input events can listen correctly right after the initialization.
+
+> The invocation of the `start` method indicates that the component has been properly initialized and you can use it with confidence.
+
+So the following code could be seen.
+
+```ts
+import { _decorator, Component, input, Input, EventMouse } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass("PlayerController")
+export class PlayerController extends Component {
+
+ start () {
+ // Your initialization goes here.
+ input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ }
+
+ onMouseUp(event: EventMouse) {
+
+
+ }
+}
+```
+
+#### Make Character Moves
+
+To make our Player move, we have to add some additional properties to the Player to describe it. Think of some questions in the high school physics class about cubes or balls. Yes, indeed, we change the position, speed, and other factors to achieve a movable character in game development.
+
+In the current game, we want to accomplish this behavior: the user presses the left/right mouse button -> determines that it is a displacement of one/two steps -> moves the character forward according to the input until it reaches the destination point.
+
+So we could add a property to the script like the following:
+
+```typescript
+// Whether to receive the jump command
+private _startJump: boolean = false;
+```
+
+With a boolean variable like `_startJump`, we can mark whether the current character is in the jump or not, to help us distinguish between different branching logic in the `update` method. Because obviously, we don't need to move the character when no input is received.
+
+> Q: Why do we handle it in the `update` method?
+>
+> A: The `update` method will be invoked by the engine in a specific time interval. If the FPS of our game is 60 (60 render frames per second), then the `update` method will be called 60 times per second. We can simulate realistic continuous behaviors by using `update` as much as possible.
+
+So we can change the code as follows:
+
+```typescript
+import { _decorator, Component, input, Input, EventMouse } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass("PlayerController")
+export class PlayerController extends Component {
+
+ // Whether to receive the jump command
+ private _startJump: boolean = false;
+ // The jump step count
+ private _jumpStep: number = 0;
+
+ start () {
+ // Your initialization goes here.
+ input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ }
+
+ onMouseUp(event: EventMouse) {
+
+
+ }
+
+ update(dt: number): void {
+ if( this._startJump){ // Handle branching logic of jump
+
+ }
+ }
+}
+```
+
+Good, here we have completed the main framework of our Player controller, so we just need to think about how to move the Player in the `update` method.
+
+In Newtonian mechanics, we have learned that if an object is to move with uniform velocity, then its position must be like the following:
+
+```txt
+P_1 = P_0 + v*t
+```
+
+In other words, we can add the current position of the object plus the velocity multiplied by the time, then we can get the new position.
+
+In our game, when the mouse button is pressed, the character will move directly 1 unit if the jump step is 1, and 2 units if the jump step is 2. So we can calculate the target position of the character (_targetPos) by using the following formula:
+
+```
+_targetPos = _curPos + step
+```
+
+It can be seen that the above formula contains three pieces of information: _targetPos、_curPos and step, so we record these properties in the script to use them in the `update` method.
+
+Add those properties in the `PlayerController` component like the following:
+
+```ts
+// The jump step
+private _jumpStep: number = 0;
+// Current position of the character
+private _curPos: Vec3 = new Vec3();
+// The target position of the character
+private _targetPos: Vec3 = new Vec3();
+```
+
+The code of `PlayerController` should look as follows:
+
+```ts
+import { _decorator, Component, input, Input, EventMouse, Vec3 } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass("PlayerController")
+export class PlayerController extends Component {
+
+ // Whether to receive the jump command
+ private _startJump: boolean = false;
+ // The jump step
+ private _jumpStep: number = 0;
+ // Current position of the character
+ private _curPos: Vec3 = new Vec3();
+ // The target position of the character
+ private _targetPos: Vec3 = new Vec3();
+ start () {
+ // Your initialization goes here.
+ input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ }
+
+ onMouseUp(event: EventMouse) {
+
+
+ }
+
+ update(dt: number): void {
+ if( this._startJump){
+
+ }
+ }
+}
+```
+
+Our next mission is to accomplish how could we get that information by computerizing.
+
+First of all, we should check whether the user has clicked the right mouse button or the left mouse button.
+
+Those determinations can be made by getting the mouse button information in the `onMouseUp` method by using the `getButton` of `EventMouse`. In the `EventMouse` event, the `getButton` will return 0 if the left button is clicked, or 2 if the right button is clicked.
+
+So let's extend the `onMouseUp` method as follows:
+
+```ts
+onMouseUp(event: EventMouse) {
+ if (event.getButton() === 0) {
+
+ }
+ else if (event.getButton() === 2) {
+
+ }
+}
+```
+
+Add a new method `jumpByStep` to the `PlayerController` component to help us calculate the destination position and speed of the character. Since the input step maybe 1 or 2 steps, so we add a numeric parameter `step` to the `jumpByStep` method to achieve better reusability.
+
+> Reusability? Such a concept sounds complicated!
+> Don't stress, it's just some engineering jargon that we can ignore when we first learn it.
+> This is just to explain more clearly why we added a method called `jumpByStep`.
+
+So, the method looks like the follows:
+
+```ts
+jumpByStep(step: number) {
+
+}
+```
+
+We use the `step` parameter to indicate the jump steps.
+
+In our game, jumping(raise and fall) must be a complete step and we don't accept any input unless the jumping process is finished, so we use `_startJump` to ignore the character's input while jumping.
+
+After that, we shall calculate how much is the character's velocity in the given time when it moves from its current position to the destination.
+
+The calculating process looks like the follows:
+
+1. Calculate current speed(_curJumpSpeed)
+2. Calculate target position(_targetPos)
+
+In order to exit the `if( this._startJump)` branch logic correctly, we have to remember the time to start the jump (_curJumpTime), because when this time has elapsed, we consider the whole jump process to be finished.
+
+Now the `jumpByStep` method looks like follows:
+
+```ts
+jumpByStep(step: number) {
+ if (this._startJump) {
+ return;
+ }
+ this._startJump = true; // Whether to start to jump
+ this._jumpStep = step; // Jump steps for this time
+ this._curJumpTime = 0; // Reset the jump time
+ this._curJumpSpeed = this._jumpStep / this._jumpTime; // Current jump step
+ this.node.getPosition(this._curPos); // use 'getPosition` to get the current position of the character
+ // target position = current position + steps
+ Vec3.add(this._targetPos, this._curPos, new Vec3(this._jumpStep, 0, 0));
+}
+```
+
+- Q: What is `Vec3.add`?
+ - `Vec3` is a 3D vector class in Cocos Creator, used to record and calculate 3D vectors.
+ - `add` is a method in `Vec3` to add two 3D vectors, we can notice that there is no `this`, because `add` is a **static method**.
+ - `Vec3.add(this._targetPos, this._curPos, new Vec3(this._jumpStep, 0, 0));` This code block indicate that we use the target position(`_targetPos`) to store the add result of current position(`_curPos`) and a new vector(`new Vec3(this._jumpStep, 0, 0)`) which represent the jump step on x axis.
+
+Sure, we can simply move the character on the X-axis, but in fact, in 3D game development, objects may move along 3 different axes, and the more familiar you are with the usage of 3D vectors, the faster we can master the 3D engine.
+
+At this moment, our code may look as follows:
+
+```ts
+import { _decorator, Component, input, Input, EventMouse, Vec3 } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass("PlayerController")
+export class PlayerController extends Component {
+
+ // Whether received jump command
+ private _startJump: boolean = false;
+ // The jump step count
+ private _jumpStep: number = 0;
+ // Current jump time
+ private _curJumpTime: number = 0;
+ // Total jump time
+ private _jumpTime: number = 0.1;
+ // current jump speed
+ private _curJumpSpeed: number = 0;
+ // current position of the
+ private _curPos: Vec3 = new Vec3();
+ // The difference of the current frame movement position during each jump
+ private _deltaPos: Vec3 = new Vec3(0, 0, 0);
+ // Target position of the character
+ private _targetPos: Vec3 = new Vec3();
+
+ start () {
+ // Your initialization goes here.
+ input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ }
+
+ onMouseUp(event: EventMouse) {
+ if (event.getButton() === 0) {
+
+ }
+ else if (event.getButton() === 2 ) {
+
+ }
+ }
+
+ jumpByStep(step: number) {
+ if (this._startJump) {
+ return;
+ }
+ this._startJump = true;
+ this._jumpStep = step;
+ this._curJumpTime = 0;
+ this._curJumpSpeed = this._jumpStep / this._jumpTime;
+ this.node.getPosition(this._curPos);
+ Vec3.add(this._targetPos, this._curPos, new Vec3(this._jumpStep, 0, 0));
+ }
+
+
+ update(dt: number): void {
+ if( this._startJump){
+
+ }
+ }
+}
+```
+
+Fascinating, now we have all the data required to calculate the character's manipulation, then we can move it in the `update` method.
+
+Remember the Newton problem we talked about above? It's time to really solve this problem.
+
+First up, we need to check the entire jump duration (_curJumpTime) has exceeded our predefined time (_jumpTime).
+
+The test here is simple: we have set _curJumpTime to 0 at input time, so `update` only needs to:
+
+```
+Jump time = last jump time + frame interval
+```
+
+The `update` method happens to provide a parameter like `deltaTime` as the frame interval.
+
+So we just add `_curJumpTime` to `deltaTime` and that's it:
+
+```ts
+update (deltaTime: number) {
+ if (this._startJump) {
+ this._curJumpTime += deltaTime;
+ }
+}
+```
+
+> You can see that we ues the '+=' operator, which is equivalent to `this._curJumpTime = this._curJumpTime + deltaTime`.
+
+When `_curJumpTime` is greater than our pre-defined `_jumpTime`, this means that the jump is over, so we need two branches to handle the end-of-jump and in-jump states, respectively:
+
+```ts
+update (deltaTime: number) {
+ if (this._startJump) {
+ this._curJumpTime += deltaTime;
+ if (this._curJumpTime > this._jumpTime) { // Jump ends
+
+
+ } else { // Jumping
+
+ }
+ }
+}
+```
+
+Finally, we refine the logic for the different branches:
+
+- End of jump: ends the jumping process, forcing the character to be displaced to the target position
+- During the jump: moves the character forward according to the velocity
+
+So our `update` method will look like this:
+
+```ts
+update (deltaTime: number) {
+ if (this._startJump) {
+ this._curJumpTime += deltaTime.
+ if (this._curJumpTime > this._jumpTime) { // end of jump
+ // end
+ this.node.setPosition(this._targetPos); // force move to target position
+ this._startJump = false; // mark the end of the jump
+ } else { // jump in progress
+ // tween
+ this.node.getPosition(this._curPos); // Get the current position
+ this._deltaPos.x = this._curJumpSpeed * deltaTime; // calculate the length of this frame that should be displaced
+ Vec3.add(this._curPos, this._curPos, this._deltaPos); // add the current position to the length of the displacement
+ this.node.setPosition(this._curPos); // set the position after displacement
+ }
+ }
+}
+```
+
+Great! You have completed the core code of this game - character control.
+
+If you still find this explanation a bit difficult, please let us know by clicking on [Get help and support](../support.md).
+
+#### Complete PlayerController
+
+We already have the complete PlayerController code, so we just need to attach it to a node to make it work.
+
+If you still find it difficult, try copying and pasting the following code into the PlayerController.ts file in your project.
+
+```ts
+import { _decorator, Component, Vec3, input, Input, EventMouse, Animation } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass("PlayerController")
+export class PlayerController extends Component {
+ /* class member could be defined like this */
+ // dummy = '';
+
+ /* use the `property` decorator if you want the member to be serializable */
+ // @property
+ // serializableDummy = 0;
+
+ // for fake tween
+ // Whether the jump command is received or not
+ private _startJump: boolean = false;
+ // Jump step length
+ private _jumpStep: number = 0.0;
+ // current jump time
+ private _curJumpTime: number = 0.0;
+ // length of each jump
+ private _jumpTime: number = 0.1;
+ // current jump speed
+ private _curJumpSpeed: number = 0.0;
+ // current character position
+ private _curPos: Vec3 = new Vec3();
+ // the difference in position of the current frame movement during each jump
+ private _deltaPos: Vec3 = new Vec3(0, 0, 0);
+ // target position of the character
+ private _targetPos: Vec3 = new Vec3();
+
+ start () {
+ // Your initialization goes here.
+ input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ }
+
+ onMouseUp(event: EventMouse) {
+ if (event.getButton() === 0) {
+ this.jumpByStep(1);
+ }
+ else if (event.getButton() === 2) {
+ this.jumpByStep(2);
+ }
+
+ }
+
+ jumpByStep(step: number) {
+ if (this._startJump) {
+ return;
+ }
+ this._startJump = true;
+ this._jumpStep = step;
+ this._curJumpTime = 0;
+ this._curJumpSpeed = this._jumpStep / this._jumpTime;
+ this.node.getPosition(this._curPos);
+ Vec3.add(this._targetPos, this._curPos, new Vec3(this._jumpStep, 0, 0));
+ }
+
+ update (deltaTime: number) {
+ if (this._startJump) {
+ this._curJumpTime += deltaTime;
+ if (this._curJumpTime > this._jumpTime) {
+ // end
+ this.node.setPosition(this._targetPos);
+ this._startJump = false;
+ } else {
+ // tween
+ this.node.getPosition(this._curPos);
+ this._deltaPos.x = this._curJumpSpeed * deltaTime;
+ Vec3.add(this._curPos, this._curPos, this._deltaPos);
+ this.node.setPosition(this._curPos);
+ }
+ }
+ }
+}
+```
+
+Now we can add the `PlayerController` component to the character node `Player`. Select the `Player` node on the **Hierarchy** panel, then click the **Add Component** button on the **Inspector** panel, and choose **Custom Script -> PlayerController** to add it to the `Player` node.
+
+
+
+To display the content on screen properly during runtime, We need to adjust some parameters of the camera, select the **Main Camera** node, and change its `Position` to (0, 0, 13), and `Color` to (50,90,255,255):
+
+
+
+Then click the **Preview** button on the center of the top toolbar.
+
+
+
+By clicking the left mouse button or right mouse button in the open browser, you may see the following screen:
+
+
+
+For more preview functions, please refer to [Project Preview & Debugging](../../editor/preview/index.md).
+
+## Add Character Animations
+
+We could notice that the horizontal movement of the character is tedious from the result of the above execution. To make out character feel like jumping you could add a vertical animation. For more information about **Animation Editor**, please refer to [Animation System](../../animation/index.md).
+
+1. Select the `Body` node in the **Hierarchy** panel, and then click the **Add Animation Clip** button in the **Animation Editor** at the bottom of the editor to create an animation clip and name it `onStep`.
+
+ 
+
+2. Enter the animation editing mode, add a `position` property track to the created clip, and then add three keyframes, the position value of each should be (0, 0, 0), (0, 0.5, 0), (0, 0, 0);
+
+ 
+
+ > **Note**: Alway remember to save animation clips when exiting animation editing mode, otherwise you work will be lost.
+
+3. We can use **Assets Manager** to create clips. Right-click on the **Assets** panel to create a new animation clip named `twoStep`, and add it to the `Animation` property of the `Body` node. To make the recording process easier, we can adjust the layout of the editor.
+
+ > **Note**: Please note that when the animation clip can not be dragged to the `Animation` property, please check the import section `import {...} from "cc"` in `PlayerController` contains `Animation`.
+
+ 
+
+4. Enter the animation edit mode, select `twoStep` clip in the dropdown menu like step 2, then add three key-frames of the `Position` property which should be (0, 0, 0), (0, 1, 0), (0, 0, 0).
+
+ 
+
+5. Import and reference the `Animation` component in the `PlayerController`, because we need to play different animation clips according to different steps.
+
+ First, reference `Animation` component of the `Body` node to `PlayerController`.
+
+ ```ts
+ @property({type: Animation})
+ public BodyAnim: Animation | null = null;
+ ```
+
+ Drag the `Body` node to the `Animation` property of the **Inspector** panel.
+
+ 
+
+ Add the following code to the jump method `jumpByStep` to play animations.
+
+ ```ts
+ if (this.BodyAnim) {
+ if (step === 1) {
+ this.BodyAnim.play('oneStep');
+ } else if (step === 2) {
+ this.BodyAnim.play('twoStep');
+ }
+ }
+ ```
+
+6. Click the **Preview** button to see the new jump animation in the open browse by clicking the left or right mouse button.
+
+ 
+
+## Runway upgrade
+
+To make our game more interesting, we need a long runway for the Player to fleet on. Duplicating a lot of Cube nodes is obviously not a good idea, we can automatically create the runway by script.
+
+### Game Manager
+
+Typically, a scene contains various functions and different types of nodes, All those nodes stored in the scene could be taken as the most important data of our game. Occasionally we need to dynamically create, visit, and delete those nodes. Although we can find a node by `find` method in Cocos Creator, actually the `find` method has to enumerate all nodes in the scenes which will cause a low accuracy. In commercial development, we use some single components to manage **some kind of** nodes or **some** nodes data which we call **Manager**.
+
+For example, in a game, we may have many characters, and we may have to create a new character, delete characters who are dead, or query the status of a character, in that case, we can create a class named `ActorManager` to manage all the characters and support the functions mentioned above.
+
+In this game, we declare a new node component named GameManager to manage all relevant nodes or data.
+
+In this case, we put all functions, such as runway generation and deletion, in GameManager to make data collection more convenient.
+
+This style of cohesion is very common in game development, do not be surprised when you see some other components such as ConfigManager or NetworkManager.
+
+Of course, there are more complex structures in complex games. Those complex, tremendous conceptions of design can improve the stability and maintainability of our applications.
+
+So let's go ahead and create such a manager.
+
+### Create GamManager
+
+1. Right-click on the **Hierarchy** panel to create a new node named `GameManager`.
+2. Right-click in `assets/Scripts` folder on the **Assets** panel to create a TypeScript component named `GameManager`.
+3. Add the `GameManager` component to the GameManager node.
+
+### Create Prefabs
+
+For nodes that need to be duplicated, we can save them to a [Prefab](../../asset/prefab.md) asset as a template of dynamic assets.
+
+> Prefabs are a built-in asset type of the engine, the main purpose of which is to provide the possibility to instantiate some kind of node. Imagine if we had 1000 enemies in our game, creating them individually would take a lot of time, to solve this problem we could dynamically clone the prefabs 1000 times.
+
+Drag the elementary Cube node to the **Assets** panel to create a Prefab.
+
+
+
+### Add Automatic Runway Creation Code
+
+The player needs a long runway, and the ideal way is to dynamically increase the length of the runway so that it can run forever. Here for convenience, firstly we generate a fixed-length runway, the runway length can be defined by yourself. In addition, we can generate some pits on the runway and GameOver when the Player jumps to the pits.
+
+First, we need to define some constants to indicate whether the current coordinates represent a pit or a rock. In Typescript, this can be done with enumerations.
+
+By using the keyword `enum` + the name of the enumeration we define the following enumeration, where `BT_NONE` represents a pit and `BT_STONE` represents a walkable surface.
+
+```typescript
+enum BlockType{
+ BT_NONE,
+ BT_STONE,
+};
+```
+
+Again, we need to define which Prefab or bodies the game manager will use to create the map.
+
+```ts
+// The runway prefab
+@property({type: Prefab})
+public cubePrfb: Prefab | null = null;
+```
+
+The editor will recognize `@property({type: Prefab})` as a prefab so that we can assign the Cube.prefab to this property in the **Inspector** panel.
+
+> A syntax like `@property` is called a [Decorator](../../scripting/decorator.md). There is various type of decorators in Cocos Creator that can use it to customize various effect to decorate custom components.
+
+To make it easier to quickly find out whether the current location is a Cube or a pit, we describe the entire track using an array
+
+```ts
+_road: BlockType[] = [];
+```
+
+Thus a basic GameManager is defined, which should look like this:
+
+```ts
+import { _decorator, Component, Prefab } from 'cc';
+const { ccclass, property } = _decorator;
+
+// Track grid type, pit (BT_NONE) or solid road (BT_STONE)
+enum BlockType {
+ BT_NONE,
+ BT_STONE,
+};
+
+@ccclass("GameManager")
+export class GameManager extends Component {
+
+ // The runway prefab
+ @property({type: Prefab})
+ public cubePrfb: Prefab | null = null;
+ // Total road length
+ @property
+ public roadLength = 50;
+ private _road: BlockType[] = [];
+
+ start () {
+ this.generateRoad();
+ }
+
+ generateRoad() {
+
+ }
+}
+```
+
+Then we generate the entire runway by the following principles.
+
+- The first location on the runway must be BT_STONE to make sure the player won't drop at the beginning of the game.
+- After the first position, we will generate a cube or a pit at random. Considering our character's poor jumping ability (up to 2 steps), we can't generate 2 or move pits continuously, so when we generate a new location, we should examine whether the previous location is a rock or a pit, and if it is a pit, we must put a rock in the current location.
+- Based on the above two principles, we save the generated block to the `_road` array to quickly query whether a location is a rock or a pit.
+- Finally, we instantiate the whole road into the scene based on the road information `_road` to accomplish the whole map.
+
+Thus the method `generateRoad` for generating the map is as follows:
+
+```ts
+generateRoad() {
+ // Prevent the track from being the old track when the game is restarted
+ // Therefore, the old track needs to be removed and the old track data cleared
+ this.node.removeAllChildren();
+ this._road = [];
+ // Make sure that the character is standing on the real road when the game is running
+ this._road.push(BlockType.BT_STONE);
+
+ // Determine the type of track for each frame
+ for (let i = 1; i < this.roadLength; i++) {
+ // If the previous track is a pit, then this one must not be a pit
+ if (this._road[i-1] === BlockType.BT_NONE) {
+ this._road.push(BlockType.BT_STONE);
+ } else {
+ this._road.push(Math.floor(Math.random() * 2));
+ }
+ }
+
+ // Generate tracks based on runway
+ for (let j = 0; j < this._road.length; j++) {
+ let block: Node = this.spawnBlockByType(this._road[j]);
+ // Determine if a road was generated, as spawnBlockByType may return a pit (with a value of null)
+ if (block) {
+ this.node.addChild(block);
+ block.setPosition(j, -1.5, 0);
+ }
+ }
+}
+```
+
+> `Math.floor`: This method is one of the methods of the Typescript math library: we know that floor means floor, and this means taking the "floor" of this method argument, i.e. rounding down.
+> `Math.random`: Again random is one of the methods of the standard math library, and is used to randomize a decimal number between 0 and 1, note that the range of values is [0, 1).
+> So `Math.floor(Math.random() * 2)` means simply that it takes a random number from [0, 2) and rounds down to 0 or 1, which corresponds to the `BT_NONE` and `BT_STONE` declared in the enumeration `BlockType`.
+> By the way, in Typescript enumerations, if you don't assign a value to the enumeration, then the enumeration values are assigned sequentially starting from 0.
+
+The method `spawnBlockByType` for generating a stone is as follows:
+
+```ts
+spawnBlockByType(type: BlockType) {
+ if (!this.cubePrfb) {
+ return null;
+ }
+
+ let block: Node | null = null;
+ // The runway is generated only for real roads
+ switch(type) {
+ case BlockType.BT_STONE:
+ block = instantiate(this.cubePrfb);
+ break;
+ }
+
+ return block;
+}
+```
+
+We can notice that when the block type is Stone, we will use the `instantiate` method to clone a new Prefab, on the other hand, if the block type is not Stone, we don't do anything.
+
+> `instantiate` is the method for cloning a Prefab in Cocos Creator. You can use it to clone not only Prefab but also clone other types of objects!
+
+The entire code of `GameManager` is as follows:
+
+```ts
+import { _decorator, Component, Prefab, instantiate, Node, CCInteger } from 'cc';
+const { ccclass, property } = _decorator;
+
+// The runway type, pit (BT_NONE) or solid road (BT_STONE)
+enum BlockType {
+ BT_NONE,
+ BT_STONE,
+};
+
+@ccclass("GameManager")
+export class GameManager extends Component {
+
+ // The stone prefab
+ @property({type: Prefab})
+ public cubePrfb: Prefab | null = null;
+ // Length of the runway
+ @property
+ public roadLength = 50;
+ private _road: BlockType[] = [];
+
+ start () {
+ this.generateRoad();
+ }
+
+ generateRoad() {
+ // Prevent the track from being the old track when the game is restarted
+ // Therefore, the old track needs to be removed and the old track data cleared
+ this.node.removeAllChildren();
+ this._road = [];
+ // Make sure that the character is standing on the real road when the game is running
+ this._road.push(BlockType.BT_STONE);
+
+ // Determine the type of track for each frame
+ for (let i = 1; i < this.roadLength; i++) {
+ // If the previous track is a pit, then this one must not be a pit
+ if (this._road[i-1] === BlockType.BT_NONE) {
+ this._road.push(BlockType.BT_STONE);
+ } else {
+ this._road.push(Math.floor(Math.random() * 2));
+ }
+ }
+
+ // Generate tracks based on runway
+ for (let j = 0; j < this._road.length; j++) {
+ let block: Node = this.spawnBlockByType(this._road[j]);
+ // Determine if a road was generated, as spawnBlockByType may return a pit (with a value of null)
+ if (block) {
+ this.node.addChild(block);
+ block.setPosition(j, -1.5, 0);
+ }
+ }
+ }
+
+ spawnBlockByType(type: BlockType) {
+ if (!this.cubePrfb) {
+ return null;
+ }
+
+ let block: Node | null = null;
+ // The runway is generated only for real roads
+ switch(type) {
+ case BlockType.BT_STONE:
+ block = instantiate(this.cubePrfb);
+ break;
+ }
+
+ return block;
+ }
+
+ // update (deltaTime: number) {
+ // // Your update function goes here.
+ // }
+}
+```
+
+Drag the pre-made Cube.prefab on to **CubePrfb** property of the **Inspector** panel.
+
+
+
+You can change the **roadLength** property of the **Inspector** panel to control the length of the runway.
+
+Now, click the **Preview** button to see the automatically created runway in the open browser.
+
+## The Player-Centered Camera
+
+We can notice that the Camera does not follow the Player node, hence we can not see the runway behind it. We can avoid this situation by making the camera a child node of Player.
+
+
+
+Thus the Camera will follow the Player's movement, now by clicking the **Preview** button, we can watch the whole runway.
+
+## Add a Start Menu
+
+The User Interface(UI) is an essential part of a game, developers can inform users of some significant information such as data, status, etc so that the user can have their strategy. We could also add the game name, an introduction, the production staff, and other information.
+
+Please refer to relevant documents such as [2D/UI](. /. /2d-object/index.md) to help understand the mechanics of the UI as a 2D part.
+
+Then we will describe a UI workflow taking the Start Menu as an example.
+
+1. Create a new Button node in the **Hierarchy** panel and rename it PlayButton
+
+ 
+
+ It can be noticed that the engine automatically creates a Canvas node in the **Hierarchy** panel, a Player button node, and a Label node. That is because any node that contains a UI component only be seen when it is under the `Canvas` node, so the editor will create a Canvas in case there is none.
+
+ Change the **String** property of the `cc.Label` component in the Label Node from "Button" to "Play".
+
+ > You may notice that Cocos Creator automatically adds a new Camera node under the "Canvas" when you create a UI node.
+ > This is a new feature in Cocos Creator. The new Camera will be in charge of the UI/2D parts, therefore the engine's render pipeline can process the UI/2D content more efficiently.
+
+2. Create an empty node named StartMenu under the Canvas node, and drag the PlayButton under it. We can switch to a 2D editing view for editing UI by clicking the 2D/3D button on the scene's toolbar. For more details on scene editing, please refer to [Scene Panel](../../editor/scene/index.md)。
+
+ 
+
+3. Create a new Sprite node named `BG` under the `StartMenu` as a background image, and drag it on the PlayButton.
+
+ 
+
+ Then set the `ContentSize` property of `cc.UITransform` component to (200, 200) in the **Inspector** panel, and drag the `internal/default_ui/default_sprite_splash` asset to its **SpriteFrame** property.
+
+ 
+
+4. Create a Label node named Title beneath the StartMenu node on the **Hierarchy** panel, and use it as the title of the start menu.
+
+ 
+
+5. Adjust other properties of the Title node such as on `Position`, `Color`, `String`, `FontSize`, etc on the **Inspector** panel by the following image:
+
+ 
+
+6. Once the required Tips nodes are added and the PlayButton is adjusted, a simple start menu is completed.
+
+ 
+
+## Add Game States
+
+For most games, we can roughly break it down into 3 different states: initialize, play, and settle. Just like in any board game, the process of placing the pieces is called initialization; the process of playing is called playing; and the final state when the two players finish the game to settle the victory/failure is called the settlement state.
+
+In the same way, we can define the game state by using an enumeration.
+
+```ts
+enum GameState{
+ GS_INIT,
+ GS_PLAYING,
+ GS_END,
+};
+```
+
+- GS_INIT(initialize): Show the game menu and initialize some resources.
+- GS_PLAYING(play): Hide the game menu, and the user can start to control the character.
+- GS_END(end): End the game and show the start menu.
+
+The current game state can be easily informed by reading the `GameState` enumeration, and we can handle some logic when the state changes.
+
+In order to allow the user to control the character in the play state rather than the game initialize, we have to enable/disable listening to the mouse event automatically. So modify the `PlayerController` script as follows:
+
+```ts
+start () {
+ // Your initialization goes here.
+ // input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+}
+
+setInputActive(active: boolean) {
+ if (active) {
+ input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ } else {
+ input.off(Input.EventType.MOUSE_UP, this.onMouseUp, this);
+ }
+}
+```
+
+And reference the `PlayerController` script in the `GameManager` script.
+
+```ts
+@property({type: PlayerController})
+public playerCtrl: PlayerController | null = null;
+```
+
+Back to Cocos Creator after saving the scripts, and drag the Player node that attached a `PlayerController` script to the `playerCtrl` property of the GameManager Node in the **Inspector** panel.
+
+Meanwhile, we need to reference the StartMenu node in the `GameManager` script to dynamically enable/disable the start menu.
+
+```ts
+@property({type: Node})
+public startMenu: Node | null = null;
+```
+
+Return to the editor after saving all scripts and drag the StartMenu node to the `startMenu` property of the GameManager node on the **Inspector** panel.
+
+
+
+### Add State Change Code
+
+Add the switch state code to the GameManager script, and add the initialization code to the `start` method.
+
+```ts
+start () {
+ this.curState = GameState.GS_INIT;
+}
+
+init() {
+ // Active start menu
+ if (this.startMenu) {
+ this.startMenu.active = true;
+ }
+ // Generate the runway
+ this.generateRoad();
+ if(this.playerCtrl){
+ // Disable user input
+ this.playerCtrl.setInputActive(false);
+ // Reset the player's position
+ this.playerCtrl.node.setPosition(Vec3.ZERO);
+ }
+}
+
+set curState (value: GameState) {
+ switch(value) {
+ case GameState.GS_INIT:
+ this.init();
+ break;
+ case GameState.GS_PLAYING:
+ if (this.startMenu) {
+ this.startMenu.active = false;
+ }
+ // When active is set to true, it will start listening for mouse events directly, while mouse up events are not yet dispatched
+ // What will happen is that the character will start moving the moment the game starts
+ // Therefore, a delay is needed here
+ setTimeout(() => {
+ if (this.playerCtrl) {
+ this.playerCtrl.setInputActive(true);
+ }
+ }, 0.1);
+ break;
+ case GameState.GS_END:
+ break;
+ }
+}
+```
+
+Here we can see in the newly added `init` method, it initializes the runway, activates the start menu, and disable user input at the same time. In any case, we will invoke this method when the game state changes to `GS_INIT`.
+
+And for the first time, accessors like `set curState` allow us to be more secure when setting the game state.
+
+### Add an Event Listener to the Play Button
+
+In order to start the game immediately after clicking the Play button, we need to listen to its click event. Add the following response code in the `GameManager` script as a means to enter the Playing state after the user clicked the button.
+
+```ts
+onStartButtonClicked() {
+ this.curState = GameState.GS_PLAYING;
+}
+```
+
+Then select the PlayButton node in the **Hierarchy** panel, add a response method to the `cc.Button` component in the **Inspector** panel, and drag the GameManager node on the `cc.Node` property.
+
+
+
+Here we can notice the element [0] of Click Events is divided into three parts, which are:
+1. Node: Here we drag and drop the GameManager node, which means that the button event will be received by the GameManager node
+2. Component: after dragging the GameManager node, you can select the node on the GameManager through the drop-down, here select the component with the same name `GameManager`.
+3. Event Handler: through the drop-down menu, select the response event of the button, here you have to select the `onStartButtonClicked` method added above as the response of **button clicked**
+
+> **Note**: The above three steps must be performed in strict order of 1->2->3.
+
+Now, by clicking the **Preview** button, we can start the game.
+
+## Add Game Over Logic
+
+Currently, the game character just runs forward dully, we need to add game rules to make it more challenging to run.
+
+1. The character needs to send a message at the end of each jump and send a message with its current position as a parameter, and record how many steps it has jumped in the `PlayerController` script:
+
+ ```ts
+ private _curMoveIndex = 0;
+ // ...
+ jumpByStep(step: number) {
+ // ...
+
+ this._curMoveIndex += step;
+ }
+ ```
+
+ And at the end of each jump sends the message:
+
+ ```ts
+ onOnceJumpEnd() {
+ this.node.emit('JumpEnd', this._curMoveIndex);
+ }
+ ```
+
+2. Listen for end-of-character jump events in the `GameManager` script, and determine the winner according to the rules, adding a failure and end judgment, and ending if the jump reaches an empty block or exceeds the maximum length value:
+
+ ```ts
+ checkResult(moveIndex: number) {
+ if (moveIndex < this.roadLength) {
+ // Jumped on the pit
+ if (this._road[moveIndex] == BlockType.BT_NONE) {
+ this.curState = GameState.GS_INIT;
+ }
+ } else { // Skipped maximum length
+ this.curState = GameState.GS_INIT;
+ }
+ }
+ ```
+
+ Listens for role jump messages and calls the judgment function:
+
+ ```ts
+ start () {
+ this.curState = GameState.GS_INIT;
+ // '?.' is Typescript's optional chain writing
+ // The equivalent of:
+ // if(this.playerCtrl ! = null) this.playerCtrl.node.on('JumpEnd', this.onPlayerJumpEnd, this).
+ // Optional chains are written in a more concise way
+ this.playerCtrl?.node.on('JumpEnd', this.onPlayerJumpEnd, this);
+ }
+
+ // ...
+ onPlayerJumpEnd(moveIndex: number) {
+ this.checkResult(moveIndex);
+ }
+ ```
+
+ If you preview the game at this point, you will find that there is an error of judgment when restarting the game, which is caused by not resetting the value of the `_curMoveIndex` property in `PlayerController.ts` when restarting. So we need to add a `reset` function to the `PlayerController` script:
+
+ ```ts
+ reset() {
+ this._curMoveIndex = 0;
+ }
+ ```
+
+ Then call `reset` in the `init` function of the `GameManager` script to reset the `_curMoveIndex` property in the `PlayerController.ts`.
+
+ ```ts
+ init() {
+ // ...
+ this.playerCtrl.reset();
+ }
+ ```
+
+## Step Count Display
+
+We can display the current number of steps on the UI so that it will be a great sense of accomplishment to watch the number of steps increasing during the jump.
+
+1. Create a new Label node named Steps under Canvas and adjust the position, font size and other properties.
+
+ 
+
+2. Reference this Label in the `GameManager` script:
+
+ ```ts
+ @property({type: Label})
+ public stepsLabel: Label | null = null;
+ ```
+
+ After saving the script and going back to the editor, drag the Steps node into the GameManager's stepsLabel property box in the properties inspector at
+
+ 
+
+3. Update the current step count data to the Steps node. Since we don't have a GameOver UI n now, we will jump back to the start menu when the game is over, so we need to see the last jump in the start screen, so we need to reset the step count to 0 when we enter the Playing state.
+
+ ```ts
+ // GameManager.ts
+ set curState (value: GameState) {
+ switch(value) {
+ case GameState.GS_INIT:
+ this.init();
+ break;
+ case GameState.GS_PLAYING:
+ if (this.startMenu) {
+ this.startMenu.active = false;
+ }
+
+ if (this.stepsLabel) {
+ this.stepsLabel.string = '0'; // Reset the number of steps to 0
+ }
+ setTimeout(() => { // Directly set active will start listening to mouse events directly, here the delay is done
+ if (this.playerCtrl) {
+ this.playerCtrl.setInputActive(true);
+ }
+ }, 0.1);
+ break;
+ case GameState.GS_END:
+ break;
+ }
+ }
+ ```
+
+ Then, in the function `onPlayerJumpEnd`, which response to the character jump, the number of steps is updated to the Label control
+
+ ```ts
+ onPlayerJumpEnd(moveIndex: number) {
+ if (this.stepsLabel) {
+ // Because in the last step there may be a jump with a large pace, but at this time, whether the jump is a large pace or a small pace should not increase the score more
+ this.stepsLabel.string = '' + (moveIndex >= this.roadLength ? this.roadLength : moveIndex);
+ }
+ this.checkResult(moveIndex);
+ }
+ ```
+
+## Conclusion
+
+Up to this point, you have basically mastered most of the contents of this chapter, next you can improve the game by improving the art and gameplay, for which we have also prepared an [advanced](./advance.md) chapter as an option. If you are interested in other features of Cocos Creator, you can click on the summary on the left.
+
+If you have any feedback or suggestions, you can visit our [forum](https://discuss.cocos2d-x.org/) or request a question on [GIT](https://github.com/cocos/cocos-docs).
diff --git a/versions/4.0/en/getting-started/helloworld/index.md b/versions/4.0/en/getting-started/helloworld/index.md
new file mode 100644
index 0000000000..2d5a0e2bbb
--- /dev/null
+++ b/versions/4.0/en/getting-started/helloworld/index.md
@@ -0,0 +1,118 @@
+# Hello World Project
+
+It's time to create and open the **Hello World** project.
+
+Before we starts, please make sure you have read the [Install and Launch](../install/index.md), installed the Cocos Dashboard, and the newest Cocos Creator editor.
+
+## Creating a new project
+
+In the **Project** tab of Cocos Dashboard, click the **New** button in the bottom right corner to enter the **New Project** page. Select the **empty** project template, set the project name and project path
+
+
+
+Then click the **Create and open** button at the bottom right to automatically create a project with an empty project template and open.
+
+
+
+- **Assets**: shows all the assets in the project's assets folder (`assets`).
+- **Scene**: working area for displaying and editing the visual content in the scene.
+- **Hierarchy**: shows all nodes in the scene and their hierarchical relationships in a tree list, all content seen in the **Scene** panel can be found in the **Hierarchy** panel with corresponding node entries
+- **Inspector**: working area for viewing and editing the properties of the currently selected node and its components
+- **Assets Preview**: Selecting an asset in the **Assets** panel displays a thumbnail of the asset in the **Assets Preview** panel. If the folder where the asset is located is selected, the thumbnails of all assets under the folder can be displayed for easy viewing.
+- **Animation**: used to create some less complex animations that need to be linked with logic, such as UI animations.
+- **Console**: used to display error reports, warnings or other log messages generated by the editor and engine.
+
+For more information about the various editor panels, please refer to [Editor Panels](../../editor/index.md).
+
+## New Scene Creation
+
+Right-click in the **Assets** panel at the bottom left and select **Create -> Scene**.
+
+
+
+Alternatively, you can create a new scene in the `asset` directory in the **Assets** panel by clicking the **+** button in the upper left corner and selecting **Scene**.
+
+
+
+## Creating Objects
+
+In the **Hierarchy** panel on the top left, right-click and select **Create -> 3D Object -> Cube**. Or you can just click the **+** button in the top left corner and select **3D Object -> Cube Cube**.
+
+
+
+A cube will be created and displayed in the **Scene** panel:
+
+
+
+## Adding Scripts
+
+- Create a new script
+
+ Right click in the **Assets** panel, select **Create -> TypeScript**, and name it "HelloWorld" to create a new script in the `asset` directory of **Assets** panel.
+
+ 
+
+- Adding code
+
+ Double-click the new script and it will be automatically opened in the script editor, provided that you specify the script editor in the editor menu bar under **Cocos Creator/File -> Preferences -> Program Manager -> Default Script Editor**.
+
+ Then add the `start()` function to the script. The `start()` function will be called when the component is activated for the first time and will output "Hello world".
+
+ ```ts
+ import { _decorator, Component, Node } from 'cc'; const { ccclass, property } = _decorator;
+
+ @ccclass('HelloWorld')
+ export class HelloWorld extends Component {
+ /* class member could be defined like this */
+ // dummy = '';
+
+ /* use `property` decorator if you want the member to be serializable */
+ // @property
+ // serializableDummy = 0;
+
+ start () {
+ // Your initialization goes here.
+ console.info('Hello world');
+ }
+
+ // update (deltaTime: number) {
+ // // Your update function goes here.
+ // }
+ }
+ ```
+
+- Binding Scripts
+
+ Select the created Cube node in the **Hierarchy** panel and click **Add Component -> Custom Script -> HelloWorld** at the bottom of the **Inspector** panel to mount the script to the Cube node. Alternatively, you can drag and drop the script directly into the **Inspector** panel.
+
+ 
+
+ > **Note**: remember to save the scene after setting it up.
+
+## Previewing the Scene
+
+Once the simple scene setup is done, you can click the **Play on Device** button on top of the editor to preview the game. Currently, previewing is supported using **Browser/Simulator**.
+
+
+
+Using the **Browser** preview as an example, Cocos Creator will run the current game scene with your default browser, as shown in the following image.
+
+
+
+Notice the output "Hello World" in the log message in the developer tools of the browser.
+
+## Modifying the Camera in the Scene
+
+In the preview we can see that the cube seems a bit too small, so we can adjust the area of the scene by adjusting the Camera in the scene, which represents the player's perspective in the game.
+
+- First, select the **Main Camera** node in the **Hierarchy** panel, and the **Scene** panel will display the transformation tool Gizmo and a small window with the player's perspective.
+
+ 
+
+- Then drag the Gizmo in the **Scene** panel or modify the **Position** property in the **Inspector** panel to make the cube in the player's view window more visible.
+
+ 
+
+- Then preview it again in the browser and you can see that the cube in the scene is now obvious.
+
+ 
diff --git a/versions/4.0/en/getting-started/helloworld/index/camera-position.png b/versions/4.0/en/getting-started/helloworld/index/camera-position.png
new file mode 100644
index 0000000000..71290c3aea
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/camera-position.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/camera.png b/versions/4.0/en/getting-started/helloworld/index/camera.png
new file mode 100644
index 0000000000..e7c1bb6662
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/camera.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/component.png b/versions/4.0/en/getting-started/helloworld/index/component.png
new file mode 100644
index 0000000000..29d9f6c39e
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/component.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/console.png b/versions/4.0/en/getting-started/helloworld/index/console.png
new file mode 100644
index 0000000000..20c5070816
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/console.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/console1.png b/versions/4.0/en/getting-started/helloworld/index/console1.png
new file mode 100644
index 0000000000..7f93df290c
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/console1.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/create-cube.png b/versions/4.0/en/getting-started/helloworld/index/create-cube.png
new file mode 100644
index 0000000000..eab97424f2
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/create-cube.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/create-scene.png b/versions/4.0/en/getting-started/helloworld/index/create-scene.png
new file mode 100644
index 0000000000..39ec8f1ec7
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/create-scene.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/create-typescript.png b/versions/4.0/en/getting-started/helloworld/index/create-typescript.png
new file mode 100644
index 0000000000..f0349c6e47
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/create-typescript.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/cube.png b/versions/4.0/en/getting-started/helloworld/index/cube.png
new file mode 100644
index 0000000000..bde3f255f6
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/cube.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/dashboard.png b/versions/4.0/en/getting-started/helloworld/index/dashboard.png
new file mode 100644
index 0000000000..bf08d6f37c
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/dashboard.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/debug.png b/versions/4.0/en/getting-started/helloworld/index/debug.png
new file mode 100644
index 0000000000..d2b9cc53d0
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/debug.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/editor-panel.png b/versions/4.0/en/getting-started/helloworld/index/editor-panel.png
new file mode 100644
index 0000000000..fed3beaa03
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/editor-panel.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/engine.png b/versions/4.0/en/getting-started/helloworld/index/engine.png
new file mode 100644
index 0000000000..1d53cbaa7e
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/engine.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/move.png b/versions/4.0/en/getting-started/helloworld/index/move.png
new file mode 100644
index 0000000000..223a276de5
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/move.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/new-empty.png b/versions/4.0/en/getting-started/helloworld/index/new-empty.png
new file mode 100644
index 0000000000..d425096f97
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/new-empty.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/new.png b/versions/4.0/en/getting-started/helloworld/index/new.png
new file mode 100644
index 0000000000..34a9d86506
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/new.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/preview.png b/versions/4.0/en/getting-started/helloworld/index/preview.png
new file mode 100644
index 0000000000..696d583850
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/preview.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/preview1.png b/versions/4.0/en/getting-started/helloworld/index/preview1.png
new file mode 100644
index 0000000000..f93ff322a1
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/preview1.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/run.png b/versions/4.0/en/getting-started/helloworld/index/run.png
new file mode 100644
index 0000000000..90de96d712
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/run.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/scene.png b/versions/4.0/en/getting-started/helloworld/index/scene.png
new file mode 100644
index 0000000000..1299117f00
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/scene.png differ
diff --git a/versions/4.0/en/getting-started/helloworld/index/script.png b/versions/4.0/en/getting-started/helloworld/index/script.png
new file mode 100644
index 0000000000..7d368327e5
Binary files /dev/null and b/versions/4.0/en/getting-started/helloworld/index/script.png differ
diff --git a/versions/4.0/en/getting-started/index.md b/versions/4.0/en/getting-started/index.md
new file mode 100644
index 0000000000..3aec7c6c0a
--- /dev/null
+++ b/versions/4.0/en/getting-started/index.md
@@ -0,0 +1,19 @@
+# Beginner's Guide
+
+Welcome to Cocos Creator. Before learning how to use it, please refer to the [Installing and Launching](install/index.md) documentation to install Cocos Creator.
+
+After installing the editor, it is important to become familiar with it, including how to create a project, the project structure, and the editor panels, by going through the following contents:
+
+- [Using Dashboard](dashboard/index.md)
+- [Project Structure](project-structure/index.md)
+- [Editor Panels](../editor/index.md)
+
+With some familiarity and understanding with the editor, it is easy to get familiar with the Cocos Creator development process with simple examples:
+
+- [Hello world!](helloworld/index.md)
+- [Quick start: Making your first game](first-game/index.md)
+
+Cocos Creator also provides a lot of examples and tutorials and supports other third-party tools and resources. Developers can also give feedback to the Cocos Creator development team directly by utilizing the following options:
+
+- [Getting Help and Support](support.md)
+- [Notes](attention/index.md)
diff --git a/versions/4.0/en/getting-started/install/index.md b/versions/4.0/en/getting-started/install/index.md
new file mode 100644
index 0000000000..5f2849c455
--- /dev/null
+++ b/versions/4.0/en/getting-started/install/index.md
@@ -0,0 +1,68 @@
+# Install and Launch
+
+Cocos Creator is equipped with a new Dashboard system which allows developers to upgrade and manage multiple versions of the engine and projects at the same time! Cocos Dashboard will serve as a unified downloader and launch portal for each Creator engine, making it easy to upgrade and manage multiple versions of Creator, as well as integrating a unified project management and creation dashboard, making it easy to work on projects with different versions of the engine at the same time.
+
+
+
+## Downloading Dashboard
+
+Download the Dashboard installation package by visiting the download link on the [Cocos Creator Product Page](https://www.cocos.com/en/creator-download).
+
+Double-click the installation package after downloading.
+
+### Installation Instructions for Windows
+
+The installer for Windows is an `.exe` executable file, usually named **CocosDashboard-vX.X.X-win32-20XXXXXX.exe**, where **vX.X.X** is the version number of Cocos Dashboard, such as v1.0.11. The string of numbers after it is the version date number.
+
+> **Notes**:
+> 1. If the version number installed on the current PC is the same as the version number of the installation package, the installation package with the same version number cannot be overwritten automatically, and it will be necessary to uninstall the previous version before continuing the installation.
+>
+> The default installation path of the application is `C:\CocosDashboard` and can be changed during the installation.
+>
+> 2. If there is an error about the digital signature of CAB file, please try to install with administrator privileges.
+>
+> 3. For some Windows PCs that are very old and have been on the intranet for a long time or have not been updated with OS patches for a long time, there may be some errors caused by missing dlls when running, try to install the system patch to solve: .
+>
+> 4. If the "Access Denied" pop-up window appears during installation, please make sure that the operating system installed on your machine is the official version of Microsoft, not a customized or streamlined third-party version.
+
+### Installation Instructions for MacOS
+
+The installer for Cocos Dashboard for MacOS is a `.dmg` file. Double-click the `.dmg` file, and drag and drop **CocosDashboard.app** into the **Applications** folder shortcut, or any other location. Then double-click the dragged **CocosDashboard.app** to get started.
+
+> **Notes**:
+> 1. If Dashboard doesn't open after downloading, it indicates that the `.dmg` or app file is corrupted, from an unknown developer, or contains malware, etc. Please right-click the `.dmg` or app file in the Finder and select **Open**, then click **Open** again in the pop-up dialog box. Then please go to **System Preferences -> Security & Privacy** and click **Open Anyway** so that it can be launched normally later.
+>
+> 2. If you get a "corrupted, can't open" message during the installation process, you need to check if there is any software like Xcode occupying the files in the Dashboard installation directory. If so, exit, then uninstall Dashboard and reinstall it.
+
+### Operating System Requirements
+
+The supported system environments for Cocos Dashboard are:
+
+- The minimum supported version of Mac OS X is OS X 10.9.
+- The minimum supported version of Windows is Windows 7 64-bit.
+
+## Running Cocos Dashboard
+
+On Windows, double-click the **CocosDashboard.exe** file in the `CocosDashboard` folder after unzipping to start Cocos Dashboard.
+
+On MacOS, double-click the dragged out **CocosDashboard.app** application icon to launch Cocos Dashboard.
+
+You can set a Quick Launch, Dock, or shortcut to the **CocosDashboard** app as desired.
+
+### Checking the Graphics Card Driver
+
+For some Windows operating systems and graphics card models, an error message such as the following may be encountered:
+
+```
+This browser does not support WebGL...
+```
+
+This is due to the editor relying on GPU rendering, which is not supported by the graphics card driver. If this happens, it can usually be fixed by making sure that the official driver for your graphics card is successfully installed.
+
+## Login with Cocos Developer Account
+
+When Cocos Dashboard is launched, the Cocos Developer Account login screen will appear. Once logged in, online services, product update notifications, and developer benefits will be available to use.
+
+To create a Cocos Developer account, sign up using the **Register** button on the login screen to go to the **Cocos Developer Center** or go directly to [this link](https://auth.cocos.com/#/sign_up/register?language=en) to register.
+
+Once registered, return to the Cocos Dashboard login screen and complete your login! After verifying your identity, we'll be in the Dashboard interface. In all cases, except for manual log out or expired login information, future logins will automatically occur with the saved information in the local session.
diff --git a/versions/4.0/en/getting-started/install/index/dashboard-editor.png b/versions/4.0/en/getting-started/install/index/dashboard-editor.png
new file mode 100644
index 0000000000..d5b0266a1e
Binary files /dev/null and b/versions/4.0/en/getting-started/install/index/dashboard-editor.png differ
diff --git a/versions/4.0/en/getting-started/install/index/language.png b/versions/4.0/en/getting-started/install/index/language.png
new file mode 100644
index 0000000000..94587fe7fe
Binary files /dev/null and b/versions/4.0/en/getting-started/install/index/language.png differ
diff --git a/versions/4.0/en/getting-started/install/index/path.png b/versions/4.0/en/getting-started/install/index/path.png
new file mode 100644
index 0000000000..4f3d854e81
Binary files /dev/null and b/versions/4.0/en/getting-started/install/index/path.png differ
diff --git a/versions/4.0/en/getting-started/install/index/startup.png b/versions/4.0/en/getting-started/install/index/startup.png
new file mode 100644
index 0000000000..83abb9fae5
Binary files /dev/null and b/versions/4.0/en/getting-started/install/index/startup.png differ
diff --git a/versions/4.0/en/getting-started/install/index/waiting.png b/versions/4.0/en/getting-started/install/index/waiting.png
new file mode 100644
index 0000000000..4b4c9c1cca
Binary files /dev/null and b/versions/4.0/en/getting-started/install/index/waiting.png differ
diff --git a/versions/4.0/en/getting-started/introduction/index.md b/versions/4.0/en/getting-started/introduction/index.md
new file mode 100644
index 0000000000..9365eced9e
--- /dev/null
+++ b/versions/4.0/en/getting-started/introduction/index.md
@@ -0,0 +1,93 @@
+# About Cocos Creator
+
+- **Q**: Is Cocos Creator a game engine?
+ **A**: It's a complete game development solution that includes a lightweight and efficient cross-platform game engine, and various UI tools that can help you develop games more quickly.
+
+- **Q**: What is the editor of Cocos Creator?
+ **A**: It is an all-in-one, extensible editor that simplifies resource management, game debugging and previewing, and multi-platform publishing. Support for Windows and Mac systems.
+
+- **Q**: I can't write programs, can I use Cocos Creator?
+ **A**: Of course! The Cocos Creator editor provides two workflows for design and development, allows designers to deeply participate in the game development process, making quick edits and iterations during the game development cycle, providing a simple and smooth way of working together.
+
+- **Q**: What platform can Cocos Creator let me develop for?
+ **A**: Cocos Creator supports all major platforms allowing games to be quickly released for the web, iOS, Android, Windows, Mac, and various mini-game platforms. A pure JavaScript-developed engine runtime is available on the web and mini-game platforms for better performance and smaller packages. On other native platforms, C++ is used to implement the underlying framework, providing greater operational efficiency.
+
+## What is Cocos Creator?
+
+Cocos Creator is a content creation-focused, scripted, component-based and data-driven game development tool. It features an easy-to-use content production workflow and a powerful developer tool suite for implementing game logic and high-performance game effects.
+
+## Workflow Description
+
+In the development stage, Cocos Creator has been able to bring great efficiency and creativity to users, but the workflow we offer goes far beyond the development. For a successful game, the entire workflow of development and debugging, commercial SDK integration, multi-platform release, testing, and launching is not only indispensable, but iterates through multiple iterations.
+
+
+
+Cocos Creator integrates the entire mobile browser game solution into the editor tool, eliminating the need to shuttle between multiple software applications. With the Cocos Creator editor open, a one-click automated process takes the least amount of time and effort to solve all the above questions. Developers can focus on the development phase and increase product competitiveness and creativity!
+
+### Creating or importing resources
+
+You can complete resource importing by dragging and dropping resources such as images, sounds, etc. into the editor's **Assets** panel.
+
+In addition, you can create scenes, prefabs, animations, scripts, particles and other resources directly within the editor.
+
+### Building scene
+
+After having some basic resources in the project, we can start to set up the scene. The scene is the most basic organization of the game content, and it is also the basic form of showing the game to the player.
+
+### Adding component scripts to implement interactive functions
+
+We can mount various built-in components and custom script components for the nodes in the scene to enable the game logic to run and interact. This includes from the most basic animation playback and button responses, to the main loop script that drives the entire game logic and the control of the player's character. Almost all game logic functions are implemented by mounting scripts to nodes in the scene.
+
+### One-click preview and release
+
+In the process of setting up the scene and developing functions, you can click to preview your work, at any time, to see the current scene running. Use your phone to scan the QR code and instantly preview the game on your phone. When the development comes to an end, the **Build** panel allows you to publish games to multiple platforms, including desktops, mobile phones, and the Web.
+
+## Features
+
+Highlights of Cocos Creator's features include:
+
+- Data properties can be adjusted at any time in the editor and can be easily declared in scripts. Designers can even adjust parameters without interfering with code.
+- UI system that support smart canvas adaptation and programming-free element alignment are perfectly adapted to device screens of any resolution.
+- An animation system that supports animated track preview and complex curve editing.
+- Scripting development using dynamic language support, you can use JavaScript to develop games, quickly preview and debug on physical machines and devices, and update your published games. TypeScript is also supported and can be mixed with your JavaScript code at the same time.
+- The underlying layer evolved from Cocos2d-x, and maintain lightweight and high performance of native level while enjoying the convenience of scripted development
+- Script componentization and an open plugin system provide developers with methods to customize workflows at different depths. The editor can be adjusted on a large scale to fit the needs of different teams and projects.
+- It comes with an easy-to-follow content production workflow and a powerful suite of developer tools for high-performance game creation.
+
+## Framework Structure
+
+Cocos Creator includes the full set of features required for game development such as the game engine, resource management, scene editing, game preview, game publishing, and integrates all functions and toolchain into one unified application.
+
+While providing a powerful and complete toolchain, the editor provides an open plug-in architecture that allows developers to easily extend the editor's functionality and allows customizations to personalize workflows using front-end common technologies such as HTML + JavaScript.
+
+Below is the technical architecture diagram of Cocos Creator
+
+
+
Figure 1
+
+
Figure 2
+
+As you can see from the figure, the editor is a development environment built on top of the Electron framework. The engine is responsible for providing many easy-to-use components and a unified interface for each platform.
+
+The combination of the engine and the editor brings the data-driven and componentized approach to functional development, as well as the perfect division of labor between the design and the program:
+
+- Designers build the visual presentation of game scenes in the editor
+- Programmers develop functional components that can be mounted to any object in the scene
+- The designer is responsible for mounting the components for objects that need to exhibit specific behavior and improving the parameters through debugging
+- The data structures and resources that programmers need to develop games
+- Designers configure various data and resources through a graphical interface
+- (From simple to complex, all kinds of workflows you can imagine can be implemented)
+
+Workflow-centric development concepts allow developers of different functions to quickly find work entry points that maximize their role, and fluently coordinate with other team members.
+
+## Instructions for use
+
+On the basis of data-driven workflow, the creation and editing of the scene becomes the focus of game development. The design work and functional development can be synchronized for seamless collaboration. Whether you're an artist, a designer, or a programmer, you can all click the **Preview** button at any point in the production process to test the latest state of the game in browser, mobile device simulators or physical device.
+
+Programmers and designers can now implement a wide range of division of labor, whether it is to build the scene first, then add functions, or to first produce functional modules and then combined debugging by designers, Cocos Creator can meet the needs of the development team. The properties defined in the script can be presented in the editor with the most appropriate visual experience to facilitate the content producer.
+
+Content resources outside the scene can be imported from outside, such as images, sounds, atlases, skeletal animations, etc. In addition, we are constantly improving the editor's production resources, including the currently completed animation editor, art people can use this tool to create very delicate and expressive animation resources, and can see the preview of the animation in the scene at any time.
+
+Supports both 2D and 3D game development with features that meet the specific needs of your various game types. Deep optimization of the editor experience and engine performance, and built-in support for middleware such as Spine, DragonBones, TiledMap, Box2D, and Texture Packer.
+
+Finally, the developed game can be published to each platform by one-click through a graphical tool, from design development to test release, Cocos Creator can handle everything for you.
diff --git a/versions/4.0/en/getting-started/introduction/structure-editor.png b/versions/4.0/en/getting-started/introduction/structure-editor.png
new file mode 100644
index 0000000000..c2356e5520
Binary files /dev/null and b/versions/4.0/en/getting-started/introduction/structure-editor.png differ
diff --git a/versions/4.0/en/getting-started/introduction/structure-engine.png b/versions/4.0/en/getting-started/introduction/structure-engine.png
new file mode 100644
index 0000000000..9d84d78813
Binary files /dev/null and b/versions/4.0/en/getting-started/introduction/structure-engine.png differ
diff --git a/versions/4.0/en/getting-started/introduction/work-flow.png b/versions/4.0/en/getting-started/introduction/work-flow.png
new file mode 100644
index 0000000000..8766798527
Binary files /dev/null and b/versions/4.0/en/getting-started/introduction/work-flow.png differ
diff --git a/versions/4.0/en/getting-started/project-structure/index.md b/versions/4.0/en/getting-started/project-structure/index.md
new file mode 100644
index 0000000000..780cf0a940
--- /dev/null
+++ b/versions/4.0/en/getting-started/project-structure/index.md
@@ -0,0 +1,67 @@
+# Project Structure
+
+Using the Dashboard, a new project can be created. `HelloWorld` is the classic first example. Once created, the project has a specific folder structure, and this structure can be used to get familiar with the Cocos Creator project folder structure.
+
+## Project Folder Structure
+
+After creating and opening a Cocos Creator project for the first time, the developer project folder will have the following structure.
+
+
+
+- `assets`: the assets directory
+
+- `build`: build directory (generated after building a platform)
+
+- `library`: directory of imported assets
+
+- `local`: log files directory
+
+- `profiles`: editor configuration
+
+- `temp`: temporary files directory
+
+- `package.json`: project configuration
+
+### `assets`
+
+`assets` is used to hold all local assets, scripts, and third-party library files in the game. Only the contents of the `assets` directory will be displayed in the **Assets** panel. Each file in `assets` generates a `.meta` file with the same name after importing the project, which is used to store the corresponding asset configuration and index information. The `.meta` file needs to be submitted to the version control system as well, please review the [Asset Management Notes --- meta Files](../../asset/meta.md) documentation.
+
+Project or design source files generated by some third-party tools, such as `.tps` files for TexturePacker, or `.psd` files for Photoshop, can optionally be managed outside of `assets`.
+
+### `build`
+
+After publishing a project using the default publish path through **Project -> Build** in the editor main menu, the editor will create a `build` directory under the project path and store all builds for the target platform.
+
+### `library`
+
+The `library` is generated by importing the assets from `assets`, where the structure of the files and the format of the assets will be processed into the form needed for the final game release.
+
+When `library` is lost or corrupted, just delete the whole `library` folder and open the project again, and the repository will be regenerated.
+
+### `local`
+
+The `local` folder contains configuration information for the project on the local machine, including the editor panel layout, window size, location, and other information. Developers do not need to care about the contents here.
+
+### `profiles`
+
+The `profiles` folder contains configuration information for the editor, including build configuration information for each target platform, scene configuration information, etc.
+
+### `extensions`
+
+The `extensions` folder is used to place custom extensions for this project. To install extensions manually, create this folder manually. To uninstall the extensions, just delete the corresponding folder in `extensions`.
+
+### `settings`
+
+`settings` contains project-specific settings, such as configuration information in the **Project Settings** panel. To synchronize project settings between developers, please add the settings directory to version control.
+
+### `temp`
+
+`temp` is a temporary folder for caching some of Cocos Creator's temporary files locally. This folder can be deleted manually after closing Cocos Creator, and developers don't need to care about the contents.
+
+### `package.json`
+
+The `package.json` file, together with the `assets` folder, serves as a flag to verify the legitimacy of a Cocos Creator project, and only folders that include these two contents can be opened as Cocos Creator projects. Developers don't need to care about the contents inside.
+
+## Version control
+
+Cocos Creator automatically generates `.gitignore` files when a new project is created to exclude files that should not be committed to the git repository. If using another version control system, or if needing to commit the project elsewhere, be careful to only commit `assets`, `extensions`, `settings`, `package.json`, and any other manually added files associated with the project.
diff --git a/versions/4.0/en/getting-started/project-structure/index/project-file.png b/versions/4.0/en/getting-started/project-structure/index/project-file.png
new file mode 100644
index 0000000000..4a1db43820
Binary files /dev/null and b/versions/4.0/en/getting-started/project-structure/index/project-file.png differ
diff --git a/versions/4.0/en/getting-started/support.md b/versions/4.0/en/getting-started/support.md
new file mode 100644
index 0000000000..22aa35b966
--- /dev/null
+++ b/versions/4.0/en/getting-started/support.md
@@ -0,0 +1,43 @@
+# Get Help and Support
+
+## Official Medias
+
+More engine news, quality tutorials, and interviews can be viewed at [](https://twitter.com/cocos2dx), [](https://www.facebook.com/cocos2dx/) or [](https://www.youtube.com/c/CocosEngine/videos).
+
+## Send Issues and Feedbacks
+
+Apart from the information provided in this guide, you can also obtain information from or send feedback to the Cocos team through the following channels at any time:
+
+- [Cocos Forum](https://discuss.cocos2d-x.org)
+- [Cocos Support](https://www.cocos.com/en/assistant)
+
+- [Submit PR for Cocos Engine on GitHub](../submit-pr/submit-pr.md)
+- [Submit Issues for Cocos Engine on GitHub](https://github.com/cocos/cocos4/issues/new/choose)
+
+## Third-party tools you may need
+
+### Code IDE
+
+- [VS Code](https://code.visualstudio.com/) Recommended coding environment for Cocos Creator.
+- [WebStorm](https://www.jetbrains.com/webstorm/)
+
+### Tools for texture atlas
+
+- [TexturePacker](https://www.codeandweb.com/texturepacker)
+
+### Tools for Bitmap font
+
+- [Glyph Designer](https://71squared.com/glyphdesigner)
+- [Hiero](https://github.com/libgdx/libgdx/wiki/Hiero)
+- [BMFont (Windows)](http://www.angelcode.com/products/bmfont/)
+
+### Tools for 2D skeleton animation
+
+- [Spine](http://www.esotericsoftware.com)
+- [Spriter](http://brashmonkey.com/)
+- [DragonBones](http://dragonbones.github.io/)
+
+### Tools for 2D particles
+
+- [Particle Designer](http://particledesigner.71squared.com/)
+- [Particle2dx](http://www.effecthub.com/particle2dx): Free online tool
diff --git a/versions/4.0/en/getting-started/support/facebook.png b/versions/4.0/en/getting-started/support/facebook.png
new file mode 100644
index 0000000000..180e1ab928
Binary files /dev/null and b/versions/4.0/en/getting-started/support/facebook.png differ
diff --git a/versions/4.0/en/getting-started/support/twitter.png b/versions/4.0/en/getting-started/support/twitter.png
new file mode 100644
index 0000000000..041a887987
Binary files /dev/null and b/versions/4.0/en/getting-started/support/twitter.png differ
diff --git a/versions/4.0/en/getting-started/support/youtube.png b/versions/4.0/en/getting-started/support/youtube.png
new file mode 100644
index 0000000000..180d6fa823
Binary files /dev/null and b/versions/4.0/en/getting-started/support/youtube.png differ
diff --git a/versions/4.0/en/glossary/index.md b/versions/4.0/en/glossary/index.md
new file mode 100644
index 0000000000..c651ef8084
--- /dev/null
+++ b/versions/4.0/en/glossary/index.md
@@ -0,0 +1,108 @@
+# Glossary
+
+In this chapter, we will collect and explain some glossaries and abbreviations in or related in Cocos Creator.
+
+## Contact us
+
+If you find any unexplained or poorly described glossaries, please send us feedback by clicking the "Have Feedback?" button on the right side of this page or [Get Help and Support](../getting-started/support.md).
+
+## Editor
+
+| Glossary | Description |
+| :--- | :--- |
+| Editor | Usually refers to the editor interface of Cocos Creator |
+| Gizmo | Some controllers in the scene editor, such as for adjusting the position, rotation, scaling, or lighting of nodes, etc. |
+
+## Graphs
+
+| Glossary | Description |
+| :--- | :--- |
+| VB, Vertex Buffer | A vertex buffer is a set of vertices in a model, often described as an array, where each element of the array is a composite structure, including properties such as Position, Texture-coordinate, Color or Normal. |
+| IB, Index Buffer | Index Buffer, which stores the indexes of the vertices in the above VB, through which the specific geometry is combined, example: If VB is \{ (0, 0, 0), (1, 0, 0), (1, 1, 0) \}, IB is [0, 2, 1], then the vertices of the triangle are drawn as follows: \{ VB[0], VB[2], VB[1] \} |
+| FPS | Frame rate, the number of renderings per second. |
+| Layer | refers to the grouping of nodes when rendering, and the [Visibility property of the camera](../editor/components/camera-component.md#camera-group-rendering) can be used to handle whether certain nodes are rendered by the camera. |
+| LOD | Level of details,which improves rendering efficiency by having models with different levels of details at different levels. |
+
+### Illumination
+
+| Glossary | Description |
+| :--- | :--- |
+| GI, Global Illumination | Global illumination, or local illumination, refers to a set of algorithms used in computer graphics to calculate and simulate realistic light sources |
+| LDR | Low Dynamic Range Light, usually refers to the color range of a single color between [0,255] (integer) or [0,1.0] (floating point), which is the color space that most display devices can display.|
+| HDR | High Dynamic Range Light refers to colors whose color gamut is outside of the color space described in the above article. The colors in the display are likely to be outside of this color range, so they need to be converted to a region recognizable by the display using **Tone Mapping** when displayed on the display device.|
+
+## 2D/UI
+
+| Glossary | Description |
+| :--- | :--- |
+| 2D Object | A 2D object created by a right-click menu within the **Hierarchy Manager**.
+| UI Object | A UI object created by the **Hierarchy Manager** right-click menu, usually encapsulating some UI element for interaction |
+| Sprite Atlas | [Atlas](../asset/atlas.md), which is used to improve rendering efficiency by combining some pieces into a single large image, and the engine provides [auto-atlas](../asset/auto-atlas.md) function |
+
+## Animation
+
+| Glossary | Description |
+| :--- | :--- |
+| Spine | A 2D animation software whose output animation files can be recognized by Cocos Creator |
+| DragonBone | A 2D animation software whose output animation files can be recognized by Cocos Creator |
+| DragonBone | A 2D animation software whose output animation files can be recognized by Cocos Creator.
+| Animation | Animation, the engine's built-in animation, no skinning, support for different nodes can be created through the editor animation function, [more](../animation/index.md)
+| SkeletalAnimation | SkeletalAnimation, animation component with skinning, [more](../animation/skeletal-animation.md) |
+| Marionette | An animation system that supports user-defined state maps, and SkeletalAnimation for rich functionality, [more](../animation/marionette/index.md) |
+
+## Physical
+
+| Glossary | Description |
+| :--- | :--- |
+| Force | The force that allows an object to move linearly |
+| Torque | the force that makes an object rotate |
+
+### 2D Physics
+
+| Glossary | Description |
+| :--- | :--- |
+| Physics backends | The type of physics engine that the engine is wrapped in, the two types of physics backends provided by Cocos Creator are **Built-In** and **Box2D** |
+| Box2D | Box2D is a well-known and efficient 2D physics engine |
+| Rigid bodies | Define objects with mass that can be affected by forces and velocities, and are usually of four types: kinematic, dynamic, static and animated.|
+| Joint2D | Physics joints are used to describe the physical connections between objects.|
+| Physical Materials | Physical materials for adjusting the handling of friction and elasticity when two physical colliding bodies collide.|
+
+### 3D Physics
+
+| Glossary | Description |
+| :--- | :--- |
+| Physics Backend | The type of physics engine that the engine encapsulates. Cocos Creator provides several physics engines including: **Built-In**, **Bullet**, **PhysX** and **cannon.js** etc., which can be modified in the project settings to adapt to different platforms and situations, **Note**: The engine unifies most of the physics engine differences. However, some physics specific are only supported in specific physics backends. |
+| Rigid body | Defines an object with mass that can be affected by forces and velocities, usually of three types: kinematic, dynamic, and static. |
+| Constraint | A physical constraint that describes the physical connection between objects.
+| Physical materials | Adjusts the handling of frictional and elastic forces when two physical colliding objects collide. |
+| Force | The force that allows the object to move linearly. |
+| Torque | Torque, the force that makes the object rotate |
+
+## Asset System
+
+| Glossary | Description |
+| :--- | :--- |
+| Bundle, Asset Bundle | A way of handling resources, where the engine algorithmically combines one or more resources into a single file (usually some kind of compressed file) for efficient storage and downloading |
+| Resources | A special directory that the engine packages into a special bundle, which is loaded via methods such as `Resources.load` |
+| Cocos Store | Cocos' resource store, where developers can sell and buy assets, source code, or complete commercial games |
+
+## Scripting and Programming
+
+| Glossary | Description |
+| :--- | :--- |
+| Component | A script class than inherits from `cc.Component`, and can be attach to a `cc.Node`. |
+| Events | Cocos Creator based on [Web Event Standard](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events) implemented as an event system for responding to hardware input or communication between nodes, [more](../engine/event/index.md). |
+
+## Native Development
+
+| Glossary | Description |
+| :--- | :--- |
+| Native | Refers to the ability provided by Cocos Creator to run on any desktop native platform or mobile native platform without relying on a browser |
+| CMake | A file format or tool for organizing C++ code |
+
+## Other Features
+
+| Glossary | Description |
+| :--- | :--- |
+| XR | Extended Reality. Cocos Creator extensions adapted to OpenXR can assist you in creating added reality features, [more](../xr/index.md). |
+| AR | Augmented reality. Technology that connects the virtual world with reality, you can use Cocos Creator to implement your own AR applications. [more](../xr/index.md).|
diff --git a/versions/4.0/en/graphics-backend/overview.md b/versions/4.0/en/graphics-backend/overview.md
new file mode 100644
index 0000000000..f0cd7ff83a
--- /dev/null
+++ b/versions/4.0/en/graphics-backend/overview.md
@@ -0,0 +1,15 @@
+# Overview
+
+Graphics backend is the native graphics API implementation of interface of GFX. Cocos creator supports:
+
+- Native
+ - GLES2
+ - GLES3
+ - Vulkan
+ - Metal
+ - NVN
+ - WebGPU on WASM
+
+- Web/MiniGames
+ - WebGL
+ - WebGL2.0
diff --git a/versions/4.0/en/guide/unity/index.md b/versions/4.0/en/guide/unity/index.md
new file mode 100644
index 0000000000..d3ff5c1453
--- /dev/null
+++ b/versions/4.0/en/guide/unity/index.md
@@ -0,0 +1,354 @@
+# Cocos Creator Quick Guide for Unity Developers
+
+With the increasing variety of game platforms and portals, developers want to be able to write their games once and publish them multiple times to different platforms and portals, and Cocos Creator is a great way to fulfill this need.
+
+In this article, we will compare the following perspectives from a Unity developer's point of view to help Unity developers quickly get started with the Cocos Creator engine.
+
+- Installation and Versioning
+- Editors
+- Editor Workflow
+- Scripting and Debugging
+- Shaders
+
+## Installation and Versioning
+
+The Unity Hub can be used to manage Unity's editor versions, projects, and templates. In Cocos Creator, you can also manage the engine, projects, and templates via the [Cocos Dash Board](https://www.cocos.com/creator-download).
+
+| Unity Hub | Cocos Dashboard |
+| :-- | :-- |
+|  |  |
+
+You can also find a large selection of extensions, resources and source code in the Store page, as well as more material to learn in the Learn page.
+
+## Editor
+
+As a Unity developer, you can seamlessly use Cocos Creator's editor in most cases, and they have a similar editor layout and usage.
+
+| Unity Editor | Cocos Creator Editor |
+| :-- | :-- |
+|  | 
+
+A slight difference is that Cocos Creator, because it is developed in Electronic+Chromium, allows you to both preview the game in a browser and run it directly in the editor.
+
+## Workflows
+
+Cocos Creator's 2D and 3D workflows are similar to Unity's, as you can read [Scene Creation Workflow](../../concepts/scene/index.md) to see Cocos Creator's workflow.
+
+### Texture Assets
+
+Importing texture assets is similar to Unity.
+
+| Unity | Cocos |
+| :-- | :-- |
+| | |
+
+Global texture compression can also be configured in the project settings
+
+
+
+### Models and animations
+
+Importing FBX in Cocos Creator is the same as Unity, just drag and drop or copy the files into the Assets directory of your project.
+
+| Unity | Cocos |
+| :-- | :-- |
+| | |
+
+Cocos Creator also supports glTF format files, as well as standard materials for DCC tools such as Maya and 3DMax.
+
+### Spine Animations
+
+Cocos Creator has a built-in Spine animation component, which you can use directly through the `spine.Skeleton` component.
+
+### Animation and State machine
+
+Cocos Creator supports keyframe animations, skeletal animations.You can edit and preview these animations directly in the editor.
+
+
+
+Similar to Unity's Animator, Cocos Creator supports the editing of animation state machines, which you can find in the [Marionette Animation System](../../animation/marionette/index.md).
+
+
+
+### Music and sound effects
+
+Cocos Creator also supports Audio Source components for playing music and sound effects.
+
+
+
+### Assets Package
+
+Similar to Unity, Cocos Creator supports co-development by importing assets packages from the outside of the editor.
+
+| Unity | Cocos |
+| :-- | :-- |
+| | |
+
+### Build and Publish
+
+In addition to being published on various native platforms like Unity, Cocos Creator also supports publishing on small game platforms such as WeChat Small Games and TikTok Small Games.
+
+| Unity | Cocos |
+| :-- | :-- |
+| | |
+
+## Scripting and Debugging
+
+Unlike Unity's GameObject, in Cocos Creator the entities in the scene are named Node, but similar to Unity, Cocos Creator is an ECS (Entity-Component-System) architecture, and you can add different components to a Node to realize the functionality of the game.
+
+
+
+### Component Lifecycle
+
+Similar to Unity, Cocos Creator's components have their own lifecycle. The system facilitates the developer's business logic by calling back registered methods within the component.
+
+
+
+### Writing Custom Components
+
+In Unity, we inherit from Monobehavior to implement our own game scripts.
+
+```csharp
+public class Player : NetworkBehaviour
+{
+ Animation _animation;
+
+ Start(){
+
+ _animation = gameObject.GetComponent();
+ }
+}
+```
+
+Cocos Creator uses Typescript to write scripts.
+
+The following example shows how to implement a custom component using Typescript.
+
+```ts
+@ccclass('MotionController')
+export class MotionController extends Component {
+
+ animation: SkeletalAnimation;
+
+ start() {
+
+ this.animation = this.getComponent(SkeletalAnimation);
+ }
+}
+```
+
+C# and Typescript are both programming languages developed by Microsoft and their ease of use is similar.
+
+### Debugging and Logging
+
+#### Logging Debugging
+
+To use logging in Unity we can use the `Debug.Log` method.
+
+To use logging in Cocos Creator, you can either use js's log printing `console.log()` or Cocos Creator's logging methods:
+
+```ts
+cc.log()
+cc.debug()
+cc.error()
+```
+
+#### Breakpoint Debugging
+
+Unity can be debugged at breakpoints using Visual Studio or VSCode.
+
+Cocos Creator uses VSCode or developer tools directly in the browser.
+
+
+
+## Material and shader writing
+
+### Materials
+
+Cocos Creator materials have a similar preview and properties panel to Unity materials.
+
+| Unity | Cocos |
+| :-- | :-- |
+| | |
+
+Unlike Unity, Cocos Creator makes it easier to view and define the state of the rendering in the pipeline in materials.
+
+
+
+### Shaders
+
+Unlike Unity, which supports CG, GLSL, and HLSL, Cocos Creator only supports GLSL as a shader programming language.
+
+The table below compares the file formats they use and the differences in DSL.
+
+| | Unity | Cocos |
+| :--- | :--- | :--- |
+| File Format | *.shader | *.effect |
+| DSL | Cg/HLSL/GLSL + Unity Shader Format | GLSL + Yaml |
+
+Unity uses a custom shader file as the DSL, while Cocos creator uses Yaml as the DSL file format.
+
+#### Shader syntax rules
+
+Unity Shader syntax rules.
+
+```shader
+Shader "Transparent/Cutout/DiffuseDoubleside" {
+Properties {
+ _Color ("Main Color", Color) = (1,1,1,1)
+ _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
+ _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
+}
+
+SubShader {
+ Tags {"IgnoreProjector"="True" "RenderType"="TransparentCutout"}
+ LOD 200
+ Cull Off
+
+CGPROGRAM
+#pragma surface surf Lambert alphatest:_Cutoff
+
+sampler2D _MainTex;
+float4 _Color;
+
+struct Input {
+ float2 uv_MainTex;
+};
+
+void surf (Input IN, inout SurfaceOutput o) {
+ half4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
+ o.Albedo = c.rgb;
+ o.Alpha = c.a;
+}
+ENDCG
+}
+
+Fallback "Transparent/Cutout/VertexLit"
+}
+
+```
+
+Cocos Creator Shader syntax rules:
+
+```
+// Effect Syntax Guide: https://github.com/cocos-creator/docs-3d/blob/master/zh/material-system/effect-syntax.md
+
+CCEffect %{
+ techniques:
+ - name: opaque
+ passes:
+ - vert: general-vs:vert # builtin header
+ frag: unlit-fs:frag
+ properties: &props
+ mainTexture: { value: white }
+ mainColor: { value: [1, 1, 1, 1], editor: { type: color } }
+ - name: transparent
+ passes:
+ - vert: general-vs:vert # builtin header
+ frag: unlit-fs:frag
+ blendState:
+ targets:
+ - blend: true
+ blendSrc: src_alpha
+ blendDst: one_minus_src_alpha
+ blendSrcAlpha: src_alpha
+ blendDstAlpha: one_minus_src_alpha
+ properties: *props
+}%
+
+CCProgram unlit-fs %{`
+ precision highp float;
+ #include