Skip to content
47 changes: 47 additions & 0 deletions Extensions/DebuggerTools/JsExtension.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,53 @@ module.exports = {
.setIncludeFile('Extensions/DebuggerTools/debuggertools.js')
.setFunctionName('gdjs.evtTools.debuggerTools.enableDebugDraw');

extension
.addAction(
'EnableDebugDraw3D',
_('Draw 3D collision shapes'),
_(
'This activates the display of wireframe meshes showing the 3D collision shapes of objects using the 3D physics engine (box, sphere, capsule, cylinder).'
),
_(
'Enable 3D debug draw of collision shapes: _PARAM1_ (color: _PARAM2_, depth test: _PARAM3_)'
),
'',
'res/actions/planicon24.png',
'res/actions/planicon.png'
)
.addCodeOnlyParameter('currentScene', '')
.addParameter('yesorno', _('Enable 3D debug draw'), '', true)
.setDefaultValue('yes')
.addParameter('color', _('Wireframe color'), '', true)
.setDefaultValue('"0;255;0"')
.addParameter(
'yesorno',
_('Apply depth test (hide shapes behind geometry)'),
'',
true
)
.setDefaultValue('yes')
.getCodeExtraInformation()
.setIncludeFile('Extensions/DebuggerTools/debuggertools.js')
.setFunctionName('gdjs.evtTools.debuggerTools.enableDebugDraw3D');

extension
.addAction(
'ToggleDebugDraw3D',
_('Toggle 3D collision shapes drawing'),
_(
'Toggles the display of wireframe meshes showing the 3D collision shapes of objects using the 3D physics engine. The last used color and depth test settings are reused.'
),
_('Toggle 3D debug draw of collision shapes'),
'',
'res/actions/planicon24.png',
'res/actions/planicon.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile('Extensions/DebuggerTools/debuggertools.js')
.setFunctionName('gdjs.evtTools.debuggerTools.toggleDebugDraw3D');

extension
.addAction(
'ConsoleLog',
Expand Down
37 changes: 37 additions & 0 deletions Extensions/DebuggerTools/debuggertools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,43 @@ namespace gdjs {
showCustomPoints
);
};

/**
* Enable or disable the 3D debug draw of collision shapes.
* @param instanceContainer - The current container.
* @param enableDebugDraw - true to enable the 3D debug draw, false to disable it.
* @param color - Wireframe color string (format "R;G;B").
* @param depthTest - true to enable depth testing on the wireframe.
*/
export const enableDebugDraw3D = function (
instanceContainer: gdjs.RuntimeInstanceContainer,
enableDebugDraw: boolean,
color: string,
depthTest: boolean
) {
const rgb = (color || '0;255;0').split(';');
const colorHex = gdjs.rgbToHexNumber(
parseInt(rgb[0], 10) || 0,
parseInt(rgb[1], 10) || 0,
parseInt(rgb[2], 10) || 0
);
instanceContainer.enableDebugDraw3D(enableDebugDraw, colorHex, depthTest);
};

/**
* Toggle the 3D debug draw of collision shapes, reusing the last color
* and depth test settings (defaulting to green / depth test on).
* @param instanceContainer - The current container.
*/
export const toggleDebugDraw3D = function (
instanceContainer: gdjs.RuntimeInstanceContainer
) {
instanceContainer.enableDebugDraw3D(
!instanceContainer._debugDraw3DEnabled,
instanceContainer._debugDraw3DColorHex,
instanceContainer._debugDraw3DDepthTest
);
};
}
}
}
98 changes: 73 additions & 25 deletions Extensions/Physics3DBehavior/Physics3DRuntimeBehavior.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,31 +409,7 @@ namespace gdjs {
this.collisionChecker =
new gdjs.Physics3DRuntimeBehavior.DefaultCollisionChecker(this);
this.owner3D = owner;
this.bodyType = behaviorData.bodyType;
this.bullet = behaviorData.bullet;
this.fixedRotation = behaviorData.fixedRotation;
this._shape = behaviorData.shape;
this.meshShapeResourceName = behaviorData.meshShapeResourceName || '';
this.shapeOrientation =
behaviorData.shape === 'Box' ? 'Z' : behaviorData.shapeOrientation;
this.shapeDimensionA = behaviorData.shapeDimensionA;
this.shapeDimensionB = behaviorData.shapeDimensionB;
this.shapeDimensionC = behaviorData.shapeDimensionC;
this.shapeOffsetX = behaviorData.shapeOffsetX || 0;
this.shapeOffsetY = behaviorData.shapeOffsetY || 0;
this.shapeOffsetZ = behaviorData.shapeOffsetZ || 0;
this.massCenterOffsetX = behaviorData.massCenterOffsetX || 0;
this.massCenterOffsetY = behaviorData.massCenterOffsetY || 0;
this.massCenterOffsetZ = behaviorData.massCenterOffsetZ || 0;
this.density = Math.max(0.0001, behaviorData.density);
this.massOverride = behaviorData.massOverride || 0;
this.friction = behaviorData.friction;
this.restitution = behaviorData.restitution;
this.linearDamping = Math.max(0, behaviorData.linearDamping);
this.angularDamping = Math.max(0, behaviorData.angularDamping);
this.gravityScale = behaviorData.gravityScale;
this.layers = behaviorData.layers;
this.masks = behaviorData.masks;
this._applyBehaviorData(behaviorData);
this._sharedData = Physics3DSharedData.getSharedData(
instanceContainer.getScene(),
behaviorData.name
Expand Down Expand Up @@ -1131,6 +1107,78 @@ namespace gdjs {
this._sharedData.stepped = false;
}

private _applyBehaviorData(data: any): void {
if ('bodyType' in data) this.bodyType = data.bodyType;
if ('bullet' in data) this.bullet = data.bullet;
if ('fixedRotation' in data) this.fixedRotation = data.fixedRotation;

if ('shape' in data) {
this._shape = data.shape;
const orientation =
'shapeOrientation' in data
? data.shapeOrientation
: this.shapeOrientation;
this.shapeOrientation = data.shape === 'Box' ? 'Z' : orientation;
} else if ('shapeOrientation' in data) {
this.shapeOrientation =
this._shape === 'Box' ? 'Z' : data.shapeOrientation;
}

if ('meshShapeResourceName' in data)
this.meshShapeResourceName = data.meshShapeResourceName || '';
if ('shapeDimensionA' in data)
this.shapeDimensionA = data.shapeDimensionA;
if ('shapeDimensionB' in data)
this.shapeDimensionB = data.shapeDimensionB;
if ('shapeDimensionC' in data)
this.shapeDimensionC = data.shapeDimensionC;
if ('shapeOffsetX' in data) this.shapeOffsetX = data.shapeOffsetX || 0;
if ('shapeOffsetY' in data) this.shapeOffsetY = data.shapeOffsetY || 0;
if ('shapeOffsetZ' in data) this.shapeOffsetZ = data.shapeOffsetZ || 0;
if ('massCenterOffsetX' in data)
this.massCenterOffsetX = data.massCenterOffsetX || 0;
if ('massCenterOffsetY' in data)
this.massCenterOffsetY = data.massCenterOffsetY || 0;
if ('massCenterOffsetZ' in data)
this.massCenterOffsetZ = data.massCenterOffsetZ || 0;
if ('density' in data) this.density = Math.max(0.0001, data.density);
if ('massOverride' in data) this.massOverride = data.massOverride || 0;
if ('friction' in data) this.friction = data.friction;
if ('restitution' in data) this.restitution = data.restitution;
if ('linearDamping' in data)
this.linearDamping = Math.max(0, data.linearDamping);
if ('angularDamping' in data)
this.angularDamping = Math.max(0, data.angularDamping);
if ('gravityScale' in data) this.gravityScale = data.gravityScale;
if ('layers' in data) this.layers = data.layers;
if ('masks' in data) this.masks = data.masks;
}

override applyBehaviorOverriding(diff: BehaviorData): boolean {
this._applyBehaviorData(diff);

// Recreate the body if any shape-related property changed.
const d = diff as any;
const shapeChanged =
'shape' in d ||
'shapeOrientation' in d ||
'shapeDimensionA' in d ||
'shapeDimensionB' in d ||
'shapeDimensionC' in d ||
'shapeOffsetX' in d ||
'shapeOffsetY' in d ||
'shapeOffsetZ' in d ||
'massCenterOffsetX' in d ||
'massCenterOffsetY' in d ||
'massCenterOffsetZ' in d ||
'meshShapeResourceName' in d ||
'bodyType' in d;
if (shapeChanged) {
this.recreateBody();
}
return true;
}

onObjectHotReloaded() {
this.updateBodyFromObject();
}
Expand Down
29 changes: 29 additions & 0 deletions GDJS/Runtime/RuntimeInstanceContainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ namespace gdjs {
_debugDrawShowHiddenInstances: boolean = false;
_debugDrawShowPointsNames: boolean = false;
_debugDrawShowCustomPoints: boolean = false;
_debugDraw3DEnabled: boolean = false;
_debugDraw3DColorHex: integer = 0x00ff00;
_debugDraw3DDepthTest: boolean = true;

_onceTriggers: OnceTriggers;

Expand Down Expand Up @@ -248,6 +251,32 @@ namespace gdjs {
this._debugDrawShowCustomPoints = showCustomPoints;
}

/**
* Activate or deactivate the 3D debug visualization for collision shapes
* of objects using the built-in 3D physics behavior.
*/
enableDebugDraw3D(
enableDebugDraw: boolean,
colorHex: integer,
depthTest: boolean
): void {
const settingsChanged =
this._debugDraw3DColorHex !== colorHex ||
this._debugDraw3DDepthTest !== depthTest;
if (
this._debugDraw3DEnabled &&
(!enableDebugDraw || settingsChanged)
) {
this.getDebuggerRenderer().clearDebugDraw3D(
this.getAdhocListOfAllInstances()
);
}

this._debugDraw3DEnabled = enableDebugDraw;
this._debugDraw3DColorHex = colorHex;
this._debugDraw3DDepthTest = depthTest;
}

/**
* Check if an object is registered, meaning that instances of it can be
* created and lives in the container.
Expand Down
12 changes: 12 additions & 0 deletions GDJS/Runtime/debugger-client/abstract-debugger-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,18 @@ namespace gdjs {
);
}
}
} else if (data.command === 'set3DCollisionsShownInEditor') {
if (inGameEditor) {
const editedInstanceContainer =
inGameEditor.getEditedInstanceContainer();
if (editedInstanceContainer) {
editedInstanceContainer.enableDebugDraw3D(
!!data.payload.enabled,
0x00ff00,
true
);
}
}
} else if (data.command === 'setBackgroundColor') {
if (inGameEditor) {
const editedInstanceContainer =
Expand Down
Loading
Loading