From 2e80ec3478fe2e418322b95032dadf529fa4d103 Mon Sep 17 00:00:00 2001 From: CreatorADOfficial Date: Wed, 22 Jul 2026 16:23:15 +0000 Subject: [PATCH] Automated Extension submission for issue #2197 --- extensions/community/Extra3D.json | 6763 +++++++++++++++++++++++++++++ 1 file changed, 6763 insertions(+) create mode 100644 extensions/community/Extra3D.json diff --git a/extensions/community/Extra3D.json b/extensions/community/Extra3D.json new file mode 100644 index 000000000..98142c01e --- /dev/null +++ b/extensions/community/Extra3D.json @@ -0,0 +1,6763 @@ +{ + "author": "", + "category": "Advanced", + "dimension": "3D", + "extensionNamespace": "", + "fullName": "Extra 3D", + "gdevelopVersion": "", + "helpPath": "", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyMy4wLjMsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iSWNvbnMiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgMzIgMzIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDMyIDMyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCS5zdDB7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9DQo8L3N0eWxlPg0KPHBhdGggY2xhc3M9InN0MCIgZD0iTTMxLDE2LjVjMCwwLTYuNyw5LjUtMTUsOS41UzEsMTYuNSwxLDE2LjVTNy43LDcsMTYsN1MzMSwxNi41LDMxLDE2LjV6Ii8+DQo8cG9seWdvbiBjbGFzcz0ic3QwIiBwb2ludHM9IjE2LDEwIDEwLDEzIDE2LDE2IDIyLDEzICIvPg0KPHBvbHlsaW5lIGNsYXNzPSJzdDAiIHBvaW50cz0iMTAsMTMgMTAsMjAgMTYsMjMgMjIsMjAgMjIsMTMgIi8+DQo8bGluZSBjbGFzcz0ic3QwIiB4MT0iMTYiIHkxPSIxNiIgeDI9IjE2IiB5Mj0iMjMiLz4NCjwvc3ZnPg0K", + "name": "Extra3D", + "previewIconUrl": "https://asset-resources.gdevelop.io/public-resources/Icons/Line Hero Pack/Master/SVG/Virtual Reality/8c2a80cffaac5417716dd0015399ff2934d97a3f65b6d7f2e2d0cd1355655d2a_Virtual Reality_3d_vision_vr.svg", + "shortDescription": "Adds Lots Of Options For Modifying, Getting 3D Objects Data.", + "version": "0.1.0", + "description": [ + "World Settings:", + "- Tone Mapping", + "", + "Debug", + "- Show Wireframe", + "", + "Mesh", + "- Move Mesh", + "- Rotate Mesh", + "- Size Mesh", + "- 3D Object On Screen (Condition)", + "- Merge Objects", + "- Delete Mesh", + "- Delete All Mesh", + "- Simplify Model", + "- Mesh Optimise", + "- Vertices Optimise", + "- Remove Invis Triangle", + "- Optimise Faces", + "- Mesh Deformer", + "- Mesh Splitting", + "", + "Terrain", + "- Create Clouds", + "- Create Terrain (One Colour)", + "- Create Textured Terrain", + "- Create Water", + "- Create Mountains", + "- Create Grass", + "- Create Path", + "- Create Light", + "- Skybox Render", + "- Skybox Time Cycle Render", + "- Delete Cloud", + "- Delete Water", + "- Delete Terrain", + "", + "Appearance", + "- Replace Model Material", + "- Tint Material", + "- Replace Model Texture", + "- Change Opacity", + "- Tint 3D Model", + "- Texture Resolution", + "- Texture Remesh", + "- Change material", + "", + "Information:", + "- Model File Size", + "- UV Count", + "- MemoryUsage", + "- Material Count", + "- Vertices Count", + "- TriangleCount", + "- Mesh Name lnside Group", + "- Mesh Name", + "- Mesh Count", + "- GLB Name", + "", + "More Updates Would Be Committed To This Extension." + ], + "tags": [ + "Simplify", + "Mesh", + "3D", + "Optimize", + "Extra", + "Tool" + ], + "authorIds": [ + "LmDPcZ5ey4WWF4VdoEQcmPVTmFu2" + ], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [], + "eventsFunctions": [ + { + "description": "Gets Mesh Count Of Models.", + "fullName": "Get Mesh Count", + "functionType": "Expression", + "group": "Information", + "name": "MeshCount", + "sentence": "Get Mesh Count", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = eventsFunctionContext.getObjects(\"Model\")[0];", + "const root = object.get3DRendererObject();", + "", + "let count = 0;", + "", + "root.traverse((child) => {", + " if (child.isMesh) count++;", + " });", + "", + " eventsFunctionContext.returnValue = count;" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "3D Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + } + ], + "objectGroups": [] + }, + { + "description": "Gets The Mesh Name In Models.", + "fullName": "Get Mesh Name", + "functionType": "StringExpression", + "group": "Information", + "name": "MeshName", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Model\");", + "", + "if (objects.length === 0) {", + " eventsFunctionContext.returnValue = \"\";", + " return;", + " }", + "", + " const root = objects[0].get3DRendererObject();", + "", + " const meshes = [];", + "", + " root.traverse((child) => {", + " if (child.isMesh || child.isSkinnedMesh) {", + " meshes.push(child);", + " }", + " });", + "", + " const index = Math.floor(eventsFunctionContext.getArgument(\"MeshID\")) - 1;", + "", + " if (index >= 0 && index < meshes.length) {", + " let name = meshes[index].name || \"\";", + "", + " //replace", + " if (name.toLowerCase().startsWith(\"mesh\")) {", + " name = \"Group \" + (index + 1);", + " }", + "", + " eventsFunctionContext.returnValue = name;", + " } else {", + " eventsFunctionContext.returnValue = \"\";", + " }" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "string" + }, + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + }, + { + "description": "Mesh ID", + "name": "MeshID", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Gets Mesh Inside a Group.", + "fullName": "Get Mesh Inside Group", + "functionType": "StringExpression", + "group": "Information", + "name": "MeshNameInsideGroup", + "sentence": "Get Mesh Inside Group", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Model\");", + "", + "if (objects.length === 0) {", + " eventsFunctionContext.returnValue = \"\";", + " return;", + " }", + "", + " const root = objects[0].get3DRendererObject();", + "", + " const groupName = eventsFunctionContext.getArgument(\"GroupName\");", + " const meshID = Number(eventsFunctionContext.getArgument(\"MeshID\"));", + "", + "", + " // Find path including Groups and Bones", + " function findPath(object, path) {", + " if (!path) return object;", + "", + " const parts = path.split(\"/\");", + " let current = object;", + "", + " for (let i = 0; i < parts.length; i++) {", + " let found = null;", + "", + " current.children.forEach((child) => {", + "", + " // Treat Bones like Groups", + " if (", + " child.name &&", + " child.name.toLowerCase() === parts[i].toLowerCase() &&", + " (child.isGroup || child.isBone || child.type === \"Object3D\")", + " ) {", + " found = child;", + " }", + "", + " });", + "", + " if (!found) {", + " return null;", + " }", + "", + " current = found;", + " }", + "", + " return current;", + " }", + "", + "", + " const target = findPath(root, groupName);", + "", + " if (!target) {", + " console.log(\"Not found:\", groupName);", + " eventsFunctionContext.returnValue = \"\";", + " return;", + " }", + "", + "", + " console.log(\"Found:\", target.name, target.type);", + "", + "", + " const meshes = [];", + "", + "", + " // Search meshes inside Group or Bone", + " target.traverse((child) => {", + "", + " if (child.isMesh || child.isSkinnedMesh) {", + " meshes.push(child);", + " }", + "", + " });", + "", + "", + " console.log(\"Meshes found:\", meshes.length);", + "", + "", + " if (meshID >= 0 && meshID < meshes.length) {", + "", + " let name = meshes[meshID].name || \"\";", + "", + " // Friendly names for auto-generated mesh names", + " if (name.toLowerCase().startsWith(\"mesh\")) {", + " name = \"Group \" + (meshID + 1);", + " }", + "", + " eventsFunctionContext.returnValue = name;", + "", + " } else {", + "", + " eventsFunctionContext.returnValue = \"\";", + "", + " }" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "string" + }, + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + }, + { + "description": "Group Name", + "longDescription": "Use this template for getting groups, body/arm or body/torso which would look for meshes inside the group body and inside body, arm group.", + "name": "GroupName", + "type": "string" + }, + { + "description": "Mesh ID", + "name": "MeshID", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Gets The Triangle Count Of Models.", + "fullName": "Get Tringle Count", + "functionType": "Expression", + "group": "Information", + "name": "TriangleCount", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Model\");", + "", + "if (objects.length === 0) {", + " eventsFunctionContext.returnValue = 0;", + " return;", + " }", + "", + " const root = objects[0].get3DRendererObject();", + "", + " let triangles = 0;", + "", + " root.traverse((child) => {", + " if (child.isMesh || child.isSkinnedMesh) {", + "", + " const geometry = child.geometry;", + "", + " if (geometry.index) {", + " // Indexed geometry", + " triangles += geometry.index.count / 3;", + " } else if (geometry.attributes.position) {", + " // Non-indexed geometry", + " triangles += geometry.attributes.position.count / 3;", + " }", + "", + " }", + " });", + "", + " eventsFunctionContext.returnValue = Math.floor(triangles);" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + } + ], + "objectGroups": [] + }, + { + "description": "Gets The Vertices Count In Models.", + "fullName": "Get Vertices Count", + "functionType": "Expression", + "group": "Information", + "name": "VerticesCount", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Model\");", + "", + "if (objects.length === 0) {", + " eventsFunctionContext.returnValue = 0;", + " return;", + " }", + "", + " const root = objects[0].get3DRendererObject();", + "", + " let vertices = 0;", + "", + " root.traverse((child) => {", + " if (child.isMesh || child.isSkinnedMesh) {", + "", + " const geometry = child.geometry;", + "", + " if (geometry && geometry.attributes.position) {", + " vertices += geometry.attributes.position.count;", + " }", + "", + " }", + " });", + "", + " eventsFunctionContext.returnValue = vertices;" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + } + ], + "objectGroups": [] + }, + { + "description": "Get Material/Textures Count In Models.", + "fullName": "Get Material Count", + "functionType": "Expression", + "group": "Information", + "name": "MaterialCount", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Model\");", + "", + "if (objects.length === 0) {", + " eventsFunctionContext.returnValue = 0;", + " return;", + " }", + "", + " const root = objects[0].get3DRendererObject();", + "", + " const materials = new Set();", + "", + " root.traverse((child) => {", + " if (child.isMesh || child.isSkinnedMesh) {", + "", + " if (Array.isArray(child.material)) {", + " child.material.forEach((mat) => {", + " materials.add(mat.uuid);", + " });", + " } else if (child.material) {", + " materials.add(child.material.uuid);", + " }", + "", + " }", + " });", + "", + " eventsFunctionContext.returnValue = materials.size;" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + } + ], + "objectGroups": [] + }, + { + "description": "Texture Memory Usage, Or VRAM In Megabytes.", + "fullName": "Texture Memory Usage", + "functionType": "Expression", + "group": "Information", + "name": "MemoryUsage", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Model\");", + "", + "if (objects.length === 0) {", + " eventsFunctionContext.returnValue = 0;", + " return;", + " }", + "", + " const root = objects[0].get3DRendererObject();", + "", + " let bytes = 0;", + "", + " root.traverse((child) => {", + " if (child.isMesh || child.isSkinnedMesh) {", + "", + " const geometry = child.geometry;", + "", + " if (geometry) {", + "", + " // Vertex attributes", + " for (const key in geometry.attributes) {", + " const attribute = geometry.attributes[key];", + "", + " bytes += attribute.array.byteLength;", + " }", + "", + " // Index buffer", + " if (geometry.index) {", + " bytes += geometry.index.array.byteLength;", + " }", + " }", + " }", + " });", + "", + "", + " //return MB", + " const megabytes = bytes / (1024 * 1024);", + "", + " eventsFunctionContext.returnValue = Number(megabytes.toFixed(2));" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + } + ], + "objectGroups": [] + }, + { + "description": "Gets The UV Count In Models.", + "fullName": "Get UV Count", + "functionType": "Expression", + "group": "Information", + "name": "UVCount", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Model\");", + "", + "if (objects.length === 0) {", + " eventsFunctionContext.returnValue = 0;", + " return;", + " }", + "", + " const root = objects[0].get3DRendererObject();", + "", + " let uvCount = 0;", + " const channels = new Set();", + "", + " root.traverse((child) => {", + "", + " if (child.isMesh || child.isSkinnedMesh) {", + "", + " const geometry = child.geometry;", + "", + " if (geometry && geometry.attributes) {", + "", + " if (geometry.attributes.uv) {", + " channels.add(\"uv\");", + " }", + "", + " if (geometry.attributes.uv2) {", + " channels.add(\"uv2\");", + " }", + "", + " }", + "", + " }", + "", + " });", + "", + " uvCount = channels.size;", + "", + " eventsFunctionContext.returnValue = uvCount;" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + } + ], + "objectGroups": [] + }, + { + "description": "Applies Tint To 3D Models.", + "fullName": "Tint 3D Model", + "functionType": "Action", + "group": "Appearance", + "name": "Tint3DModel", + "sentence": "Tint 3D Model _PARAM1_,_PARAM3_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Model\");", + "", + "if (objects.length === 0) {", + " return;", + " }", + "", + " const root = objects[0].get3DRendererObject();", + "", + " const colorString = eventsFunctionContext.getArgument(\"Color\");", + "", + " ", + " const rgb = colorString.split(\";\").map(Number);", + "", + " const r = rgb[0] / 255;", + " const g = rgb[1] / 255;", + " const b = rgb[2] / 255;", + "", + " root.traverse((child) => {", + "", + " if (child.isMesh || child.isSkinnedMesh) {", + "", + " const materials = Array.isArray(child.material)", + " ? child.material", + " : [child.material];", + "", + " materials.forEach((mat) => {", + "", + " if (mat && mat.color) {", + " mat.color.setRGB(r, g, b);", + " mat.needsUpdate = true;", + " }", + "", + " });", + " }", + "", + " });" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Model", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + }, + { + "description": "Color", + "name": "Color", + "type": "color" + } + ], + "objectGroups": [] + }, + { + "description": "Change The Visibility Of Model.", + "fullName": "Change Opacity", + "functionType": "Action", + "group": "Appearance", + "name": "ChnageOpacity", + "sentence": "Change Opacity _PARAM1_,_PARAM3_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Model\");", + "", + "if (objects.length === 0) return;", + "", + "const alpha = Number(eventsFunctionContext.getArgument(\"Opacity\")) / 255;", + "", + "const root = objects[0].get3DRendererObject();", + "", + "root.traverse((child) => {", + "", + " if (child.isMesh && child.material) {", + "", + " const materials = Array.isArray(child.material)", + " ? child.material", + " : [child.material];", + "", + " materials.forEach((mat) => {", + "", + " mat.transparent = alpha < 1;", + " mat.opacity = alpha;", + " mat.needsUpdate = true;", + "", + " });", + "", + " }", + "", + " });" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Model", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + }, + { + "description": "Opacity (0-255)", + "name": "Opacity", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "File Size Of a 3D Model.", + "fullName": "Model File Size", + "functionType": "StringExpression", + "group": "Information", + "name": "ModelFileSize", + "sentence": "Model File Size", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Model\");", + "", + "if (objects.length === 0) {", + " eventsFunctionContext.returnValue = \"\";", + " return;", + " }", + "", + " let bytes = 0;", + "", + " const root = objects[0].get3DRendererObject();", + "", + " root.traverse((child) => {", + "", + " if (child.isMesh && child.geometry) {", + "", + " for (const key in child.geometry.attributes) {", + " const attr = child.geometry.attributes[key];", + "", + " if (attr.array) {", + " bytes += attr.array.byteLength;", + " }", + " }", + "", + " if (child.geometry.index && child.geometry.index.array) {", + " bytes += child.geometry.index.array.byteLength;", + " }", + "", + " }", + "", + " });", + "", + "", + " let size;", + "", + " if (bytes < 1024) {", + " size = bytes.toFixed(0) + \" B\";", + " }", + " else if (bytes < 1024 * 1024) {", + " size = (bytes / 1024).toFixed(2) + \" KB\";", + " }", + " else {", + " size = (bytes / 1024 / 1024).toFixed(2) + \" MB\";", + " }", + "", + "", + " eventsFunctionContext.returnValue = size;" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "string" + }, + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + } + ], + "objectGroups": [] + }, + { + "description": "Replaces The Texture Of a Model.", + "fullName": "Replace Model Texture", + "functionType": "Action", + "group": "Appearance", + "name": "ReplaceModelTexture", + "sentence": "Replace Model Texture _PARAM1_,_PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const imageManager = runtimeScene.getGame().getImageManager();", + "", + "const pixiTexture = imageManager.getPIXITexture(", + " eventsFunctionContext.getArgument(\"Texture\")", + " );", + "", + " const objects = eventsFunctionContext.getObjects(\"Model\");", + "", + " if (objects.length > 0 && pixiTexture) {", + "", + " const root = objects[0].get3DRendererObject();", + "", + " root.traverse((child) => {", + "", + " if (child.isMesh && child.material) {", + "", + " const materials = Array.isArray(child.material)", + " ? child.material", + " : [child.material];", + "", + " materials.forEach((mat) => {", + "", + " const texture = new THREE.Texture(", + " pixiTexture.baseTexture.resource.source", + " );", + "", + " texture.needsUpdate = true;", + "", + " mat.map = texture;", + " mat.needsUpdate = true;", + "", + " });", + "", + " }", + "", + " });", + "", + " }" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + }, + { + "description": "Texture", + "name": "Texture", + "type": "imageResource" + } + ], + "objectGroups": [] + }, + { + "description": "Replaces a Material In a Model With a Texture.", + "fullName": "Replace Material With Texture", + "functionType": "Action", + "group": "Appearance", + "name": "ReplaceModelMaterial", + "sentence": "Replace Material With Texture _PARAM1_,_PARAM2_,_PARAM3_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Model\");", + "", + "if (objects.length === 0) return;", + "", + "const textureName = eventsFunctionContext.getArgument(\"Texture\");", + "const id = Number(eventsFunctionContext.getArgument(\"ID\"));", + "", + "const imageManager = runtimeScene.getGame().getImageManager();", + "", + "const pixiTexture = imageManager.getPIXITexture(textureName);", + "", + "if (!pixiTexture) return;", + "", + "const texture = new THREE.Texture(", + " pixiTexture.baseTexture.resource.source", + " );", + "", + " texture.needsUpdate = true;", + "", + " let index = 0;", + "", + " const root = objects[0].get3DRendererObject();", + "", + " root.traverse((child) => {", + "", + " if (child.isMesh && child.material) {", + "", + " const materials = Array.isArray(child.material)", + " ? child.material", + " : [child.material];", + "", + " materials.forEach((mat) => {", + "", + " if (mat.map) {", + "", + " if (index === id) {", + " mat.map = texture;", + " mat.needsUpdate = true;", + " }", + "", + " index++;", + " }", + "", + " });", + "", + " }", + "", + " });" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + }, + { + "description": "Material ID", + "longDescription": "The Material Is The Texture Of The Model Or The Looks Of a Model And It's Parts.", + "name": "ID", + "type": "expression" + }, + { + "description": "Texture", + "name": "Texture", + "type": "imageResource" + } + ], + "objectGroups": [] + }, + { + "description": "Tints The Material/Texture Of a Model.", + "fullName": "Tint Material Of Model", + "functionType": "Action", + "group": "Appearance", + "name": "TintMaterial", + "sentence": "Tint Material Of Model _PARAM1_,_PARAM2_,_PARAM3_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Model\");", + "", + "if (objects.length === 0) return;", + "", + "const id = Number(eventsFunctionContext.getArgument(\"ID\"));", + "const color = eventsFunctionContext.getArgument(\"Color\").split(\";\");", + "", + "const r = Number(color[0]) / 255;", + "const g = Number(color[1]) / 255;", + "const b = Number(color[2]) / 255;", + "", + "let index = 0;", + "", + "const root = objects[0].get3DRendererObject();", + "", + "root.traverse((child) => {", + "", + " if (child.isMesh && child.material) {", + "", + " const materials = Array.isArray(child.material)", + " ? child.material", + " : [child.material];", + "", + " materials.forEach((mat) => {", + "", + " if (index === id) {", + " mat.color.setRGB(r, g, b);", + " mat.needsUpdate = true;", + " }", + "", + " index++;", + "", + " });", + " }", + "", + " });" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + }, + { + "description": "Material ID", + "name": "ID", + "type": "expression" + }, + { + "description": "Color", + "name": "Color", + "type": "color" + } + ], + "objectGroups": [] + }, + { + "description": "Delete Mesh In a Model.", + "fullName": "Delete Mesh", + "functionType": "Action", + "group": "Mesh", + "name": "DeleteMesh", + "sentence": "Delete Mesh _PARAM1_,_PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Model\");", + "", + "if (objects.length === 0) return;", + "", + "const id = Number(eventsFunctionContext.getArgument(\"MeshID\"));", + "", + "let index = 0;", + "", + "const root = objects[0].get3DRendererObject();", + "", + "const remove = [];", + "", + "root.traverse((child) => {", + "", + " if (child.isMesh) {", + "", + " if (index === id) {", + " remove.push(child);", + " }", + "", + " index++;", + "", + " }", + "", + " });", + "", + " remove.forEach((mesh) => {", + " mesh.parent.remove(mesh);", + " });" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + }, + { + "description": "Mesh ID", + "name": "MeshID", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Moves The Mesh In a Model.", + "fullName": "Move Mesh In Model", + "functionType": "Action", + "group": "Mesh", + "name": "MoveMesh", + "sentence": "Move Mesh In Model _PARAM1_,_PARAM2_,_PARAM3_,_PARAM4_,_PARAM5_,_PARAM6_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Model\");", + "", + "if (objects.length === 0) return;", + "", + "const boneID = Number(eventsFunctionContext.getArgument(\"MeshID\"));", + "const mode = eventsFunctionContext.getArgument(\"Mode\");", + "", + "const x = Number(eventsFunctionContext.getArgument(\"X\")) / 100;", + "const y = Number(eventsFunctionContext.getArgument(\"Y\")) / 100;", + "const z = Number(eventsFunctionContext.getArgument(\"Z\")) / 100;", + "", + "const root = objects[0].get3DRendererObject();", + "", + "let skinnedMesh = null;", + "", + "root.traverse((child) => {", + " if (child.isSkinnedMesh && child.skeleton) {", + " skinnedMesh = child;", + " }", + " });", + "", + " if (!skinnedMesh) return;", + "", + " const bone = skinnedMesh.skeleton.bones[boneID];", + "", + " if (!bone) return;", + "", + " const nx = -x;", + " const ny = y;", + " const nz = -z;", + "", + " if (mode === \"Add\") {", + " bone.position.x += nx;", + " bone.position.y += ny;", + " bone.position.z += nz;", + " }", + " else if (mode === \"Subtract\") {", + " bone.position.x -= nx;", + " bone.position.y -= ny;", + " bone.position.z -= nz;", + " }", + " else if (mode === \"Set\") {", + " bone.position.set(nx, ny, nz);", + " }", + "", + " bone.updateMatrixWorld(true);" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + }, + { + "description": "Mesh ID", + "name": "MeshID", + "type": "expression" + }, + { + "description": "X Position", + "name": "X", + "type": "expression" + }, + { + "description": "Y position", + "name": "Y", + "type": "expression" + }, + { + "description": "Z Position", + "name": "Z", + "type": "expression" + }, + { + "description": "Mode", + "name": "Mode", + "supplementaryInformation": "[\"Set\",\"Add\",\"Subtract\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "description": "Rotates The Mesh In a Model.", + "fullName": "Rotate Mesh In Model", + "functionType": "Action", + "group": "Mesh", + "name": "RotateMesh", + "sentence": "Rotate Mesh In Model _PARAM1_,_PARAM2_,_PARAM3_,_PARAM4_,_PARAM5_,_PARAM6_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const models = eventsFunctionContext.getObjects(\"Model\");", + "", + "if (models.length === 0) return;", + "", + "const boneID = Number(eventsFunctionContext.getArgument(\"MeshID\"));", + "const mode = eventsFunctionContext.getArgument(\"Mode\");", + "", + "const x = THREE.MathUtils.degToRad(Number(eventsFunctionContext.getArgument(\"X\")));", + "const y = THREE.MathUtils.degToRad(Number(eventsFunctionContext.getArgument(\"Y\")));", + "const z = THREE.MathUtils.degToRad(Number(eventsFunctionContext.getArgument(\"Z\")));", + "", + "const root = models[0].get3DRendererObject();", + "", + "let skinnedMesh = null;", + "", + "root.traverse((child) => {", + " if (child.isSkinnedMesh && child.skeleton) {", + " skinnedMesh = child;", + " }", + " });", + "", + " if (!skinnedMesh) return;", + "", + " const bone = skinnedMesh.skeleton.bones[boneID];", + "", + " if (!bone) return;", + "", + " if (mode === \"Add\") {", + " bone.rotation.x += x;", + " bone.rotation.y += y;", + " bone.rotation.z += z;", + " }", + " else if (mode === \"Subtract\") {", + " bone.rotation.x -= x;", + " bone.rotation.y -= y;", + " bone.rotation.z -= z;", + " }", + " else if (mode === \"Set\") {", + " bone.rotation.set(x, y, z);", + " }", + "", + " bone.updateMatrixWorld(true);" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + }, + { + "description": "Mesh ID", + "name": "MeshID", + "type": "expression" + }, + { + "description": "X Rotation", + "name": "X", + "type": "expression" + }, + { + "description": "Y Rotation", + "name": "Y", + "type": "expression" + }, + { + "description": "Z Rotation", + "name": "Z", + "type": "expression" + }, + { + "description": "Mode", + "name": "Mode", + "supplementaryInformation": "[\"Set\",\"Add\",\"Subtract\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "description": "Changes The Size Of The Mesh In a Model.", + "fullName": "Size Mesh In Model", + "functionType": "Action", + "group": "Mesh", + "name": "SizeMesh", + "sentence": "Move Mesh In Model _PARAM1_,_PARAM2_,_PARAM3_,_PARAM4_,_PARAM5_,_PARAM6_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const models = eventsFunctionContext.getObjects(\"Model\");", + "", + "if (models.length === 0) return;", + "", + "const boneID = Number(eventsFunctionContext.getArgument(\"MeshID\"));", + "const mode = eventsFunctionContext.getArgument(\"Mode\");", + "", + "const x = Number(eventsFunctionContext.getArgument(\"Width\"));", + "const y = Number(eventsFunctionContext.getArgument(\"Height\"));", + "const z = Number(eventsFunctionContext.getArgument(\"Depth\"));", + "", + "const root = models[0].get3DRendererObject();", + "", + "let skinnedMesh = null;", + "", + "root.traverse((child) => {", + " if (child.isSkinnedMesh && child.skeleton) {", + " skinnedMesh = child;", + " }", + " });", + "", + " if (!skinnedMesh) return;", + "", + " const bone = skinnedMesh.skeleton.bones[boneID];", + "", + " if (!bone) return;", + "", + " if (mode === \"Add\") {", + " bone.scale.x += x;", + " bone.scale.y += y;", + " bone.scale.z += z;", + " }", + " else if (mode === \"Subtract\") {", + " bone.scale.x -= x;", + " bone.scale.y -= y;", + " bone.scale.z -= z;", + " }", + " else if (mode === \"Set\") {", + " bone.scale.set(x, y, z);", + " }", + "", + " bone.updateMatrixWorld(true);" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + }, + { + "description": "Mesh ID", + "name": "MeshID", + "type": "expression" + }, + { + "description": "Width", + "name": "Width", + "type": "expression" + }, + { + "description": "Height", + "name": "Height", + "type": "expression" + }, + { + "description": "Depth", + "name": "Depth", + "type": "expression" + }, + { + "description": "Mode", + "name": "Mode", + "supplementaryInformation": "[\"Set\",\"Add\",\"Subtract\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "description": "Changes The Resolution Of Model Texture.", + "fullName": "Texture Resolution Of Mesh", + "functionType": "Action", + "group": "Appearance", + "name": "TextureResMesh", + "sentence": "Texture Resolution Of Mesh _PARAM1_,_PARAM2_,_PARAM3_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const models = eventsFunctionContext.getObjects(\"Model\");", + "", + "if (models.length === 0) return;", + "", + "const meshID = Number(eventsFunctionContext.getArgument(\"MeshID\"));", + "const scale = Number(eventsFunctionContext.getArgument(\"Quality\"));", + "", + "const root = models[0].get3DRendererObject();", + "", + "let mesh = null;", + "let index = 0;", + "", + "root.traverse((child) => {", + " if (child.isMesh) {", + " if (index === meshID) {", + " mesh = child;", + " }", + " index++;", + " }", + " });", + "", + " if (!mesh) return;", + "", + " const material = Array.isArray(mesh.material)", + " ? mesh.material[0]", + " : mesh.material;", + "", + " if (!material) return;", + "", + " if (!material.userData) {", + " material.userData = {};", + " }", + "", + " if (!material.map || !material.map.image) return;", + "", + " if (!material.userData.originalTexture) {", + " material.userData.originalTexture = material.map;", + " }", + "", + " if (scale >= 1) {", + " material.map = material.userData.originalTexture;", + " material.needsUpdate = true;", + " return;", + " }", + "", + " const original = material.userData.originalTexture;", + " const image = original.image;", + "", + " const canvas = document.createElement(\"canvas\");", + " const ctx = canvas.getContext(\"2d\");", + "", + " canvas.width = Math.max(1, Math.floor(image.width * scale));", + " canvas.height = Math.max(1, Math.floor(image.height * scale));", + "", + " ctx.imageSmoothingEnabled = true;", + " ctx.imageSmoothingQuality = \"high\";", + "", + " ctx.drawImage(", + " image,", + " 0,", + " 0,", + " canvas.width,", + " canvas.height", + " );", + "", + " const lowTexture = new THREE.CanvasTexture(canvas);", + "", + " lowTexture.flipY = original.flipY;", + " lowTexture.wrapS = original.wrapS;", + " lowTexture.wrapT = original.wrapT;", + " lowTexture.minFilter = THREE.LinearMipmapLinearFilter;", + " lowTexture.magFilter = THREE.LinearFilter;", + " lowTexture.generateMipmaps = true;", + "", + " material.map = lowTexture;", + " material.needsUpdate = true;" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + }, + { + "description": "MeshID", + "name": "MeshID", + "type": "expression" + }, + { + "description": "Quality (0-1)", + "longDescription": "0.5 Is 2X Worse Quality.", + "name": "Quality", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Changes The Resolution Of Model Texture.", + "fullName": "Texture Resolution", + "functionType": "Action", + "group": "Appearance", + "name": "TextureResolution", + "sentence": "Texture Resolution _PARAM1_,_PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const models = eventsFunctionContext.getObjects(\"Model\");", + "", + "if (models.length === 0) return;", + "", + "const scale = Number(eventsFunctionContext.getArgument(\"Quality\"));", + "", + "const root = models[0].get3DRendererObject();", + "", + "root.traverse((mesh) => {", + " if (!mesh.isMesh) return;", + "", + " const materials = Array.isArray(mesh.material)", + " ? mesh.material", + " : [mesh.material];", + "", + " materials.forEach((material) => {", + " if (!material) return;", + "", + " if (!material.userData) {", + " material.userData = {};", + " }", + "", + " if (material.map && !material.userData.originalTexture) {", + " material.userData.originalTexture = material.map;", + " }", + "", + " if (scale >= 1) {", + " if (material.userData.originalTexture) {", + " material.map = material.userData.originalTexture;", + " material.needsUpdate = true;", + " }", + " return;", + " }", + "", + " const original = material.userData.originalTexture;", + "", + " if (!original || !original.image) return;", + "", + " const canvas = document.createElement(\"canvas\");", + " const ctx = canvas.getContext(\"2d\");", + "", + " canvas.width = Math.max(1, Math.floor(original.image.width * scale));", + " canvas.height = Math.max(1, Math.floor(original.image.height * scale));", + "", + " ctx.imageSmoothingEnabled = true;", + " ctx.imageSmoothingQuality = \"high\";", + "", + " ctx.drawImage(", + " original.image,", + " 0,", + " 0,", + " canvas.width,", + " canvas.height", + " );", + "", + " const lowTexture = new THREE.CanvasTexture(canvas);", + "", + " lowTexture.flipY = original.flipY;", + " lowTexture.wrapS = original.wrapS;", + " lowTexture.wrapT = original.wrapT;", + " lowTexture.colorSpace = original.colorSpace;", + " lowTexture.generateMipmaps = true;", + " lowTexture.minFilter = THREE.LinearMipmapLinearFilter;", + " lowTexture.magFilter = THREE.LinearFilter;", + "", + " material.map = lowTexture;", + " material.needsUpdate = true;", + " });", + " });" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + }, + { + "description": "Quality (0-1)", + "longDescription": "0.5 Is 2X Worse Quality.", + "name": "Quality", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Simplify Meshes For Optimisation, Combine And More.", + "fullName": "Mesh Simplfier", + "functionType": "Action", + "group": "Mesh", + "name": "SimplifyModel", + "sentence": "Mesh Simplifier _PARAM1_,_PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Model\");", + "const quality = Math.max(0, Math.min(1, Number(eventsFunctionContext.getArgument(\"Quality\"))));", + "", + "if (objects.length === 0) return;", + "", + "const root = objects[0].get3DRendererObject();", + "", + "root.traverse(mesh => {", + "", + " if (!mesh.isMesh) return;", + "", + "", + " if (!mesh.userData.originalGeometry)", + " mesh.userData.originalGeometry = mesh.geometry.clone();", + "", + "", + " if (quality >= 1) {", + " mesh.geometry.dispose();", + " mesh.geometry = mesh.userData.originalGeometry.clone();", + " return;", + " }", + "", + "", + " const geo = mesh.userData.originalGeometry.clone();", + "", + " const pos = geo.attributes.position;", + " const index = geo.index;", + "", + "", + " let vertices = [];", + "", + " for (let i = 0; i < pos.count; i++) {", + "", + " vertices.push({", + " x: pos.getX(i),", + " y: pos.getY(i),", + " z: pos.getZ(i)", + " });", + "", + " }", + "", + "", + " let faces = [];", + "", + " for (let i = 0; i < index.count; i += 3) {", + "", + " faces.push([", + " index.getX(i),", + " index.getX(i+1),", + " index.getX(i+2)", + " ]);", + "", + " }", + "", + "", + " let center = {", + " x:0,", + " y:0,", + " z:0", + " };", + "", + "", + " for (let v of vertices) {", + "", + " center.x += v.x;", + " center.y += v.y;", + " center.z += v.z;", + "", + " }", + "", + "", + " center.x /= vertices.length;", + " center.y /= vertices.length;", + " center.z /= vertices.length;", + "", + "", + " ", + " let originalRadius = 0;", + "", + " for (let v of vertices) {", + "", + " let dx = v.x - center.x;", + " let dy = v.y - center.y;", + " let dz = v.z - center.z;", + "", + " let d = Math.sqrt(dx*dx + dy*dy + dz*dz);", + "", + " if (d > originalRadius)", + " originalRadius = d;", + "", + " }", + "", + "", + " for (let v of vertices) {", + "", + " v.x = center.x + (v.x - center.x) * quality;", + " v.y = center.y + (v.y - center.y) * quality;", + " v.z = center.z + (v.z - center.z) * quality;", + "", + " }", + "", + "", + " let newRadius = 0;", + "", + " for (let v of vertices) {", + "", + " let dx = v.x - center.x;", + " let dy = v.y - center.y;", + " let dz = v.z - center.z;", + "", + " let d = Math.sqrt(dx*dx + dy*dy + dz*dz);", + "", + " if (d > newRadius)", + " newRadius = d;", + "", + " }", + "", + "", + " if (newRadius > 0) {", + "", + " let scale = originalRadius / newRadius;", + "", + " for (let v of vertices) {", + "", + " v.x = center.x + (v.x - center.x) * scale;", + " v.y = center.y + (v.y - center.y) * scale;", + " v.z = center.z + (v.z - center.z) * scale;", + "", + " }", + "", + " }", + " let mergeDistance = (1 - quality) * 0.9;", + "", + " let map = new Array(vertices.length).fill(-1);", + " let merged = [];", + "", + "", + " for (let i = 0; i < vertices.length; i++) {", + "", + " if (map[i] !== -1)", + " continue;", + "", + "", + " let v = vertices[i];", + "", + " let id = merged.length;", + "", + "", + " merged.push({", + " x:v.x,", + " y:v.y,", + " z:v.z", + " });", + "", + "", + " map[i] = id;", + "", + "", + " for (let j = i + 1; j < vertices.length; j++) {", + "", + " if (map[j] !== -1)", + " continue;", + "", + "", + " let b = vertices[j];", + "", + "", + " let dx = v.x - b.x;", + " let dy = v.y - b.y;", + " let dz = v.z - b.z;", + "", + "", + " let dist = dx*dx + dy*dy + dz*dz;", + "", + "", + " if (dist < mergeDistance * mergeDistance) {", + "", + " map[j] = id;", + "", + " }", + "", + " }", + "", + " }", + "", + "", + " let newFaces = [];", + "", + "", + " for (let f of faces) {", + "", + " let a = map[f[0]];", + " let b = map[f[1]];", + " let c = map[f[2]];", + "", + "", + " ", + " if (", + " a !== b &&", + " b !== c &&", + " a !== c", + " ) {", + "", + " newFaces.push(", + " a,", + " b,", + " c", + " );", + "", + " }", + "", + " }", + "", + "", + " let newPositions = [];", + "", + "", + " for (let v of merged) {", + "", + " newPositions.push(", + " v.x,", + " v.y,", + " v.z", + " );", + "", + " }", + "", + "", + " let newGeometry = new THREE.BufferGeometry();", + "", + "", + " newGeometry.setAttribute(", + " \"position\",", + " new THREE.Float32BufferAttribute(", + " newPositions,", + " 3", + " )", + " );", + "", + "", + " newGeometry.setIndex(newFaces);", + "", + " newGeometry.computeVertexNormals();", + "", + "", + " mesh.geometry.dispose();", + "", + " mesh.geometry = newGeometry;", + "", + "", + " });" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + }, + { + "description": "Quality (0-1)", + "longDescription": "0.5 = 2X Lower Quality.", + "name": "Quality", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Deletes All Mesh.", + "fullName": "Delete All Mesh", + "functionType": "Action", + "group": "Mesh", + "name": "DeleteAllMesh", + "sentence": "Delete All Mesh _PARAM1_,_PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Model\");", + "const mode = Number(eventsFunctionContext.getArgument(\"Mode\"));", + "", + "if (objects.length === 0) return;", + "", + "const obj = objects[0];", + "", + "const root = obj.get3DRendererObject();", + "", + "if (!root) return;", + "", + "", + "if (mode === 0) {", + "", + " if (!root.userData.savedMesh) {", + "", + " root.userData.savedMesh = root.clone(true);", + " root.userData.savedPosition = root.position.clone();", + " root.userData.savedRotation = root.rotation.clone();", + " root.userData.savedScale = root.scale.clone();", + "", + " }", + "", + "", + " if (root.parent) {", + " root.parent.remove(root);", + " }", + "", + "", + " root.userData.meshDeleted = true;", + "", + " }", + "", + "", + " if (mode === 1) {", + "", + " if (", + " root.userData.meshDeleted &&", + " root.userData.savedMesh", + " ) {", + "", + "", + " const restored = root.userData.savedMesh.clone(true);", + "", + "", + " restored.position.copy(", + " root.userData.savedPosition", + " );", + "", + " restored.rotation.copy(", + " root.userData.savedRotation", + " );", + "", + " restored.scale.copy(", + " root.userData.savedScale", + " );", + "", + "", + " if (root.parent === null) {", + "", + " const scene =", + " obj.getRuntimeScene()", + " .getLayer(\"\")", + " .getRenderer()", + " .getThreeScene();", + "", + "", + " scene.add(restored);", + "", + " }", + "", + "", + " root.userData.meshDeleted = false;", + "", + " }", + "", + " }" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + }, + { + "description": "Mode", + "longDescription": "0 = Delete And 1 = Recreate.", + "name": "Mode", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "True If The Object Is Visible On The Screen And Not Behind Another One.", + "fullName": "Object Visible On Screen", + "functionType": "Condition", + "group": "Mesh", + "name": "ObjectVisible", + "sentence": "Object Visible On Screen _PARAM1_,_PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Object\");", + "const obstacles = eventsFunctionContext.getObjects(\"Obstacle\");", + "const rayCount = 1;", + "", + "if (objects.length === 0) {", + " eventsFunctionContext.returnValue = false;", + " return;", + " }", + "", + "", + " const target = objects[0].get3DRendererObject();", + "", + " if (!target) {", + " eventsFunctionContext.returnValue = false;", + " return;", + " }", + "", + "", + " const renderer =", + " runtimeScene", + " .getLayer(objects[0].getLayer())", + " .getRenderer();", + "", + " const camera = renderer.getThreeCamera();", + "", + "", + " if (!camera) {", + " eventsFunctionContext.returnValue = false;", + " return;", + " }", + "", + "", + " // Get obstacle meshes", + "", + " let obstacleMeshes = [];", + "", + " for (const obstacle of obstacles) {", + "", + " const mesh = obstacle.get3DRendererObject();", + "", + " if (!mesh) continue;", + "", + " mesh.traverse(child => {", + "", + " if (child.isMesh) {", + " obstacleMeshes.push(child);", + " }", + "", + " });", + " }", + "", + "", + " // Get target meshes", + "", + " let targetMeshes = [];", + "", + " target.traverse(child => {", + "", + " if (child.isMesh) {", + " targetMeshes.push(child);", + " }", + "", + " });", + "", + "", + " // Combine objects ray can hit", + "", + " const rayObjects = obstacleMeshes.concat(targetMeshes);", + "", + "", + " // Camera position", + "", + " const cameraPos = new THREE.Vector3();", + " camera.getWorldPosition(cameraPos);", + "", + "", + " // Target position in 3D", + "", + " const targetPos = new THREE.Vector3();", + " target.getWorldPosition(targetPos);", + "", + "", + " // Direction camera faces", + "", + " const cameraDirection = new THREE.Vector3();", + " camera.getWorldDirection(cameraDirection);", + "", + "", + " // Direction to target (X Y Z)", + "", + " const baseDirection = new THREE.Vector3()", + " .subVectors(targetPos, cameraPos)", + " .normalize();", + "", + "", + " // Behind camera check", + "", + " if (cameraDirection.dot(baseDirection) <= 0) {", + "", + " eventsFunctionContext.returnValue = false;", + " return;", + "", + " }", + "", + "", + " // Distance in 3D", + "", + " const distance =", + " cameraPos.distanceTo(targetPos);", + "", + "", + " // Fire rays", + "", + " for (let i = 0; i < rayCount; i++) {", + "", + "", + " let spread = 0;", + "", + "", + " if (rayCount > 1) {", + " spread =", + " -90 + (180 * i / (rayCount - 1));", + " }", + "", + "", + " const direction =", + " baseDirection.clone();", + "", + "", + " // Spread horizontally around camera", + "", + " direction.applyAxisAngle(", + " camera.up,", + " THREE.MathUtils.degToRad(spread)", + " );", + "", + "", + " const raycaster = new THREE.Raycaster();", + "", + "", + " raycaster.set(", + " cameraPos,", + " direction.normalize()", + " );", + "", + "", + " raycaster.far = distance;", + "", + "", + "", + " const hits =", + " raycaster.intersectObjects(", + " rayObjects,", + " true", + " );", + "", + "", + "", + " if (hits.length > 0) {", + "", + "", + " const firstHit = hits[0].object;", + "", + "", + " let hitTarget = false;", + "", + "", + " target.traverse(child => {", + "", + " if (child === firstHit) {", + " hitTarget = true;", + " }", + "", + " });", + "", + "", + " if (hitTarget) {", + "", + " eventsFunctionContext.returnValue = true;", + " return;", + "", + " }", + "", + " // Obstacle hit first:", + " // cancel this ray and try next one", + "", + " }", + "", + " }", + "", + "", + " // No ray reached target", + "", + " eventsFunctionContext.returnValue = false;" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + }, + { + "description": "Obstacle", + "name": "Obstacle", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Merge Object2's Mesh With Object1.", + "fullName": "Merge Objects", + "functionType": "Action", + "group": "Mesh", + "name": "MergeOBJ", + "sentence": "Merge Objects _PARAM1_,_PARAM2_,_PARAM3_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object1 = eventsFunctionContext.getObjects(\"Object\")[0];", + "const object2Instances = eventsFunctionContext.getObjects(\"Object2\");", + "", + "if (!object1 || object2Instances.length === 0) return;", + "", + "const target = object1.get3DRendererObject();", + "", + "if (!target) return;", + "", + "target.updateMatrixWorld(true);", + "", + "for (let i = 0; i < object2Instances.length; i++) {", + "", + " const source = object2Instances[i].get3DRendererObject();", + "", + " if (!source) continue;", + "", + " source.updateMatrixWorld(true);", + "", + " source.traverse((child) => {", + "", + " if (child.isMesh) {", + "", + " const newMesh = new THREE.Mesh(", + " child.geometry,", + " child.material", + " );", + "", + " const worldMatrix = child.matrixWorld.clone();", + "", + " const targetInverse = new THREE.Matrix4()", + " .copy(target.matrixWorld)", + " .invert();", + "", + " newMesh.applyMatrix4(", + " targetInverse.multiply(worldMatrix)", + " );", + "", + " target.add(newMesh);", + " }", + "", + " });", + "", + " ", + " if (source.parent) {", + " source.parent.remove(source);", + " }", + " }" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object 1", + "name": "Object", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + }, + { + "description": "Object 2", + "name": "Object2", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "Object3D2", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Creates Clouds In The Sky.", + "fullName": "Create Clouds", + "functionType": "Action", + "group": "Terrain", + "name": "CloudGen", + "sentence": "Create Clouds _PARAM1_,_PARAM2_,_PARAM3_,_PARAM4_,_PARAM5_,_PARAM6_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const color = eventsFunctionContext.getArgument(\"Color\") || \"255;255;255\";", + "const count = eventsFunctionContext.getArgument(\"Count\") || 20;", + "const height = eventsFunctionContext.getArgument(\"Height\") || 500;", + "const spread = eventsFunctionContext.getArgument(\"Spread\") || 1000;", + "const speed = eventsFunctionContext.getArgument(\"Speed\") || 0.05;", + "const cloudScale = eventsFunctionContext.getArgument(\"Scale\") || 5;", + "const name = eventsFunctionContext.getArgument(\"Name\") || \"Cloud\";", + "", + "", + "//RGB", + "const rgb = color.split(\";\");", + "", + "const r = Number(rgb[0]) / 255;", + "const g = Number(rgb[1]) / 255;", + "const b = Number(rgb[2]) / 255;", + "", + "", + "gdjs.CloudObjects = gdjs.CloudObjects || [];", + "", + "", + "//create", + "for (let i = 0; i < count; i++) {", + "", + " const material = new THREE.MeshBasicMaterial({", + " color: new THREE.Color(r, g, b),", + " transparent: true,", + " opacity: 0.8,", + " depthWrite: false", + " });", + "", + "", + " const size =", + " (30 + Math.random() * 50) * cloudScale;", + "", + "", + " const cloudPart = new THREE.Mesh(", + " new THREE.SphereGeometry(", + " size,", + " 8,", + " 8", + " ),", + " material", + " );", + " cloudPart.name = name;", + "", + "", + " //flat ", + " cloudPart.scale.set(", + " 1.5,", + " 1.5,", + " 0.35", + " );", + " cloudPart.position.set(", + " (Math.random() - 0.5) * spread,", + " (Math.random() - 0.5) * spread,", + " height + Math.random() * (cloudScale * 10)", + " );", + "", + "", + " cloudPart.userData.speed = speed;", + "", + "", + " runtimeScene", + " .getLayer(\"Base layer\")", + " .getRenderer()", + " .getThreeScene()", + " .add(cloudPart);", + "", + "", + " gdjs.CloudObjects.push(cloudPart);", + " }", + "", + "", + " //move clouds", + " for (const cloud of gdjs.CloudObjects) {", + "", + " cloud.position.x += cloud.userData.speed;", + "", + " if (cloud.position.x > spread / 2) {", + " cloud.position.x = -spread / 2;", + " }", + " }" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Color", + "name": "Color", + "type": "color" + }, + { + "description": "Number Of Clouds (1000)", + "name": "Count", + "type": "expression" + }, + { + "description": "Spread (12000)", + "name": "Spread", + "type": "expression" + }, + { + "description": "Height (1500)", + "name": "Height", + "type": "expression" + }, + { + "description": "Speed", + "name": "Speed", + "type": "expression" + }, + { + "description": "Scale (5)", + "name": "Scale", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Creates Mountains Around The Camera.", + "fullName": "Create Mountains", + "functionType": "Action", + "group": "Terrain", + "name": "MoutainGen", + "sentence": "Create Mountains _PARAM1_,_PARAM2_,_PARAM3_,_PARAM4_,_PARAM5_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const count = eventsFunctionContext.getArgument(\"Count\") || 30;", + "const radius = eventsFunctionContext.getArgument(\"Radius\") || 2000;", + "const height = eventsFunctionContext.getArgument(\"Height\") || 500;", + "const width = eventsFunctionContext.getArgument(\"Width\") || 800;", + "", + "const color = eventsFunctionContext.getArgument(\"Color\") || \"80;90;100\";", + "", + "", + "// RGB color", + "const rgb = color.split(\";\");", + "", + "const r = Number(rgb[0]) / 255;", + "const g = Number(rgb[1]) / 255;", + "const b = Number(rgb[2]) / 255;", + "", + "", + "// Camera position", + "const cameraX = gdjs.evtTools.camera.getCameraX(", + " runtimeScene,", + " \"Base layer\"", + " );", + "", + " const cameraY = gdjs.evtTools.camera.getCameraY(", + " runtimeScene,", + " \"Base layer\"", + " );", + "", + "", + " const layer = runtimeScene.getLayer(\"Base layer\");", + "", + " const scene = layer", + " .getRenderer()", + " .getThreeScene();", + "", + "", + " gdjs.MountainPlanes = gdjs.MountainPlanes || [];", + "", + "", + " // Create mountains", + " for (let i = 0; i < count; i++) {", + "", + "", + " // Vertical triangle (X + Z)", + " const vertices = new Float32Array([", + " -width / 2, 0, 0,", + " width / 2, 0, 0,", + " 0, 0, height", + " ]);", + "", + "", + " const geometry = new THREE.BufferGeometry();", + "", + " geometry.setAttribute(", + " \"position\",", + " new THREE.BufferAttribute(vertices, 3)", + " );", + "", + " geometry.computeVertexNormals();", + "", + "", + " const material = new THREE.MeshBasicMaterial({", + "", + " color: new THREE.Color(", + " r,", + " g,", + " b", + " ),", + "", + " side: THREE.DoubleSide", + "", + " });", + "", + "", + " const mountain = new THREE.Mesh(", + " geometry,", + " material", + " );", + "", + "", + " // Random position around camera", + " const angle = Math.random() * Math.PI * 2;", + "", + " const distance =", + " radius * (0.5 + Math.random() * 0.5);", + "", + "", + " mountain.position.set(", + "", + " cameraX + Math.cos(angle) * distance,", + "", + " cameraY + Math.sin(angle) * distance,", + "", + " 0", + "", + " );", + "", + "", + " // Face camera direction", + " mountain.rotation.z = -angle;", + "", + "", + " scene.add(mountain);", + "", + " gdjs.MountainPlanes.push(mountain);", + " }" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Color", + "name": "Color", + "type": "color" + }, + { + "description": "Number Of Mountains (1000)", + "name": "Count", + "type": "expression" + }, + { + "description": "Radius", + "name": "Radius", + "type": "expression" + }, + { + "description": "Height (1500)", + "name": "Height", + "type": "expression" + }, + { + "description": "Width", + "name": "Width", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Creates Terrain.", + "fullName": "Create Terrain", + "functionType": "Action", + "group": "Terrain", + "name": "TerrainGen", + "sentence": "Create Terrain _PARAM1_,_PARAM2_,_PARAM3_,_PARAM4_,_PARAM5_,_PARAM6_,_PARAM7_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const size = eventsFunctionContext.getArgument(\"Size\") || 2000;", + "const segments = eventsFunctionContext.getArgument(\"Segments\") || 100;", + "const height = eventsFunctionContext.getArgument(\"Height\") || 100;", + "", + "const createX = eventsFunctionContext.getArgument(\"CreateX\") || 0;", + "const createY = eventsFunctionContext.getArgument(\"CreateY\") || 0;", + "const createZ = eventsFunctionContext.getArgument(\"CreateZ\") || 0;", + "", + "const color = eventsFunctionContext.getArgument(\"Color\") || \"80;160;60\";", + "", + "", + "const rgb = color.split(\";\");", + "", + "const r = Number(rgb[0]) / 255;", + "const g = Number(rgb[1]) / 255;", + "const b = Number(rgb[2]) / 255;", + "", + "", + "const vertices = [];", + "const indices = [];", + "", + "const half = size / 2;", + "", + "", + "// Create X/Y ground with Z height", + "for (let y = 0; y <= segments; y++) {", + "", + " for (let x = 0; x <= segments; x++) {", + "", + " const posX =", + " (x / segments) * size - half;", + "", + " const posY =", + " (y / segments) * size - half;", + "", + "", + " const h =", + " Math.sin(posX * 0.01) *", + " Math.cos(posY * 0.01) *", + " height;", + "", + "", + " vertices.push(", + " posX,", + " posY,", + " h", + " );", + " }", + " }", + "", + "", + " // Faces", + " for (let y = 0; y < segments; y++) {", + "", + " for (let x = 0; x < segments; x++) {", + "", + " const a = y * (segments + 1) + x;", + " const b = a + 1;", + " const c = a + segments + 1;", + " const d = c + 1;", + "", + "", + " indices.push(", + " a,", + " b,", + " c,", + "", + " b,", + " d,", + " c", + " );", + " }", + " }", + "", + "", + " const geometry = new THREE.BufferGeometry();", + "", + " geometry.setAttribute(", + " \"position\",", + " new THREE.Float32BufferAttribute(vertices, 3)", + " );", + "", + " geometry.setIndex(indices);", + "", + " geometry.computeVertexNormals();", + "", + "", + " const material = new THREE.MeshStandardMaterial({", + " color: new THREE.Color(r,g,b),", + " side: THREE.DoubleSide", + " });", + "", + "", + " const terrain = new THREE.Mesh(", + " geometry,", + " material", + " );", + "", + "", + " terrain.position.set(", + " createX,", + " createY,", + " createZ", + " );", + "", + "", + " runtimeScene", + " .getLayer(\"Base layer\")", + " .getRenderer()", + " .getThreeScene()", + " .add(terrain);" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Color", + "name": "Color", + "type": "color" + }, + { + "description": "Number Of Segments", + "longDescription": "The More Segments Used The More Realistic The Terrain Would Look.", + "name": "Segments", + "type": "expression" + }, + { + "description": "Size", + "name": "Size", + "type": "expression" + }, + { + "description": "Height", + "name": "Height", + "type": "expression" + }, + { + "description": "X", + "name": "X", + "type": "expression" + }, + { + "description": "Y", + "name": "Y", + "type": "expression" + }, + { + "description": "Z", + "name": "Z", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Creates Terrain With Texture.", + "fullName": "Create Textured Terrain", + "functionType": "Action", + "group": "Terrain", + "name": "TerrainTexturedGen", + "sentence": "Create Textured Terrain _PARAM1_,_PARAM2_,_PARAM3_,_PARAM4_,_PARAM5_, _PARAM6_,_PARAM7_,_PARAM8_,_PARAM9_,_PARAM10_, _PARAM11_,_PARAM12_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const size = eventsFunctionContext.getArgument(\"Size\") || 2000;", + "const segments = eventsFunctionContext.getArgument(\"Segments\") || 100;", + "const height = eventsFunctionContext.getArgument(\"Height\") || 100;", + "const terrainName = eventsFunctionContext.getArgument(\"Name\") || \"terrain\";", + "", + "const textureName = eventsFunctionContext.getArgument(\"Texture\");", + "const textureRepeat = eventsFunctionContext.getArgument(\"TextureRepeat\") || 20;", + "", + "const createX = eventsFunctionContext.getArgument(\"X\") || 0;", + "const createY = eventsFunctionContext.getArgument(\"Y\") || 0;", + "const createZ = eventsFunctionContext.getArgument(\"Z\") || 0;", + "", + "const worldX = eventsFunctionContext.getArgument(\"WorldX\") || 0;", + "const worldY = eventsFunctionContext.getArgument(\"WorldY\") || 0;", + "", + "const seed = eventsFunctionContext.getArgument(\"Seed\") || 12345;", + "", + "const vertices = [];", + "const uvs = [];", + "const indices = [];", + "", + "const half = size / 2;", + "", + "//seed random", + "function seededRandom(x, y) {", + "", + "let value = ", + " Math.sin( ", + " x * 12.9898 + ", + " y * 78.233 + ", + " seed * 0.12345 ", + " ) * 43758.5453; ", + "", + " return value - Math.floor(value);", + "", + " }", + "", + " //large biome size", + " const biomeSize = 10000;", + "", + " //generate vertex", + " for (let y = 0; y <= segments; y++) {", + "", + " for (let x = 0; x <= segments; x++) { ", + "", + "", + " const posX = ", + " (x / segments) * size - half + worldX; ", + "", + " const posY = ", + " (y / segments) * size - half + worldY; ", + "", + "", + "", + " //biome position ", + " const chunkX = Math.floor(posX / biomeSize); ", + " const chunkY = Math.floor(posY / biomeSize); ", + "", + "", + " const biome = ", + " seededRandom(chunkX, chunkY); ", + "", + "", + " let multiplier; ", + "", + "", + " if (biome < 0.45) { ", + "", + " // Plains ", + " multiplier = 0.05; ", + "", + " } else if (biome < 0.8) { ", + "", + " // Hills ", + " multiplier = 0.35; ", + "", + " } else { ", + "", + " // Mountains ", + " multiplier = 1; ", + "", + " } ", + "", + "", + "", + " // Terrain noise ", + " let noise = 0; ", + "", + "", + " noise += ", + " Math.sin(posX * 0.0004) * ", + " Math.cos(posY * 0.0004) * ", + " 0.6; ", + "", + "", + " noise += ", + " Math.sin( ", + " posX * 0.0012 + ", + " posY * 0.0009 ", + " ) * 0.25; ", + "", + "", + " noise += ", + " Math.cos( ", + " posX * 0.003 - ", + " posY * 0.002 ", + " ) * 0.1; ", + "", + "", + "", + " noise = Math.max( ", + " -1, ", + " Math.min(1, noise) ", + " ); ", + "", + "", + " const h = ", + " noise * ", + " height * ", + " multiplier; ", + "", + "", + "", + " vertices.push( ", + " posX - worldX, ", + " posY - worldY, ", + " h ", + " ); ", + "", + "", + " uvs.push( ", + " (x / segments) * textureRepeat, ", + " (1 - y / segments) * textureRepeat ", + " ); ", + " }", + "", + " }", + "", + " // Faces", + " for (let y = 0; y < segments; y++) {", + "", + " for (let x = 0; x < segments; x++) { ", + "", + " const a = y * (segments + 1) + x; ", + " const b = a + 1; ", + " const c = a + segments + 1; ", + " const d = c + 1; ", + "", + "", + " indices.push( ", + " a,b,c, ", + " b,d,c ", + " ); ", + " }", + "", + " }", + "", + " const geometry = new THREE.BufferGeometry();", + "", + " geometry.setAttribute(", + " \"position\",", + " new THREE.Float32BufferAttribute(", + " vertices,", + " 3", + " )", + " );", + "", + " geometry.setAttribute(", + " \"uv\",", + " new THREE.Float32BufferAttribute(", + " uvs,", + " 2", + " )", + " );", + "", + " geometry.setIndex(indices);", + "", + " geometry.computeVertexNormals();", + " //oimo", + " //load texture", + " let texture = null;", + "", + " if (textureName) {", + "", + " const pixiTexture = ", + " runtimeScene ", + " .getGame() ", + " .getImageManager() ", + " .getPIXITexture(textureName); ", + "", + "", + " if (pixiTexture) { ", + "", + " texture = new THREE.Texture( ", + " pixiTexture.baseTexture.resource.source ", + " ); ", + "", + "", + " texture.wrapS = THREE.RepeatWrapping; ", + " texture.wrapT = THREE.RepeatWrapping; ", + "", + " texture.flipY = false; ", + "", + " texture.needsUpdate = true; ", + " }", + "", + " }", + "", + " // Material", + " const material = new THREE.MeshStandardMaterial({", + "", + " map: texture, ", + "", + " side: THREE.DoubleSide", + "", + " });", + "", + " // Create terrain mesh", + " const terrain = new THREE.Mesh(", + " geometry,", + " material", + " );", + " terrain.name = terrainName;", + "", + " //place chunk in world", + " terrain.position.set(", + " createX + worldX,", + " createY,", + " createZ + worldY", + " );", + "", + " //add to scene", + " runtimeScene", + " .getLayer(\"Base layer\")", + " .getRenderer()", + " .getThreeScene()", + " .add(terrain);", + " " + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Number Of Segments", + "longDescription": "The More Segments Used The More Realistic The Terrain Would Look.", + "name": "Segments", + "type": "expression" + }, + { + "description": "Size", + "name": "Size", + "type": "expression" + }, + { + "description": "Height", + "name": "Height", + "type": "expression" + }, + { + "description": "X", + "name": "X", + "type": "expression" + }, + { + "description": "Y", + "name": "Y", + "type": "expression" + }, + { + "description": "Z", + "name": "Z", + "type": "expression" + }, + { + "description": "Texture", + "name": "Texture", + "type": "imageResource" + }, + { + "description": "Texture Repeat (20)", + "name": "TextureRepeat", + "type": "expression" + }, + { + "description": "Seed", + "name": "Seed", + "type": "expression" + }, + { + "description": "World X", + "name": "WorldX", + "type": "expression" + }, + { + "description": "World Y", + "name": "WorldY", + "type": "expression" + }, + { + "description": "Object Name", + "name": "Name", + "type": "string" + } + ], + "objectGroups": [] + }, + { + "description": "Creates Water At Position.", + "fullName": "Create Water", + "functionType": "Action", + "group": "Terrain", + "name": "Water", + "sentence": "Create Water _PARAM1_,_PARAM2_,_PARAM3_,_PARAM4_,_PARAM5_, _PARAM6_,_PARAM7_,_PARAM8_,_PARAM9_,_PARAM10_, _PARAM11_, _PARAM12_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const scene = runtimeScene", + " .getLayer(\"Base layer\")", + " .getRenderer()", + " .getThreeScene();", + "", + "", + " //arguments", + "", + " const x = Number(eventsFunctionContext.getArgument(\"X\")) || 0;", + " const y = Number(eventsFunctionContext.getArgument(\"Y\")) || 0;", + " const z = Number(eventsFunctionContext.getArgument(\"Z\")) || 0;", + "", + "", + " const width =", + " Number(eventsFunctionContext.getArgument(\"Width\")) || 1000;", + "", + " const height =", + " Number(eventsFunctionContext.getArgument(\"Height\")) || 50;", + "", + " const depth =", + " Number(eventsFunctionContext.getArgument(\"Depth\")) || 1000;", + "", + "", + " const wind =", + " Number(eventsFunctionContext.getArgument(\"Wind\")) || 1;", + "", + "", + " const direction =", + " Number(eventsFunctionContext.getArgument(\"Direction\")) || 0;", + "", + "", + "const name = eventsFunctionContext.getArgument(\"Name\") || \"Water\";", + " const segments =", + " Math.min(", + " Number(eventsFunctionContext.getArgument(\"Segments\")) || 50,", + " 200", + " );", + "", + "", + " const colorString =", + " eventsFunctionContext.getArgument(\"Color\") || \"0;120;255\";", + "", + "", + " const reflection =", + " eventsFunctionContext.getArgument(\"Reflection\") || false;", + "", + "", + "", + " // RGB color", + "", + " const rgb = colorString", + " .split(\";\")", + " .map(Number);", + "", + "", + " const color = new THREE.Color(", + " (rgb[0] || 0) / 255,", + " (rgb[1] || 0) / 255,", + " (rgb[2] || 255) / 255", + " );", + "", + "", + "", + " //wind direction", + "", + " const dirRad =", + " direction * Math.PI / 180;", + "", + "", + " const windX = Math.cos(dirRad);", + " const windY = Math.sin(dirRad);", + "", + "", + "", + " // Create box", + "", + " const geometry = new THREE.BoxGeometry(", + " width,", + " depth,", + " height,", + " segments,", + " segments,", + " 1", + " );", + "", + "", + "", + " const material = new THREE.MeshPhongMaterial({", + "", + " color: color,", + "", + " transparent: true,", + "", + " opacity: 0.75,", + "", + " shininess: 200,", + "", + " specular: new THREE.Color(1,1,1),", + "", + " side: THREE.DoubleSide", + "", + " });", + "", + "", + "", + " const water = new THREE.Mesh(", + " geometry,", + " material", + " );", + "", + "water.name = name;", + " water.position.set(", + " x,", + " y,", + " z", + " );", + "", + "", + "", + " scene.add(water);", + "", + "", + "", + " //store top vertices", + "", + " const topVertices = [];", + "", + " const positions =", + " geometry.attributes.position;", + "", + "", + "", + " for (let i = 0; i < positions.count; i++) {", + "", + "", + " // top of water", + "", + " if (", + " positions.getZ(i) > height / 2 - 0.1", + " ) {", + "", + " topVertices.push({", + "", + " index: i,", + "", + " x: positions.getX(i),", + "", + " y: positions.getY(i)", + "", + " });", + "", + " }", + "", + " }", + "", + "", + "", + " //eave height", + "", + " const waveHeight =", + " Math.min(", + " wind * 3,", + " height * 0.45", + " );", + "", + "", + "", + "", + " //animate", + "", + " water.userData.animate = function(){", + "", + "", + " const time =", + " performance.now() * 0.001;", + "", + "", + " const pos =", + " geometry.attributes.position;", + "", + "", + "", + " for (const v of topVertices) {", + "", + "", + " const wave =", + "", + " Math.sin(", + "", + " (", + " v.x * windX +", + " v.y * windY", + " )", + " *", + " 0.03", + " +", + " time *", + " (1 + wind * 0.2)", + "", + " )", + " *", + " waveHeight;", + "", + "", + "", + " const extra =", + "", + " Math.cos(", + "", + " (", + " v.x * -windY +", + " v.y * windX", + " )", + " *", + " 0.02", + " +", + " time", + "", + " )", + " *", + " waveHeight *", + " 0.4;", + "", + "", + "", + " pos.setZ(", + "", + " v.index,", + "", + " height / 2 +", + " wave +", + " extra", + "", + " );", + "", + " }", + "", + "", + "", + " pos.needsUpdate = true;", + "", + " geometry.computeVertexNormals();", + "", + " };", + "", + "", + "", + "", + " // Save water objects", + "", + " if (!window.waterObjects)", + " window.waterObjects = [];", + "", + "", + " window.waterObjects.push(water);", + "", + "", + "", + " //reflection", + "", + " if (reflection) {", + "", + " material.envMapIntensity = 1;", + "", + " }", + "", + "", + "", + " //animation loop", + "", + " if (!window.waterLoopStarted) {", + "", + "", + " window.waterLoopStarted = true;", + "", + "", + " function waterLoop(){", + "", + "", + " for (const w of window.waterObjects) {", + "", + " if (w.userData.animate)", + " w.userData.animate();", + "", + " }", + "", + "", + " requestAnimationFrame(", + " waterLoop", + " );", + "", + " }", + "", + "", + " waterLoop();", + "", + " }", + "", + "", + "", + " console.log(", + " \"Water created Z-up\",", + " \"Wind:\",", + " wind,", + " \"Direction:\",", + " direction,", + " \"Segments:\",", + " segments", + " );", + " console.log(scene.children.map(o => o.name));" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Color", + "name": "Color", + "type": "color" + }, + { + "description": "X", + "name": "X", + "type": "expression" + }, + { + "description": "Y", + "name": "Y", + "type": "expression" + }, + { + "description": "Z", + "name": "Z", + "type": "expression" + }, + { + "description": "Width", + "name": "Width", + "type": "expression" + }, + { + "description": "Height", + "name": "Height", + "type": "expression" + }, + { + "description": "Depth", + "name": "Depth", + "type": "expression" + }, + { + "description": "Number Of Segments", + "longDescription": "The More Segments Used The More Realistic The Terrain Would Look.", + "name": "Segments", + "type": "expression" + }, + { + "description": "Reflection", + "name": "Reflection", + "type": "expression" + }, + { + "description": "Wind Strength (1)", + "name": "Wind", + "type": "expression" + }, + { + "description": "Direction (0-360)", + "longDescription": "The Direction Of The Wind.", + "name": "Direction", + "type": "expression" + }, + { + "description": "Object Name", + "name": "Name", + "type": "string" + } + ], + "objectGroups": [] + }, + { + "description": "Creates Grass.", + "fullName": "Create Grass", + "functionType": "Action", + "group": "Terrain", + "name": "Grass", + "sentence": "Create Grass _PARAM1_,_PARAM2_,_PARAM3_,_PARAM4_, _PARAM5_,_PARAM6_,_PARAM7_,_PARAM8_,_PARAM9_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const spread =", + "Number(eventsFunctionContext.getArgument(\"Spread\")) || 100;", + "", + "const count =", + "Number(eventsFunctionContext.getArgument(\"Count\")) || 1000;", + "", + "const centerX =", + "Number(eventsFunctionContext.getArgument(\"X\")) || 0;", + "", + "const centerY =", + "Number(eventsFunctionContext.getArgument(\"Y\")) || 0;", + "", + "const centerZ =", + "Number(eventsFunctionContext.getArgument(\"Z\")) || 0;", + "", + "const quality =", + "Math.max(", + " 1,", + " Number(eventsFunctionContext.getArgument(\"Quality\")) || 2", + " );", + "", + " const maxHeight =", + " Number(eventsFunctionContext.getArgument(\"Height\")) || 1.5;", + "", + " const bladeSize =", + " Number(eventsFunctionContext.getArgument(\"Size\")) || 0.08;", + "", + " const colorArg =", + " eventsFunctionContext.getArgument(\"Color\") || \"50;200;50\";", + "", + "", + " const rgb =", + " colorArg.split(\";\").map(Number);", + "", + "", + " const baseColor =", + " new THREE.Color(", + " rgb[0] / 255,", + " rgb[1] / 255,", + " rgb[2] / 255", + " );", + "", + " const darkColor =", + " new THREE.Color(", + " rgb[0] * 0.65 / 255,", + " rgb[1] * 0.65 / 255,", + " rgb[2] * 0.65 / 255", + " );", + "", + "", + " const scene =", + " runtimeScene", + " .getLayer(\"Base layer\")", + " .getRenderer()", + " .getThreeScene();", + "", + "", + " if (!runtimeScene.__GrassMesh)", + " {", + " const vertices = [];", + " const colors = [];", + " const indices = [];", + "", + " let index = 0;", + "", + "", + "", + " function addTriangle(a,b,c,color)", + " {", + " vertices.push(", + " ...a,", + " ...b,", + " ...c", + " );", + "", + " for(let i=0;i<3;i++)", + " {", + " colors.push(", + " color.r,", + " color.g,", + " color.b", + " );", + " }", + "", + " indices.push(", + " index,", + " index+1,", + " index+2", + " );", + "", + " index += 3;", + " }", + "", + "", + "", + " function addBlade(", + " baseX,", + " baseZ,", + " angle", + " )", + " {", + " const height =", + " maxHeight;", + "", + " const groundY =", + " centerY;", + "", + " const segments =", + " quality + 2;", + "", + " const dirX =", + " Math.cos(angle);", + "", + " const dirZ =", + " Math.sin(angle);", + "", + " let lastX = baseX;", + " let lastY = groundY;", + " let lastZ = baseZ;", + "", + " for(let i=0;i m.dispose());", + " else", + " mesh.material.dispose();", + " }", + "", + " " + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Name", + "name": "Name", + "type": "string" + } + ], + "objectGroups": [] + }, + { + "description": "Delete Water By Name.", + "fullName": "Delete Water", + "functionType": "Action", + "group": "Terrain", + "name": "WaterDelete", + "sentence": "Delete Water _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const scene =", + "runtimeScene", + ".getLayer(\"Base layer\")", + ".getRenderer()", + ".getThreeScene();", + "", + "", + "const name =", + "eventsFunctionContext.getArgument(\"Name\");", + "", + "", + "const water =", + "scene.getObjectByName(name);", + "", + "", + "if (!water)", + "{", + " console.log(\"Water not found:\", name);", + " return;", + " }", + "", + "", + " // Remove from scene", + " scene.remove(water);", + "", + "", + " // Remove from water animation list", + " if (window.waterObjects)", + " {", + " window.waterObjects =", + " window.waterObjects.filter(", + " w => w !== water", + " );", + " }", + "", + "", + " // Free memory", + " if (water.geometry)", + " water.geometry.dispose();", + "", + "", + " if (water.material)", + " {", + " if (Array.isArray(water.material))", + " {", + " water.material.forEach(m => m.dispose());", + " }", + " else", + " {", + " water.material.dispose();", + " }", + " }", + "", + "", + " " + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Name", + "name": "Name", + "type": "string" + } + ], + "objectGroups": [] + }, + { + "description": "Delete Cloud By Name.", + "fullName": "Delete Cloud", + "functionType": "Action", + "group": "Terrain", + "name": "CloudDlete", + "sentence": "Delete Cloud _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const scene =", + "runtimeScene", + ".getLayer(\"Base layer\")", + ".getRenderer()", + ".getThreeScene();", + "", + "", + "const name =", + "eventsFunctionContext.getArgument(\"Name\");", + "", + "", + "let clouds = null;", + "", + "", + "scene.traverse((obj) =>", + "{", + " if (obj.name === name)", + " clouds = obj;", + " });", + "", + "", + " if (!clouds)", + " {", + " console.log(\"Clouds not found:\", name);", + " return;", + " }", + "", + "", + " scene.remove(clouds);", + "", + "", + " // Free memory", + " if (clouds.geometry)", + " clouds.geometry.dispose();", + "", + "", + " if (clouds.material)", + " {", + " if (Array.isArray(clouds.material))", + " {", + " clouds.material.forEach(m => m.dispose());", + " }", + " else", + " {", + " clouds.material.dispose();", + " }", + " }", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Name", + "name": "Name", + "type": "string" + } + ], + "objectGroups": [] + }, + { + "description": "Creates Path On Top Of Terrain.", + "fullName": "Create Path", + "functionType": "Action", + "group": "Terrain", + "name": "CreatePath", + "sentence": "Create Path _PARAM1_, _PARAM2_, _PARAM3_,_PARAM4_, _PARAM5_, _PARAM6_,_PARAM7_,_PARAM8_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const scene =", + "runtimeScene", + ".getLayer(\"Base layer\")", + ".getRenderer()", + ".getThreeScene();", + "", + "", + "const terrainName =", + "eventsFunctionContext.getArgument(\"TerrainName\");", + "", + "const textureName =", + "eventsFunctionContext.getArgument(\"Texture\");", + "", + "", + "const posX =", + "Number(eventsFunctionContext.getArgument(\"X\")) || 0;", + "", + "const posZ =", + "Number(eventsFunctionContext.getArgument(\"Y\")) || 0;", + "", + "", + "const width =", + "Number(eventsFunctionContext.getArgument(\"Width\")) || 10;", + "", + "const depth =", + "Number(eventsFunctionContext.getArgument(\"Depth\")) || 10;", + "", + "", + "const segments =", + "Math.max(", + " 1,", + " Math.floor(", + " Number(eventsFunctionContext.getArgument(\"Segments\")) || 10", + " )", + " );", + "", + "", + " const heightOffset =", + " Number(eventsFunctionContext.getArgument(\"HeightOffset\")) || 0.02;", + "", + "", + " let terrain = null;", + "", + "", + " scene.traverse((obj)=>", + " {", + " if (obj.name === terrainName)", + " terrain = obj;", + " });", + "", + "", + " if (!terrain)", + " {", + " console.log(\"Terrain not found:\", terrainName);", + " return;", + " }", + "", + "", + " if (!terrain.geometry)", + " {", + " console.log(\"Terrain has no geometry\");", + " return;", + " }", + "", + "", + " terrain.updateMatrixWorld(true);", + "", + "", + " const raycaster =", + " new THREE.Raycaster();", + "", + "", + " const vertices = [];", + " const uvs = [];", + " const indices = [];", + "", + "", + " const stepX =", + " width / segments;", + "", + " const stepZ =", + " depth / segments;", + "", + "", + " const startX =", + " posX - width / 2;", + "", + " const startZ =", + " posZ - depth / 2;", + "", + "", + " const grid = [];", + "", + "", + " for (let z = 0; z <= segments; z++)", + " {", + " grid[z] = [];", + "", + " for (let x = 0; x <= segments; x++)", + " {", + " grid[z][x] = {", + " x:", + " startX + x * stepX,", + "", + " z:", + " startZ + z * stepZ,", + "", + " y: 0", + " };", + " }", + " }", + "", + " for (let z = 0; z <= segments; z++)", + " {", + " for (let x = 0; x <= segments; x++)", + " {", + " const point = grid[z][x];", + "", + " const origin = new THREE.Vector3(", + " point.x,", + " 10000,", + " point.z", + " );", + "", + "", + " const direction = new THREE.Vector3(", + " 0,", + " -1,", + " 0", + " );", + "", + "", + " raycaster.set(", + " origin,", + " direction", + " );", + "", + "", + " const hit =", + " raycaster.intersectObject(", + " terrain,", + " true", + " );", + "", + "", + " if (hit.length > 0)", + " {", + " point.y =", + " hit[0].point.y + heightOffset;", + " }", + " else", + " {", + " point.y = 0;", + " }", + "", + "", + " vertices.push(", + " point.x,", + " point.y,", + " point.z", + " );", + "", + "", + " uvs.push(", + " x / segments,", + " z / segments", + " );", + " }", + " }", + "", + "", + "", + " for (let z = 0; z < segments; z++)", + " {", + " for (let x = 0; x < segments; x++)", + " {", + " const a =", + " z * (segments + 1) + x;", + "", + " const b =", + " a + 1;", + "", + " const c =", + " a + (segments + 1);", + "", + " const d =", + " c + 1;", + "", + "", + " indices.push(", + " a,", + " c,", + " b", + " );", + "", + " indices.push(", + " b,", + " c,", + " d", + " );", + " }", + " }", + "", + " const geometry =", + " new THREE.BufferGeometry();", + "", + "", + " geometry.setAttribute(", + " \"position\",", + " new THREE.Float32BufferAttribute(", + " vertices,", + " 3", + " )", + " );", + "", + "", + " geometry.setAttribute(", + " \"uv\",", + " new THREE.Float32BufferAttribute(", + " uvs,", + " 2", + " )", + " );", + "", + "", + " geometry.setIndex(indices);", + "", + "", + " geometry.computeVertexNormals();", + "", + "", + "", + " const pixiTexture =", + " runtimeScene", + " .getGame()", + " .getImageManager()", + " .getPIXITexture(textureName);", + "", + "", + " if (!pixiTexture)", + " {", + " console.log(", + " \"Texture not found:\",", + " textureName", + " );", + " return;", + " }", + "", + "", + " const texture =", + " new THREE.Texture(", + " pixiTexture.baseTexture.resource.source", + " );", + "", + "", + " texture.needsUpdate = true;", + "", + "", + " texture.wrapS =", + " THREE.RepeatWrapping;", + "", + " texture.wrapT =", + " THREE.RepeatWrapping;", + "", + "", + " const material =", + " new THREE.MeshStandardMaterial({", + " map: texture,", + " side: THREE.DoubleSide", + " });", + "", + " const path =", + " new THREE.Mesh(", + " geometry,", + " material", + " );", + "", + " path.name =", + " \"Path_\" + Date.now();", + "", + " scene.add(path);" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Terrain Name", + "name": "TerrainName", + "type": "string" + }, + { + "description": "Texture", + "name": "Texture", + "type": "imageResource" + }, + { + "description": "X", + "name": "X", + "type": "expression" + }, + { + "description": "Y", + "name": "Y", + "type": "expression" + }, + { + "description": "Width", + "name": "Width", + "type": "expression" + }, + { + "description": "Depth", + "name": "Depth", + "type": "expression" + }, + { + "description": "Height Offset", + "name": "HeightOffset", + "type": "expression" + }, + { + "description": "Segments", + "name": "Segments", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Name Of The Model GLB.", + "fullName": "GLB Model Name", + "functionType": "StringExpression", + "group": "Information", + "name": "GlbName", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const model = eventsFunctionContext.getObjects(\"Model\")[0];", + "", + "if (model)", + "{", + " const root = model.get3DRendererObject();", + "", + " let foundName = \"\";", + "", + " root.traverse((child) =>", + " {", + " if (child.name && !foundName)", + " foundName = child.name;", + " });", + "", + " eventsFunctionContext.returnValue = foundName;", + " }" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "string" + }, + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + } + ], + "objectGroups": [] + }, + { + "description": "Remove Unused Vertices.", + "fullName": "Mesh Optimiser", + "functionType": "Action", + "group": "Mesh", + "name": "MeshOptimiser", + "sentence": "Mesh Optimiser _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const modelObjects =", + "eventsFunctionContext.getObjects(\"Model\");", + "", + "if (modelObjects.length === 0)", + " return;", + "", + " const root =", + " modelObjects[0].get3DRendererObject();", + "", + " root.traverse((mesh) =>", + " {", + " if (!mesh.isMesh || !mesh.geometry)", + " return;", + "", + " const geometry = mesh.geometry;", + "", + " if (!geometry.index)", + " return;", + "", + " const index =", + " geometry.index.array;", + "", + " const used = new Set();", + "", + " for (let i = 0; i < index.length; i++)", + " {", + " used.add(index[i]);", + " }", + "", + "", + " const oldPositions =", + " geometry.attributes.position.array;", + "", + " const oldAttributes =", + " geometry.attributes;", + "", + "", + " const map = new Map();", + " const newVertices = [];", + "", + " let newIndex = 0;", + "", + "", + " used.forEach((oldIndex) =>", + " {", + " map.set(oldIndex, newIndex++);", + "", + " for (const key in oldAttributes)", + " {", + " if (key === \"position\")", + " {", + " const attr =", + " oldAttributes[key];", + "", + " newVertices.push(", + " attr.getX(oldIndex),", + " attr.getY(oldIndex),", + " attr.getZ(oldIndex)", + " );", + " }", + " }", + " });", + "", + "", + " const newIndices = [];", + "", + " for (let i = 0; i < index.length; i++)", + " {", + " newIndices.push(", + " map.get(index[i])", + " );", + " }", + "", + "", + " geometry.setAttribute(", + " \"position\",", + " new THREE.Float32BufferAttribute(", + " newVertices,", + " 3", + " )", + " );", + "", + "", + " geometry.setIndex(newIndices);", + "", + " geometry.computeVertexNormals();", + "", + " geometry.computeBoundingBox();", + " geometry.computeBoundingSphere();", + " });", + "", + "", + " " + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Model", + "name": "Model", + "supplementaryInformation": "Scene3D::Model3DObject", + "type": "objectList" + } + ], + "objectGroups": [] + }, + { + "description": "Optimise Vertices, Combine Duplicates.", + "fullName": "Optimise Vertices", + "functionType": "Action", + "group": "Mesh", + "name": "OptimiseVertecies", + "sentence": "Optimise Vertices _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const modelObjects =", + "eventsFunctionContext.getObjects(\"Model\");", + "", + "if (modelObjects.length === 0)", + " return;", + "", + " const root =", + " modelObjects[0].get3DRendererObject();", + "", + "", + " root.traverse((mesh) =>", + " {", + " if (!mesh.isMesh || !mesh.geometry)", + " return;", + "", + "", + " const geometry = mesh.geometry;", + "", + " if (!geometry.index)", + " return;", + "", + "", + " const position =", + " geometry.attributes.position;", + "", + "", + " const index =", + " geometry.index.array;", + "", + "", + " const vertexMap = new Map();", + "", + " const newPositions = [];", + " const newIndices = [];", + "", + " const remap = [];", + "", + "", + " for (let i = 0; i < position.count; i++)", + " {", + " const x = position.getX(i);", + " const y = position.getY(i);", + " const z = position.getZ(i);", + "", + "", + " const key =", + " x.toFixed(6) + \"_\" +", + " y.toFixed(6) + \"_\" +", + " z.toFixed(6);", + "", + "", + " if (!vertexMap.has(key))", + " {", + " vertexMap.set(", + " key,", + " newPositions.length / 3", + " );", + "", + " newPositions.push(", + " x,", + " y,", + " z", + " );", + " }", + "", + "", + " remap[i] =", + " vertexMap.get(key);", + " }", + "", + "", + " for (let i = 0; i < index.length; i++)", + " {", + " newIndices.push(", + " remap[index[i]]", + " );", + " }", + "", + "", + " geometry.setAttribute(", + " \"position\",", + " new THREE.Float32BufferAttribute(", + " newPositions,", + " 3", + " )", + " );", + "", + "", + " geometry.setIndex(newIndices);", + "", + " geometry.computeVertexNormals();", + " geometry.computeBoundingBox();", + " geometry.computeBoundingSphere();", + " });", + "", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Model", + "name": "Model", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Removes Invisible Triangles For Optimisation.", + "fullName": "Remove Degenerate Tringles", + "functionType": "Action", + "group": "Mesh", + "name": "RemoveInvisTringle", + "sentence": "Remove Degenerate Triangles _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const modelObjects =", + "eventsFunctionContext.getObjects(\"Model\");", + "", + "if (modelObjects.length === 0)", + " return;", + "", + "", + " const root =", + " modelObjects[0].get3DRendererObject();", + "", + "", + " root.traverse((mesh)=>", + " {", + " if (!mesh.isMesh || !mesh.geometry)", + " return;", + "", + "", + " const geometry =", + " mesh.geometry;", + "", + "", + " if (!geometry.index)", + " return;", + "", + "", + " const position =", + " geometry.attributes.position;", + "", + "", + " const index =", + " geometry.index.array;", + "", + "", + " const newIndices = [];", + "", + "", + " for (let i = 0; i < index.length; i += 3)", + " {", + " const a = index[i];", + " const b = index[i + 1];", + " const c = index[i + 2];", + "", + "", + " const ax = position.getX(a);", + " const ay = position.getY(a);", + " const az = position.getZ(a);", + "", + "", + " const bx = position.getX(b);", + " const by = position.getY(b);", + " const bz = position.getZ(b);", + "", + "", + " const cx = position.getX(c);", + " const cy = position.getY(c);", + " const cz = position.getZ(c);", + "", + "", + " const abx = bx - ax;", + " const aby = by - ay;", + " const abz = bz - az;", + "", + "", + " const acx = cx - ax;", + " const acy = cy - ay;", + " const acz = cz - az;", + "", + "", + " const crossX =", + " aby * acz - abz * acy;", + "", + " const crossY =", + " abz * acx - abx * acz;", + "", + " const crossZ =", + " abx * acy - aby * acx;", + "", + "", + " const area =", + " Math.sqrt(", + " crossX * crossX +", + " crossY * crossY +", + " crossZ * crossZ", + " );", + "", + "", + " if (area > 0.000001)", + " {", + " newIndices.push(", + " a,", + " b,", + " c", + " );", + " }", + " }", + "", + "", + " geometry.setIndex(newIndices);", + "", + " geometry.computeVertexNormals();", + " geometry.computeBoundingBox();", + " geometry.computeBoundingSphere();", + " });", + "", + "", + " " + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Model", + "name": "Model", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Stop Rendering Inside Faces.", + "fullName": "Optimise Faces", + "functionType": "Action", + "group": "Mesh", + "name": "OptimiseFaces", + "sentence": "Optimise Faces _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const models =", + "eventsFunctionContext.getObjects(\"Model\");", + "", + "if (models.length === 0)", + " return;", + "", + " const root =", + " models[0].get3DRendererObject();", + "", + "", + " root.traverse((mesh)=>", + " {", + " if (!mesh.isMesh)", + " return;", + "", + "", + " if (Array.isArray(mesh.material))", + " {", + " mesh.material.forEach((mat)=>", + " {", + " mat.side = THREE.FrontSide;", + " mat.needsUpdate = true;", + " });", + " }", + " else", + " {", + " mesh.material.side = THREE.FrontSide;", + " mesh.material.needsUpdate = true;", + " }", + " });" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Model", + "name": "Model", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Render Skybox Around The Player.", + "fullName": "Render Skybox", + "functionType": "Action", + "group": "Terrain", + "name": "RenderSky", + "sentence": "Render Skybox _PARAM1_,_PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const textureName =", + "eventsFunctionContext.getArgument(\"Texture\");", + "", + "const size =", + "Number(eventsFunctionContext.getArgument(\"Size\")) || 500;", + "", + "", + "const currentLayer =", + "runtimeScene.getLayer(\"Base layer\");", + "", + "", + "if (!runtimeScene.__Skybox)", + "{", + " const pixiTexture =", + " runtimeScene", + " .getGame()", + " .getImageManager()", + " .getPIXITexture(textureName);", + "", + "", + " if (!pixiTexture)", + " {", + " ", + " return;", + " }", + "", + "", + " const source =", + " pixiTexture.baseTexture.resource.source;", + "", + "", + " const imageWidth =", + " source.width;", + "", + " const imageHeight =", + " source.height;", + "", + "", + " function createFace(tileX, tileY)", + " {", + " const tex =", + " new THREE.Texture(source);", + "", + "", + " tex.needsUpdate = true;", + "", + " tex.flipY = false;", + "", + " tex.wrapS =", + " THREE.ClampToEdgeWrapping;", + "", + " tex.wrapT =", + " THREE.ClampToEdgeWrapping;", + "", + "", + " tex.generateMipmaps = false;", + "", + " tex.minFilter =", + " THREE.LinearFilter;", + "", + " tex.magFilter =", + " THREE.LinearFilter;", + "", + "", + " const tileWidth =", + " imageWidth / 4;", + "", + " const tileHeight =", + " imageHeight / 3;", + "", + "", + " const inset = 4;", + "", + "", + " const startX =", + " tileX * tileWidth + inset;", + "", + " const startY =", + " tileY * tileHeight + inset;", + "", + "", + " tex.repeat.set(", + " (tileWidth - inset * 2) / imageWidth,", + " (tileHeight - inset * 2) / imageHeight", + " );", + "", + "", + " tex.offset.set(", + " startX / imageWidth,", + " 1 - ((startY + tileHeight - inset) / imageHeight)", + " );", + "", + "", + " return new THREE.MeshBasicMaterial({", + " map: tex,", + " side: THREE.BackSide,", + " depthWrite: false", + " });", + " }", + "", + "", + " const materials = [", + "", + " // Right 3,2", + " createFace(2,1),", + "", + " // Left 1,2", + " createFace(0,1),", + "", + " // Top 2,1", + " createFace(1,0),", + "", + " // Bottom 2,3", + " createFace(1,2),", + "", + " // Front 2,2", + " createFace(1,1),", + "", + " // Back 4,2", + " createFace(3,1)", + "", + " ];", + "", + "", + " const geometry =", + " new THREE.BoxGeometry(", + " size,", + " size,", + " size", + " ).toNonIndexed();", + "", + "", + " const skybox =", + " new THREE.Mesh(", + " geometry,", + " materials", + " );", + "", + "", + " skybox.name =", + " \"Skybox\";", + "", + "", + " skybox.rotation.set(", + " -Math.PI / 2,", + " Math.PI,", + " 0", + " );", + "", + "", + " // Hide tiny seams between faces", + " skybox.scale.set(", + " 1.002,", + " 1.002,", + " 1.002", + " );", + "", + "", + " const scene =", + " currentLayer", + " .getRenderer()", + " .getThreeScene();", + "", + "", + " if (!scene)", + " {", + " console.log(\"Three scene missing\");", + " return;", + " }", + "", + "", + " scene.add(skybox);", + "", + "", + " runtimeScene.__Skybox =", + " skybox;", + " }", + "", + "", + "", + " const skybox =", + " runtimeScene.__Skybox;", + "", + "", + " if (skybox)", + " {", + " const cameraCenterX =", + " currentLayer.getCameraX();", + "", + " const cameraCenterY =", + " currentLayer.getCameraY();", + "", + " const cameraCenterZ =", + " gdjs.scene3d.camera.getCameraZ(", + " runtimeScene,", + " \"Base layer\",", + " 0", + " );", + "", + "", + " skybox.position.set(", + " cameraCenterX,", + " cameraCenterY,", + " cameraCenterZ", + " );", + " }" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Texture Atlas", + "name": "Texture", + "type": "imageResource" + }, + { + "description": "Size", + "name": "Size", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Render Skybox Around The Player With Time Cycle.", + "fullName": "Render Skybox With Time", + "functionType": "Action", + "group": "Terrain", + "name": "RenderSkyTime", + "sentence": "Render Skybox With Time _PARAM1_,_PARAM2_,_PARAM3_,_PARAM4_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const dayName = eventsFunctionContext.getArgument(\"Texture\");", + "const nightName = eventsFunctionContext.getArgument(\"NightTexture\");", + "", + "const size =", + "Number(eventsFunctionContext.getArgument(\"Size\")) || 500;", + "", + "const speed =", + "Number(eventsFunctionContext.getArgument(\"Time\")) || 0.01;", + "", + "", + "const layer =", + "runtimeScene.getLayer(\"Base layer\");", + "", + "", + "", + "function getSource(name)", + "{", + " const texture =", + " runtimeScene", + " .getGame()", + " .getImageManager()", + " .getPIXITexture(name);", + "", + " if (!texture) return null;", + "", + " return texture.baseTexture.resource.source;", + " }", + "", + "", + "", + " function cropAtlas(source, x, y)", + " {", + " const tileW =", + " source.width / 4;", + "", + " const tileH =", + " source.height / 3;", + "", + "", + " const canvas =", + " document.createElement(\"canvas\");", + "", + "", + " canvas.width =", + " Math.round(tileW);", + "", + " canvas.height =", + " Math.round(tileH);", + "", + "", + " const ctx =", + " canvas.getContext(\"2d\");", + "", + "", + " ctx.imageSmoothingEnabled = false;", + "", + "", + " ctx.drawImage(", + " source,", + "", + " Math.round(x * tileW),", + " Math.round(y * tileH),", + "", + " Math.round(tileW),", + " Math.round(tileH),", + "", + " 0,", + " 0,", + "", + " canvas.width,", + " canvas.height", + " );", + "", + "", + " const tex =", + " new THREE.CanvasTexture(canvas);", + "", + "", + " tex.needsUpdate = true;", + "", + " tex.flipY = false;", + "", + " tex.generateMipmaps = false;", + "", + " tex.minFilter =", + " THREE.NearestFilter;", + "", + " tex.magFilter =", + " THREE.NearestFilter;", + "", + "", + " return tex;", + " }", + "", + "", + "", + " function createMaterial(day, night)", + " {", + " return new THREE.ShaderMaterial({", + "", + " uniforms:", + " {", + " day:", + " {", + " value: day", + " },", + "", + " night:", + " {", + " value: night", + " },", + "", + " blend:", + " {", + " value: 1", + " }", + " },", + "", + "", + " vertexShader:`", + "", + " varying vec2 vUv;", + "", + " void main()", + " {", + " vUv = uv;", + "", + " gl_Position =", + " projectionMatrix *", + " modelViewMatrix *", + " vec4(position,1.0);", + " }", + "", + " `,", + "", + "", + " fragmentShader:`", + "", + " uniform sampler2D day;", + " uniform sampler2D night;", + " uniform float blend;", + "", + " varying vec2 vUv;", + "", + "", + " void main()", + " {", + " vec4 d =", + " texture2D(day,vUv);", + "", + " vec4 n =", + " texture2D(night,vUv);", + "", + "", + " gl_FragColor =", + " mix(n,d,blend);", + " }", + "", + " `,", + "", + "", + " side:", + " THREE.BackSide,", + "", + " depthWrite:false", + "", + " });", + " }", + "", + "", + "", + "", + " if (!runtimeScene.__Skybox)", + " {", + " const day =", + " getSource(dayName);", + "", + " const night =", + " getSource(nightName);", + "", + "", + " if (!day || !night)", + " {", + " console.log(\"Missing skybox texture\");", + " return;", + " }", + "", + "", + "", + " function face(x,y)", + " {", + " return createMaterial(", + " cropAtlas(day,x,y),", + " cropAtlas(night,x,y)", + " );", + " }", + "", + "", + "", + " const materials =", + " [", + " face(2,1), // Right", + " face(0,1), // Left", + " face(1,2), // Top ✅ swapped", + " face(1,0), // Bottom ✅ swapped", + " face(1,1), // Front", + " face(3,1) // Back", + " ];", + "", + "", + "", + " const geometry =", + " new THREE.BoxGeometry(", + " size,", + " size,", + " size", + " )", + " .toNonIndexed();", + "", + "", + "", + " const sky =", + " new THREE.Mesh(", + " geometry,", + " materials", + " );", + "", + "", + " sky.rotation.set(", + " -Math.PI / 2,", + " Math.PI,", + " 0", + " );", + "", + "", + " sky.scale.set(", + " 1.002,", + " 1.002,", + " 1.002", + " );", + "", + "", + "", + " layer", + " .getRenderer()", + " .getThreeScene()", + " .add(sky);", + "", + "", + "", + " runtimeScene.__Skybox =", + " sky;", + "", + "", + " runtimeScene.__SkyTime = 1;", + " runtimeScene.__SkyDirection = -1;", + " }", + "", + "", + "", + "", + " runtimeScene.__SkyTime +=", + " (speed * 0.0001) *", + " runtimeScene.__SkyDirection;", + "", + "", + "", + " if (runtimeScene.__SkyTime <= 0)", + " {", + " runtimeScene.__SkyTime = 0;", + " runtimeScene.__SkyDirection = 1;", + " }", + "", + "", + " if (runtimeScene.__SkyTime >= 1)", + " {", + " runtimeScene.__SkyTime = 1;", + " runtimeScene.__SkyDirection = -1;", + " }", + "", + "", + "", + "", + " const sky =", + " runtimeScene.__Skybox;", + "", + "", + " if (sky)", + " {", + " sky.position.set(", + "", + " layer.getCameraX(),", + "", + " layer.getCameraY(),", + "", + " gdjs.scene3d.camera.getCameraZ(", + " runtimeScene,", + " \"Base layer\",", + " 0", + " )", + " );", + "", + "", + " sky.material.forEach(mat =>", + " {", + " mat.uniforms.blend.value =", + " runtimeScene.__SkyTime;", + " });", + " }" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Day Texture", + "name": "Texture", + "type": "imageResource" + }, + { + "description": "Night Texture", + "name": "NightTexture", + "type": "imageResource" + }, + { + "description": "Time (0-1)", + "name": "Time", + "type": "expression" + }, + { + "description": "Size", + "name": "Size", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Creates Light At Point.", + "fullName": "Create Light", + "functionType": "Action", + "group": "Terrain", + "name": "CreateLight", + "sentence": "Create Light _PARAM1_,_PARAM2_,_PARAM3_,_PARAM4_,_PARAM5_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const x =", + "Number(eventsFunctionContext.getArgument(\"X\")) || 0;", + "", + "const y =", + "Number(eventsFunctionContext.getArgument(\"Y\")) || 0;", + "", + "const z =", + "Number(eventsFunctionContext.getArgument(\"Z\")) || 0;", + "", + "", + "const strength =", + "Number(eventsFunctionContext.getArgument(\"Strength\")) || 1;", + "", + "", + "const colorArg =", + "eventsFunctionContext.getArgument(\"Color\") || \"255;255;255\";", + "", + "", + "const layer =", + "runtimeScene.getLayer(\"Base layer\");", + "", + "", + "", + "if (!runtimeScene.__Extra3DLight)", + "{", + " const rgb =", + " colorArg.split(\";\").map(Number);", + "", + "", + " const color =", + " new THREE.Color(", + " rgb[0] / 255,", + " rgb[1] / 255,", + " rgb[2] / 255", + " );", + "", + "", + " const light =", + " new THREE.PointLight(", + " color,", + " strength,", + " 0", + " );", + "", + "", + " light.position.set(", + " x,", + " y,", + " z", + " );", + "", + "", + " light.name =", + " \"Extra3D World Light\";", + "", + "", + " layer", + " .getRenderer()", + " .getThreeScene()", + " .add(light);", + "", + "", + " runtimeScene.__Extra3DLight =", + " light;", + " }", + "", + "", + "", + " const light =", + " runtimeScene.__Extra3DLight;", + "", + "", + " light.intensity =", + " strength;" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Strength", + "name": "Strength", + "type": "expression" + }, + { + "description": "Color", + "name": "Color", + "type": "color" + }, + { + "description": "X", + "name": "X", + "type": "expression" + }, + { + "description": "Y", + "name": "Y", + "type": "expression" + }, + { + "description": "Z", + "name": "Z", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Show The Wireframe Of Models.", + "fullName": "Show Wireframe", + "functionType": "Action", + "group": "Debug", + "name": "ShowWireFrame", + "sentence": "Snow Wireframe _PARAM1_,_PARAM3_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects =", + "eventsFunctionContext.getObjects(\"Model\");", + "", + "", + "if(objects.length === 0)", + " return;", + "", + "", + " const myObject =", + " objects[0];", + "", + "", + " const model =", + " myObject.get3DRendererObject();", + "", + "", + " if(!model)", + " return;", + "", + "", + "", + " const scene =", + " runtimeScene", + " .getLayer(\"Base layer\")", + " .getRenderer()", + " .getThreeScene();", + "", + "", + "", + " const colorArg =", + " eventsFunctionContext.getArgument(\"Color\") || \"0;255;0\";", + "", + "", + " const rgb =", + " colorArg.split(\";\").map(Number);", + "", + "", + " const material =", + " new THREE.LineBasicMaterial(", + " {", + " color:", + " new THREE.Color(", + " rgb[0] / 255,", + " rgb[1] / 255,", + " rgb[2] / 255", + " )", + " });", + "", + "", + "", + " const group =", + " new THREE.Group();", + "", + "", + " group.name =", + " \"Debug_Wireframe\";", + "", + "", + "", + " model.updateMatrixWorld(true);", + "", + "", + "", + " model.traverse(", + " (mesh)=>", + " {", + " if(mesh.isMesh)", + " {", + " const geometry =", + " new THREE.WireframeGeometry(", + " mesh.geometry", + " );", + "", + "", + " const pos =", + " geometry.attributes.position;", + "", + "", + " for(let i = 0; i < pos.count; i++)", + " {", + " pos.setXYZ(", + " i,", + " pos.getX(i) * 1.0005,", + " pos.getY(i) * 1.0005,", + " pos.getZ(i) * 1.0005", + " );", + " }", + "", + "", + " pos.needsUpdate = true;", + "", + "", + "", + " const wire =", + " new THREE.LineSegments(", + " geometry,", + " material", + " );", + "", + "", + " wire.applyMatrix4(", + " mesh.matrixWorld", + " );", + "", + "", + " group.add(", + " wire", + " );", + " }", + " });", + "", + "", + "", + " scene.add(", + " group", + " );" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Model", + "name": "Model", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + }, + { + "description": "Color", + "name": "Color", + "type": "color" + } + ], + "objectGroups": [] + }, + { + "description": "Switch Tone-Mapping For Cinematic Looks.", + "fullName": "Tone-Mapping", + "functionType": "Action", + "group": "World Settings", + "name": "ToneMapping", + "sentence": "Tone-Mapping _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const mode =", + " String(", + " eventsFunctionContext.getArgument(\"Mode\")", + " ).toUpperCase();", + "", + "", + " const renderer =", + " runtimeScene", + " .getGame()", + " .getRenderer()", + " .getThreeRenderer();", + "", + "", + " if(!renderer)", + " return;", + "", + "", + "", + " switch(mode)", + " {", + "", + " case \"NONE\":", + " renderer.toneMapping =", + " THREE.NoToneMapping;", + " break;", + "", + "", + " case \"LINEAR\":", + " renderer.toneMapping =", + " THREE.LinearToneMapping;", + " break;", + "", + "", + " case \"REINHARD\":", + " renderer.toneMapping =", + " THREE.ReinhardToneMapping;", + " break;", + "", + "", + " case \"CINEON\":", + " renderer.toneMapping =", + " THREE.CineonToneMapping;", + " break;", + "", + "", + " case \"ACES\":", + " renderer.toneMapping =", + " THREE.ACESFilmicToneMapping;", + " break;", + "", + "", + " default:", + " console.warn(", + " \"Unknown tone mapping:\",", + " mode", + " );", + " return;", + "", + " }", + "", + "", + " renderer.toneMappingExposure = 1;", + "", + "", + " console.log(", + " \"Tone Mapping:\",", + " mode", + " );" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Mode", + "name": "Mode", + "supplementaryInformation": "[\"NONE\",\"LINEAR\",\"REINHARD\",\"ACES\",\"CINEON\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "description": "Change Object Material.", + "fullName": "Material Content", + "functionType": "Action", + "group": "Appearance", + "name": "ChnageMaterial", + "sentence": "Material Content _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Object\");", + "", + "if (objects.length === 0)", + " return;", + "", + "", + " const type =", + " String(", + " eventsFunctionContext.getArgument(\"Type\")", + " ).toUpperCase();", + "", + "", + "", + " const root =", + " objects[0].get3DRendererObject();", + "", + "", + " if (!root)", + " return;", + "", + "", + "", + " root.traverse(mesh =>", + " {", + " if (!mesh.isMesh)", + " return;", + "", + "", + " let material;", + "", + "", + " switch(type)", + " {", + "", + " case \"METAL\":", + " material = new THREE.MeshStandardMaterial({", + " metalness: 1,", + " roughness: 0.15", + " });", + " break;", + "", + "", + " case \"GLASS\":", + " material = new THREE.MeshPhysicalMaterial({", + " transmission: 1,", + " roughness: 0,", + " transparent: true,", + " opacity: 0.35,", + " ior: 1.5", + " });", + " break;", + "", + "", + " case \"WATER\":", + " material = new THREE.MeshPhysicalMaterial({", + " transmission: 0.8,", + " roughness: 0.05,", + " transparent: true,", + " opacity: 0.7,", + " ior: 1.33", + " });", + " break;", + "", + "", + " case \"PLASTIC\":", + " material = new THREE.MeshStandardMaterial({", + " metalness: 0,", + " roughness: 0.35", + " });", + " break;", + "", + "", + " case \"WOOD\":", + " material = new THREE.MeshStandardMaterial({", + " roughness: 0.7,", + " metalness: 0", + " });", + " break;", + "", + "", + " case \"STONE\":", + " case \"CONCRETE\":", + " case \"BRICK\":", + " material = new THREE.MeshStandardMaterial({", + " roughness: 0.95,", + " metalness: 0", + " });", + " break;", + "", + "", + " case \"ICE\":", + " material = new THREE.MeshPhysicalMaterial({", + " transmission: 0.6,", + " roughness: 0.1,", + " ior: 1.31,", + " transparent: true", + " });", + " break;", + "", + "", + " case \"SNOW\":", + " material = new THREE.MeshStandardMaterial({", + " roughness: 0.95,", + " metalness: 0", + " });", + " break;", + "", + "", + " case \"RUBBER\":", + " material = new THREE.MeshStandardMaterial({", + " roughness: 0.8,", + " metalness: 0", + " });", + " break;", + "", + "", + " case \"CHROME\":", + " material = new THREE.MeshStandardMaterial({", + " metalness: 1,", + " roughness: 0", + " });", + " break;", + "", + "", + " case \"GOLD\":", + " material = new THREE.MeshStandardMaterial({", + " color: 0xffd700,", + " metalness: 1,", + " roughness: 0.2", + " });", + " break;", + "", + "", + " case \"SILVER\":", + " material = new THREE.MeshStandardMaterial({", + " color: 0xffffff,", + " metalness: 1,", + " roughness: 0.15", + " });", + " break;", + "", + "", + " case \"EMISSIVE\":", + " material = new THREE.MeshStandardMaterial({", + " emissive: 0xffffff,", + " emissiveIntensity: 3", + " });", + " break;", + "", + "", + " case \"FABRIC\":", + " material = new THREE.MeshStandardMaterial({", + " roughness: 1,", + " metalness: 0", + " });", + "", + " material.sheen = 1;", + " break;", + "", + "", + " case \"LEATHER\":", + " material = new THREE.MeshStandardMaterial({", + " roughness: 0.65,", + " metalness: 0", + " });", + "", + " material.sheen = 0.2;", + " break;", + "", + "", + " case \"CERAMIC\":", + " material = new THREE.MeshPhysicalMaterial({", + " roughness: 0.25,", + " clearcoat: 0.4", + " });", + " break;", + "", + "", + " case \"MARBLE\":", + " material = new THREE.MeshPhysicalMaterial({", + " roughness: 0.35,", + " clearcoat: 0.2", + " });", + " break;", + "", + "", + " default:", + " console.warn(", + " \"Unknown material type:\",", + " type", + " );", + " return;", + " }", + "", + "", + "", + " // keep old color if possible", + " if(mesh.material && mesh.material.color)", + " {", + " material.color.copy(", + " mesh.material.color", + " );", + " }", + "", + "", + " mesh.material.dispose();", + "", + " mesh.material = material;", + "", + " mesh.material.needsUpdate = true;", + "", + " });", + "", + "", + " console.log(", + " \"Material changed to:\",", + " type", + " );" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + }, + { + "description": "Type", + "name": "Type", + "supplementaryInformation": "[\"METAL\",\"GLASS\",\"WATER\",\"WOOD\",\"STONE\",\"CONCRETE\",\"BRICK\",\"ICE\",\"SNOW\",\"RUBBER\",\"CHROME\",\"SILVER\",\"GOLD\",\"EMISSIVE\",\"FABRIC\",\"LEATHER\",\"CERAMIC\",\"MARBLE\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "description": "Deform Mesh From a Point, Useful For Car Hit Deformations.", + "fullName": "Mesh Deformation", + "functionType": "Action", + "group": "Mesh", + "name": "MeshDeformer", + "sentence": "Mesh Deformation _PARAM1_,_PARAM2_,_PARAM3_,_PARAM4_,_PARAM5_,_PARAM6_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Object\");", + "", + "if (objects.length === 0)", + " return;", + "", + "", + " const centerX = Number(eventsFunctionContext.getArgument(\"X\"));", + " const centerY = Number(eventsFunctionContext.getArgument(\"Y\"));", + " const centerZ = Number(eventsFunctionContext.getArgument(\"Z\"));", + "", + " const strength = Number(eventsFunctionContext.getArgument(\"Strength\"));", + "", + "", + " const root = objects[0].get3DRendererObject();", + "", + " if (!root)", + " return;", + "", + "", + "", + " const center = new THREE.Vector3(", + " centerX,", + " centerY,", + " centerZ", + " );", + "", + "", + "", + " root.traverse(mesh =>", + " {", + " if (!mesh.isMesh)", + " return;", + "", + "", + " const geometry = mesh.geometry;", + "", + " const position =", + " geometry.attributes.position;", + "", + "", + " if (!position)", + " return;", + "", + "", + "", + " for (let i = 0; i < position.count; i++)", + " {", + "", + " const vertex = new THREE.Vector3(", + " position.getX(i),", + " position.getY(i),", + " position.getZ(i)", + " );", + "", + "", + " const distance =", + " vertex.distanceTo(center);", + "", + "", + "", + " // closer vertices deform more", + " const falloff =", + " Math.max(0, 1 - distance);", + "", + "", + "", + " const direction =", + " new THREE.Vector3()", + " .subVectors(center, vertex)", + " .normalize();", + "", + "", + "", + " vertex.add(", + " direction.multiplyScalar(", + " strength * falloff", + " )", + " );", + "", + "", + "", + " position.setXYZ(", + " i,", + " vertex.x,", + " vertex.y,", + " vertex.z", + " );", + "", + " }", + "", + "", + " position.needsUpdate = true;", + "", + " geometry.computeVertexNormals();", + "", + " });", + "", + "", + " console.log(", + " \"Mesh pulled toward:\",", + " centerX,", + " centerY,", + " centerZ", + " );" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + }, + { + "description": "X", + "name": "X", + "type": "expression" + }, + { + "description": "Y", + "name": "Y", + "type": "expression" + }, + { + "description": "Z", + "name": "Z", + "type": "expression" + }, + { + "description": "Strength", + "name": "Strength", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Split a Large Mesh Into Smaller Pieces.", + "fullName": "Mesh Component Splitting", + "functionType": "Action", + "group": "Mesh", + "name": "MeshSpliting", + "sentence": "Mesh Component Splitting _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const objects = eventsFunctionContext.getObjects(\"Object\");", + "", + "if (objects.length === 0)", + " return;", + "", + "", + " const root = objects[0].get3DRendererObject();", + "", + " if (!root)", + " return;", + "", + "", + "", + " root.traverse(mesh =>", + " {", + " if (!mesh.isMesh)", + " return;", + "", + "", + " const geometry = mesh.geometry;", + "", + " const pos = geometry.attributes.position;", + "", + " const index = geometry.index;", + "", + "", + " if (!pos || !index)", + " return;", + "", + "", + "", + " // Build vertex connection map", + "", + " const connections = [];", + "", + " for (let i = 0; i < pos.count; i++)", + " connections[i] = new Set();", + "", + "", + "", + " for (let i = 0; i < index.count; i += 3)", + " {", + " const a = index.getX(i);", + " const b = index.getX(i+1);", + " const c = index.getX(i+2);", + "", + "", + " connections[a].add(b);", + " connections[a].add(c);", + "", + " connections[b].add(a);", + " connections[b].add(c);", + "", + " connections[c].add(a);", + " connections[c].add(b);", + " }", + "", + "", + "", + " // Find connected islands", + "", + " const visited = new Set();", + "", + " const parts = [];", + "", + "", + " for (let v = 0; v < pos.count; v++)", + " {", + " if (visited.has(v))", + " continue;", + "", + "", + " const group = [];", + "", + " const stack = [v];", + "", + " visited.add(v);", + "", + "", + " while(stack.length)", + " {", + " const current = stack.pop();", + "", + " group.push(current);", + "", + "", + " connections[current].forEach(next =>", + " {", + " if (!visited.has(next))", + " {", + " visited.add(next);", + " stack.push(next);", + " }", + " });", + "", + " }", + "", + "", + " parts.push(group);", + " }", + "", + "", + "", + " if (parts.length <= 1)", + " {", + " console.log(\"No separate parts found\");", + " return;", + " }", + "", + "", + "", + " const parent = mesh.parent;", + "", + "", + "", + " parts.forEach((vertices, id) =>", + " {", + "", + " const vertexMap = new Map();", + "", + " const newPositions = [];", + "", + " const newIndices = [];", + "", + "", + "", + " vertices.forEach((old, i) =>", + " {", + " vertexMap.set(old, i);", + "", + " newPositions.push(", + " pos.getX(old),", + " pos.getY(old),", + " pos.getZ(old)", + " );", + " });", + "", + "", + "", + " for (let i = 0; i < index.count; i += 3)", + " {", + " const a = index.getX(i);", + " const b = index.getX(i+1);", + " const c = index.getX(i+2);", + "", + "", + " if (", + " vertexMap.has(a) &&", + " vertexMap.has(b) &&", + " vertexMap.has(c)", + " )", + " {", + " newIndices.push(", + " vertexMap.get(a),", + " vertexMap.get(b),", + " vertexMap.get(c)", + " );", + " }", + " }", + "", + "", + "", + " const newGeo =", + " new THREE.BufferGeometry();", + "", + "", + " newGeo.setAttribute(", + " \"position\",", + " new THREE.Float32BufferAttribute(", + " newPositions,", + " 3", + " )", + " );", + "", + "", + " newGeo.setIndex(newIndices);", + "", + " newGeo.computeVertexNormals();", + "", + "", + "", + " const newMesh =", + " new THREE.Mesh(", + " newGeo,", + " mesh.material", + " );", + "", + "", + " newMesh.name =", + " mesh.name + \"_Part_\" + id;", + "", + "", + " newMesh.position.copy(mesh.position);", + " newMesh.rotation.copy(mesh.rotation);", + " newMesh.scale.copy(mesh.scale);", + "", + "", + "", + " parent.add(newMesh);", + "", + " });", + "", + "", + "", + " mesh.visible = false;", + "", + "", + " console.log(", + " \"Demeshed:\",", + " parts.length,", + " \"parts\"", + " );", + "", + " });" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "folderName": "World Settings", + "children": [ + { + "functionName": "ToneMapping" + } + ] + }, + { + "folderName": "Debug", + "children": [ + { + "functionName": "ShowWireFrame" + } + ] + }, + { + "folderName": "Mesh", + "children": [ + { + "functionName": "MoveMesh" + }, + { + "functionName": "RotateMesh" + }, + { + "functionName": "SizeMesh" + }, + { + "functionName": "ObjectVisible" + }, + { + "functionName": "MergeOBJ" + }, + { + "functionName": "DeleteMesh" + }, + { + "functionName": "DeleteAllMesh" + }, + { + "functionName": "SimplifyModel" + }, + { + "functionName": "MeshOptimiser" + }, + { + "functionName": "OptimiseVertecies" + }, + { + "functionName": "RemoveInvisTringle" + }, + { + "functionName": "OptimiseFaces" + }, + { + "functionName": "MeshDeformer" + }, + { + "functionName": "MeshSpliting" + } + ] + }, + { + "folderName": "Terrain", + "children": [ + { + "functionName": "CloudDlete" + }, + { + "functionName": "WaterDelete" + }, + { + "functionName": "DeleteTerrain" + }, + { + "functionName": "CloudGen" + }, + { + "functionName": "MoutainGen" + }, + { + "functionName": "TerrainGen" + }, + { + "functionName": "TerrainTexturedGen" + }, + { + "functionName": "Water" + }, + { + "functionName": "Grass" + }, + { + "functionName": "CreatePath" + }, + { + "functionName": "RenderSky" + }, + { + "functionName": "RenderSkyTime" + }, + { + "functionName": "CreateLight" + } + ] + }, + { + "folderName": "Appearance", + "children": [ + { + "functionName": "ReplaceModelMaterial" + }, + { + "functionName": "TintMaterial" + }, + { + "functionName": "ReplaceModelTexture" + }, + { + "functionName": "ChnageOpacity" + }, + { + "functionName": "Tint3DModel" + }, + { + "functionName": "TextureResolution" + }, + { + "functionName": "TextureResMesh" + }, + { + "functionName": "ChnageMaterial" + } + ] + }, + { + "folderName": "Information", + "children": [ + { + "functionName": "ModelFileSize" + }, + { + "functionName": "UVCount" + }, + { + "functionName": "MemoryUsage" + }, + { + "functionName": "MaterialCount" + }, + { + "functionName": "VerticesCount" + }, + { + "functionName": "TriangleCount" + }, + { + "functionName": "MeshNameInsideGroup" + }, + { + "functionName": "MeshName" + }, + { + "functionName": "MeshCount" + }, + { + "functionName": "GlbName" + } + ] + } + ] + }, + "eventsBasedBehaviors": [], + "eventsBasedObjects": [] +}