diff --git a/Extensions/3D/JsExtension.js b/Extensions/3D/JsExtension.js
index a1600760912c..5ba30f92b0a4 100644
--- a/Extensions/3D/JsExtension.js
+++ b/Extensions/3D/JsExtension.js
@@ -3071,9 +3071,9 @@ module.exports = {
/** @type {number} */
_defaultDepth;
- /** @type {[number, number, number] | null} */
+ /** @type {[number | null, number | null, number | null]} */
_originPoint;
- /** @type {[number, number, number] | null} */
+ /** @type {[number | null, number | null, number | null]} */
_centerPoint;
/** @type {[number, number, number]} */
@@ -3168,11 +3168,31 @@ module.exports = {
}
getOriginPoint() {
- return this._originPoint || this._modelOriginPoint;
+ return [
+ this._originPoint[0] === null
+ ? this._modelOriginPoint[0]
+ : this._originPoint[0],
+ this._originPoint[1] === null
+ ? this._modelOriginPoint[1]
+ : this._originPoint[1],
+ this._originPoint[2] === null
+ ? this._modelOriginPoint[2]
+ : this._originPoint[2],
+ ];
}
getCenterPoint() {
- return this._centerPoint || this._modelOriginPoint;
+ return [
+ this._centerPoint[0] === null
+ ? this._modelOriginPoint[0]
+ : this._centerPoint[0],
+ this._centerPoint[1] === null
+ ? this._modelOriginPoint[1]
+ : this._centerPoint[1],
+ this._centerPoint[2] === null
+ ? this._modelOriginPoint[2]
+ : this._centerPoint[2],
+ ];
}
_updateDefaultTransformation(
@@ -3219,12 +3239,23 @@ module.exports = {
// Center the model.
const centerPoint = this._centerPoint;
- if (centerPoint) {
- threeObject.position.set(
- -(boundingBox.min.x + modelWidth * centerPoint[0]),
- // The model is flipped on Y axis.
- -(boundingBox.min.y + modelHeight * (1 - centerPoint[1])),
- -(boundingBox.min.z + modelDepth * centerPoint[2])
+ if (centerPoint[0]) {
+ threeObject.position.x = -(
+ boundingBox.min.x +
+ modelWidth * centerPoint[0]
+ );
+ }
+ if (centerPoint[1]) {
+ // The model is flipped on Y axis.
+ threeObject.position.y = -(
+ boundingBox.min.y +
+ modelHeight * (1 - centerPoint[1])
+ );
+ }
+ if (centerPoint[2]) {
+ threeObject.position.z = -(
+ boundingBox.min.z +
+ modelDepth * centerPoint[2]
);
}
@@ -3320,8 +3351,8 @@ module.exports = {
}
/**
- * @param {[number, number, number] | null} point1
- * @param {[number, number, number] | null} point2
+ * @param {[number | null, number | null, number | null]} point1
+ * @param {[number | null, number | null, number | null]} point2
* @returns {boolean}
*/
const isSamePoint = (point1, point2) => {
@@ -3337,14 +3368,16 @@ module.exports = {
/**
* @param {string} location
- * @returns {[number, number, number] | null}
+ * @returns {[number | null, number | null, number | null]}
*/
const getPointForLocation = (location) => {
switch (location) {
case 'ModelOrigin':
- return null;
+ return [null, null, null];
case 'ObjectCenter':
return [0.5, 0.5, 0.5];
+ case 'CenteredOnZ':
+ return [null, null, 0.5];
case 'BottomCenterZ':
return [0.5, 0.5, 0];
case 'BottomCenterY':
@@ -3352,7 +3385,7 @@ module.exports = {
case 'TopLeft':
return [0, 0, 0];
default:
- return null;
+ return [null, null, null];
}
};
@@ -3367,10 +3400,10 @@ module.exports = {
_rotationY = 0;
_rotationZ = 0;
_keepAspectRatio = false;
- /** @type {[number, number, number] | null} */
- _originPoint = null;
- /** @type {[number, number, number] | null} */
- _centerPoint = null;
+ /** @type {[number | null, number | null, number | null]} */
+ _originPoint = [null, null, null];
+ /** @type {[number | null, number | null, number | null]} */
+ _centerPoint = [null, null, null];
/** @type {[number, number, number]} */
_modelOriginPoint = [0, 0, 0];
@@ -3436,11 +3469,31 @@ module.exports = {
}
getOriginPoint() {
- return this._originPoint || this._modelOriginPoint;
+ return [
+ this._originPoint[0] === null
+ ? this._modelOriginPoint[0]
+ : this._originPoint[0],
+ this._originPoint[1] === null
+ ? this._modelOriginPoint[1]
+ : this._originPoint[1],
+ this._originPoint[2] === null
+ ? this._modelOriginPoint[2]
+ : this._originPoint[2],
+ ];
}
getCenterPoint() {
- return this._centerPoint || this._modelOriginPoint;
+ return [
+ this._centerPoint[0] === null
+ ? this._modelOriginPoint[0]
+ : this._centerPoint[0],
+ this._centerPoint[1] === null
+ ? this._modelOriginPoint[1]
+ : this._centerPoint[1],
+ this._centerPoint[2] === null
+ ? this._modelOriginPoint[2]
+ : this._centerPoint[2],
+ ];
}
_updateDefaultTransformation() {
@@ -3493,12 +3546,23 @@ module.exports = {
// Center the model.
const centerPoint = this._centerPoint;
- if (centerPoint) {
- threeModelGroup.position.set(
- -(boundingBox.min.x + modelWidth * centerPoint[0]),
- // The model is flipped on Y axis.
- -(boundingBox.min.y + modelHeight * (1 - centerPoint[1])),
- -(boundingBox.min.z + modelDepth * centerPoint[2])
+ if (centerPoint[0] !== null) {
+ threeModelGroup.position.x = -(
+ boundingBox.min.x +
+ modelWidth * centerPoint[0]
+ );
+ }
+ if (centerPoint[1] !== null) {
+ // The model is flipped on Y axis.
+ threeModelGroup.position.y = -(
+ boundingBox.min.y +
+ modelHeight * (1 - centerPoint[1])
+ );
+ }
+ if (centerPoint[2] !== null) {
+ threeModelGroup.position.z = -(
+ boundingBox.min.z +
+ modelDepth * centerPoint[2]
);
}
diff --git a/Extensions/3D/Model3DObjectConfiguration.cpp b/Extensions/3D/Model3DObjectConfiguration.cpp
index c3067342fcc3..68900235da06 100644
--- a/Extensions/3D/Model3DObjectConfiguration.cpp
+++ b/Extensions/3D/Model3DObjectConfiguration.cpp
@@ -22,7 +22,7 @@ using namespace std;
Model3DObjectConfiguration::Model3DObjectConfiguration()
: width(100), height(100), depth(100), rotationX(90), rotationY(0),
rotationZ(90), modelResourceName(""), materialType("StandardWithoutMetalness"),
- originLocation("ModelOrigin"), centerLocation("ModelOrigin"),
+ originLocation("ModelOrigin"), centerLocation("CenteredOnZ"),
keepAspectRatio(true), crossfadeDuration(0.1f), isCastingShadow(true), isReceivingShadow(true) {}
bool Model3DObjectConfiguration::UpdateProperty(const gd::String &propertyName,
@@ -89,6 +89,8 @@ bool Model3DObjectConfiguration::UpdateProperty(const gd::String &propertyName,
centerLocation = "ModelOrigin";
else if (normalizedValue == "objectcenter")
centerLocation = "ObjectCenter";
+ else if (normalizedValue == "centeredonz")
+ centerLocation = "CenteredOnZ";
else if (normalizedValue == "bottomcenterz")
centerLocation = "BottomCenterZ";
else if (normalizedValue == "bottomcentery")
@@ -206,6 +208,7 @@ Model3DObjectConfiguration::GetProperties() const {
.SetType("choice")
.AddChoice("ModelOrigin", _("Model origin"))
.AddChoice("ObjectCenter", _("Object center"))
+ .AddChoice("CenteredOnZ", _("Centered on Z only"))
.AddChoice("BottomCenterZ", _("Bottom center (Z)"))
.AddChoice("BottomCenterY", _("Bottom center (Y)"))
.SetLabel(_("Center point"))
diff --git a/Extensions/3D/Model3DRuntimeObject.ts b/Extensions/3D/Model3DRuntimeObject.ts
index 5c6aba48f9d1..300cda4f18c8 100644
--- a/Extensions/3D/Model3DRuntimeObject.ts
+++ b/Extensions/3D/Model3DRuntimeObject.ts
@@ -3,8 +3,8 @@ namespace gdjs {
type Model3DObjectNetworkSyncDataType = {
mt: number;
- op: FloatPoint3D | null;
- cp: FloatPoint3D | null;
+ op: LocationPoint | null;
+ cp: LocationPoint | null;
anis: Model3DAnimation[];
ai: integer;
ass: float;
@@ -38,6 +38,7 @@ namespace gdjs {
centerLocation:
| 'ModelOrigin'
| 'ObjectCenter'
+ | 'CenteredOnZ'
| 'BottomCenterZ'
| 'BottomCenterY';
animations: Model3DAnimation[];
@@ -47,12 +48,14 @@ namespace gdjs {
};
}
- type FloatPoint3D = [float, float, float];
+ type LocationPoint = [float | null, float | null, float | null];
- const getPointForLocation = (location: string): FloatPoint3D | null => {
+ const getPointForLocation = (location: string): LocationPoint => {
switch (location) {
case 'ModelOrigin':
- return null;
+ return [null, null, null];
+ case 'CenteredOnZ':
+ return [null, null, 0.5];
case 'ObjectCenter':
return [0.5, 0.5, 0.5];
case 'BottomCenterZ':
@@ -62,7 +65,7 @@ namespace gdjs {
case 'TopLeft':
return [0, 0, 0];
default:
- return null;
+ return [null, null, null];
}
};
@@ -90,7 +93,7 @@ namespace gdjs {
* configuration.
* @see gdjs.Model3DRuntimeObject3DRenderer.getOriginPoint
*/
- _originPoint: FloatPoint3D | null;
+ _originPoint: LocationPoint;
/**
* The local point of the model that is used as rotation center.
*
@@ -101,7 +104,7 @@ namespace gdjs {
* configuration.
* @see gdjs.Model3DRuntimeObject3DRenderer.getCenterPoint
*/
- _centerPoint: FloatPoint3D | null;
+ _centerPoint: LocationPoint;
_animations: Model3DAnimation[];
_currentAnimationIndex: integer = 0;
@@ -275,10 +278,10 @@ namespace gdjs {
this._materialType = networkSyncData.mt;
}
if (networkSyncData.op !== undefined) {
- this._originPoint = networkSyncData.op;
+ this._originPoint = networkSyncData.op || [null, null, null];
}
if (networkSyncData.cp !== undefined) {
- this._centerPoint = networkSyncData.cp;
+ this._centerPoint = networkSyncData.cp || [null, null, null];
}
if (networkSyncData.anis !== undefined) {
this._animations = networkSyncData.anis;
diff --git a/Extensions/3D/Model3DRuntimeObject3DRenderer.ts b/Extensions/3D/Model3DRuntimeObject3DRenderer.ts
index 1b08ce28fcd4..1bd06bc122c7 100644
--- a/Extensions/3D/Model3DRuntimeObject3DRenderer.ts
+++ b/Extensions/3D/Model3DRuntimeObject3DRenderer.ts
@@ -130,12 +130,34 @@ namespace gdjs {
);
}
- getOriginPoint() {
- return this._model3DRuntimeObject._originPoint || this._modelOriginPoint;
+ getOriginPoint(): FloatPoint3D {
+ //@ts-ignore
+ const point: FloatPoint3D = gdjs.staticArray(
+ Model3DRuntimeObject3DRenderer.prototype.getOriginPoint
+ );
+ const originPoint = this._model3DRuntimeObject._originPoint;
+ point[0] =
+ originPoint[0] === null ? this._modelOriginPoint[0] : originPoint[0];
+ point[1] =
+ originPoint[1] === null ? this._modelOriginPoint[1] : originPoint[1];
+ point[2] =
+ originPoint[2] === null ? this._modelOriginPoint[2] : originPoint[2];
+ return point;
}
- getCenterPoint() {
- return this._model3DRuntimeObject._centerPoint || this._modelOriginPoint;
+ getCenterPoint(): FloatPoint3D {
+ //@ts-ignore
+ const point: FloatPoint3D = gdjs.staticArray(
+ Model3DRuntimeObject3DRenderer.prototype.getCenterPoint
+ );
+ const centerPoint = this._model3DRuntimeObject._centerPoint;
+ point[0] =
+ centerPoint[0] === null ? this._modelOriginPoint[0] : centerPoint[0];
+ point[1] =
+ centerPoint[1] === null ? this._modelOriginPoint[1] : centerPoint[1];
+ point[2] =
+ centerPoint[2] === null ? this._modelOriginPoint[2] : centerPoint[2];
+ return point;
}
/**
@@ -177,12 +199,23 @@ namespace gdjs {
// Center the model.
const centerPoint = this._model3DRuntimeObject._centerPoint;
- if (centerPoint) {
- threeObject.position.set(
- -(boundingBox.min.x + modelWidth * centerPoint[0]),
- // The model is flipped on Y axis.
- -(boundingBox.min.y + modelHeight * (1 - centerPoint[1])),
- -(boundingBox.min.z + modelDepth * centerPoint[2])
+ if (centerPoint[0] !== null) {
+ threeObject.position.x = -(
+ boundingBox.min.x +
+ modelWidth * centerPoint[0]
+ );
+ }
+ if (centerPoint[1] !== null) {
+ // The model is flipped on Y axis.
+ threeObject.position.y = -(
+ boundingBox.min.y +
+ modelHeight * (1 - centerPoint[1])
+ );
+ }
+ if (centerPoint[2] !== null) {
+ threeObject.position.z = -(
+ boundingBox.min.z +
+ modelDepth * centerPoint[2]
);
}
diff --git a/newIDE/app/src/ObjectEditor/Editors/Model3DEditor.js b/newIDE/app/src/ObjectEditor/Editors/Model3DEditor.js
index 554a25d67bfb..0e42e9beb6b2 100644
--- a/newIDE/app/src/ObjectEditor/Editors/Model3DEditor.js
+++ b/newIDE/app/src/ObjectEditor/Editors/Model3DEditor.js
@@ -32,6 +32,7 @@ import * as SkeletonUtils from 'three/examples/jsm/utils/SkeletonUtils';
import * as THREE from 'three';
import { PropertyCheckbox, PropertyField } from './PropertyFields';
import ResourceSelectorWithThumbnail from '../../ResourcesList/ResourceSelectorWithThumbnail';
+import { ChoiceProperty } from '../../BehaviorsEditor/Editors/Physics2Editor';
const gd: libGDevelop = global.gd;
@@ -188,8 +189,7 @@ const Model3DEditor = ({
properties.get('originLocation').getValue()
);
const onOriginLocationChange = React.useCallback(
- // $FlowFixMe[missing-local-annot]
- (event, index: number, newValue: string) => {
+ (event: any, index: number, newValue: string) => {
onChangeProperty('originLocation', newValue);
setOriginLocation(newValue);
},
@@ -573,99 +573,27 @@ const Model3DEditor = ({
expand
noColumnMargin
>
-
-
-
-
-
-
-
- {
+
+ {
onChangeProperty('centerLocation', newValue);
}}
- fullWidth
- >
-
-
-
-
-
+ />
Lighting
- {
+ {
onChangeProperty('materialType', newValue);
}}
- >
-
-
-
-
+ />
{properties.get('materialType').getValue() !== 'Basic' &&
!hasLight(layout) && (