mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 11:37:58 +02:00
Merge pull request #4252 from thoys/20224
CR for Job #20224 - Make virtualKeyboard.js go to locations and support gamepads
This commit is contained in:
commit
d896f3a811
11 changed files with 749 additions and 259 deletions
248
examples/controllers/oculus/goTo.js
Normal file
248
examples/controllers/oculus/goTo.js
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
//
|
||||||
|
// goTo.js
|
||||||
|
// examples
|
||||||
|
//
|
||||||
|
// Created by Thijs Wenker on 12/28/14.
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Control a virtual keyboard using your favorite HMD.
|
||||||
|
// Usage: Enable VR-mode and go to First person mode,
|
||||||
|
// look at the key that you would like to press, and press the spacebar on your "REAL" keyboard.
|
||||||
|
//
|
||||||
|
// Enter a location URL using your HMD. Press Enter to pop-up the virtual keyboard and location input.
|
||||||
|
// Press Space on the keyboard or the X button on your gamepad to press a key that you have selected.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
Script.include("../../libraries/globals.js");
|
||||||
|
Script.include("../../libraries/virtualKeyboard.js");
|
||||||
|
|
||||||
|
const MAX_SHOW_INSTRUCTION_TIMES = 2;
|
||||||
|
const INSTRUCTIONS_SETTING = "GoToInstructionsShowCounter"
|
||||||
|
|
||||||
|
var windowDimensions = Controller.getViewportDimensions();
|
||||||
|
|
||||||
|
function Instructions(imageURL, originalWidth, originalHeight) {
|
||||||
|
var tthis = this;
|
||||||
|
this.originalSize = {w: originalWidth, h: originalHeight};
|
||||||
|
this.visible = false;
|
||||||
|
this.overlay = Overlays.addOverlay("image", {
|
||||||
|
imageURL: imageURL,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: originalWidth,
|
||||||
|
height: originalHeight,
|
||||||
|
alpha: 1,
|
||||||
|
visible: this.visible
|
||||||
|
});
|
||||||
|
|
||||||
|
this.show = function() {
|
||||||
|
var timesShown = Settings.getValue(INSTRUCTIONS_SETTING);
|
||||||
|
timesShown = timesShown === "" ? 0 : parseInt(timesShown);
|
||||||
|
print(timesShown);
|
||||||
|
if (timesShown < MAX_SHOW_INSTRUCTION_TIMES) {
|
||||||
|
Settings.setValue(INSTRUCTIONS_SETTING, timesShown + 1);
|
||||||
|
tthis.visible = true;
|
||||||
|
tthis.rescale();
|
||||||
|
Overlays.editOverlay(tthis.overlay, {visible: tthis.visible});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tthis.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.remove = function() {
|
||||||
|
Overlays.deleteOverlay(tthis.overlay);
|
||||||
|
tthis.visible = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.rescale = function() {
|
||||||
|
var scale = Math.min(windowDimensions.x / tthis.originalSize.w, windowDimensions.y / tthis.originalSize.h);
|
||||||
|
var newWidth = tthis.originalSize.w * scale;
|
||||||
|
var newHeight = tthis.originalSize.h * scale;
|
||||||
|
Overlays.editOverlay(tthis.overlay, {
|
||||||
|
x: (windowDimensions.x / 2) - (newWidth / 2),
|
||||||
|
y: (windowDimensions.y / 2) - (newHeight / 2),
|
||||||
|
width: newWidth,
|
||||||
|
height: newHeight
|
||||||
|
});
|
||||||
|
};
|
||||||
|
this.rescale();
|
||||||
|
};
|
||||||
|
|
||||||
|
var theInstruction = new Instructions(HIFI_PUBLIC_BUCKET + "images/tutorial-goTo.svg", 457, 284.1);
|
||||||
|
|
||||||
|
var firstControllerPlugged = false;
|
||||||
|
|
||||||
|
|
||||||
|
var cursor = new Cursor({visible: false});
|
||||||
|
var keyboard = new Keyboard({visible: false});
|
||||||
|
var textFontSize = 9;
|
||||||
|
var text = null;
|
||||||
|
var locationURL = "";
|
||||||
|
|
||||||
|
function appendChar(char) {
|
||||||
|
locationURL += char;
|
||||||
|
updateTextOverlay();
|
||||||
|
Overlays.editOverlay(text, {text: locationURL});
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteChar() {
|
||||||
|
if (locationURL.length > 0) {
|
||||||
|
locationURL = locationURL.substring(0, locationURL.length - 1);
|
||||||
|
updateTextOverlay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTextOverlay() {
|
||||||
|
var maxLineWidth = Overlays.textSize(text, locationURL).width;
|
||||||
|
var suggestedFontSize = (windowDimensions.x / maxLineWidth) * textFontSize * 0.90;
|
||||||
|
var maxFontSize = 140;
|
||||||
|
textFontSize = (suggestedFontSize > maxFontSize) ? maxFontSize : suggestedFontSize;
|
||||||
|
var topMargin = (250 - textFontSize) / 4;
|
||||||
|
Overlays.editOverlay(text, {text: locationURL, font: {size: textFontSize}, topMargin: topMargin, visible: keyboard.visible});
|
||||||
|
maxLineWidth = Overlays.textSize(text, locationURL).width;
|
||||||
|
Overlays.editOverlay(text, {leftMargin: (windowDimensions.x - maxLineWidth) / 2});
|
||||||
|
}
|
||||||
|
|
||||||
|
keyboard.onKeyPress = function(event) {
|
||||||
|
if (event.event == 'keypress') {
|
||||||
|
appendChar(event.char);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
keyboard.onKeyRelease = function(event) {
|
||||||
|
// you can cancel a key by releasing its focusing before releasing it
|
||||||
|
if (event.focus) {
|
||||||
|
if (event.event == 'delete') {
|
||||||
|
deleteChar();
|
||||||
|
} else if (event.event == 'submit' || event.event == 'enter') {
|
||||||
|
print("going to hifi://" + locationURL);
|
||||||
|
location = "hifi://" + locationURL;
|
||||||
|
locationURL = "";
|
||||||
|
keyboard.hide();
|
||||||
|
cursor.hide();
|
||||||
|
updateTextOverlay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
keyboard.onFullyLoaded = function() {
|
||||||
|
print("Virtual-keyboard fully loaded.");
|
||||||
|
var dimensions = Controller.getViewportDimensions();
|
||||||
|
text = Overlays.addOverlay("text", {
|
||||||
|
x: 0,
|
||||||
|
y: dimensions.y - keyboard.height() - 260,
|
||||||
|
width: dimensions.x,
|
||||||
|
height: 250,
|
||||||
|
backgroundColor: { red: 255, green: 255, blue: 255},
|
||||||
|
color: { red: 0, green: 0, blue: 0},
|
||||||
|
topMargin: 5,
|
||||||
|
leftMargin: 0,
|
||||||
|
font: {size: textFontSize},
|
||||||
|
text: "",
|
||||||
|
alpha: 0.8,
|
||||||
|
visible: keyboard.visible
|
||||||
|
});
|
||||||
|
updateTextOverlay();
|
||||||
|
// the cursor is being loaded after the keyboard, else it will be on the background of the keyboard
|
||||||
|
cursor.initialize();
|
||||||
|
cursor.updateVisibility(keyboard.visible);
|
||||||
|
cursor.onUpdate = function(position) {
|
||||||
|
keyboard.setFocusPosition(position.x, position.y);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function keyPressEvent(event) {
|
||||||
|
if (theInstruction.visible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (event.key === SPACEBAR_CHARCODE) {
|
||||||
|
keyboard.pressFocussedKey();
|
||||||
|
} else if (event.key === ENTER_CHARCODE || event.key === RETURN_CHARCODE) {
|
||||||
|
keyboard.toggle();
|
||||||
|
if (cursor !== undefined) {
|
||||||
|
cursor.updateVisibility(keyboard.visible);
|
||||||
|
}
|
||||||
|
Overlays.editOverlay(text, {visible: keyboard.visible});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function keyReleaseEvent(event) {
|
||||||
|
if (theInstruction.visible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (event.key === SPACEBAR_CHARCODE) {
|
||||||
|
keyboard.releaseKeys();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function scriptEnding() {
|
||||||
|
keyboard.remove();
|
||||||
|
cursor.remove();
|
||||||
|
Overlays.deleteOverlay(text);
|
||||||
|
Overlays.deleteOverlay(textSizeMeasureOverlay);
|
||||||
|
Controller.releaseKeyEvents({key: SPACEBAR_CHARCODE});
|
||||||
|
Controller.releaseKeyEvents({key: RETURN_CHARCODE});
|
||||||
|
Controller.releaseKeyEvents({key: ENTER_CHARCODE});
|
||||||
|
theInstruction.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
function reportButtonValue(button, newValue, oldValue) {
|
||||||
|
if (theInstruction.visible) {
|
||||||
|
if (button == Joysticks.BUTTON_FACE_BOTTOM && newValue) {
|
||||||
|
theInstruction.remove();
|
||||||
|
}
|
||||||
|
} else if (button == Joysticks.BUTTON_FACE_BOTTOM) {
|
||||||
|
if (newValue) {
|
||||||
|
keyboard.pressFocussedKey();
|
||||||
|
} else {
|
||||||
|
keyboard.releaseKeys();
|
||||||
|
}
|
||||||
|
} else if (button == Joysticks.BUTTON_FACE_RIGHT && newValue) {
|
||||||
|
deleteChar();
|
||||||
|
} else if (button == Joysticks.BUTTON_FACE_LEFT && newValue) {
|
||||||
|
keyboard.hide();
|
||||||
|
if (cursor !== undefined) {
|
||||||
|
cursor.hide();
|
||||||
|
}
|
||||||
|
Overlays.editOverlay(text, {visible: false});
|
||||||
|
} else if (button == Joysticks.BUTTON_RIGHT_SHOULDER && newValue) {
|
||||||
|
if (keyboard.visible) {
|
||||||
|
print("going to hifi://" + locationURL);
|
||||||
|
location = "hifi://" + locationURL;
|
||||||
|
locationURL = "";
|
||||||
|
keyboard.hide();
|
||||||
|
cursor.hide();
|
||||||
|
updateTextOverlay();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
keyboard.show();
|
||||||
|
if (cursor !== undefined) {
|
||||||
|
cursor.show();
|
||||||
|
}
|
||||||
|
Overlays.editOverlay(text, {visible: true});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addJoystick(gamepad) {
|
||||||
|
gamepad.buttonStateChanged.connect(reportButtonValue);
|
||||||
|
if (!firstControllerPlugged) {
|
||||||
|
firstControllerPlugged = true;
|
||||||
|
theInstruction.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var allJoysticks = Joysticks.getAllJoysticks();
|
||||||
|
for (var i = 0; i < allJoysticks.length; i++) {
|
||||||
|
addJoystick(allJoysticks[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Joysticks.joystickAdded.connect(addJoystick);
|
||||||
|
Controller.captureKeyEvents({key: RETURN_CHARCODE});
|
||||||
|
Controller.captureKeyEvents({key: ENTER_CHARCODE});
|
||||||
|
Controller.captureKeyEvents({key: SPACEBAR_CHARCODE});
|
||||||
|
Controller.keyPressEvent.connect(keyPressEvent);
|
||||||
|
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
||||||
|
Script.scriptEnding.connect(scriptEnding);
|
183
examples/controllers/oculus/virtualKeyboardTextEntityExample.js
Normal file
183
examples/controllers/oculus/virtualKeyboardTextEntityExample.js
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
//
|
||||||
|
// virtualKeyboardTextEntityExample.js
|
||||||
|
// examples
|
||||||
|
//
|
||||||
|
// Created by Thijs Wenker on 12/28/14.
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Control a virtual keyboard using your favorite HMD.
|
||||||
|
// Usage: Enable VR-mode and go to First person mode,
|
||||||
|
// look at the key that you would like to press, and press the spacebar on your "REAL" keyboard.
|
||||||
|
//
|
||||||
|
// leased some code from newEditEntities.js for Text Entity example
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
Script.include("../../libraries/globals.js");
|
||||||
|
Script.include("../../libraries/virtualKeyboard.js");
|
||||||
|
|
||||||
|
const SPAWN_DISTANCE = 1;
|
||||||
|
const DEFAULT_TEXT_DIMENSION_Z = 0.02;
|
||||||
|
|
||||||
|
const TEXT_MARGIN_TOP = 0.15;
|
||||||
|
const TEXT_MARGIN_LEFT = 0.15;
|
||||||
|
const TEXT_MARGIN_RIGHT = 0.17;
|
||||||
|
const TEXT_MARGIN_BOTTOM = 0.17;
|
||||||
|
|
||||||
|
var windowDimensions = Controller.getViewportDimensions();
|
||||||
|
var cursor = new Cursor();
|
||||||
|
var keyboard = new Keyboard();
|
||||||
|
var textFontSize = 9;
|
||||||
|
var text = null;
|
||||||
|
var textText = "";
|
||||||
|
var textSizeMeasureOverlay = Overlays.addOverlay("text3d", {visible: false});
|
||||||
|
|
||||||
|
function appendChar(char) {
|
||||||
|
textText += char;
|
||||||
|
updateTextOverlay();
|
||||||
|
Overlays.editOverlay(text, {text: textText});
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteChar() {
|
||||||
|
if (textText.length > 0) {
|
||||||
|
textText = textText.substring(0, textText.length - 1);
|
||||||
|
updateTextOverlay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTextOverlay() {
|
||||||
|
var textLines = textText.split("\n");
|
||||||
|
var suggestedFontSize = (windowDimensions.x / Overlays.textSize(text, textText).width) * textFontSize * 0.90;
|
||||||
|
var maxFontSize = 170 / textLines.length;
|
||||||
|
textFontSize = (suggestedFontSize > maxFontSize) ? maxFontSize : suggestedFontSize;
|
||||||
|
var topMargin = (250 - (textFontSize * textLines.length)) / 4;
|
||||||
|
Overlays.editOverlay(text, {text: textText, font: {size: textFontSize}, topMargin: topMargin});
|
||||||
|
Overlays.editOverlay(text, {leftMargin: (windowDimensions.x - Overlays.textSize(text, textLines).width) / 2});
|
||||||
|
}
|
||||||
|
|
||||||
|
keyboard.onKeyPress = function(event) {
|
||||||
|
if (event.event == 'keypress') {
|
||||||
|
appendChar(event.char);
|
||||||
|
} else if (event.event == 'enter') {
|
||||||
|
appendChar("\n");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
keyboard.onKeyRelease = function(event) {
|
||||||
|
print("Key release event test");
|
||||||
|
// you can cancel a key by releasing its focusing before releasing it
|
||||||
|
if (event.focus) {
|
||||||
|
if (event.event == 'delete') {
|
||||||
|
deleteChar();
|
||||||
|
} else if (event.event == 'submit') {
|
||||||
|
print(textText);
|
||||||
|
|
||||||
|
var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE));
|
||||||
|
|
||||||
|
var textLines = textText.split("\n");
|
||||||
|
var maxLineWidth = Overlays.textSize(textSizeMeasureOverlay, textText).width;
|
||||||
|
var usernameLine = "--" + GlobalServices.myUsername;
|
||||||
|
var usernameWidth = Overlays.textSize(textSizeMeasureOverlay, usernameLine).width;
|
||||||
|
if (maxLineWidth < usernameWidth) {
|
||||||
|
maxLineWidth = usernameWidth;
|
||||||
|
} else {
|
||||||
|
var spaceableWidth = maxLineWidth - usernameWidth;
|
||||||
|
//TODO: WORKAROUND WARNING BELOW Fix this when spaces are not trimmed out of the textsize calculation anymore
|
||||||
|
var spaceWidth = Overlays.textSize(textSizeMeasureOverlay, "| |").width
|
||||||
|
- Overlays.textSize(textSizeMeasureOverlay, "||").width;
|
||||||
|
var numberOfSpaces = Math.floor(spaceableWidth / spaceWidth);
|
||||||
|
for (var i = 0; i < numberOfSpaces; i++) {
|
||||||
|
usernameLine = " " + usernameLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var dimension_x = maxLineWidth + TEXT_MARGIN_RIGHT + TEXT_MARGIN_LEFT;
|
||||||
|
if (position.x > 0 && position.y > 0 && position.z > 0) {
|
||||||
|
Entities.addEntity({
|
||||||
|
type: "Text",
|
||||||
|
rotation: MyAvatar.orientation,
|
||||||
|
position: position,
|
||||||
|
dimensions: { x: dimension_x, y: (textLines.length + 1) * 0.14 + TEXT_MARGIN_TOP + TEXT_MARGIN_BOTTOM, z: DEFAULT_TEXT_DIMENSION_Z },
|
||||||
|
backgroundColor: { red: 0, green: 0, blue: 0 },
|
||||||
|
textColor: { red: 255, green: 255, blue: 255 },
|
||||||
|
text: textText + "\n" + usernameLine,
|
||||||
|
lineHeight: 0.1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
textText = "";
|
||||||
|
updateTextOverlay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
keyboard.onFullyLoaded = function() {
|
||||||
|
print("Virtual-keyboard fully loaded.");
|
||||||
|
var dimensions = Controller.getViewportDimensions();
|
||||||
|
text = Overlays.addOverlay("text", {
|
||||||
|
x: 0,
|
||||||
|
y: dimensions.y - keyboard.height() - 260,
|
||||||
|
width: dimensions.x,
|
||||||
|
height: 250,
|
||||||
|
backgroundColor: { red: 255, green: 255, blue: 255},
|
||||||
|
color: { red: 0, green: 0, blue: 0},
|
||||||
|
topMargin: 5,
|
||||||
|
leftMargin: 0,
|
||||||
|
font: {size: textFontSize},
|
||||||
|
text: "",
|
||||||
|
alpha: 0.8
|
||||||
|
});
|
||||||
|
updateTextOverlay();
|
||||||
|
// the cursor is being loaded after the keyboard, else it will be on the background of the keyboard
|
||||||
|
cursor.initialize();
|
||||||
|
cursor.onUpdate = function(position) {
|
||||||
|
keyboard.setFocusPosition(position.x, position.y);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function keyPressEvent(event) {
|
||||||
|
if (event.key === SPACEBAR_CHARCODE) {
|
||||||
|
keyboard.pressFocussedKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function keyReleaseEvent(event) {
|
||||||
|
if (event.key === SPACEBAR_CHARCODE) {
|
||||||
|
keyboard.releaseKeys();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function scriptEnding() {
|
||||||
|
keyboard.remove();
|
||||||
|
cursor.remove();
|
||||||
|
Overlays.deleteOverlay(text);
|
||||||
|
Overlays.deleteOverlay(textSizeMeasureOverlay);
|
||||||
|
Controller.releaseKeyEvents({key: SPACEBAR_CHARCODE});
|
||||||
|
}
|
||||||
|
|
||||||
|
function reportButtonValue(button, newValue, oldValue) {
|
||||||
|
if (button == Joysticks.BUTTON_FACE_BOTTOM) {
|
||||||
|
if (newValue) {
|
||||||
|
keyboard.pressFocussedKey();
|
||||||
|
} else {
|
||||||
|
keyboard.releaseKeys();
|
||||||
|
}
|
||||||
|
} else if (button == Joysticks.BUTTON_FACE_RIGHT && newValue) {
|
||||||
|
deleteChar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addJoystick(gamepad) {
|
||||||
|
gamepad.buttonStateChanged.connect(reportButtonValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
var allJoysticks = Joysticks.getAllJoysticks();
|
||||||
|
for (var i = 0; i < allJoysticks.length; i++) {
|
||||||
|
addJoystick(allJoysticks[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Joysticks.joystickAdded.connect(addJoystick);
|
||||||
|
Controller.captureKeyEvents({key: SPACEBAR_CHARCODE});
|
||||||
|
Controller.keyPressEvent.connect(keyPressEvent);
|
||||||
|
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
||||||
|
Script.scriptEnding.connect(scriptEnding);
|
|
@ -9,179 +9,50 @@
|
||||||
// Usage: Enable VR-mode and go to First person mode,
|
// Usage: Enable VR-mode and go to First person mode,
|
||||||
// look at the key that you would like to press, and press the spacebar on your "REAL" keyboard.
|
// look at the key that you would like to press, and press the spacebar on your "REAL" keyboard.
|
||||||
//
|
//
|
||||||
// leased some code from newEditEntities.js for Text Entity example
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
// experimental 3dmode
|
||||||
|
THREE_D_MODE = false;
|
||||||
|
|
||||||
const KBD_UPPERCASE_DEFAULT = 0;
|
KBD_UPPERCASE_DEFAULT = 0;
|
||||||
const KBD_LOWERCASE_DEFAULT = 1;
|
KBD_LOWERCASE_DEFAULT = 1;
|
||||||
const KBD_UPPERCASE_HOVER = 2;
|
KBD_UPPERCASE_HOVER = 2;
|
||||||
const KBD_LOWERCASE_HOVER = 3;
|
KBD_LOWERCASE_HOVER = 3;
|
||||||
const KBD_BACKGROUND = 4;
|
KBD_BACKGROUND = 4;
|
||||||
|
|
||||||
const KEYBOARD_URL = HIFI_PUBLIC_BUCKET + "images/keyboard.svg";
|
KEYBOARD_URL = HIFI_PUBLIC_BUCKET + "images/keyboard.svg";
|
||||||
const CURSOR_URL = HIFI_PUBLIC_BUCKET + "images/cursor.svg";
|
CURSOR_URL = HIFI_PUBLIC_BUCKET + "images/cursor.svg";
|
||||||
|
|
||||||
const SPACEBAR_CHARCODE = 32;
|
RETURN_CHARCODE = 0x01000004;
|
||||||
|
ENTER_CHARCODE = 0x01000005;
|
||||||
|
SPACEBAR_CHARCODE = 32;
|
||||||
|
|
||||||
const KEYBOARD_WIDTH = 1174.7;
|
KEYBOARD_WIDTH = 1174.7;
|
||||||
const KEYBOARD_HEIGHT = 434.1;
|
KEYBOARD_HEIGHT = 434.1;
|
||||||
|
|
||||||
const CURSOR_WIDTH = 33.9;
|
CURSOR_WIDTH = 33.9;
|
||||||
const CURSOR_HEIGHT = 33.9;
|
CURSOR_HEIGHT = 33.9;
|
||||||
|
|
||||||
|
KEYBOARD_SCALE_MULTIPLIER = 0.50;
|
||||||
|
|
||||||
// VIEW_ANGLE can be adjusted to your likings, the smaller the faster movement.
|
// VIEW_ANGLE can be adjusted to your likings, the smaller the faster movement.
|
||||||
// Try setting it to 60 if it goes too fast for you.
|
// Try setting it to 60 if it goes too fast for you.
|
||||||
const VIEW_ANGLE = 40.0;
|
const VIEW_ANGLE = 40.0;
|
||||||
const VIEW_ANGLE_BY_TWO = VIEW_ANGLE / 2;
|
const VIEW_ANGLE_BY_TWO = VIEW_ANGLE / 2;
|
||||||
|
|
||||||
const SPAWN_DISTANCE = 1;
|
|
||||||
const DEFAULT_TEXT_DIMENSION_Z = 0.02;
|
|
||||||
|
|
||||||
const BOUND_X = 0;
|
const BOUND_X = 0;
|
||||||
const BOUND_Y = 1;
|
const BOUND_Y = 1;
|
||||||
const BOUND_W = 2;
|
const BOUND_W = 2;
|
||||||
const BOUND_H = 3;
|
const BOUND_H = 3;
|
||||||
|
|
||||||
const KEY_STATE_LOWER = 0;
|
KEY_STATE_LOWER = 0;
|
||||||
const KEY_STATE_UPPER = 1;
|
KEY_STATE_UPPER = 1;
|
||||||
|
|
||||||
const TEXT_MARGIN_TOP = 0.15;
|
|
||||||
const TEXT_MARGIN_LEFT = 0.15;
|
|
||||||
const TEXT_MARGIN_RIGHT = 0.17;
|
|
||||||
const TEXT_MARGIN_BOTTOM = 0.17;
|
|
||||||
|
|
||||||
var windowDimensions = Controller.getViewportDimensions();
|
var windowDimensions = Controller.getViewportDimensions();
|
||||||
var cursor = null;
|
|
||||||
var keyboard = new Keyboard();
|
|
||||||
var textFontSize = 9;
|
|
||||||
var text = null;
|
|
||||||
var textText = "";
|
|
||||||
var textSizeMeasureOverlay = Overlays.addOverlay("text3d", {visible: false});
|
|
||||||
|
|
||||||
function appendChar(char) {
|
KeyboardKey = (function(keyboard, keyProperties) {
|
||||||
textText += char;
|
|
||||||
updateTextOverlay();
|
|
||||||
Overlays.editOverlay(text, {text: textText});
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteChar() {
|
|
||||||
if (textText.length > 0) {
|
|
||||||
textText = textText.substring(0, textText.length - 1);
|
|
||||||
updateTextOverlay();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateTextOverlay() {
|
|
||||||
var textLines = textText.split("\n");
|
|
||||||
var maxLineWidth = 0;
|
|
||||||
for (textLine in textLines) {
|
|
||||||
var lineWidth = Overlays.textSize(text, textLines[textLine]).width;
|
|
||||||
if (lineWidth > maxLineWidth) {
|
|
||||||
maxLineWidth = lineWidth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var suggestedFontSize = (windowDimensions.x / maxLineWidth) * textFontSize * 0.90;
|
|
||||||
var maxFontSize = 190 / textLines.length;
|
|
||||||
textFontSize = (suggestedFontSize > maxFontSize) ? maxFontSize : suggestedFontSize;
|
|
||||||
var topMargin = (250 - (textFontSize * textLines.length)) / 4;
|
|
||||||
Overlays.editOverlay(text, {text: textText, font: {size: textFontSize}, topMargin: topMargin});
|
|
||||||
var maxLineWidth = 0;
|
|
||||||
for (textLine in textLines) {
|
|
||||||
var lineWidth = Overlays.textSize(text, textLines[textLine]).width;
|
|
||||||
if (lineWidth > maxLineWidth) {
|
|
||||||
maxLineWidth = lineWidth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Overlays.editOverlay(text, {leftMargin: (windowDimensions.x - maxLineWidth) / 2});
|
|
||||||
}
|
|
||||||
|
|
||||||
keyboard.onKeyPress = function(event) {
|
|
||||||
if (event.event == 'keypress') {
|
|
||||||
appendChar(event.char);
|
|
||||||
} else if (event.event == 'enter') {
|
|
||||||
appendChar("\n");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
keyboard.onKeyRelease = function(event) {
|
|
||||||
print("Key release event test");
|
|
||||||
// you can cancel a key by releasing its focusing before releasing it
|
|
||||||
if (event.focus) {
|
|
||||||
if (event.event == 'delete') {
|
|
||||||
deleteChar();
|
|
||||||
} else if (event.event == 'submit') {
|
|
||||||
print(textText);
|
|
||||||
|
|
||||||
var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE));
|
|
||||||
|
|
||||||
var textLines = textText.split("\n");
|
|
||||||
var maxLineWidth = 0;
|
|
||||||
for (textLine in textLines) {
|
|
||||||
var lineWidth = Overlays.textSize(textSizeMeasureOverlay, textLines[textLine]).width;
|
|
||||||
if (lineWidth > maxLineWidth) {
|
|
||||||
maxLineWidth = lineWidth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var usernameLine = "--" + GlobalServices.myUsername;
|
|
||||||
var usernameWidth = Overlays.textSize(textSizeMeasureOverlay, usernameLine).width;
|
|
||||||
if (maxLineWidth < usernameWidth) {
|
|
||||||
maxLineWidth = usernameWidth;
|
|
||||||
} else {
|
|
||||||
var spaceableWidth = maxLineWidth - usernameWidth;
|
|
||||||
var spaceWidth = Overlays.textSize(textSizeMeasureOverlay, " ").width;
|
|
||||||
var numberOfSpaces = Math.floor(spaceableWidth / spaceWidth);
|
|
||||||
for (var i = 0; i < numberOfSpaces; i++) {
|
|
||||||
usernameLine = " " + usernameLine;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var dimension_x = maxLineWidth + TEXT_MARGIN_RIGHT + TEXT_MARGIN_LEFT;
|
|
||||||
if (position.x > 0 && position.y > 0 && position.z > 0) {
|
|
||||||
Entities.addEntity({
|
|
||||||
type: "Text",
|
|
||||||
rotation: MyAvatar.orientation,
|
|
||||||
position: position,
|
|
||||||
dimensions: { x: dimension_x, y: (textLines.length + 1) * 0.14 + TEXT_MARGIN_TOP + TEXT_MARGIN_BOTTOM, z: DEFAULT_TEXT_DIMENSION_Z },
|
|
||||||
backgroundColor: { red: 0, green: 0, blue: 0 },
|
|
||||||
textColor: { red: 255, green: 255, blue: 255 },
|
|
||||||
text: textText + "\n" + usernameLine
|
|
||||||
});
|
|
||||||
}
|
|
||||||
textText = "";
|
|
||||||
updateTextOverlay();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
keyboard.onFullyLoaded = function() {
|
|
||||||
print("Virtual-keyboard fully loaded.");
|
|
||||||
var dimensions = Controller.getViewportDimensions();
|
|
||||||
text = Overlays.addOverlay("text", {
|
|
||||||
x: 0,
|
|
||||||
y: dimensions.y - keyboard.height() - 260,
|
|
||||||
width: dimensions.x,
|
|
||||||
height: 250,
|
|
||||||
backgroundColor: { red: 255, green: 255, blue: 255},
|
|
||||||
color: { red: 0, green: 0, blue: 0},
|
|
||||||
topMargin: 5,
|
|
||||||
leftMargin: 0,
|
|
||||||
font: {size: textFontSize},
|
|
||||||
text: "",
|
|
||||||
alpha: 0.8
|
|
||||||
});
|
|
||||||
updateTextOverlay();
|
|
||||||
// the cursor is being loaded after the keyboard, else it will be on the background of the keyboard
|
|
||||||
cursor = new Cursor();
|
|
||||||
cursor.onUpdate = function(position) {
|
|
||||||
keyboard.setFocusPosition(position.x, position.y);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
function KeyboardKey(keyboard, keyProperties) {
|
|
||||||
var tthis = this;
|
var tthis = this;
|
||||||
this._focus = false;
|
this._focus = false;
|
||||||
this._beingPressed = false;
|
this._beingPressed = false;
|
||||||
|
@ -247,6 +118,11 @@ function KeyboardKey(keyboard, keyProperties) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
this.updateVisibility = function() {
|
||||||
|
for (var i = 0; i < tthis.bounds.length; i++) {
|
||||||
|
Overlays.editOverlay(tthis.overlays[i], {visible: tthis.keyboard.visible});
|
||||||
|
}
|
||||||
|
};
|
||||||
this.rescale = function() {
|
this.rescale = function() {
|
||||||
for (var i = 0; i < tthis.bounds.length; i++) {
|
for (var i = 0; i < tthis.bounds.length; i++) {
|
||||||
Overlays.editOverlay(tthis.overlays[i], {
|
Overlays.editOverlay(tthis.overlays[i], {
|
||||||
|
@ -271,24 +147,48 @@ function KeyboardKey(keyboard, keyProperties) {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
for (var i = 0; i < this.bounds.length; i++) {
|
for (var i = 0; i < this.bounds.length; i++) {
|
||||||
var newOverlay = Overlays.cloneOverlay(this.keyboard.background);
|
if (THREE_D_MODE) {
|
||||||
Overlays.editOverlay(newOverlay, {
|
this.overlays.push(Overlays.addOverlay("billboard", {
|
||||||
|
scale: 1,
|
||||||
|
rotation: MyAvatar.rotation,
|
||||||
|
isFacingAvatar: false,
|
||||||
|
url: KEYBOARD_URL,
|
||||||
|
alpha: 1,
|
||||||
|
position: {
|
||||||
|
x: MyAvatar.position.x,// + this.bounds[i][BOUND_X] * 0.01,// /*+ this.keyboard.getX()*/ + this.bounds[i][BOUND_X] * keyboard.scale,
|
||||||
|
y: MyAvatar.position.y,// - this.bounds[i][BOUND_Y] * 0.01,// /*+ this.keyboard.getY()*/ + this.bounds[i][BOUND_Y] * keyboard.scale,
|
||||||
|
z: MyAvatar.position.z
|
||||||
|
},
|
||||||
|
width: this.bounds[i][BOUND_W] * keyboard.scale,
|
||||||
|
height: this.bounds[i][BOUND_H] * keyboard.scale,
|
||||||
|
subImage: {width: this.bounds[i][BOUND_W], height: this.bounds[i][BOUND_H], x: this.bounds[i][BOUND_X], y: (KEYBOARD_HEIGHT * this.keyState) + this.bounds[i][BOUND_Y]},
|
||||||
|
alpha: 1,
|
||||||
|
visible: tthis.keyboard.visible
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
this.overlays.push(Overlays.addOverlay("image", {
|
||||||
|
imageURL: KEYBOARD_URL,
|
||||||
x: this.keyboard.getX() + this.bounds[i][BOUND_X] * keyboard.scale,
|
x: this.keyboard.getX() + this.bounds[i][BOUND_X] * keyboard.scale,
|
||||||
y: this.keyboard.getY() + this.bounds[i][BOUND_Y] * keyboard.scale,
|
y: this.keyboard.getY() + this.bounds[i][BOUND_Y] * keyboard.scale,
|
||||||
width: this.bounds[i][BOUND_W] * keyboard.scale,
|
width: this.bounds[i][BOUND_W] * keyboard.scale,
|
||||||
height: this.bounds[i][BOUND_H] * keyboard.scale,
|
height: this.bounds[i][BOUND_H] * keyboard.scale,
|
||||||
subImage: {width: this.bounds[i][BOUND_W], height: this.bounds[i][BOUND_H], x: this.bounds[i][BOUND_X], y: (KEYBOARD_HEIGHT * this.keyState) + this.bounds[i][BOUND_Y]},
|
subImage: {width: this.bounds[i][BOUND_W], height: this.bounds[i][BOUND_H], x: this.bounds[i][BOUND_X], y: (KEYBOARD_HEIGHT * this.keyState) + this.bounds[i][BOUND_Y]},
|
||||||
alpha: 1
|
alpha: 1,
|
||||||
|
visible: tthis.keyboard.visible
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this.overlays.push(newOverlay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Keyboard() {
|
Keyboard = (function(params) {
|
||||||
|
if (params === undefined) {
|
||||||
|
params = {};
|
||||||
|
}
|
||||||
var tthis = this;
|
var tthis = this;
|
||||||
this.focussed_key = -1;
|
this.focussed_key = -1;
|
||||||
this.scale = windowDimensions.x / KEYBOARD_WIDTH;
|
this.scale = (windowDimensions.x / KEYBOARD_WIDTH) * KEYBOARD_SCALE_MULTIPLIER;
|
||||||
this.shift = false;
|
this.shift = false;
|
||||||
|
this.visible = params.visible != undefined ? params.visible : true;
|
||||||
this.width = function() {
|
this.width = function() {
|
||||||
return KEYBOARD_WIDTH * tthis.scale;
|
return KEYBOARD_WIDTH * tthis.scale;
|
||||||
};
|
};
|
||||||
|
@ -301,6 +201,20 @@ function Keyboard() {
|
||||||
this.getY = function() {
|
this.getY = function() {
|
||||||
return windowDimensions.y - this.height();
|
return windowDimensions.y - this.height();
|
||||||
};
|
};
|
||||||
|
if (THREE_D_MODE) {
|
||||||
|
this.background = Overlays.addOverlay("billboard", {
|
||||||
|
scale: 1,
|
||||||
|
position: MyAvatar.position,
|
||||||
|
rotation: MyAvatar.rotation,
|
||||||
|
width: this.width(),
|
||||||
|
height: this.height(),
|
||||||
|
subImage: {width: KEYBOARD_WIDTH, height: KEYBOARD_HEIGHT, y: KEYBOARD_HEIGHT * KBD_BACKGROUND},
|
||||||
|
isFacingAvatar: false,
|
||||||
|
url: KEYBOARD_URL,
|
||||||
|
alpha: 1,
|
||||||
|
visible: this.visible
|
||||||
|
});
|
||||||
|
} else {
|
||||||
this.background = Overlays.addOverlay("image", {
|
this.background = Overlays.addOverlay("image", {
|
||||||
x: this.getX(),
|
x: this.getX(),
|
||||||
y: this.getY(),
|
y: this.getY(),
|
||||||
|
@ -308,10 +222,12 @@ function Keyboard() {
|
||||||
height: this.height(),
|
height: this.height(),
|
||||||
subImage: {width: KEYBOARD_WIDTH, height: KEYBOARD_HEIGHT, y: KEYBOARD_HEIGHT * KBD_BACKGROUND},
|
subImage: {width: KEYBOARD_WIDTH, height: KEYBOARD_HEIGHT, y: KEYBOARD_HEIGHT * KBD_BACKGROUND},
|
||||||
imageURL: KEYBOARD_URL,
|
imageURL: KEYBOARD_URL,
|
||||||
alpha: 1
|
alpha: 1,
|
||||||
|
visible: this.visible
|
||||||
});
|
});
|
||||||
|
}
|
||||||
this.rescale = function() {
|
this.rescale = function() {
|
||||||
this.scale = windowDimensions.x / KEYBOARD_WIDTH;
|
this.scale = (windowDimensions.x / KEYBOARD_WIDTH) * KEYBOARD_SCALE_MULTIPLIER;
|
||||||
Overlays.editOverlay(tthis.background, {
|
Overlays.editOverlay(tthis.background, {
|
||||||
x: this.getX(),
|
x: this.getX(),
|
||||||
y: this.getY(),
|
y: this.getY(),
|
||||||
|
@ -349,6 +265,9 @@ function Keyboard() {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.pressFocussedKey = function() {
|
this.pressFocussedKey = function() {
|
||||||
|
if (!tthis.visible) {
|
||||||
|
return tthis;
|
||||||
|
}
|
||||||
if (tthis.focussed_key != -1) {
|
if (tthis.focussed_key != -1) {
|
||||||
if (tthis.keys[tthis.focussed_key].event == 'shift') {
|
if (tthis.keys[tthis.focussed_key].event == 'shift') {
|
||||||
tthis.toggleShift();
|
tthis.toggleShift();
|
||||||
|
@ -402,6 +321,32 @@ function Keyboard() {
|
||||||
for (var i = 0; i < this.keys.length; i++) {
|
for (var i = 0; i < this.keys.length; i++) {
|
||||||
this.keys[i].remove();
|
this.keys[i].remove();
|
||||||
}
|
}
|
||||||
|
// resets the cursor and magnifier
|
||||||
|
this.updateVisibility(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.show = function() {
|
||||||
|
tthis.updateVisibility(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.hide = function() {
|
||||||
|
tthis.updateVisibility(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.toggle = function() {
|
||||||
|
tthis.updateVisibility(!tthis.visible);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.updateVisibility = function(visible) {
|
||||||
|
tthis.visible = visible;
|
||||||
|
if (HMD.magnifier == visible) {
|
||||||
|
HMD.toggleMagnifier();
|
||||||
|
}
|
||||||
|
Window.cursorVisible = !visible;
|
||||||
|
Overlays.editOverlay(tthis.background, { visible: tthis.visible });
|
||||||
|
for (var i = 0; i < this.keys.length; i++) {
|
||||||
|
this.keys[i].updateVisibility();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onKeyPress = null;
|
this.onKeyPress = null;
|
||||||
|
@ -502,23 +447,27 @@ function Keyboard() {
|
||||||
|
|
||||||
{bounds: [[899, 355, 263, 67]], event: 'submit'}
|
{bounds: [[899, 355, 263, 67]], event: 'submit'}
|
||||||
];
|
];
|
||||||
|
for (var i = 0; i < keyProperties.length; i++) {
|
||||||
|
this.keys.push(new KeyboardKey(this, keyProperties[i]));
|
||||||
|
}
|
||||||
this.keyboardTextureLoaded = function() {
|
this.keyboardTextureLoaded = function() {
|
||||||
if (Overlays.isLoaded(tthis.background)) {
|
if (Overlays.isLoaded(tthis.background)) {
|
||||||
Script.clearInterval(tthis.keyboardTextureLoaded_timer);
|
Script.clearInterval(tthis.keyboardTextureLoaded_timer);
|
||||||
for (var i = 0; i < keyProperties.length; i++) {
|
|
||||||
tthis.keys.push(new KeyboardKey(tthis, keyProperties[i]));
|
|
||||||
}
|
|
||||||
if (keyboard.onFullyLoaded != null) {
|
if (keyboard.onFullyLoaded != null) {
|
||||||
tthis.onFullyLoaded();
|
tthis.onFullyLoaded();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.keyboardTextureLoaded_timer = Script.setInterval(this.keyboardTextureLoaded, 250);
|
this.keyboardTextureLoaded_timer = Script.setInterval(this.keyboardTextureLoaded, 250);
|
||||||
}
|
});
|
||||||
|
|
||||||
function Cursor() {
|
Cursor = (function(params) {
|
||||||
|
if (params === undefined) {
|
||||||
|
params = {};
|
||||||
|
}
|
||||||
var tthis = this;
|
var tthis = this;
|
||||||
|
this.initialize = function() {
|
||||||
|
this.visible = params.visible != undefined ? params.visible : true;
|
||||||
this.x = windowDimensions.x / 2;
|
this.x = windowDimensions.x / 2;
|
||||||
this.y = windowDimensions.y / 2;
|
this.y = windowDimensions.y / 2;
|
||||||
this.overlay = Overlays.addOverlay("image", {
|
this.overlay = Overlays.addOverlay("image", {
|
||||||
|
@ -527,7 +476,8 @@ function Cursor() {
|
||||||
width: CURSOR_WIDTH,
|
width: CURSOR_WIDTH,
|
||||||
height: CURSOR_HEIGHT,
|
height: CURSOR_HEIGHT,
|
||||||
imageURL: CURSOR_URL,
|
imageURL: CURSOR_URL,
|
||||||
alpha: 1
|
alpha: 1,
|
||||||
|
visible: this.visible
|
||||||
});
|
});
|
||||||
this.remove = function() {
|
this.remove = function() {
|
||||||
Overlays.deleteOverlay(this.overlay);
|
Overlays.deleteOverlay(this.overlay);
|
||||||
|
@ -541,6 +491,19 @@ function Cursor() {
|
||||||
this.getY = function() {
|
this.getY = function() {
|
||||||
return tthis.y;
|
return tthis.y;
|
||||||
};
|
};
|
||||||
|
this.show = function() {
|
||||||
|
tthis.updateVisibility(true);
|
||||||
|
};
|
||||||
|
this.hide = function() {
|
||||||
|
tthis.updateVisibility(false);
|
||||||
|
};
|
||||||
|
this.toggle = function() {
|
||||||
|
tthis.updateVisibility(!tthis.visible);
|
||||||
|
};
|
||||||
|
this.updateVisibility = function(visible) {
|
||||||
|
tthis.visible = visible;
|
||||||
|
Overlays.editOverlay(this.overlay, { visible: tthis.visible });
|
||||||
|
};
|
||||||
this.onUpdate = null;
|
this.onUpdate = null;
|
||||||
this.update = function() {
|
this.update = function() {
|
||||||
var newWindowDimensions = Controller.getViewportDimensions();
|
var newWindowDimensions = Controller.getViewportDimensions();
|
||||||
|
@ -553,14 +516,16 @@ function Cursor() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
var editobject = {};
|
var editobject = {};
|
||||||
if (MyAvatar.getHeadFinalYaw() <= VIEW_ANGLE_BY_TWO && MyAvatar.getHeadFinalYaw() >= -1 * VIEW_ANGLE_BY_TWO) {
|
var hudLookatPosition = HMD.getHUDLookAtPosition2D();
|
||||||
angle = ((-1 * MyAvatar.getHeadFinalYaw()) + VIEW_ANGLE_BY_TWO) / VIEW_ANGLE;
|
if (hudLookatPosition === null) {
|
||||||
tthis.x = angle * windowDimensions.x;
|
return;
|
||||||
|
}
|
||||||
|
if (tthis.x !== hudLookatPosition.x) {
|
||||||
|
tthis.x = hudLookatPosition.x;
|
||||||
editobject.x = tthis.x - (CURSOR_WIDTH / 2);
|
editobject.x = tthis.x - (CURSOR_WIDTH / 2);
|
||||||
}
|
}
|
||||||
if (MyAvatar.getHeadFinalPitch() <= VIEW_ANGLE_BY_TWO && MyAvatar.getHeadFinalPitch() >= -1 * VIEW_ANGLE_BY_TWO) {
|
if (tthis.y !== hudLookatPosition.y) {
|
||||||
angle = ((-1 * MyAvatar.getHeadFinalPitch()) + VIEW_ANGLE_BY_TWO) / VIEW_ANGLE;
|
tthis.y = hudLookatPosition.y;
|
||||||
tthis.y = angle * windowDimensions.y;
|
|
||||||
editobject.y = tthis.y - (CURSOR_HEIGHT / 2);
|
editobject.y = tthis.y - (CURSOR_HEIGHT / 2);
|
||||||
}
|
}
|
||||||
if (Object.keys(editobject).length > 0) {
|
if (Object.keys(editobject).length > 0) {
|
||||||
|
@ -571,28 +536,5 @@ function Cursor() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Script.update.connect(this.update);
|
Script.update.connect(this.update);
|
||||||
}
|
};
|
||||||
|
});
|
||||||
function keyPressEvent(event) {
|
|
||||||
if (event.key === SPACEBAR_CHARCODE) {
|
|
||||||
keyboard.pressFocussedKey();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function keyReleaseEvent(event) {
|
|
||||||
if (event.key === SPACEBAR_CHARCODE) {
|
|
||||||
keyboard.releaseKeys();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function scriptEnding() {
|
|
||||||
keyboard.remove();
|
|
||||||
cursor.remove();
|
|
||||||
Overlays.deleteOverlay(text);
|
|
||||||
Overlays.deleteOverlay(textSizeMeasureOverlay);
|
|
||||||
Controller.releaseKeyEvents({key: SPACEBAR_CHARCODE});
|
|
||||||
}
|
|
||||||
Controller.captureKeyEvents({key: SPACEBAR_CHARCODE});
|
|
||||||
Controller.keyPressEvent.connect(keyPressEvent);
|
|
||||||
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
|
||||||
Script.scriptEnding.connect(scriptEnding);
|
|
|
@ -111,6 +111,7 @@
|
||||||
#include "scripting/AccountScriptingInterface.h"
|
#include "scripting/AccountScriptingInterface.h"
|
||||||
#include "scripting/AudioDeviceScriptingInterface.h"
|
#include "scripting/AudioDeviceScriptingInterface.h"
|
||||||
#include "scripting/ClipboardScriptingInterface.h"
|
#include "scripting/ClipboardScriptingInterface.h"
|
||||||
|
#include "scripting/HMDScriptingInterface.h"
|
||||||
#include "scripting/JoystickScriptingInterface.h"
|
#include "scripting/JoystickScriptingInterface.h"
|
||||||
#include "scripting/GlobalServicesScriptingInterface.h"
|
#include "scripting/GlobalServicesScriptingInterface.h"
|
||||||
#include "scripting/LocationScriptingInterface.h"
|
#include "scripting/LocationScriptingInterface.h"
|
||||||
|
@ -3492,6 +3493,10 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
||||||
|
|
||||||
scriptEngine->registerGlobalObject("UndoStack", &_undoStackScriptingInterface);
|
scriptEngine->registerGlobalObject("UndoStack", &_undoStackScriptingInterface);
|
||||||
|
|
||||||
|
QScriptValue hmdInterface = scriptEngine->registerGlobalObject("HMD", &HMDScriptingInterface::getInstance());
|
||||||
|
scriptEngine->registerFunction(hmdInterface, "getHUDLookAtPosition2D", HMDScriptingInterface::getHUDLookAtPosition2D, 0);
|
||||||
|
scriptEngine->registerFunction(hmdInterface, "getHUDLookAtPosition3D", HMDScriptingInterface::getHUDLookAtPosition3D, 0);
|
||||||
|
|
||||||
#ifdef HAVE_RTMIDI
|
#ifdef HAVE_RTMIDI
|
||||||
scriptEngine->registerGlobalObject("MIDI", &MIDIManager::getInstance());
|
scriptEngine->registerGlobalObject("MIDI", &MIDIManager::getInstance());
|
||||||
#endif
|
#endif
|
||||||
|
|
56
interface/src/scripting/HMDScriptingInterface.cpp
Normal file
56
interface/src/scripting/HMDScriptingInterface.cpp
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
//
|
||||||
|
// HMDScriptingInterface.cpp
|
||||||
|
// interface/src/scripting
|
||||||
|
//
|
||||||
|
// Created by Thijs Wenker on 1/12/15.
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "HMDScriptingInterface.h"
|
||||||
|
|
||||||
|
#include <avatar/AvatarManager.h>
|
||||||
|
|
||||||
|
HMDScriptingInterface& HMDScriptingInterface::getInstance() {
|
||||||
|
static HMDScriptingInterface sharedInstance;
|
||||||
|
return sharedInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HMDScriptingInterface::getHUDLookAtPosition3D(glm::vec3& result) const {
|
||||||
|
Camera* camera = Application::getInstance()->getCamera();
|
||||||
|
glm::vec3 position = camera->getPosition();
|
||||||
|
glm::quat orientation = camera->getOrientation();
|
||||||
|
|
||||||
|
glm::vec3 direction = orientation * glm::vec3(0.0f, 0.0f, -1.0f);
|
||||||
|
|
||||||
|
ApplicationOverlay& applicationOverlay = Application::getInstance()->getApplicationOverlay();
|
||||||
|
|
||||||
|
return applicationOverlay.calculateRayUICollisionPoint(position, direction, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
QScriptValue HMDScriptingInterface::getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine) {
|
||||||
|
|
||||||
|
glm::vec3 hudIntersection;
|
||||||
|
|
||||||
|
if ((&HMDScriptingInterface::getInstance())->getHUDLookAtPosition3D(hudIntersection)) {
|
||||||
|
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||||
|
glm::vec3 sphereCenter = myAvatar->getDefaultEyePosition();
|
||||||
|
glm::vec3 direction = glm::inverse(myAvatar->getOrientation()) * (hudIntersection - sphereCenter);
|
||||||
|
glm::quat rotation = ::rotationBetween(glm::vec3(0.0f, 0.0f, -1.0f), direction);
|
||||||
|
glm::vec3 eulers = ::safeEulerAngles(rotation);
|
||||||
|
return qScriptValueFromValue<glm::vec2>(engine, Application::getInstance()->getApplicationOverlay()
|
||||||
|
.sphericalToOverlay(glm::vec2(eulers.y, -eulers.x)));
|
||||||
|
}
|
||||||
|
return QScriptValue::NullValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScriptValue HMDScriptingInterface::getHUDLookAtPosition3D(QScriptContext* context, QScriptEngine* engine) {
|
||||||
|
glm::vec3 result;
|
||||||
|
HMDScriptingInterface* hmdInterface = &HMDScriptingInterface::getInstance();
|
||||||
|
if ((&HMDScriptingInterface::getInstance())->getHUDLookAtPosition3D(result)) {
|
||||||
|
return qScriptValueFromValue<glm::vec3>(engine, result);
|
||||||
|
}
|
||||||
|
return QScriptValue::NullValue;
|
||||||
|
}
|
42
interface/src/scripting/HMDScriptingInterface.h
Normal file
42
interface/src/scripting/HMDScriptingInterface.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
//
|
||||||
|
// HMDScriptingInterface.h
|
||||||
|
// interface/src/scripting
|
||||||
|
//
|
||||||
|
// Created by Thijs Wenker on 1/12/15.
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_HMDScriptingInterface_h
|
||||||
|
#define hifi_HMDScriptingInterface_h
|
||||||
|
|
||||||
|
#include <GLMHelpers.h>
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
|
#include "devices/OculusManager.h"
|
||||||
|
|
||||||
|
class HMDScriptingInterface : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(bool magnifier READ getMagnifier)
|
||||||
|
Q_PROPERTY(bool active READ isHMDMode)
|
||||||
|
public:
|
||||||
|
static HMDScriptingInterface& getInstance();
|
||||||
|
|
||||||
|
static QScriptValue getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine);
|
||||||
|
static QScriptValue getHUDLookAtPosition3D(QScriptContext* context, QScriptEngine* engine);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void toggleMagnifier() { Application::getInstance()->getApplicationOverlay().toggleMagnifier(); };
|
||||||
|
|
||||||
|
private:
|
||||||
|
HMDScriptingInterface() {};
|
||||||
|
bool getMagnifier() const { return Application::getInstance()->getApplicationOverlay().hasMagnifier(); };
|
||||||
|
bool isHMDMode() const { return Application::getInstance()->isHMDMode(); }
|
||||||
|
|
||||||
|
bool getHUDLookAtPosition3D(glm::vec3& result) const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_HMDScriptingInterface_h
|
|
@ -139,6 +139,7 @@ ApplicationOverlay::ApplicationOverlay() :
|
||||||
_alpha(1.0f),
|
_alpha(1.0f),
|
||||||
_oculusUIRadius(1.0f),
|
_oculusUIRadius(1.0f),
|
||||||
_crosshairTexture(0),
|
_crosshairTexture(0),
|
||||||
|
_magnifier(true),
|
||||||
_previousBorderWidth(-1),
|
_previousBorderWidth(-1),
|
||||||
_previousBorderHeight(-1),
|
_previousBorderHeight(-1),
|
||||||
_previousMagnifierBottomLeft(),
|
_previousMagnifierBottomLeft(),
|
||||||
|
@ -559,7 +560,7 @@ void ApplicationOverlay::renderPointers() {
|
||||||
|
|
||||||
_reticlePosition[MOUSE] = position;
|
_reticlePosition[MOUSE] = position;
|
||||||
_reticleActive[MOUSE] = true;
|
_reticleActive[MOUSE] = true;
|
||||||
_magActive[MOUSE] = true;
|
_magActive[MOUSE] = _magnifier;
|
||||||
_reticleActive[LEFT_CONTROLLER] = false;
|
_reticleActive[LEFT_CONTROLLER] = false;
|
||||||
_reticleActive[RIGHT_CONTROLLER] = false;
|
_reticleActive[RIGHT_CONTROLLER] = false;
|
||||||
} else if (qApp->getLastMouseMoveWasSimulated() && Menu::getInstance()->isOptionChecked(MenuOption::SixenseMouseInput)) {
|
} else if (qApp->getLastMouseMoveWasSimulated() && Menu::getInstance()->isOptionChecked(MenuOption::SixenseMouseInput)) {
|
||||||
|
@ -718,6 +719,9 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) {
|
||||||
|
|
||||||
//Renders a small magnification of the currently bound texture at the coordinates
|
//Renders a small magnification of the currently bound texture at the coordinates
|
||||||
void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) {
|
void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) {
|
||||||
|
if (!_magnifier) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
auto glCanvas = DependencyManager::get<GLCanvas>();
|
auto glCanvas = DependencyManager::get<GLCanvas>();
|
||||||
|
|
||||||
const int widgetWidth = glCanvas->width();
|
const int widgetWidth = glCanvas->width();
|
||||||
|
|
|
@ -37,6 +37,9 @@ public:
|
||||||
QPoint getPalmClickLocation(const PalmData *palm) const;
|
QPoint getPalmClickLocation(const PalmData *palm) const;
|
||||||
bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const;
|
bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const;
|
||||||
|
|
||||||
|
bool hasMagnifier() const { return _magnifier; }
|
||||||
|
void toggleMagnifier() { _magnifier = !_magnifier; }
|
||||||
|
|
||||||
float getOculusUIAngularSize() const { return _oculusUIAngularSize; }
|
float getOculusUIAngularSize() const { return _oculusUIAngularSize; }
|
||||||
void setOculusUIAngularSize(float oculusUIAngularSize) { _oculusUIAngularSize = oculusUIAngularSize; }
|
void setOculusUIAngularSize(float oculusUIAngularSize) { _oculusUIAngularSize = oculusUIAngularSize; }
|
||||||
|
|
||||||
|
@ -109,6 +112,7 @@ private:
|
||||||
bool _magActive[NUMBER_OF_RETICLES];
|
bool _magActive[NUMBER_OF_RETICLES];
|
||||||
float _magSizeMult[NUMBER_OF_RETICLES];
|
float _magSizeMult[NUMBER_OF_RETICLES];
|
||||||
quint64 _lastMouseMove;
|
quint64 _lastMouseMove;
|
||||||
|
bool _magnifier;
|
||||||
|
|
||||||
float _alpha;
|
float _alpha;
|
||||||
float _oculusUIRadius;
|
float _oculusUIRadius;
|
||||||
|
|
|
@ -272,8 +272,12 @@ QScriptValue ScriptEngine::registerGlobalObject(const QString& name, QObject* ob
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptEngine::registerFunction(const QString& name, QScriptEngine::FunctionSignature fun, int numArguments) {
|
void ScriptEngine::registerFunction(const QString& name, QScriptEngine::FunctionSignature fun, int numArguments) {
|
||||||
|
registerFunction(globalObject(), name, fun, numArguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptEngine::registerFunction(QScriptValue parent, const QString& name, QScriptEngine::FunctionSignature fun, int numArguments) {
|
||||||
QScriptValue scriptFun = newFunction(fun, numArguments);
|
QScriptValue scriptFun = newFunction(fun, numArguments);
|
||||||
globalObject().setProperty(name, scriptFun);
|
parent.setProperty(name, scriptFun);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptEngine::registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter,
|
void ScriptEngine::registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter,
|
||||||
|
|
|
@ -58,6 +58,8 @@ public:
|
||||||
void registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter,
|
void registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter,
|
||||||
QScriptEngine::FunctionSignature setter, QScriptValue object = QScriptValue::NullValue);
|
QScriptEngine::FunctionSignature setter, QScriptValue object = QScriptValue::NullValue);
|
||||||
void registerFunction(const QString& name, QScriptEngine::FunctionSignature fun, int numArguments = -1);
|
void registerFunction(const QString& name, QScriptEngine::FunctionSignature fun, int numArguments = -1);
|
||||||
|
void registerFunction(QScriptValue parent, const QString& name, QScriptEngine::FunctionSignature fun,
|
||||||
|
int numArguments = -1);
|
||||||
|
|
||||||
Q_INVOKABLE void setIsAvatar(bool isAvatar);
|
Q_INVOKABLE void setIsAvatar(bool isAvatar);
|
||||||
bool isAvatar() const { return _isAvatar; }
|
bool isAvatar() const { return _isAvatar; }
|
||||||
|
|
Loading…
Reference in a new issue