mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-29 22:22:54 +02:00
Merge pull request #5421 from thoys/20552
CR for Job #20552 - Add the ability to modify the parameters of planky from a popup dialog
This commit is contained in:
commit
ee641335fa
2 changed files with 464 additions and 104 deletions
|
@ -12,29 +12,297 @@
|
||||||
//
|
//
|
||||||
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||||
|
|
||||||
const NUM_LAYERS = 16;
|
Script.include("../../libraries/toolBars.js");
|
||||||
const BASE_DIMENSION = { x: 7, y: 2, z: 7 };
|
|
||||||
const BLOCKS_PER_LAYER = 3;
|
const DEFAULT_NUM_LAYERS = 16;
|
||||||
const BLOCK_SIZE = {x: 0.2, y: 0.1, z: 0.8};
|
const DEFAULT_BASE_DIMENSION = { x: 7, y: 2, z: 7 };
|
||||||
const BLOCK_SPACING = BLOCK_SIZE.x / 3;
|
const DEFAULT_BLOCKS_PER_LAYER = 3;
|
||||||
|
const DEFAULT_BLOCK_SIZE = {x: 0.2, y: 0.1, z: 0.8};
|
||||||
|
const DEFAULT_BLOCK_SPACING = DEFAULT_BLOCK_SIZE.x / DEFAULT_BLOCKS_PER_LAYER;
|
||||||
// BLOCK_HEIGHT_VARIATION removes a random percentages of the default block height per block. (for example 0.001 %)
|
// BLOCK_HEIGHT_VARIATION removes a random percentages of the default block height per block. (for example 0.001 %)
|
||||||
const BLOCK_HEIGHT_VARIATION = 0.001;
|
const DEFAULT_BLOCK_HEIGHT_VARIATION = 0.001;
|
||||||
const GRAVITY = {x: 0, y: -2.8, z: 0};
|
const DEFAULT_GRAVITY = {x: 0, y: -2.8, z: 0};
|
||||||
const DENSITY = 2000;
|
const DEFAULT_DENSITY = 2000;
|
||||||
const DAMPING_FACTOR = 0.98;
|
const DEFAULT_DAMPING_FACTOR = 0.98;
|
||||||
const ANGULAR_DAMPING_FACTOR = 0.8;
|
const DEFAULT_ANGULAR_DAMPING_FACTOR = 0.8;
|
||||||
const FRICTION = 0.99;
|
const DEFAULT_FRICTION = 0.99;
|
||||||
const RESTITUTION = 0.0;
|
const DEFAULT_RESTITUTION = 0.0;
|
||||||
const SPAWN_DISTANCE = 3;
|
const DEFAULT_SPAWN_DISTANCE = 3;
|
||||||
const BLOCK_YAW_OFFSET = 45;
|
const DEFAULT_BLOCK_YAW_OFFSET = 45;
|
||||||
|
|
||||||
|
var editMode = false;
|
||||||
|
|
||||||
const BUTTON_DIMENSIONS = {width: 49, height: 49};
|
const BUTTON_DIMENSIONS = {width: 49, height: 49};
|
||||||
const MAXIMUM_PERCENTAGE = 100.0;
|
const MAXIMUM_PERCENTAGE = 100.0;
|
||||||
|
const NO_ANGLE = 0;
|
||||||
|
const RIGHT_ANGLE = 90;
|
||||||
|
|
||||||
var windowWidth = Window.innerWidth;
|
var windowWidth = Window.innerWidth;
|
||||||
var size;
|
var size;
|
||||||
var pieces = [];
|
var pieces = [];
|
||||||
var ground = false;
|
var ground = false;
|
||||||
var layerRotated = false;
|
var layerRotated = false;
|
||||||
|
var button;
|
||||||
|
var cogButton;
|
||||||
|
var toolBar;
|
||||||
|
|
||||||
|
SettingsWindow = function() {
|
||||||
|
var _this = this;
|
||||||
|
this.plankyStack = null;
|
||||||
|
this.webWindow = null;
|
||||||
|
this.init = function(plankyStack) {
|
||||||
|
_this.webWindow = new WebWindow('Planky', Script.resolvePath('../../html/plankySettings.html'), 255, 500, true);
|
||||||
|
_this.webWindow.setVisible(false);
|
||||||
|
_this.webWindow.eventBridge.webEventReceived.connect(_this.onWebEventReceived);
|
||||||
|
_this.plankyStack = plankyStack;
|
||||||
|
};
|
||||||
|
this.sendData = function(data) {
|
||||||
|
_this.webWindow.eventBridge.emitScriptEvent(JSON.stringify(data));
|
||||||
|
};
|
||||||
|
this.onWebEventReceived = function(data) {
|
||||||
|
data = JSON.parse(data);
|
||||||
|
switch (data.action) {
|
||||||
|
case 'loaded':
|
||||||
|
_this.sendData({action: 'load', options: _this.plankyStack.options.getJSON()})
|
||||||
|
break;
|
||||||
|
case 'value-change':
|
||||||
|
_this.plankyStack.onValueChanged(data.option, data.value);
|
||||||
|
break;
|
||||||
|
case 'factory-reset':
|
||||||
|
_this.plankyStack.options.factoryReset();
|
||||||
|
_this.sendData({action: 'load', options: _this.plankyStack.options.getJSON()})
|
||||||
|
break;
|
||||||
|
case 'save-default':
|
||||||
|
_this.plankyStack.options.save();
|
||||||
|
break;
|
||||||
|
case 'cleanup':
|
||||||
|
_this.plankyStack.deRez();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Window.alert('[planky] unknown action ' + data.action);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
PlankyOptions = function() {
|
||||||
|
var _this = this;
|
||||||
|
this.factoryReset = function() {
|
||||||
|
_this.setDefaults();
|
||||||
|
Settings.setValue('plankyOptions', '');
|
||||||
|
};
|
||||||
|
this.save = function() {
|
||||||
|
Settings.setValue('plankyOptions', JSON.stringify(_this.getJSON()));
|
||||||
|
};
|
||||||
|
this.load = function() {
|
||||||
|
_this.setDefaults();
|
||||||
|
var plankyOptions = Settings.getValue('plankyOptions')
|
||||||
|
if (plankyOptions === null || plankyOptions === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var options = JSON.parse(plankyOptions);
|
||||||
|
for (option in options) {
|
||||||
|
_this[option] = options[option];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.getJSON = function() {
|
||||||
|
return {
|
||||||
|
numLayers: _this.numLayers,
|
||||||
|
baseDimension: _this.baseDimension,
|
||||||
|
blocksPerLayer: _this.blocksPerLayer,
|
||||||
|
blockSize: _this.blockSize,
|
||||||
|
blockSpacing: _this.blockSpacing,
|
||||||
|
blockHeightVariation: _this.blockHeightVariation,
|
||||||
|
gravity: _this.gravity,
|
||||||
|
density: _this.density,
|
||||||
|
dampingFactor: _this.dampingFactor,
|
||||||
|
angularDampingFactor: _this.angularDampingFactor,
|
||||||
|
friction: _this.friction,
|
||||||
|
restitution: _this.restitution,
|
||||||
|
spawnDistance: _this.spawnDistance,
|
||||||
|
blockYawOffset: _this.blockYawOffset,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
this.setDefaults = function() {
|
||||||
|
_this.numLayers = DEFAULT_NUM_LAYERS;
|
||||||
|
_this.baseDimension = DEFAULT_BASE_DIMENSION;
|
||||||
|
_this.blocksPerLayer = DEFAULT_BLOCKS_PER_LAYER;
|
||||||
|
_this.blockSize = DEFAULT_BLOCK_SIZE;
|
||||||
|
_this.blockSpacing = DEFAULT_BLOCK_SPACING;
|
||||||
|
_this.blockHeightVariation = DEFAULT_BLOCK_HEIGHT_VARIATION;
|
||||||
|
_this.gravity = DEFAULT_GRAVITY;
|
||||||
|
_this.density = DEFAULT_DENSITY;
|
||||||
|
_this.dampingFactor = DEFAULT_DAMPING_FACTOR;
|
||||||
|
_this.angularDampingFactor = DEFAULT_ANGULAR_DAMPING_FACTOR;
|
||||||
|
_this.friction = DEFAULT_FRICTION;
|
||||||
|
_this.restitution = DEFAULT_RESTITUTION;
|
||||||
|
_this.spawnDistance = DEFAULT_SPAWN_DISTANCE;
|
||||||
|
_this.blockYawOffset = DEFAULT_BLOCK_YAW_OFFSET;
|
||||||
|
};
|
||||||
|
this.load();
|
||||||
|
};
|
||||||
|
|
||||||
|
// The PlankyStack exists out of rows and layers
|
||||||
|
PlankyStack = function() {
|
||||||
|
var _this = this;
|
||||||
|
this.planks = [];
|
||||||
|
this.ground = false;
|
||||||
|
this.editLines = [];
|
||||||
|
this.options = new PlankyOptions();
|
||||||
|
|
||||||
|
this.deRez = function() {
|
||||||
|
_this.planks.forEach(function(plank) {
|
||||||
|
Entities.deleteEntity(plank.entity);
|
||||||
|
});
|
||||||
|
_this.planks = [];
|
||||||
|
if (_this.ground) {
|
||||||
|
Entities.deleteEntity(_this.ground);
|
||||||
|
}
|
||||||
|
_this.editLines.forEach(function(line) {
|
||||||
|
Entities.deleteEntity(line);
|
||||||
|
})
|
||||||
|
_this.editLines = [];
|
||||||
|
if (_this.centerLine) {
|
||||||
|
Entities.deleteEntity(_this.centerLine);
|
||||||
|
}
|
||||||
|
_this.ground = false;
|
||||||
|
_this.centerLine = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.rez = function() {
|
||||||
|
if (_this.planks.length > 0) {
|
||||||
|
_this.deRez();
|
||||||
|
}
|
||||||
|
_this.baseRotation = Quat.fromPitchYawRollDegrees(0.0, MyAvatar.bodyYaw, 0.0);
|
||||||
|
var basePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(_this.options.spawnDistance, Quat.getFront(_this.baseRotation)));
|
||||||
|
basePosition.y = grabLowestJointY();
|
||||||
|
_this.basePosition = basePosition;
|
||||||
|
_this.refresh();
|
||||||
|
};
|
||||||
|
|
||||||
|
//private function
|
||||||
|
var refreshGround = function() {
|
||||||
|
if (!_this.ground) {
|
||||||
|
_this.ground = Entities.addEntity({
|
||||||
|
type: 'Model',
|
||||||
|
modelURL: HIFI_PUBLIC_BUCKET + 'eric/models/woodFloor.fbx',
|
||||||
|
dimensions: _this.options.baseDimension,
|
||||||
|
position: Vec3.sum(_this.basePosition, {y: -(_this.options.baseDimension.y / 2)}),
|
||||||
|
rotation: _this.baseRotation,
|
||||||
|
shapeType: 'box'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// move ground to rez position/rotation
|
||||||
|
Entities.editEntity(_this.ground, {dimensions: _this.options.baseDimension, position: Vec3.sum(_this.basePosition, {y: -(_this.options.baseDimension.y / 2)}), rotation: _this.baseRotation});
|
||||||
|
};
|
||||||
|
|
||||||
|
var refreshLines = function() {
|
||||||
|
if (_this.editLines.length === 0) {
|
||||||
|
_this.editLines.push(Entities.addEntity({
|
||||||
|
type: 'Line',
|
||||||
|
dimensions: {x: 5, y: 21, z: 5},
|
||||||
|
position: Vec3.sum(_this.basePosition, {y: -(_this.options.baseDimension.y / 2)}),
|
||||||
|
lineWidth: 7,
|
||||||
|
color: {red: 20, green: 20, blue: 20},
|
||||||
|
linePoints: [{x: 0, y: 0, z: 0}, {x: 0, y: 10, z: 0}],
|
||||||
|
visible: editMode
|
||||||
|
}));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_this.editLines.forEach(function(line) {
|
||||||
|
Entities.editEntity(line, {visible: editMode});
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
var trimDimension = function(dimension, maxIndex) {
|
||||||
|
var removingPlanks = [];
|
||||||
|
_this.planks.forEach(function(plank, index, object) {
|
||||||
|
if (plank[dimension] > maxIndex) {
|
||||||
|
removingPlanks.push(index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
removingPlanks.reverse();
|
||||||
|
for (var i = 0; i < removingPlanks.length; i++) {
|
||||||
|
Entities.deleteEntity(_this.planks[removingPlanks[i]].entity);
|
||||||
|
_this.planks.splice(removingPlanks[i], 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var createOrUpdate = function(layer, row) {
|
||||||
|
var found = false;
|
||||||
|
var layerRotated = layer % 2 === 0;
|
||||||
|
var layerRotation = Quat.fromPitchYawRollDegrees(0, layerRotated ? NO_ANGLE : RIGHT_ANGLE, 0.0);
|
||||||
|
var blockPositionXZ = (row - (_this.options.blocksPerLayer / 2) + 0.5) * (_this.options.blockSpacing + _this.options.blockSize.x);
|
||||||
|
var localTransform = Vec3.multiplyQbyV(_this.offsetRot, {
|
||||||
|
x: (layerRotated ? blockPositionXZ : 0),
|
||||||
|
y: (_this.options.blockSize.y / 2) + (_this.options.blockSize.y * layer),
|
||||||
|
z: (layerRotated ? 0 : blockPositionXZ)
|
||||||
|
});
|
||||||
|
var newProperties = {
|
||||||
|
type: 'Model',
|
||||||
|
modelURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/block.fbx',
|
||||||
|
shapeType: 'box',
|
||||||
|
name: 'PlankyBlock' + layer + '-' + row,
|
||||||
|
dimensions: Vec3.sum(_this.options.blockSize, {x: 0, y: -((_this.options.blockSize.y * (_this.options.blockHeightVariation / MAXIMUM_PERCENTAGE)) * Math.random()), z: 0}),
|
||||||
|
position: Vec3.sum(_this.basePosition, localTransform),
|
||||||
|
rotation: Quat.multiply(layerRotation, _this.offsetRot),
|
||||||
|
damping: _this.options.dampingFactor,
|
||||||
|
restitution: _this.options.restitution,
|
||||||
|
friction: _this.options.friction,
|
||||||
|
angularDamping: _this.options.angularDampingFactor,
|
||||||
|
gravity: _this.options.gravity,
|
||||||
|
density: _this.options.density,
|
||||||
|
velocity: {x: 0, y: 0, z: 0},
|
||||||
|
angularVelocity: Quat.fromPitchYawRollDegrees(0, 0, 0),
|
||||||
|
ignoreForCollisions: true
|
||||||
|
};
|
||||||
|
_this.planks.forEach(function(plank, index, object) {
|
||||||
|
if (plank.layer === layer && plank.row === row) {
|
||||||
|
Entities.editEntity(plank.entity, newProperties);
|
||||||
|
found = true;
|
||||||
|
// break loop:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!found) {
|
||||||
|
_this.planks.push({layer: layer, row: row, entity: Entities.addEntity(newProperties)})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.onValueChanged = function(option, value) {
|
||||||
|
_this.options[option] = value;
|
||||||
|
if (['numLayers', 'blocksPerLayer', 'blockSize', 'blockSpacing', 'blockHeightVariation'].indexOf(option) !== -1) {
|
||||||
|
_this.refresh();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.refresh = function() {
|
||||||
|
refreshGround();
|
||||||
|
refreshLines();
|
||||||
|
trimDimension('layer', _this.options.numLayers - 1);
|
||||||
|
trimDimension('row', _this.options.blocksPerLayer - 1);
|
||||||
|
_this.offsetRot = Quat.multiply(_this.baseRotation, Quat.fromPitchYawRollDegrees(0.0, _this.options.blockYawOffset, 0.0));
|
||||||
|
for (var layer = 0; layer < _this.options.numLayers; layer++) {
|
||||||
|
for (var row = 0; row < _this.options.blocksPerLayer; row++) {
|
||||||
|
createOrUpdate(layer, row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!editMode) {
|
||||||
|
_this.planks.forEach(function(plank, index, object) {
|
||||||
|
Entities.editEntity(plank.entity, {ignoreForCollisions: false, collisionsWillMove: true});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.isFound = function() {
|
||||||
|
//TODO: identify entities here until one is found
|
||||||
|
return _this.planks.length > 0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var settingsWindow = new SettingsWindow();
|
||||||
|
var plankyStack = new PlankyStack();
|
||||||
|
settingsWindow.init(plankyStack);
|
||||||
|
|
||||||
function grabLowestJointY() {
|
function grabLowestJointY() {
|
||||||
var jointNames = MyAvatar.getJointNames();
|
var jointNames = MyAvatar.getJointNames();
|
||||||
|
@ -47,108 +315,60 @@ function grabLowestJointY() {
|
||||||
return floorY;
|
return floorY;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getButtonPosX() {
|
toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL, "highfidelity.games.planky", function (windowDimensions, toolbar) {
|
||||||
return windowWidth - ((BUTTON_DIMENSIONS.width / 2) + BUTTON_DIMENSIONS.width);
|
return {
|
||||||
}
|
x: windowDimensions.x - (toolbar.width * 1.1),
|
||||||
|
y: toolbar.height / 2
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
var button = Overlays.addOverlay('image', {
|
button = toolBar.addTool({
|
||||||
x: getButtonPosX(),
|
|
||||||
y: 10,
|
|
||||||
width: BUTTON_DIMENSIONS.width,
|
width: BUTTON_DIMENSIONS.width,
|
||||||
height: BUTTON_DIMENSIONS.height,
|
height: BUTTON_DIMENSIONS.height,
|
||||||
imageURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/planky_button.svg',
|
imageURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/planky_button.svg',
|
||||||
alpha: 0.8
|
alpha: 0.8,
|
||||||
|
visible: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cogButton = toolBar.addTool({
|
||||||
|
width: BUTTON_DIMENSIONS.width,
|
||||||
|
height: BUTTON_DIMENSIONS.height,
|
||||||
|
imageURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/cog.svg',
|
||||||
|
subImage: { x: 0, y: BUTTON_DIMENSIONS.height, width: BUTTON_DIMENSIONS.width, height: BUTTON_DIMENSIONS.height },
|
||||||
|
alpha: 0.8,
|
||||||
|
visible: true
|
||||||
|
}, true, false);
|
||||||
|
|
||||||
function resetBlocks() {
|
Controller.mousePressEvent.connect(function(event) {
|
||||||
pieces.forEach(function(piece) {
|
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
|
||||||
Entities.deleteEntity(piece);
|
if (toolBar.clicked(clickedOverlay) === button) {
|
||||||
});
|
if (!plankyStack.isFound()) {
|
||||||
pieces = [];
|
plankyStack.rez();
|
||||||
var avatarRot = Quat.fromPitchYawRollDegrees(0.0, MyAvatar.bodyYaw, 0.0);
|
return;
|
||||||
basePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(SPAWN_DISTANCE, Quat.getFront(avatarRot)));
|
}
|
||||||
basePosition.y = grabLowestJointY() - (BASE_DIMENSION.y / 2);
|
plankyStack.refresh();
|
||||||
if (!ground) {
|
} else if (toolBar.clicked(clickedOverlay) === cogButton) {
|
||||||
ground = Entities.addEntity({
|
editMode = !editMode;
|
||||||
type: 'Model',
|
toolBar.selectTool(cogButton, editMode);
|
||||||
modelURL: HIFI_PUBLIC_BUCKET + 'eric/models/woodFloor.fbx',
|
settingsWindow.webWindow.setVisible(editMode);
|
||||||
dimensions: BASE_DIMENSION,
|
if(plankyStack.planks.length) {
|
||||||
position: basePosition,
|
plankyStack.refresh();
|
||||||
rotation: avatarRot,
|
|
||||||
shapeType: 'box'
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Entities.editEntity(ground, {position: basePosition, rotation: avatarRot});
|
|
||||||
}
|
|
||||||
var offsetRot = Quat.multiply(avatarRot, Quat.fromPitchYawRollDegrees(0.0, BLOCK_YAW_OFFSET, 0.0));
|
|
||||||
basePosition.y += (BASE_DIMENSION.y / 2);
|
|
||||||
for (var layerIndex = 0; layerIndex < NUM_LAYERS; layerIndex++) {
|
|
||||||
var layerRotated = layerIndex % 2 === 0;
|
|
||||||
var offset = -(BLOCK_SPACING);
|
|
||||||
var layerRotation = Quat.fromPitchYawRollDegrees(0, layerRotated ? 0 : 90, 0.0);
|
|
||||||
for (var blockIndex = 0; blockIndex < BLOCKS_PER_LAYER; blockIndex++) {
|
|
||||||
var blockPositionXZ = BLOCK_SIZE.x * blockIndex - (BLOCK_SIZE.x * 3 / 2 - BLOCK_SIZE.x / 2);
|
|
||||||
var localTransform = Vec3.multiplyQbyV(offsetRot, {
|
|
||||||
x: (layerRotated ? blockPositionXZ + offset: 0),
|
|
||||||
y: (BLOCK_SIZE.y / 2) + (BLOCK_SIZE.y * layerIndex),
|
|
||||||
z: (layerRotated ? 0 : blockPositionXZ + offset)
|
|
||||||
});
|
|
||||||
pieces.push(Entities.addEntity({
|
|
||||||
type: 'Model',
|
|
||||||
modelURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/block.fbx',
|
|
||||||
shapeType: 'box',
|
|
||||||
name: 'PlankyBlock' + ((layerIndex * BLOCKS_PER_LAYER) + blockIndex),
|
|
||||||
dimensions: {
|
|
||||||
x: BLOCK_SIZE.x,
|
|
||||||
y: BLOCK_SIZE.y - ((BLOCK_SIZE.y * (BLOCK_HEIGHT_VARIATION / MAXIMUM_PERCENTAGE)) * Math.random()),
|
|
||||||
z: BLOCK_SIZE.z
|
|
||||||
},
|
|
||||||
position: {
|
|
||||||
x: basePosition.x + localTransform.x,
|
|
||||||
y: basePosition.y + localTransform.y,
|
|
||||||
z: basePosition.z + localTransform.z
|
|
||||||
},
|
|
||||||
rotation: Quat.multiply(layerRotation, offsetRot),
|
|
||||||
collisionsWillMove: true,
|
|
||||||
damping: DAMPING_FACTOR,
|
|
||||||
restitution: RESTITUTION,
|
|
||||||
friction: FRICTION,
|
|
||||||
angularDamping: ANGULAR_DAMPING_FACTOR,
|
|
||||||
gravity: GRAVITY,
|
|
||||||
density: DENSITY
|
|
||||||
}));
|
|
||||||
offset += BLOCK_SPACING;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
function mousePressEvent(event) {
|
Script.update.connect(function() {
|
||||||
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
|
if (windowWidth !== Window.innerWidth) {
|
||||||
if (clickedOverlay === button) {
|
windowWidth = Window.innerWidth;
|
||||||
resetBlocks();
|
Overlays.editOverlay(button, {x: getButtonPosX()});
|
||||||
|
Overlays.editOverlay(cogButton, {x: getCogButtonPosX()});
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
Controller.mousePressEvent.connect(mousePressEvent);
|
Script.scriptEnding.connect(function() {
|
||||||
|
toolBar.cleanup();
|
||||||
function cleanup() {
|
|
||||||
Overlays.deleteOverlay(button);
|
|
||||||
if (ground) {
|
if (ground) {
|
||||||
Entities.deleteEntity(ground);
|
Entities.deleteEntity(ground);
|
||||||
}
|
}
|
||||||
pieces.forEach(function(piece) {
|
plankyStack.deRez();
|
||||||
Entities.deleteEntity(piece);
|
});
|
||||||
});
|
|
||||||
pieces = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function onUpdate() {
|
|
||||||
if (windowWidth != Window.innerWidth) {
|
|
||||||
windowWidth = Window.innerWidth;
|
|
||||||
Overlays.editOverlay(button, {x: getButtonPosX()});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Script.update.connect(onUpdate)
|
|
||||||
Script.scriptEnding.connect(cleanup);
|
|
||||||
|
|
140
examples/html/plankySettings.html
Normal file
140
examples/html/plankySettings.html
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" type="text/css" href="style.css">
|
||||||
|
<script type="text/javascript" src="jquery-2.1.4.min.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var properties = [];
|
||||||
|
function sendWebEvent(data) {
|
||||||
|
EventBridge.emitWebEvent(JSON.stringify(data));
|
||||||
|
}
|
||||||
|
PropertyInput = function(key, label, value, attributes) {
|
||||||
|
this.key = key;
|
||||||
|
this.label = label;
|
||||||
|
this.value = value;
|
||||||
|
this.attributes = attributes;
|
||||||
|
var self = this;
|
||||||
|
this.construct = function() {
|
||||||
|
self.widget = $('<div>').addClass('property').append(self.createLabel()).append(self.createValueDiv());
|
||||||
|
$('#properties-list').append(self.widget);
|
||||||
|
};
|
||||||
|
this.createValue = self.__proto__.createValue;
|
||||||
|
this.getValue = self.__proto__.getValue;
|
||||||
|
this.createValueDiv = function() {
|
||||||
|
self.inputDiv = $('<div>').addClass('value').append(self.createValue());
|
||||||
|
return self.inputDiv;
|
||||||
|
};
|
||||||
|
this.addButton = function(id, buttonText) {
|
||||||
|
self.inputDiv.append($('<div>').append($('<input>').attr('type', 'button').attr('id', id).val(buttonText)));
|
||||||
|
};
|
||||||
|
this.createWidget = function() {
|
||||||
|
self.widget = $('<div>').addClass('property').append(self.createLabel()).append(self.inputDiv);
|
||||||
|
return self.widget;
|
||||||
|
};
|
||||||
|
this.createLabel = function() {
|
||||||
|
self.label = $('<div>').addClass('label').text(label);
|
||||||
|
return self.label;
|
||||||
|
};
|
||||||
|
this.setValue = function(value) {
|
||||||
|
self.input.val(value);
|
||||||
|
};
|
||||||
|
this.construct();
|
||||||
|
};
|
||||||
|
|
||||||
|
var valueChangeHandler = function() {
|
||||||
|
|
||||||
|
sendWebEvent({
|
||||||
|
action: 'value-change',
|
||||||
|
option: $(this).data('var-name'),
|
||||||
|
value: properties[$(this).data('var-name')].getValue()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
NumberInput = function(key, label, value, attributes) {
|
||||||
|
PropertyInput.call(this, key, label, value, attributes);
|
||||||
|
};
|
||||||
|
NumberInput.prototype = Object.create(PropertyInput.prototype);
|
||||||
|
NumberInput.prototype.constructor = NumberInput;
|
||||||
|
NumberInput.prototype.createValue = function() {
|
||||||
|
this.input = $('<input>').data('var-name', this.key).attr('name', this.key).attr('type', 'number').val(this.value).on('change', valueChangeHandler);
|
||||||
|
if (this.attributes !== undefined) {
|
||||||
|
this.input.attr(this.attributes);
|
||||||
|
}
|
||||||
|
return this.input;
|
||||||
|
};
|
||||||
|
NumberInput.prototype.getValue = function() {
|
||||||
|
return parseFloat(this.input.val());
|
||||||
|
};
|
||||||
|
|
||||||
|
CoordinateInput = function(key, label, value, attributes) {
|
||||||
|
PropertyInput.call(this, key, label, value, attributes);
|
||||||
|
};
|
||||||
|
CoordinateInput.prototype = Object.create(PropertyInput.prototype);
|
||||||
|
CoordinateInput.prototype.constructor = CoordinateInput;
|
||||||
|
CoordinateInput.prototype.createValue = function() {
|
||||||
|
this.inputX = $('<input>').data('var-name', this.key).attr('name', this.key + '-x').attr('type', 'number').addClass('coord').val(this.value.x).on('change', valueChangeHandler);
|
||||||
|
this.inputY = $('<input>').data('var-name', this.key).attr('name', this.key + '-y').attr('type', 'number').addClass('coord').val(this.value.y).on('change', valueChangeHandler);
|
||||||
|
this.inputZ = $('<input>').data('var-name', this.key).attr('name', this.key + '-z').attr('type', 'number').addClass('coord').val(this.value.z).on('change', valueChangeHandler);
|
||||||
|
if (this.attributes !== undefined) {
|
||||||
|
this.inputX.attr(this.attributes);
|
||||||
|
this.inputY.attr(this.attributes);
|
||||||
|
this.inputZ.attr(this.attributes);
|
||||||
|
}
|
||||||
|
return [encapsulateInput(this.inputX, 'X'), encapsulateInput(this.inputY, 'Y'), encapsulateInput(this.inputZ, 'Z')];
|
||||||
|
};
|
||||||
|
CoordinateInput.prototype.getValue = function() {
|
||||||
|
return {x: parseFloat(this.inputX.val()), y: parseFloat(this.inputY.val()), z: parseFloat(this.inputZ.val())};
|
||||||
|
};
|
||||||
|
function encapsulateInput(input, label) {
|
||||||
|
return $('<div>').addClass('input-area').append(label + ' ').append(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addHeader(label) {
|
||||||
|
$('#properties-list').append($('<div>').addClass('section-header').append($('<label>').text(label)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$(function() {
|
||||||
|
addHeader('Stack Settings');
|
||||||
|
properties['numLayers'] = new NumberInput('numLayers', 'Layers', 17, {'min': 0, 'max': 300, 'step': 1});
|
||||||
|
properties['blocksPerLayer'] = new NumberInput('blocksPerLayer', 'Blocks per layer', 4, {'min': 1, 'max': 100, 'step': 1});
|
||||||
|
properties['blockSize'] = new CoordinateInput('blockSize', 'Block size', {x: 0.2, y: 0.1, z: 0.8}, {'min': 0.05, 'max': 20, 'step': 0.1});
|
||||||
|
properties['blockSpacing'] = new NumberInput('blockSpacing', 'Block spacing', properties['blockSize'].getValue().x / properties['blocksPerLayer'].getValue(), {'min': 0, 'max': 20, 'step': 0.01});
|
||||||
|
properties['blockSpacing'].addButton('btn-recalculate-spacing', 'Recalculate spacing');
|
||||||
|
$('#btn-recalculate-spacing').on('click', function() {
|
||||||
|
properties['blockSpacing'].setValue(properties['blockSize'].getValue().x / properties['blocksPerLayer'].getValue());
|
||||||
|
});
|
||||||
|
properties['blockHeightVariation'] = new NumberInput('blockHeightVariation', 'Block height variation (%)', 0.1, {'min': 0, 'max': 1, 'step': 0.01});
|
||||||
|
addHeader('Physics Settings');
|
||||||
|
properties['gravity'] = new CoordinateInput('gravity', 'Gravity', {x: 0, y: -2.8, z: 0}, {'step': 0.01});
|
||||||
|
properties['density'] = new NumberInput('density', 'Density', 4000, {'min': 0, 'max': 4000, 'step': 1});
|
||||||
|
properties['dampingFactor'] = new NumberInput('dampingFactor', 'Damping factor', 0.98, {'min': 0, 'max': 1, 'step': 0.01});
|
||||||
|
properties['angularDampingFactor'] = new NumberInput('angularDampingFactor', 'Angular damping factor', 0.8, {'min': 0, 'max': 1, 'step': 0.01});
|
||||||
|
properties['friction'] = new NumberInput('friction', 'Friction', 0.99, {'min': 0, 'max': 1, 'step': 0.01});
|
||||||
|
properties['restitution'] = new NumberInput('restitution', 'Restitution', 0.0, {'min': 0, 'max': 1, 'step': 0.01});
|
||||||
|
addHeader('Spawn Settings');
|
||||||
|
properties['spawnDistance'] = new NumberInput('spawnDistance', 'Spawn distance (meters)', 3);
|
||||||
|
properties['blockYawOffset'] = new NumberInput('blockYawOffset', 'Block yaw offset (degrees)', 45, {'min': 0, 'max': 360, 'step': 1});
|
||||||
|
properties['baseDimension'] = new CoordinateInput('baseDimension', 'Base dimension', {x: 7, y: 2, z: 7}, {'min': 0.5, 'max': 200, 'step': 0.1});
|
||||||
|
addHeader('Actions');
|
||||||
|
$('#properties-list')
|
||||||
|
.append($('<input>').val('factory reset').attr('type', 'button').on('click', function() { sendWebEvent({action: 'factory-reset'}); }))
|
||||||
|
.append($('<input>').val('save as default').attr('type', 'button').on('click', function() { sendWebEvent({action: 'save-default'}); }))
|
||||||
|
.append($('<input>').val('cleanup planky').attr('type', 'button').on('click', function() { sendWebEvent({action: 'cleanup'}); }));
|
||||||
|
if (window.EventBridge !== undefined) {
|
||||||
|
EventBridge.scriptEventReceived.connect(function(data) {
|
||||||
|
data = JSON.parse(data);
|
||||||
|
if (data.action == 'load') {
|
||||||
|
$.each(data.options, function(option, value) {
|
||||||
|
properties[option].setValue(value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
sendWebEvent({action: 'loaded'});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body class="properties">
|
||||||
|
<div id="properties-list"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in a new issue