mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
78 Commits
cursor/ini
...
experiment
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e2c5c1be74 | ||
![]() |
e53d1d830e | ||
![]() |
f7625194f5 | ||
![]() |
da2de649ab | ||
![]() |
be6e05bfad | ||
![]() |
ad6ee2342c | ||
![]() |
8c840480b0 | ||
![]() |
92c1bc9199 | ||
![]() |
aaab5f5ae1 | ||
![]() |
dafa56d2f2 | ||
![]() |
a92a7ee3ce | ||
![]() |
2629755290 | ||
![]() |
ec6470bd72 | ||
![]() |
4615a6456a | ||
![]() |
1b1ea873ae | ||
![]() |
81b3c69618 | ||
![]() |
c2eb58360c | ||
![]() |
e1159b3748 | ||
![]() |
2022af743b | ||
![]() |
7828970797 | ||
![]() |
289b001584 | ||
![]() |
b35f427451 | ||
![]() |
6edb7aaec9 | ||
![]() |
e8a4be338c | ||
![]() |
1ebab8ba95 | ||
![]() |
ec37b03548 | ||
![]() |
6c3ff254db | ||
![]() |
b3675cd3c6 | ||
![]() |
76f70dfc36 | ||
![]() |
5ce9ec2283 | ||
![]() |
32d70ff5b7 | ||
![]() |
58fa20591c | ||
![]() |
df54f30221 | ||
![]() |
6a109a7e44 | ||
![]() |
ac4172ec33 | ||
![]() |
c15aeb6a82 | ||
![]() |
ccf5859596 | ||
![]() |
b5f5bfa1c0 | ||
![]() |
bd473029e0 | ||
![]() |
c77ac93c0b | ||
![]() |
72cb5a7f2c | ||
![]() |
772a6980e1 | ||
![]() |
63f637c44f | ||
![]() |
18c7eef5b2 | ||
![]() |
79b331d009 | ||
![]() |
06776447f2 | ||
![]() |
c1fe0a4e61 | ||
![]() |
d68920e84d | ||
![]() |
79e868f1fe | ||
![]() |
2a556c9e4e | ||
![]() |
dfb98df8fb | ||
![]() |
8bff97c586 | ||
![]() |
af0779d902 | ||
![]() |
cdc9e0b85a | ||
![]() |
ae32d09a09 | ||
![]() |
a8ed839003 | ||
![]() |
bdbf6a1a3b | ||
![]() |
9a301b4737 | ||
![]() |
6113769520 | ||
![]() |
775c02a57e | ||
![]() |
fb299d428a | ||
![]() |
acaee8e728 | ||
![]() |
4230ef7780 | ||
![]() |
68b45e301e | ||
![]() |
e7fddec3ad | ||
![]() |
bf3c4ba2e8 | ||
![]() |
9742310d1d | ||
![]() |
540b507895 | ||
![]() |
91fdf7009f | ||
![]() |
582371f954 | ||
![]() |
a9fe0bb661 | ||
![]() |
259b8eefe7 | ||
![]() |
a3428e92fb | ||
![]() |
38df69378b | ||
![]() |
74269731db | ||
![]() |
b3febdcec7 | ||
![]() |
5decafa778 | ||
![]() |
96b053f699 |
@@ -695,7 +695,7 @@ module.exports = {
|
||||
.addCondition(
|
||||
'IsDynamic',
|
||||
_('Is dynamic'),
|
||||
_('Test if an object is dynamic.'),
|
||||
_('Check if an object is dynamic.'),
|
||||
_('_PARAM0_ is dynamic'),
|
||||
_('Dynamics'),
|
||||
'res/physics32.png',
|
||||
@@ -727,7 +727,7 @@ module.exports = {
|
||||
.addCondition(
|
||||
'IsStatic',
|
||||
_('Is static'),
|
||||
_('Test if an object is static.'),
|
||||
_('Check if an object is static.'),
|
||||
_('_PARAM0_ is static'),
|
||||
_('Dynamics'),
|
||||
'res/physics32.png',
|
||||
@@ -759,7 +759,7 @@ module.exports = {
|
||||
.addCondition(
|
||||
'IsKinematic',
|
||||
_('Is kinematic'),
|
||||
_('Test if an object is kinematic.'),
|
||||
_('Check if an object is kinematic.'),
|
||||
_('_PARAM0_ is kinematic'),
|
||||
_('Dynamics'),
|
||||
'res/physics32.png',
|
||||
@@ -790,9 +790,9 @@ module.exports = {
|
||||
aut
|
||||
.addCondition(
|
||||
'IsBullet',
|
||||
_('Is treat as bullet'),
|
||||
_('Test if an object is being treat as a bullet.'),
|
||||
_('_PARAM0_ is bullet'),
|
||||
_('Is treated as a bullet'),
|
||||
_('Check if the object is being treated as a bullet.'),
|
||||
_('_PARAM0_ is treated as a bullet'),
|
||||
_('Dynamics'),
|
||||
'res/physics32.png',
|
||||
'res/physics32.png'
|
||||
@@ -825,7 +825,7 @@ module.exports = {
|
||||
.addCondition(
|
||||
'HasFixedRotation',
|
||||
_('Has fixed rotation'),
|
||||
_('Test if an object has fixed rotation.'),
|
||||
_('Check if an object has fixed rotation.'),
|
||||
_('_PARAM0_ has fixed rotation'),
|
||||
_('Dynamics'),
|
||||
'res/physics32.png',
|
||||
@@ -859,7 +859,7 @@ module.exports = {
|
||||
.addCondition(
|
||||
'IsSleepingAllowed',
|
||||
_('Is sleeping allowed'),
|
||||
_('Test if an object can sleep.'),
|
||||
_('Check if an object can sleep.'),
|
||||
_('_PARAM0_ can sleep'),
|
||||
_('Dynamics'),
|
||||
'res/physics32.png',
|
||||
@@ -898,7 +898,7 @@ module.exports = {
|
||||
.addCondition(
|
||||
'IsSleeping',
|
||||
_('Is sleeping'),
|
||||
_('Test if an object is sleeping.'),
|
||||
_('Check if an object is sleeping.'),
|
||||
_('_PARAM0_ is sleeping'),
|
||||
_('Dynamics'),
|
||||
'res/physics32.png',
|
||||
@@ -1267,7 +1267,7 @@ module.exports = {
|
||||
.addCondition(
|
||||
'LayerEnabled',
|
||||
_('Layer enabled'),
|
||||
_('Test if an object has a specific layer enabled.'),
|
||||
_('Check if an object has a specific layer enabled.'),
|
||||
_('_PARAM0_ has layer _PARAM2_ enabled'),
|
||||
_('Filtering'),
|
||||
'res/physics32.png',
|
||||
@@ -1303,7 +1303,7 @@ module.exports = {
|
||||
.addCondition(
|
||||
'MaskEnabled',
|
||||
_('Mask enabled'),
|
||||
_('Test if an object has a specific mask enabled.'),
|
||||
_('Check if an object has a specific mask enabled.'),
|
||||
_('_PARAM0_ has mask _PARAM2_ enabled'),
|
||||
_('Filtering'),
|
||||
'res/physics32.png',
|
||||
@@ -1897,7 +1897,7 @@ module.exports = {
|
||||
.addCondition(
|
||||
'JointFirstObject',
|
||||
_('Joint first object'),
|
||||
_('Test if an object is the first object on a joint.'),
|
||||
_('Check if an object is the first object on a joint.'),
|
||||
_('_PARAM0_ is the first object for joint _PARAM2_'),
|
||||
_('Joints'),
|
||||
'res/physics32.png',
|
||||
@@ -1913,7 +1913,7 @@ module.exports = {
|
||||
.addCondition(
|
||||
'JointSecondObject',
|
||||
_('Joint second object'),
|
||||
_('Test if an object is the second object on a joint.'),
|
||||
_('Check if an object is the second object on a joint.'),
|
||||
_('_PARAM0_ is the second object for joint _PARAM2_'),
|
||||
_('Joints'),
|
||||
'res/physics32.png',
|
||||
@@ -2382,7 +2382,7 @@ module.exports = {
|
||||
.addCondition(
|
||||
'RevoluteJointLimitsEnabled',
|
||||
_('Revolute joint limits enabled'),
|
||||
_('Test if a revolute joint limits are enabled.'),
|
||||
_('Check if a revolute joint limits are enabled.'),
|
||||
_('Limits for revolute joint _PARAM2_ are enabled'),
|
||||
_('Joints/Revolute'),
|
||||
'JsPlatform/Extensions/revolute_joint24.png',
|
||||
@@ -2461,7 +2461,7 @@ module.exports = {
|
||||
.addCondition(
|
||||
'RevoluteJointMotorEnabled',
|
||||
_('Revolute joint motor enabled'),
|
||||
_('Test if a revolute joint motor is enabled.'),
|
||||
_('Check if a revolute joint motor is enabled.'),
|
||||
_('Motor of revolute joint _PARAM2_ is enabled'),
|
||||
_('Joints/Revolute'),
|
||||
'JsPlatform/Extensions/revolute_joint24.png',
|
||||
@@ -2700,7 +2700,7 @@ module.exports = {
|
||||
.addCondition(
|
||||
'PrismaticJointLimitsEnabled',
|
||||
_('Prismatic joint limits enabled'),
|
||||
_('Test if a prismatic joint limits are enabled.'),
|
||||
_('Check if a prismatic joint limits are enabled.'),
|
||||
_('Limits for prismatic joint _PARAM2_ are enabled'),
|
||||
_('Joints/Prismatic'),
|
||||
'JsPlatform/Extensions/prismatic_joint24.png',
|
||||
@@ -2779,7 +2779,7 @@ module.exports = {
|
||||
.addCondition(
|
||||
'PrismaticJointMotorEnabled',
|
||||
_('Prismatic joint motor enabled'),
|
||||
_('Test if a prismatic joint motor is enabled.'),
|
||||
_('Check if a prismatic joint motor is enabled.'),
|
||||
_('Motor for prismatic joint _PARAM2_ is enabled'),
|
||||
_('Joints/Prismatic'),
|
||||
'JsPlatform/Extensions/prismatic_joint24.png',
|
||||
@@ -3459,7 +3459,7 @@ module.exports = {
|
||||
.addCondition(
|
||||
'WheelJointMotorEnabled',
|
||||
_('Wheel joint motor enabled'),
|
||||
_('Test if a wheel joint motor is enabled.'),
|
||||
_('Check if a wheel joint motor is enabled.'),
|
||||
_('Motor for wheel joint _PARAM2_ is enabled'),
|
||||
_('Joints/Wheel'),
|
||||
'JsPlatform/Extensions/wheel_joint24.png',
|
||||
@@ -4203,7 +4203,7 @@ module.exports = {
|
||||
.getCodeExtraInformation()
|
||||
.addIncludeFile('Extensions/Physics2Behavior/physics2tools.js')
|
||||
.addIncludeFile('Extensions/Physics2Behavior/physics2runtimebehavior.js')
|
||||
.setFunctionName('gdjs.physics2.objectsCollide');
|
||||
.setFunctionName('gdjs.physics2.areObjectsColliding');
|
||||
|
||||
extension
|
||||
.addCondition(
|
||||
|
@@ -1,6 +1,6 @@
|
||||
namespace gdjs {
|
||||
export namespace physics2 {
|
||||
export const objectsCollide = function (
|
||||
export const areObjectsColliding = function (
|
||||
objectsLists1: Hashtable<Array<gdjs.RuntimeObject>>,
|
||||
behaviorName: string,
|
||||
objectsLists2: Hashtable<Array<gdjs.RuntimeObject>>,
|
||||
|
2463
Extensions/Physics3DBehavior/JsExtension.js
Normal file
2463
Extensions/Physics3DBehavior/JsExtension.js
Normal file
File diff suppressed because it is too large
Load Diff
1884
Extensions/Physics3DBehavior/Physics3DRuntimeBehavior.ts
Normal file
1884
Extensions/Physics3DBehavior/Physics3DRuntimeBehavior.ts
Normal file
File diff suppressed because it is too large
Load Diff
90
Extensions/Physics3DBehavior/Physics3DTools.ts
Normal file
90
Extensions/Physics3DBehavior/Physics3DTools.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
namespace gdjs {
|
||||
export namespace physics3d {
|
||||
export const areObjectsColliding = function (
|
||||
objectsLists1: Hashtable<Array<gdjs.RuntimeObject>>,
|
||||
behaviorName: string,
|
||||
objectsLists2: Hashtable<Array<gdjs.RuntimeObject>>,
|
||||
behaviorName2: string,
|
||||
inverted: boolean
|
||||
) {
|
||||
return gdjs.evtTools.object.twoListsTest(
|
||||
gdjs.Physics3DRuntimeBehavior.areObjectsColliding,
|
||||
objectsLists1,
|
||||
objectsLists2,
|
||||
inverted,
|
||||
behaviorName
|
||||
);
|
||||
};
|
||||
|
||||
export const haveObjectsStartedColliding = function (
|
||||
objectsLists1: Hashtable<Array<gdjs.RuntimeObject>>,
|
||||
behaviorName: string,
|
||||
objectsLists2: Hashtable<Array<gdjs.RuntimeObject>>,
|
||||
behaviorName2: string,
|
||||
inverted: boolean
|
||||
) {
|
||||
return gdjs.evtTools.object.twoListsTest(
|
||||
gdjs.Physics3DRuntimeBehavior.hasCollisionStartedBetween,
|
||||
objectsLists1,
|
||||
objectsLists2,
|
||||
inverted,
|
||||
behaviorName
|
||||
);
|
||||
};
|
||||
|
||||
export const haveObjectsStoppedColliding = function (
|
||||
objectsLists1: Hashtable<Array<gdjs.RuntimeObject>>,
|
||||
behaviorName: string,
|
||||
objectsLists2: Hashtable<Array<gdjs.RuntimeObject>>,
|
||||
behaviorName2: string,
|
||||
inverted: boolean
|
||||
) {
|
||||
return gdjs.evtTools.object.twoListsTest(
|
||||
gdjs.Physics3DRuntimeBehavior.hasCollisionStoppedBetween,
|
||||
objectsLists1,
|
||||
objectsLists2,
|
||||
inverted,
|
||||
behaviorName
|
||||
);
|
||||
};
|
||||
|
||||
type BehaviorNamePair = { character: string; physics: string };
|
||||
|
||||
const isOnPlatformAdapter = (
|
||||
characterObject: gdjs.RuntimeObject,
|
||||
physicsObject: gdjs.RuntimeObject,
|
||||
behaviorNamePair: BehaviorNamePair
|
||||
): boolean => {
|
||||
const characterBehavior = characterObject.getBehavior(
|
||||
behaviorNamePair.character
|
||||
) as gdjs.PhysicsCharacter3DRuntimeBehavior;
|
||||
const physicsBehavior = physicsObject.getBehavior(
|
||||
behaviorNamePair.physics
|
||||
) as gdjs.Physics3DRuntimeBehavior;
|
||||
if (!characterBehavior || !physicsBehavior) {
|
||||
return false;
|
||||
}
|
||||
return characterBehavior.isOnFloorObject(physicsBehavior);
|
||||
};
|
||||
|
||||
const behaviorNamePair: BehaviorNamePair = { character: '', physics: '' };
|
||||
|
||||
export const isOnPlatform = (
|
||||
characterObjectsLists: Hashtable<Array<gdjs.RuntimeObject>>,
|
||||
characterBehaviorName: string,
|
||||
physicsObjectsLists: Hashtable<Array<gdjs.RuntimeObject>>,
|
||||
physicsBehaviorName: string,
|
||||
inverted: boolean
|
||||
) => {
|
||||
behaviorNamePair.character = characterBehaviorName;
|
||||
behaviorNamePair.physics = physicsBehaviorName;
|
||||
return gdjs.evtTools.object.twoListsTest(
|
||||
isOnPlatformAdapter,
|
||||
characterObjectsLists,
|
||||
physicsObjectsLists,
|
||||
inverted,
|
||||
behaviorNamePair
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
1423
Extensions/Physics3DBehavior/PhysicsCharacter3DRuntimeBehavior.ts
Normal file
1423
Extensions/Physics3DBehavior/PhysicsCharacter3DRuntimeBehavior.ts
Normal file
File diff suppressed because it is too large
Load Diff
4874
Extensions/Physics3DBehavior/jolt-physics.d.ts
vendored
Normal file
4874
Extensions/Physics3DBehavior/jolt-physics.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
describe('Physics3DRuntimeBehavior', () => {});
|
@@ -231,9 +231,13 @@ namespace gdjs {
|
||||
...super.getNetworkSyncData(),
|
||||
props: {
|
||||
cs: this._currentSpeed,
|
||||
|
||||
// TODO Try to remove these 3 fields from the synch
|
||||
// They are reset every frame and are not part of the state.
|
||||
rdx: this._requestedDeltaX,
|
||||
rdy: this._requestedDeltaY,
|
||||
ldy: this._lastDeltaY,
|
||||
|
||||
cfs: this._currentFallSpeed,
|
||||
cj: this._canJump,
|
||||
ldl: this._lastDirectionIsLeft,
|
||||
|
@@ -30,7 +30,12 @@
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="module">
|
||||
// import latest
|
||||
import initJolt from 'https://www.unpkg.com/jolt-physics/dist/jolt-physics.wasm-compat.js';
|
||||
//import initJolt from './Extensions/Physics3DBehavior/jolt-physics.multithread.wasm-compat.js';
|
||||
globalThis.initializeJoltPhysics = initJolt;
|
||||
</script>
|
||||
<!-- GDJS_CUSTOM_HTML -->
|
||||
<script>
|
||||
|
||||
|
2
newIDE/app/public/JsPlatform/Extensions/physics3d.svg
Normal file
2
newIDE/app/public/JsPlatform/Extensions/physics3d.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m7 0-6 3.5v7l6 3.5 6-3.5v-7l-6-3.5z" fill="#2e388a"/><g transform="translate(-.0405 .026)" fill="none" stroke="#53a6da" stroke-width=".7"><path d="m8.294 9.112c-1.291 0.7556-2.601 1.165-3.664 1.229-1.085 0.0656-1.803-0.2277-2.095-0.7272-0.2924-0.4996-0.1966-1.269 0.3921-2.183 0.5768-0.8956 1.575-1.837 2.866-2.593 1.291-0.7556 2.601-1.165 3.664-1.229 1.085-0.06552 1.803 0.2277 2.095 0.7272s0.1964 1.269-0.3862 2.174-1.581 1.846-2.872 2.602z"/><path d="m5.787 9.112c1.291 0.7556 2.601 1.165 3.664 1.229 1.085 0.0656 1.803-0.2277 2.095-0.7272 0.2924-0.4996 0.1966-1.269-0.3921-2.183-0.5768-0.8956-1.575-1.837-2.866-2.593-1.291-0.7556-2.601-1.165-3.664-1.229-1.085-0.06552-1.803 0.2277-2.095 0.7272s-0.1964 1.269 0.3862 2.174 1.581 1.846 2.872 2.602z"/><path d="m7.038 1.75c-0.5788 0-1.194 0.4711-1.686 1.441-0.4817 0.9502-0.7898 2.287-0.7898 3.783s0.3081 2.833 0.7898 3.783c0.4916 0.9697 1.107 1.441 1.686 1.441s1.194-0.4712 1.686-1.441c0.4817-0.9502 0.7898-2.287 0.7898-3.783s-0.3081-2.833-0.7898-3.783c-0.4916-0.9698-1.107-1.441-1.686-1.441z"/></g><path d="m7 8c0.5524 0 1-0.4478 1-1 0-0.5524-0.4478-1-1-1s-1 0.4478-1 1c0 0.5524 0.4478 1 1 1z" fill="#fff" stroke-width=".6439"/></svg>
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m7 0-6 3.5v7l6 3.5 6-3.5v-7l-6-3.5z" fill="#2e388a"/><g fill="#27aae1" stroke-width=".7"><path d="m9.1 3.801v1.398h-0.6992-2.801-2.1v1.4 1.4h1.4v-1.4h0.6992v2.801h-2.1v1.4h2.1 1.4v-1.4h1.4 0.6992v1.4h1.4v-1.4-1.4h-2.1v-1.4h2.1v-1.4-1.398h-1.4z"/><path d="m7 5.2c0.7732 0 1.4-0.6268 1.4-1.4s-0.6268-1.4-1.4-1.4-1.4 0.6268-1.4 1.4 0.6268 1.4 1.4 1.4z"/></g></svg>
|
After Width: | Height: | Size: 528 B |
@@ -1,6 +1,7 @@
|
||||
// @flow
|
||||
import BehaviorPropertiesEditor from './Editors/BehaviorPropertiesEditor';
|
||||
import Physics2Editor from './Editors/Physics2Editor';
|
||||
import Physics3DEditor from './Editors/Physics3DEditor';
|
||||
|
||||
/**
|
||||
* A service returning editor components for each behavior type.
|
||||
@@ -16,6 +17,9 @@ const BehaviorsEditorService = {
|
||||
'Physics2::Physics2Behavior': {
|
||||
component: Physics2Editor,
|
||||
},
|
||||
'Physics3D::Physics3DBehavior': {
|
||||
component: Physics3DEditor,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
402
newIDE/app/src/BehaviorsEditor/Editors/Physics3DEditor/index.js
Normal file
402
newIDE/app/src/BehaviorsEditor/Editors/Physics3DEditor/index.js
Normal file
@@ -0,0 +1,402 @@
|
||||
// @flow
|
||||
import { t } from '@lingui/macro';
|
||||
import { Trans } from '@lingui/macro';
|
||||
|
||||
import * as React from 'react';
|
||||
import { Line, Column, Spacer } from '../../../UI/Grid';
|
||||
import Checkbox from '../../../UI/Checkbox';
|
||||
import SelectField from '../../../UI/SelectField';
|
||||
import SelectOption from '../../../UI/SelectOption';
|
||||
import SemiControlledTextField from '../../../UI/SemiControlledTextField';
|
||||
import { getMeasurementUnitShortLabel } from '../../../PropertiesEditor/PropertiesMapToSchema';
|
||||
import MeasurementUnitDocumentation from '../../../PropertiesEditor/MeasurementUnitDocumentation';
|
||||
import { type BehaviorEditorProps } from '../BehaviorEditorProps.flow';
|
||||
import Text from '../../../UI/Text';
|
||||
import DismissableAlertMessage from '../../../UI/DismissableAlertMessage';
|
||||
import { ResponsiveLineStackLayout } from '../../../UI/Layout';
|
||||
import useForceUpdate from '../../../Utils/UseForceUpdate';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import ButtonGroup from '@material-ui/core/ButtonGroup';
|
||||
import InputAdornment from '@material-ui/core/InputAdornment';
|
||||
import Tooltip from '@material-ui/core/Tooltip';
|
||||
|
||||
type Props = BehaviorEditorProps;
|
||||
|
||||
const NumericProperty = (props: {|
|
||||
id?: string,
|
||||
properties: gdMapStringPropertyDescriptor,
|
||||
propertyName: string,
|
||||
step: number,
|
||||
onUpdate: (newValue: string) => void,
|
||||
|}) => {
|
||||
const { properties, propertyName, step, onUpdate, id } = props;
|
||||
const property = properties.get(propertyName);
|
||||
|
||||
return (
|
||||
<SemiControlledTextField
|
||||
id={id}
|
||||
fullWidth
|
||||
value={property.getValue()}
|
||||
key={propertyName}
|
||||
floatingLabelText={property.getLabel()}
|
||||
step={step}
|
||||
onChange={onUpdate}
|
||||
type="number"
|
||||
endAdornment={<UnitAdornment property={property} />}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const UnitAdornment = (props: {| property: gdPropertyDescriptor |}) => {
|
||||
const { property } = props;
|
||||
const measurementUnit = property.getMeasurementUnit();
|
||||
return (
|
||||
<Tooltip
|
||||
title={
|
||||
<MeasurementUnitDocumentation
|
||||
label={measurementUnit.getLabel()}
|
||||
description={measurementUnit.getDescription()}
|
||||
elementsWithWords={measurementUnit.getElementsWithWords()}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<InputAdornment position="end">
|
||||
{getMeasurementUnitShortLabel(measurementUnit)}
|
||||
</InputAdornment>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
const BitGroupEditor = (props: {|
|
||||
bits: Array<boolean>,
|
||||
onChange: (index: number, value: boolean) => void,
|
||||
firstIndex: number,
|
||||
disabled: boolean,
|
||||
|}) => {
|
||||
return (
|
||||
<div style={{ overflowX: 'auto', flex: 1 }}>
|
||||
<ButtonGroup disableElevation fullWidth disabled={props.disabled}>
|
||||
{props.bits.map((bit, index) => (
|
||||
<Button
|
||||
key={props.firstIndex + index}
|
||||
variant={bit ? 'contained' : 'outlined'}
|
||||
color={bit ? 'primary' : 'default'}
|
||||
onClick={() => props.onChange(props.firstIndex + index, !bit)}
|
||||
>
|
||||
{props.firstIndex + index + 1}
|
||||
</Button>
|
||||
))}
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const isBitEnabled = (bitsValue: number, pos: number) => {
|
||||
return !!(bitsValue & (1 << pos));
|
||||
};
|
||||
|
||||
const enableBit = (bitsValue: number, pos: number, enable: boolean) => {
|
||||
if (enable) bitsValue |= 1 << pos;
|
||||
else bitsValue &= ~(1 << pos);
|
||||
return bitsValue;
|
||||
};
|
||||
|
||||
const Physics3DEditor = (props: Props) => {
|
||||
const { behavior, onBehaviorUpdated } = props;
|
||||
const forceUpdate = useForceUpdate();
|
||||
|
||||
const updateBehaviorProperty = React.useCallback(
|
||||
(property, value) => {
|
||||
behavior.updateProperty(property, value);
|
||||
forceUpdate();
|
||||
onBehaviorUpdated();
|
||||
},
|
||||
[behavior, forceUpdate, onBehaviorUpdated]
|
||||
);
|
||||
|
||||
const properties = behavior.getProperties();
|
||||
const staticBits = Array(4).fill(null);
|
||||
const dynamicBits = Array(4).fill(null);
|
||||
const shape = properties.get('shape').getValue();
|
||||
const layersValues = parseInt(properties.get('layers').getValue(), 10);
|
||||
const masksValues = parseInt(properties.get('masks').getValue(), 10);
|
||||
|
||||
const isStatic = properties.get('bodyType').getValue() === 'Static';
|
||||
|
||||
return (
|
||||
<Column
|
||||
expand
|
||||
// Avoid overflow on small screens
|
||||
noOverflowParent
|
||||
>
|
||||
<Line>
|
||||
<SelectField
|
||||
id="physics3d-parameter-body-type"
|
||||
key={'bodyType'}
|
||||
fullWidth
|
||||
floatingLabelText={properties.get('bodyType').getLabel()}
|
||||
value={properties.get('bodyType').getValue()}
|
||||
onChange={(e, i, newValue: string) =>
|
||||
updateBehaviorProperty('bodyType', newValue)
|
||||
}
|
||||
>
|
||||
{[
|
||||
<SelectOption
|
||||
key={'dynamic'}
|
||||
value={'Dynamic'}
|
||||
label={t`Dynamic`}
|
||||
/>,
|
||||
<SelectOption key={'static'} value={'Static'} label={t`Static`} />,
|
||||
<SelectOption
|
||||
key={'kinematic'}
|
||||
value={'Kinematic'}
|
||||
label={t`Kinematic`}
|
||||
/>,
|
||||
]}
|
||||
</SelectField>
|
||||
</Line>
|
||||
<ResponsiveLineStackLayout>
|
||||
<Checkbox
|
||||
label={properties.get('bullet').getLabel()}
|
||||
checked={properties.get('bullet').getValue() === 'true'}
|
||||
onCheck={(e, checked) =>
|
||||
updateBehaviorProperty('bullet', checked ? '1' : '0')
|
||||
}
|
||||
/>
|
||||
<Checkbox
|
||||
label={properties.get('fixedRotation').getLabel()}
|
||||
checked={properties.get('fixedRotation').getValue() === 'true'}
|
||||
onCheck={(e, checked) =>
|
||||
updateBehaviorProperty('fixedRotation', checked ? '1' : '0')
|
||||
}
|
||||
/>
|
||||
</ResponsiveLineStackLayout>
|
||||
<Line>
|
||||
<DismissableAlertMessage
|
||||
identifier="physics2-shape-collisions"
|
||||
kind="info"
|
||||
>
|
||||
<Trans>
|
||||
The shape used in the Physics behavior is independent from the
|
||||
collision mask of the object. Be sure to use the "Collision"
|
||||
condition provided by the Physics behavior in the events. The usual
|
||||
"Collision" condition won't take into account the shape that you've
|
||||
set up here.
|
||||
</Trans>
|
||||
</DismissableAlertMessage>
|
||||
</Line>
|
||||
<ResponsiveLineStackLayout>
|
||||
<SelectField
|
||||
id="physics3d-parameter-shape"
|
||||
fullWidth
|
||||
floatingLabelText={properties.get('shape').getLabel()}
|
||||
value={properties.get('shape').getValue()}
|
||||
onChange={(e, i, newValue: string) =>
|
||||
updateBehaviorProperty('shape', newValue)
|
||||
}
|
||||
>
|
||||
<SelectOption key={'sphere'} value={'Sphere'} label={t`Sphere`} />
|
||||
<SelectOption key={'box'} value={'Box'} label={t`Box`} />
|
||||
<SelectOption key={'capsule'} value={'Capsule'} label={t`Capsule`} />
|
||||
<SelectOption
|
||||
key={'cylinder'}
|
||||
value={'Cylinder'}
|
||||
label={t`Cylinder`}
|
||||
/>
|
||||
</SelectField>
|
||||
<SelectField
|
||||
id="physics3d-parameter-shape-orientation"
|
||||
fullWidth
|
||||
floatingLabelText={properties.get('shapeOrientation').getLabel()}
|
||||
value={properties.get('shapeOrientation').getValue()}
|
||||
onChange={(e, i, newValue: string) =>
|
||||
updateBehaviorProperty('shapeOrientation', newValue)
|
||||
}
|
||||
disabled={
|
||||
properties.get('shape').getValue() === 'Sphere' ||
|
||||
properties.get('shape').getValue() === 'Box'
|
||||
}
|
||||
>
|
||||
<SelectOption key={'shape-orientation-z'} value={'Z'} label={t`Z`} />
|
||||
<SelectOption key={'shape-orientation-y'} value={'Y'} label={t`Y`} />
|
||||
<SelectOption key={'shape-orientation-x'} value={'X'} label={t`X`} />
|
||||
</SelectField>
|
||||
</ResponsiveLineStackLayout>
|
||||
<ResponsiveLineStackLayout>
|
||||
<SemiControlledTextField
|
||||
fullWidth
|
||||
value={properties.get('shapeDimensionA').getValue()}
|
||||
key={'shapeDimensionA'}
|
||||
floatingLabelText={shape === 'Box' ? 'Width' : 'Radius'}
|
||||
min={0}
|
||||
onChange={newValue =>
|
||||
updateBehaviorProperty('shapeDimensionA', newValue)
|
||||
}
|
||||
type="number"
|
||||
endAdornment={
|
||||
<UnitAdornment property={properties.get('shapeDimensionA')} />
|
||||
}
|
||||
/>
|
||||
{shape !== 'Sphere' && (
|
||||
<SemiControlledTextField
|
||||
fullWidth
|
||||
value={properties.get('shapeDimensionB').getValue()}
|
||||
key={'shapeDimensionB'}
|
||||
floatingLabelText={shape === 'Box' ? 'Width' : 'Depth'}
|
||||
min={0}
|
||||
onChange={newValue =>
|
||||
updateBehaviorProperty('shapeDimensionB', newValue)
|
||||
}
|
||||
type="number"
|
||||
endAdornment={
|
||||
<UnitAdornment property={properties.get('shapeDimensionB')} />
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{shape === 'Box' && (
|
||||
<SemiControlledTextField
|
||||
fullWidth
|
||||
value={properties.get('shapeDimensionC').getValue()}
|
||||
key={'shapeDimensionC'}
|
||||
floatingLabelText={'Depth'}
|
||||
min={0}
|
||||
onChange={newValue =>
|
||||
updateBehaviorProperty('shapeDimensionC', newValue)
|
||||
}
|
||||
type="number"
|
||||
endAdornment={
|
||||
<UnitAdornment property={properties.get('shapeDimensionC')} />
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</ResponsiveLineStackLayout>
|
||||
<ResponsiveLineStackLayout>
|
||||
<NumericProperty
|
||||
id="physics3d-parameter-density"
|
||||
properties={properties}
|
||||
propertyName={'density'}
|
||||
step={0.1}
|
||||
onUpdate={newValue =>
|
||||
updateBehaviorProperty(
|
||||
'density',
|
||||
parseFloat(newValue) > 0 ? newValue : '0'
|
||||
)
|
||||
}
|
||||
/>
|
||||
<NumericProperty
|
||||
properties={properties}
|
||||
propertyName={'gravityScale'}
|
||||
step={0.1}
|
||||
onUpdate={newValue =>
|
||||
updateBehaviorProperty('gravityScale', newValue)
|
||||
}
|
||||
/>
|
||||
</ResponsiveLineStackLayout>
|
||||
<ResponsiveLineStackLayout>
|
||||
<NumericProperty
|
||||
properties={properties}
|
||||
propertyName={'friction'}
|
||||
step={0.1}
|
||||
onUpdate={newValue =>
|
||||
updateBehaviorProperty(
|
||||
'friction',
|
||||
parseFloat(newValue) > 0 ? newValue : '0'
|
||||
)
|
||||
}
|
||||
/>
|
||||
<NumericProperty
|
||||
properties={properties}
|
||||
propertyName={'restitution'}
|
||||
step={0.1}
|
||||
onUpdate={newValue =>
|
||||
updateBehaviorProperty(
|
||||
'restitution',
|
||||
parseFloat(newValue) > 0 ? newValue : '0'
|
||||
)
|
||||
}
|
||||
/>
|
||||
</ResponsiveLineStackLayout>
|
||||
<ResponsiveLineStackLayout>
|
||||
<NumericProperty
|
||||
properties={properties}
|
||||
propertyName={'linearDamping'}
|
||||
step={0.05}
|
||||
onUpdate={newValue =>
|
||||
updateBehaviorProperty('linearDamping', newValue)
|
||||
}
|
||||
/>
|
||||
<NumericProperty
|
||||
id="physics3d-parameter-angular-damping"
|
||||
properties={properties}
|
||||
propertyName={'angularDamping'}
|
||||
step={0.05}
|
||||
onUpdate={newValue =>
|
||||
updateBehaviorProperty('angularDamping', newValue)
|
||||
}
|
||||
/>
|
||||
</ResponsiveLineStackLayout>
|
||||
<Line>
|
||||
<Text style={{ marginRight: 10 }}>
|
||||
{properties.get('layers').getLabel()}
|
||||
</Text>
|
||||
<BitGroupEditor
|
||||
key={'static-layers'}
|
||||
firstIndex={0}
|
||||
bits={staticBits.map(
|
||||
(_, index) => isBitEnabled(layersValues, index) && isStatic
|
||||
)}
|
||||
onChange={(index, value) => {
|
||||
const newValue = enableBit(layersValues, index, value);
|
||||
updateBehaviorProperty('layers', newValue.toString(10));
|
||||
}}
|
||||
disabled={!isStatic}
|
||||
/>
|
||||
<Spacer />
|
||||
<BitGroupEditor
|
||||
key={'dynamic-layers'}
|
||||
firstIndex={4}
|
||||
bits={dynamicBits.map(
|
||||
(_, index) => isBitEnabled(layersValues, index + 4) && !isStatic
|
||||
)}
|
||||
onChange={(index, value) => {
|
||||
const newValue = enableBit(layersValues, index, value);
|
||||
updateBehaviorProperty('layers', newValue.toString(10));
|
||||
}}
|
||||
disabled={isStatic}
|
||||
/>
|
||||
</Line>
|
||||
<Line>
|
||||
<Text style={{ marginRight: 10 }}>
|
||||
{properties.get('masks').getLabel()}
|
||||
</Text>
|
||||
<BitGroupEditor
|
||||
key={'static-mask'}
|
||||
firstIndex={0}
|
||||
bits={staticBits.map(
|
||||
(_, index) => isBitEnabled(masksValues, index) || isStatic
|
||||
)}
|
||||
onChange={(index, value) => {
|
||||
const newValue = enableBit(masksValues, index, value);
|
||||
updateBehaviorProperty('masks', newValue.toString(10));
|
||||
}}
|
||||
disabled={isStatic}
|
||||
/>
|
||||
<Spacer />
|
||||
<BitGroupEditor
|
||||
key={'dynamic-mask'}
|
||||
firstIndex={4}
|
||||
bits={dynamicBits.map(
|
||||
(_, index) => isBitEnabled(masksValues, index + 4) || isStatic
|
||||
)}
|
||||
onChange={(index, value) => {
|
||||
const newValue = enableBit(masksValues, index, value);
|
||||
updateBehaviorProperty('masks', newValue.toString(10));
|
||||
}}
|
||||
disabled={isStatic}
|
||||
/>
|
||||
</Line>
|
||||
</Column>
|
||||
);
|
||||
};
|
||||
|
||||
export default Physics3DEditor;
|
Reference in New Issue
Block a user