mirror of
https://github.com/overte-org/overte.git
synced 2025-04-14 13:27:01 +02:00
Merge pull request #13495 from thoys/feat/create/native-windows
Create App: Native windows
This commit is contained in:
commit
25406fa464
15 changed files with 936 additions and 222 deletions
interface/resources/qml
InteractiveWindow.qml
hifi/tablet
scripts/system
|
@ -120,12 +120,8 @@ Windows.Window {
|
|||
|
||||
Component.onCompleted: {
|
||||
// Fix for parent loss on OSX:
|
||||
parent.heightChanged.connect(function() {
|
||||
updateContentParent();
|
||||
});
|
||||
parent.widthChanged.connect(function() {
|
||||
updateContentParent();
|
||||
});
|
||||
parent.heightChanged.connect(updateContentParent);
|
||||
parent.widthChanged.connect(updateContentParent);
|
||||
|
||||
x = interactiveWindowPosition.x;
|
||||
y = interactiveWindowPosition.y;
|
||||
|
@ -194,6 +190,11 @@ Windows.Window {
|
|||
initialized = true;
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
parent.heightChanged.disconnect(updateContentParent);
|
||||
parent.widthChanged.disconnect(updateContentParent);
|
||||
}
|
||||
|
||||
// Handle message traffic from the script that launched us to the loaded QML
|
||||
function fromScript(message) {
|
||||
if (root.dynamicContent && root.dynamicContent.fromScript) {
|
||||
|
|
15
interface/resources/qml/hifi/tablet/EditEntityList.qml
Normal file
15
interface/resources/qml/hifi/tablet/EditEntityList.qml
Normal file
|
@ -0,0 +1,15 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
import QtWebChannel 1.0
|
||||
import "../../controls"
|
||||
import "../toolbars"
|
||||
import QtGraphicalEffects 1.0
|
||||
import "../../controls-uit" as HifiControls
|
||||
import "../../styles-uit"
|
||||
|
||||
|
||||
WebView {
|
||||
id: entityListToolWebView
|
||||
url: Paths.defaultScripts + "/system/html/entityList.html"
|
||||
enabled: true
|
||||
}
|
|
@ -9,7 +9,6 @@ import "../../styles-uit"
|
|||
|
||||
TabBar {
|
||||
id: editTabView
|
||||
// anchors.fill: parent
|
||||
width: parent.width
|
||||
contentWidth: parent.width
|
||||
padding: 0
|
||||
|
@ -34,7 +33,7 @@ TabBar {
|
|||
width: parent.width
|
||||
clip: true
|
||||
|
||||
contentHeight: createEntitiesFlow.height + importButton.height + assetServerButton.height +
|
||||
contentHeight: createEntitiesFlow.height + importButton.height + assetServerButton.height +
|
||||
header.anchors.topMargin + createEntitiesFlow.anchors.topMargin +
|
||||
assetServerButton.anchors.topMargin + importButton.anchors.topMargin +
|
||||
header.paintedHeight
|
||||
|
@ -77,8 +76,9 @@ TabBar {
|
|||
text: "MODEL"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "newModelButton" }
|
||||
});
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newModelButton" }
|
||||
});
|
||||
editTabView.currentIndex = 2
|
||||
}
|
||||
}
|
||||
|
@ -88,8 +88,9 @@ TabBar {
|
|||
text: "CUBE"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "newCubeButton" }
|
||||
});
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newCubeButton" }
|
||||
});
|
||||
editTabView.currentIndex = 2
|
||||
}
|
||||
}
|
||||
|
@ -99,8 +100,9 @@ TabBar {
|
|||
text: "SPHERE"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "newSphereButton" }
|
||||
});
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newSphereButton" }
|
||||
});
|
||||
editTabView.currentIndex = 2
|
||||
}
|
||||
}
|
||||
|
@ -110,8 +112,9 @@ TabBar {
|
|||
text: "LIGHT"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "newLightButton" }
|
||||
});
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newLightButton" }
|
||||
});
|
||||
editTabView.currentIndex = 2
|
||||
}
|
||||
}
|
||||
|
@ -121,8 +124,9 @@ TabBar {
|
|||
text: "TEXT"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "newTextButton" }
|
||||
});
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newTextButton" }
|
||||
});
|
||||
editTabView.currentIndex = 2
|
||||
}
|
||||
}
|
||||
|
@ -132,8 +136,9 @@ TabBar {
|
|||
text: "IMAGE"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "newImageButton" }
|
||||
});
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newImageButton" }
|
||||
});
|
||||
editTabView.currentIndex = 2
|
||||
}
|
||||
}
|
||||
|
@ -143,8 +148,9 @@ TabBar {
|
|||
text: "WEB"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "newWebButton" }
|
||||
});
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newWebButton" }
|
||||
});
|
||||
editTabView.currentIndex = 2
|
||||
}
|
||||
}
|
||||
|
@ -154,8 +160,9 @@ TabBar {
|
|||
text: "ZONE"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "newZoneButton" }
|
||||
});
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newZoneButton" }
|
||||
});
|
||||
editTabView.currentIndex = 2
|
||||
}
|
||||
}
|
||||
|
@ -165,8 +172,9 @@ TabBar {
|
|||
text: "PARTICLE"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "newParticleButton" }
|
||||
});
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newParticleButton" }
|
||||
});
|
||||
editTabView.currentIndex = 4
|
||||
}
|
||||
}
|
||||
|
@ -176,8 +184,9 @@ TabBar {
|
|||
text: "MATERIAL"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "newMaterialButton" }
|
||||
});
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newMaterialButton" }
|
||||
});
|
||||
editTabView.currentIndex = 2
|
||||
}
|
||||
}
|
||||
|
@ -196,8 +205,9 @@ TabBar {
|
|||
anchors.topMargin: 35
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "openAssetBrowserButton" }
|
||||
});
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "openAssetBrowserButton" }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,8 +224,9 @@ TabBar {
|
|||
anchors.topMargin: 20
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "importEntitiesButton" }
|
||||
});
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "importEntitiesButton" }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
58
interface/resources/qml/hifi/tablet/EditTools.qml
Normal file
58
interface/resources/qml/hifi/tablet/EditTools.qml
Normal file
|
@ -0,0 +1,58 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.3
|
||||
|
||||
// FIXME pretty non-DRY code, should figure out a way to optionally hide one tab from the tab view, keep in sync with Edit.qml
|
||||
StackView {
|
||||
id: editRoot
|
||||
objectName: "stack"
|
||||
|
||||
signal sendToScript(var message);
|
||||
|
||||
topPadding: 40
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
bottomPadding: 0
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
property var itemProperties: {"y": editRoot.topPadding,
|
||||
"width": editRoot.availableWidth,
|
||||
"height": editRoot.availableHeight }
|
||||
Component.onCompleted: {
|
||||
tab.currentIndex = 0
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: "#404040" //default background color
|
||||
EditToolsTabView {
|
||||
id: tab
|
||||
anchors.fill: parent
|
||||
currentIndex: -1
|
||||
onCurrentIndexChanged: {
|
||||
editRoot.replace(null, tab.itemAt(currentIndex).visualItem,
|
||||
itemProperties,
|
||||
StackView.Immediate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function pushSource(path) {
|
||||
editRoot.push(Qt.resolvedUrl("../../" + path), itemProperties,
|
||||
StackView.Immediate);
|
||||
editRoot.currentItem.sendToScript.connect(editRoot.sendToScript);
|
||||
}
|
||||
|
||||
function popSource() {
|
||||
editRoot.pop(StackView.Immediate);
|
||||
}
|
||||
|
||||
// Passes script messages to the item on the top of the stack
|
||||
function fromScript(message) {
|
||||
var currentItem = editRoot.currentItem;
|
||||
if (currentItem && currentItem.fromScript) {
|
||||
currentItem.fromScript(message);
|
||||
} else if (tab.fromScript) {
|
||||
tab.fromScript(message);
|
||||
}
|
||||
}
|
||||
}
|
328
interface/resources/qml/hifi/tablet/EditToolsTabView.qml
Normal file
328
interface/resources/qml/hifi/tablet/EditToolsTabView.qml
Normal file
|
@ -0,0 +1,328 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
import QtWebChannel 1.0
|
||||
import "../../controls"
|
||||
import "../toolbars"
|
||||
import QtGraphicalEffects 1.0
|
||||
import "../../controls-uit" as HifiControls
|
||||
import "../../styles-uit"
|
||||
|
||||
TabBar {
|
||||
id: editTabView
|
||||
width: parent.width
|
||||
contentWidth: parent.width
|
||||
padding: 0
|
||||
spacing: 0
|
||||
|
||||
readonly property QtObject tabIndex: QtObject {
|
||||
readonly property int create: 0
|
||||
readonly property int properties: 1
|
||||
readonly property int grid: 2
|
||||
readonly property int particle: 3
|
||||
}
|
||||
|
||||
readonly property HifiConstants hifi: HifiConstants {}
|
||||
|
||||
EditTabButton {
|
||||
title: "CREATE"
|
||||
active: true
|
||||
enabled: true
|
||||
property string originalUrl: ""
|
||||
|
||||
property Component visualItem: Component {
|
||||
|
||||
Rectangle {
|
||||
color: "#404040"
|
||||
id: container
|
||||
|
||||
Flickable {
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
clip: true
|
||||
|
||||
contentHeight: createEntitiesFlow.height + importButton.height + assetServerButton.height +
|
||||
header.anchors.topMargin + createEntitiesFlow.anchors.topMargin +
|
||||
assetServerButton.anchors.topMargin + importButton.anchors.topMargin +
|
||||
header.paintedHeight
|
||||
|
||||
contentWidth: width
|
||||
|
||||
ScrollBar.vertical : ScrollBar {
|
||||
visible: parent.contentHeight > parent.height
|
||||
width: 20
|
||||
background: Rectangle {
|
||||
color: hifi.colors.tableScrollBackgroundDark
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: header
|
||||
color: "#ffffff"
|
||||
text: "Choose an Entity Type to Create:"
|
||||
font.pixelSize: 14
|
||||
font.bold: true
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 28
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 28
|
||||
}
|
||||
|
||||
Flow {
|
||||
id: createEntitiesFlow
|
||||
spacing: 35
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 55
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 55
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 70
|
||||
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/create-icons/94-model-01.svg"
|
||||
text: "MODEL"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newModelButton" }
|
||||
});
|
||||
editTabView.currentIndex = tabIndex.properties
|
||||
}
|
||||
}
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/create-icons/21-cube-01.svg"
|
||||
text: "CUBE"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newCubeButton" }
|
||||
});
|
||||
editTabView.currentIndex = tabIndex.properties
|
||||
}
|
||||
}
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/create-icons/22-sphere-01.svg"
|
||||
text: "SPHERE"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newSphereButton" }
|
||||
});
|
||||
editTabView.currentIndex = tabIndex.properties
|
||||
}
|
||||
}
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/create-icons/24-light-01.svg"
|
||||
text: "LIGHT"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newLightButton" }
|
||||
});
|
||||
editTabView.currentIndex = tabIndex.properties
|
||||
}
|
||||
}
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/create-icons/20-text-01.svg"
|
||||
text: "TEXT"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newTextButton" }
|
||||
});
|
||||
editTabView.currentIndex = tabIndex.properties
|
||||
}
|
||||
}
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/create-icons/image.svg"
|
||||
text: "IMAGE"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newImageButton" }
|
||||
});
|
||||
editTabView.currentIndex = tabIndex.properties
|
||||
}
|
||||
}
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/create-icons/25-web-1-01.svg"
|
||||
text: "WEB"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newWebButton" }
|
||||
});
|
||||
editTabView.currentIndex = tabIndex.properties
|
||||
}
|
||||
}
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/create-icons/23-zone-01.svg"
|
||||
text: "ZONE"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newZoneButton" }
|
||||
});
|
||||
editTabView.currentIndex = tabIndex.properties
|
||||
}
|
||||
}
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/create-icons/90-particles-01.svg"
|
||||
text: "PARTICLE"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newParticleButton" }
|
||||
});
|
||||
editTabView.currentIndex = tabIndex.particle
|
||||
}
|
||||
}
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/create-icons/126-material-01.svg"
|
||||
text: "MATERIAL"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "newMaterialButton" }
|
||||
});
|
||||
editTabView.currentIndex = tabIndex.properties
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
id: assetServerButton
|
||||
text: "Open This Domain's Asset Server"
|
||||
color: hifi.buttons.black
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 55
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 55
|
||||
anchors.top: createEntitiesFlow.bottom
|
||||
anchors.topMargin: 35
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "openAssetBrowserButton" }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
id: importButton
|
||||
text: "Import Entities (.json)"
|
||||
color: hifi.buttons.black
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 55
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 55
|
||||
anchors.top: assetServerButton.bottom
|
||||
anchors.topMargin: 20
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked",
|
||||
params: { buttonName: "importEntitiesButton" }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} // Flickable
|
||||
}
|
||||
}
|
||||
|
||||
EditTabButton {
|
||||
title: "PROPERTIES"
|
||||
active: true
|
||||
enabled: true
|
||||
property string originalUrl: ""
|
||||
|
||||
property Component visualItem: Component {
|
||||
WebView {
|
||||
id: entityPropertiesWebView
|
||||
url: Paths.defaultScripts + "/system/html/entityProperties.html"
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EditTabButton {
|
||||
title: "GRID"
|
||||
active: true
|
||||
enabled: true
|
||||
property string originalUrl: ""
|
||||
|
||||
property Component visualItem: Component {
|
||||
WebView {
|
||||
id: gridControlsWebView
|
||||
url: Paths.defaultScripts + "/system/html/gridControls.html"
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EditTabButton {
|
||||
title: "P"
|
||||
active: true
|
||||
enabled: true
|
||||
property string originalUrl: ""
|
||||
|
||||
property Component visualItem: Component {
|
||||
WebView {
|
||||
id: particleExplorerWebView
|
||||
url: Paths.defaultScripts + "/system/particle_explorer/particleExplorer.html"
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fromScript(message) {
|
||||
switch (message.method) {
|
||||
case 'selectTab':
|
||||
selectTab(message.params.id);
|
||||
break;
|
||||
default:
|
||||
console.warn('Unrecognized message:', JSON.stringify(message));
|
||||
}
|
||||
}
|
||||
|
||||
// Changes the current tab based on tab index or title as input
|
||||
function selectTab(id) {
|
||||
if (typeof id === 'number') {
|
||||
if (id >= tabIndex.create && id <= tabIndex.particle) {
|
||||
editTabView.currentIndex = id;
|
||||
} else {
|
||||
console.warn('Attempt to switch to invalid tab:', id);
|
||||
}
|
||||
} else if (typeof id === 'string'){
|
||||
switch (id.toLowerCase()) {
|
||||
case 'create':
|
||||
editTabView.currentIndex = tabIndex.create;
|
||||
break;
|
||||
case 'properties':
|
||||
editTabView.currentIndex = tabIndex.properties;
|
||||
break;
|
||||
case 'grid':
|
||||
editTabView.currentIndex = tabIndex.grid;
|
||||
break;
|
||||
case 'particle':
|
||||
editTabView.currentIndex = tabIndex.particle;
|
||||
break;
|
||||
default:
|
||||
console.warn('Attempt to switch to invalid tab:', id);
|
||||
}
|
||||
} else {
|
||||
console.warn('Attempt to switch tabs with invalid input:', JSON.stringify(id));
|
||||
}
|
||||
}
|
||||
}
|
5
interface/resources/qml/hifi/tablet/EntityList.qml
Normal file
5
interface/resources/qml/hifi/tablet/EntityList.qml
Normal file
|
@ -0,0 +1,5 @@
|
|||
WebView {
|
||||
id: entityListToolWebView
|
||||
url: Paths.defaultScripts + "/system/html/entityList.html"
|
||||
enabled: true
|
||||
}
|
|
@ -29,12 +29,16 @@ Rectangle {
|
|||
property bool keyboardRasied: false
|
||||
|
||||
function errorMessageBox(message) {
|
||||
return desktop.messageBox({
|
||||
icon: hifi.icons.warning,
|
||||
defaultButton: OriginalDialogs.StandardButton.Ok,
|
||||
title: "Error",
|
||||
text: message
|
||||
});
|
||||
try {
|
||||
return desktop.messageBox({
|
||||
icon: hifi.icons.warning,
|
||||
defaultButton: OriginalDialogs.StandardButton.Ok,
|
||||
title: "Error",
|
||||
text: message
|
||||
});
|
||||
} catch(e) {
|
||||
Window.alert(message);
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
|
|
20
interface/resources/qml/hifi/tablet/NewMaterialWindow.qml
Normal file
20
interface/resources/qml/hifi/tablet/NewMaterialWindow.qml
Normal file
|
@ -0,0 +1,20 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
StackView {
|
||||
id: stackView
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 10
|
||||
anchors.rightMargin: 10
|
||||
anchors.topMargin: 40
|
||||
|
||||
signal sendToScript(var message);
|
||||
|
||||
NewMaterialDialog {
|
||||
id: dialog
|
||||
anchors.fill: parent
|
||||
Component.onCompleted:{
|
||||
dialog.sendToScript.connect(stackView.sendToScript);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,12 +29,16 @@ Rectangle {
|
|||
property bool keyboardRasied: false
|
||||
|
||||
function errorMessageBox(message) {
|
||||
return desktop.messageBox({
|
||||
icon: hifi.icons.warning,
|
||||
defaultButton: OriginalDialogs.StandardButton.Ok,
|
||||
title: "Error",
|
||||
text: message
|
||||
});
|
||||
try {
|
||||
return desktop.messageBox({
|
||||
icon: hifi.icons.warning,
|
||||
defaultButton: OriginalDialogs.StandardButton.Ok,
|
||||
title: "Error",
|
||||
text: message
|
||||
});
|
||||
} catch(e) {
|
||||
Window.alert(message);
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
|
|
20
interface/resources/qml/hifi/tablet/NewModelWindow.qml
Normal file
20
interface/resources/qml/hifi/tablet/NewModelWindow.qml
Normal file
|
@ -0,0 +1,20 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
StackView {
|
||||
id: stackView
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 10
|
||||
anchors.rightMargin: 10
|
||||
anchors.topMargin: 40
|
||||
|
||||
signal sendToScript(var message);
|
||||
|
||||
NewModelDialog {
|
||||
id: dialog
|
||||
anchors.fill: parent
|
||||
Component.onCompleted:{
|
||||
dialog.sendToScript.connect(stackView.sendToScript);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,17 +10,15 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
/* global Script, SelectionDisplay, LightOverlayManager, CameraManager, Grid, GridTool, EntityListTool, Vec3, SelectionManager, Overlays, OverlayWebWindow, UserActivityLogger,
|
||||
Settings, Entities, Tablet, Toolbars, Messages, Menu, Camera, progressDialog, tooltip, MyAvatar, Quat, Controller, Clipboard, HMD, UndoStack, ParticleExplorerTool */
|
||||
/* global Script, SelectionDisplay, LightOverlayManager, CameraManager, Grid, GridTool, EntityListTool, Vec3, SelectionManager,
|
||||
Overlays, OverlayWebWindow, UserActivityLogger, Settings, Entities, Tablet, Toolbars, Messages, Menu, Camera,
|
||||
progressDialog, tooltip, MyAvatar, Quat, Controller, Clipboard, HMD, UndoStack, ParticleExplorerTool, OverlaySystemWindow */
|
||||
|
||||
(function() { // BEGIN LOCAL_SCOPE
|
||||
|
||||
"use strict";
|
||||
|
||||
var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||
var EDIT_TOGGLE_BUTTON = "com.highfidelity.interface.system.editButton";
|
||||
var SYSTEM_TOOLBAR = "com.highfidelity.interface.toolbar.system";
|
||||
var EDIT_TOOLBAR = "com.highfidelity.interface.toolbar.edit";
|
||||
|
||||
Script.include([
|
||||
"libraries/stringHelpers.js",
|
||||
|
@ -36,13 +34,43 @@ Script.include([
|
|||
"libraries/entityIconOverlayManager.js"
|
||||
]);
|
||||
|
||||
var CreateWindow = Script.require('./modules/createWindow.js');
|
||||
|
||||
var TITLE_OFFSET = 60;
|
||||
var CREATE_TOOLS_WIDTH = 490;
|
||||
var MAX_DEFAULT_ENTITY_LIST_HEIGHT = 942;
|
||||
|
||||
var createToolsWindow = new CreateWindow(
|
||||
Script.resourcesPath() + "qml/hifi/tablet/EditTools.qml",
|
||||
'Create Tools',
|
||||
'com.highfidelity.create.createToolsWindow',
|
||||
function () {
|
||||
var windowHeight = Window.innerHeight - TITLE_OFFSET;
|
||||
if (windowHeight > MAX_DEFAULT_ENTITY_LIST_HEIGHT) {
|
||||
windowHeight = MAX_DEFAULT_ENTITY_LIST_HEIGHT;
|
||||
}
|
||||
return {
|
||||
size: {
|
||||
x: CREATE_TOOLS_WIDTH,
|
||||
y: windowHeight
|
||||
},
|
||||
position: {
|
||||
x: Window.x + Window.innerWidth - CREATE_TOOLS_WIDTH,
|
||||
y: Window.y + TITLE_OFFSET
|
||||
}
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
var selectionDisplay = SelectionDisplay;
|
||||
var selectionManager = SelectionManager;
|
||||
|
||||
var PARTICLE_SYSTEM_URL = Script.resolvePath("assets/images/icon-particles.svg");
|
||||
var POINT_LIGHT_URL = Script.resolvePath("assets/images/icon-point-light.svg");
|
||||
var SPOT_LIGHT_URL = Script.resolvePath("assets/images/icon-spot-light.svg");
|
||||
entityIconOverlayManager = new EntityIconOverlayManager(['Light', 'ParticleEffect'], function(entityID) {
|
||||
|
||||
var entityIconOverlayManager = new EntityIconOverlayManager(['Light', 'ParticleEffect'], function(entityID) {
|
||||
var properties = Entities.getEntityProperties(entityID, ['type', 'isSpotlight']);
|
||||
if (properties.type === 'Light') {
|
||||
return {
|
||||
|
@ -59,7 +87,8 @@ var cameraManager = new CameraManager();
|
|||
|
||||
var grid = new Grid();
|
||||
var gridTool = new GridTool({
|
||||
horizontalGrid: grid
|
||||
horizontalGrid: grid,
|
||||
createToolsWindow: createToolsWindow
|
||||
});
|
||||
gridTool.setVisible(false);
|
||||
|
||||
|
@ -207,7 +236,7 @@ function hideMarketplace() {
|
|||
// }
|
||||
|
||||
function adjustPositionPerBoundingBox(position, direction, registration, dimensions, orientation) {
|
||||
// Adjust the position such that the bounding box (registration, dimenions, and orientation) lies behind the original
|
||||
// Adjust the position such that the bounding box (registration, dimensions and orientation) lies behind the original
|
||||
// position in the given direction.
|
||||
var CORNERS = [
|
||||
{ x: 0, y: 0, z: 0 },
|
||||
|
@ -232,7 +261,6 @@ function adjustPositionPerBoundingBox(position, direction, registration, dimensi
|
|||
return position;
|
||||
}
|
||||
|
||||
var TOOLS_PATH = Script.resolvePath("assets/images/tools/");
|
||||
var GRABBABLE_ENTITIES_MENU_CATEGORY = "Edit";
|
||||
|
||||
// Handles any edit mode updates required when domains have switched
|
||||
|
@ -260,6 +288,7 @@ var toolBar = (function () {
|
|||
toolBar,
|
||||
activeButton = null,
|
||||
systemToolbar = null,
|
||||
dialogWindow = null,
|
||||
tablet = null;
|
||||
|
||||
function createNewEntity(properties) {
|
||||
|
@ -356,6 +385,13 @@ var toolBar = (function () {
|
|||
return entityID;
|
||||
}
|
||||
|
||||
function closeExistingDialogWindow() {
|
||||
if (dialogWindow) {
|
||||
dialogWindow.close();
|
||||
dialogWindow = null;
|
||||
}
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
that.setActive(false);
|
||||
if (tablet) {
|
||||
|
@ -438,7 +474,7 @@ var toolBar = (function () {
|
|||
if (materialURL.startsWith("materialData")) {
|
||||
materialData = JSON.stringify({
|
||||
"materials": {}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
var DEFAULT_LAYERED_MATERIAL_PRIORITY = 1;
|
||||
|
@ -458,15 +494,23 @@ var toolBar = (function () {
|
|||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
tablet.popFromStack();
|
||||
switch (message.method) {
|
||||
case "newModelDialogAdd":
|
||||
handleNewModelDialogResult(message.params);
|
||||
break;
|
||||
case "newEntityButtonClicked":
|
||||
buttonHandlers[message.params.buttonName]();
|
||||
break;
|
||||
case "newMaterialDialogAdd":
|
||||
handleNewMaterialDialogResult(message.params);
|
||||
break;
|
||||
case "newModelDialogAdd":
|
||||
handleNewModelDialogResult(message.params);
|
||||
closeExistingDialogWindow();
|
||||
break;
|
||||
case "newModelDialogCancel":
|
||||
closeExistingDialogWindow();
|
||||
break;
|
||||
case "newEntityButtonClicked":
|
||||
buttonHandlers[message.params.buttonName]();
|
||||
break;
|
||||
case "newMaterialDialogAdd":
|
||||
handleNewMaterialDialogResult(message.params);
|
||||
closeExistingDialogWindow();
|
||||
break;
|
||||
case "newMaterialDialogCancel":
|
||||
closeExistingDialogWindow();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -501,6 +545,13 @@ var toolBar = (function () {
|
|||
checkEditPermissionsAndUpdate();
|
||||
});
|
||||
|
||||
HMD.displayModeChanged.connect(function() {
|
||||
if (isActive) {
|
||||
tablet.gotoHomeScreen();
|
||||
}
|
||||
that.setActive(false);
|
||||
});
|
||||
|
||||
Entities.canAdjustLocksChanged.connect(function (canAdjustLocks) {
|
||||
if (isActive && !canAdjustLocks) {
|
||||
that.setActive(false);
|
||||
|
@ -527,11 +578,13 @@ var toolBar = (function () {
|
|||
});
|
||||
createButton = activeButton;
|
||||
tablet.screenChanged.connect(function (type, url) {
|
||||
if (isActive && (type !== "QML" || url !== "hifi/tablet/Edit.qml")) {
|
||||
that.setActive(false)
|
||||
var isGoingToHomescreenOnDesktop = (!HMD.active && (url === 'hifi/tablet/TabletHome.qml' || url === ''));
|
||||
if (isActive && (type !== "QML" || url !== "hifi/tablet/Edit.qml") && !isGoingToHomescreenOnDesktop) {
|
||||
that.setActive(false);
|
||||
}
|
||||
});
|
||||
tablet.fromQml.connect(fromQml);
|
||||
createToolsWindow.fromQml.addListener(fromQml);
|
||||
|
||||
createButton.clicked.connect(function() {
|
||||
if ( ! (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified()) ) {
|
||||
|
@ -550,12 +603,29 @@ var toolBar = (function () {
|
|||
addButton("openAssetBrowserButton", function() {
|
||||
Window.showAssetServer();
|
||||
});
|
||||
function createNewEntityDialogButtonCallback(entityType) {
|
||||
return function() {
|
||||
if (HMD.active) {
|
||||
// tablet version of new-model dialog
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
tablet.pushOntoStack("hifi/tablet/New" + entityType + "Dialog.qml");
|
||||
} else {
|
||||
closeExistingDialogWindow();
|
||||
var qmlPath = Script.resourcesPath() + "qml/hifi/tablet/New" + entityType + "Window.qml";
|
||||
var DIALOG_WINDOW_SIZE = { x: 500, y: 300 };
|
||||
dialogWindow = Desktop.createWindow(qmlPath, {
|
||||
title: "New " + entityType + " Entity",
|
||||
flags: Desktop.ALWAYS_ON_TOP | Desktop.CLOSE_BUTTON_HIDES,
|
||||
presentationMode: Desktop.PresentationMode.NATIVE,
|
||||
size: DIALOG_WINDOW_SIZE,
|
||||
visible: true
|
||||
});
|
||||
dialogWindow.fromQml.connect(fromQml);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
addButton("newModelButton", function () {
|
||||
// tablet version of new-model dialog
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
tablet.pushOntoStack("hifi/tablet/NewModelDialog.qml");
|
||||
});
|
||||
addButton("newModelButton", createNewEntityDialogButtonCallback("Model"));
|
||||
|
||||
addButton("newCubeButton", function () {
|
||||
createNewEntity({
|
||||
|
@ -716,11 +786,7 @@ var toolBar = (function () {
|
|||
});
|
||||
});
|
||||
|
||||
addButton("newMaterialButton", function () {
|
||||
// tablet version of new material dialog
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
tablet.pushOntoStack("hifi/tablet/NewMaterialDialog.qml");
|
||||
});
|
||||
addButton("newMaterialButton", createNewEntityDialogButtonCallback("Material"));
|
||||
|
||||
that.setActive(false);
|
||||
}
|
||||
|
@ -743,6 +809,8 @@ var toolBar = (function () {
|
|||
Controller.captureEntityClickEvents();
|
||||
} else {
|
||||
Controller.releaseEntityClickEvents();
|
||||
|
||||
closeExistingDialogWindow();
|
||||
}
|
||||
if (active === isActive) {
|
||||
return;
|
||||
|
@ -769,7 +837,12 @@ var toolBar = (function () {
|
|||
selectionDisplay.triggerMapping.disable();
|
||||
tablet.landscape = false;
|
||||
} else {
|
||||
tablet.loadQMLSource("hifi/tablet/Edit.qml", true);
|
||||
if (HMD.active) {
|
||||
tablet.loadQMLSource("hifi/tablet/Edit.qml", true);
|
||||
} else {
|
||||
// make other apps inactive while in desktop mode
|
||||
tablet.gotoHomeScreen();
|
||||
}
|
||||
UserActivityLogger.enabledEdit();
|
||||
entityListTool.setVisible(true);
|
||||
gridTool.setVisible(true);
|
||||
|
@ -790,17 +863,6 @@ var toolBar = (function () {
|
|||
return that;
|
||||
})();
|
||||
|
||||
|
||||
function isLocked(properties) {
|
||||
// special case to lock the ground plane model in hq.
|
||||
if (location.hostname === "hq.highfidelity.io" &&
|
||||
properties.modelURL === HIFI_PUBLIC_BUCKET + "ozan/Terrain_Reduce_forAlpha.fbx") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
var selectedEntityID;
|
||||
var orientation;
|
||||
var intersection;
|
||||
|
@ -1047,68 +1109,62 @@ function mouseClickEvent(event) {
|
|||
return;
|
||||
}
|
||||
properties = Entities.getEntityProperties(foundEntity);
|
||||
if (isLocked(properties)) {
|
||||
if (wantDebug) {
|
||||
print("Model locked " + properties.id);
|
||||
var halfDiagonal = Vec3.length(properties.dimensions) / 2.0;
|
||||
|
||||
if (wantDebug) {
|
||||
print("Checking properties: " + properties.id + " " + " - Half Diagonal:" + halfDiagonal);
|
||||
}
|
||||
// P P - Model
|
||||
// /| A - Palm
|
||||
// / | d B - unit vector toward tip
|
||||
// / | X - base of the perpendicular line
|
||||
// A---X----->B d - distance fom axis
|
||||
// x x - distance from A
|
||||
//
|
||||
// |X-A| = (P-A).B
|
||||
// X === A + ((P-A).B)B
|
||||
// d = |P-X|
|
||||
|
||||
var A = pickRay.origin;
|
||||
var B = Vec3.normalize(pickRay.direction);
|
||||
var P = properties.position;
|
||||
|
||||
var x = Vec3.dot(Vec3.subtract(P, A), B);
|
||||
|
||||
var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) *
|
||||
180 / Math.PI;
|
||||
|
||||
var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) &&
|
||||
(allowSmallModels || angularSize > MIN_ANGULAR_SIZE);
|
||||
|
||||
if (0 < x && sizeOK) {
|
||||
selectedEntityID = foundEntity;
|
||||
orientation = MyAvatar.orientation;
|
||||
intersection = rayPlaneIntersection(pickRay, P, Quat.getForward(orientation));
|
||||
|
||||
if (event.isShifted) {
|
||||
particleExplorerTool.destroyWebView();
|
||||
}
|
||||
if (properties.type !== "ParticleEffect") {
|
||||
particleExplorerTool.destroyWebView();
|
||||
}
|
||||
|
||||
if (!event.isShifted) {
|
||||
selectionManager.setSelections([foundEntity]);
|
||||
} else {
|
||||
selectionManager.addEntity(foundEntity, true);
|
||||
}
|
||||
} else {
|
||||
var halfDiagonal = Vec3.length(properties.dimensions) / 2.0;
|
||||
|
||||
if (wantDebug) {
|
||||
print("Checking properties: " + properties.id + " " + " - Half Diagonal:" + halfDiagonal);
|
||||
print("Model selected: " + foundEntity);
|
||||
}
|
||||
// P P - Model
|
||||
// /| A - Palm
|
||||
// / | d B - unit vector toward tip
|
||||
// / | X - base of the perpendicular line
|
||||
// A---X----->B d - distance fom axis
|
||||
// x x - distance from A
|
||||
//
|
||||
// |X-A| = (P-A).B
|
||||
// X === A + ((P-A).B)B
|
||||
// d = |P-X|
|
||||
selectionDisplay.select(selectedEntityID, event);
|
||||
|
||||
var A = pickRay.origin;
|
||||
var B = Vec3.normalize(pickRay.direction);
|
||||
var P = properties.position;
|
||||
|
||||
var x = Vec3.dot(Vec3.subtract(P, A), B);
|
||||
|
||||
var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) *
|
||||
180 / Math.PI;
|
||||
|
||||
var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) &&
|
||||
(allowSmallModels || angularSize > MIN_ANGULAR_SIZE);
|
||||
|
||||
if (0 < x && sizeOK) {
|
||||
selectedEntityID = foundEntity;
|
||||
orientation = MyAvatar.orientation;
|
||||
intersection = rayPlaneIntersection(pickRay, P, Quat.getForward(orientation));
|
||||
|
||||
if (event.isShifted) {
|
||||
particleExplorerTool.destroyWebView();
|
||||
}
|
||||
if (properties.type !== "ParticleEffect") {
|
||||
particleExplorerTool.destroyWebView();
|
||||
}
|
||||
|
||||
if (!event.isShifted) {
|
||||
selectionManager.setSelections([foundEntity]);
|
||||
} else {
|
||||
selectionManager.addEntity(foundEntity, true);
|
||||
}
|
||||
|
||||
if (wantDebug) {
|
||||
print("Model selected: " + foundEntity);
|
||||
}
|
||||
selectionDisplay.select(selectedEntityID, event);
|
||||
|
||||
if (Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)) {
|
||||
cameraManager.enable();
|
||||
cameraManager.focus(selectionManager.worldPosition,
|
||||
selectionManager.worldDimensions,
|
||||
Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
|
||||
}
|
||||
if (Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)) {
|
||||
cameraManager.enable();
|
||||
cameraManager.focus(selectionManager.worldPosition,
|
||||
selectionManager.worldDimensions,
|
||||
Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
|
||||
}
|
||||
}
|
||||
} else if (event.isRightButton) {
|
||||
|
@ -1368,11 +1424,7 @@ function selectAllEtitiesInCurrentSelectionBox(keepIfTouching) {
|
|||
var localPosition = Vec3.multiplyQbyV(Quat.inverse(selectionManager.localRotation),
|
||||
Vec3.subtract(position,
|
||||
selectionManager.localPosition));
|
||||
return insideBox({
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
}, selectionManager.localDimensions, localPosition);
|
||||
return insideBox(Vec3.ZERO, selectionManager.localDimensions, localPosition);
|
||||
};
|
||||
}
|
||||
for (var i = 0; i < entities.length; ++i) {
|
||||
|
@ -1476,7 +1528,7 @@ function parentSelectedEntities() {
|
|||
return;
|
||||
}
|
||||
var parentCheck = false;
|
||||
var lastEntityId = selectedEntities[selectedEntities.length-1];
|
||||
var lastEntityId = selectedEntities[selectedEntities.length - 1];
|
||||
selectedEntities.forEach(function (id, index) {
|
||||
if (lastEntityId !== id) {
|
||||
var parentId = Entities.getEntityProperties(id, ["parentID"]).parentID;
|
||||
|
@ -1489,7 +1541,7 @@ function parentSelectedEntities() {
|
|||
|
||||
if (parentCheck) {
|
||||
Window.notify("Entities parented");
|
||||
}else {
|
||||
} else {
|
||||
Window.notify("Entities are already parented to last");
|
||||
}
|
||||
} else {
|
||||
|
@ -1902,8 +1954,6 @@ function pushCommandForSelections(createdEntityData, deletedEntityData) {
|
|||
UndoStack.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData);
|
||||
}
|
||||
|
||||
var ENTITY_PROPERTIES_URL = Script.resolvePath('html/entityProperties.html');
|
||||
|
||||
var ServerScriptStatusMonitor = function(entityID, statusCallback) {
|
||||
var self = this;
|
||||
|
||||
|
@ -1947,13 +1997,14 @@ var PropertiesTool = function (opts) {
|
|||
var currentSelectedEntityID = null;
|
||||
var statusMonitor = null;
|
||||
|
||||
webView.setVisible(visible);
|
||||
|
||||
that.setVisible = function (newVisible) {
|
||||
visible = newVisible;
|
||||
webView.setVisible(visible);
|
||||
webView.setVisible(HMD.active && visible);
|
||||
createToolsWindow.setVisible(!HMD.active && visible);
|
||||
};
|
||||
|
||||
that.setVisible(false);
|
||||
|
||||
function updateScriptStatus(info) {
|
||||
info.type = "server_script_status";
|
||||
webView.emitScriptEvent(JSON.stringify(info));
|
||||
|
@ -1982,7 +2033,7 @@ var PropertiesTool = function (opts) {
|
|||
statusMonitor = null;
|
||||
}
|
||||
currentSelectedEntityID = null;
|
||||
} else if (currentSelectedEntityID != selectionManager.selections[0]) {
|
||||
} else if (currentSelectedEntityID !== selectionManager.selections[0]) {
|
||||
if (statusMonitor !== null) {
|
||||
statusMonitor.stop();
|
||||
}
|
||||
|
@ -2008,11 +2059,14 @@ var PropertiesTool = function (opts) {
|
|||
selections.push(entity);
|
||||
}
|
||||
data.selections = selections;
|
||||
|
||||
webView.emitScriptEvent(JSON.stringify(data));
|
||||
createToolsWindow.emitScriptEvent(JSON.stringify(data));
|
||||
}
|
||||
selectionManager.addEventListener(updateSelections);
|
||||
|
||||
webView.webEventReceived.connect(function (data) {
|
||||
|
||||
var onWebEventReceived = function(data) {
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
}
|
||||
|
@ -2034,16 +2088,8 @@ var PropertiesTool = function (opts) {
|
|||
} else if (data.properties) {
|
||||
if (data.properties.dynamic === false) {
|
||||
// this object is leaving dynamic, so we zero its velocities
|
||||
data.properties.velocity = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
};
|
||||
data.properties.angularVelocity = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
};
|
||||
data.properties.velocity = Vec3.ZERO;
|
||||
data.properties.angularVelocity = Vec3.ZERO;
|
||||
}
|
||||
if (data.properties.rotation !== undefined) {
|
||||
var rotation = data.properties.rotation;
|
||||
|
@ -2171,7 +2217,11 @@ var PropertiesTool = function (opts) {
|
|||
} else if (data.type === "propertiesPageReady") {
|
||||
updateSelections(true);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
createToolsWindow.webEventReceived.addListener(this, onWebEventReceived);
|
||||
|
||||
webView.webEventReceived.connect(onWebEventReceived);
|
||||
|
||||
return that;
|
||||
};
|
||||
|
@ -2186,6 +2236,8 @@ var PopupMenu = function () {
|
|||
var overlays = [];
|
||||
var overlayInfo = {};
|
||||
|
||||
var visible = false;
|
||||
|
||||
var upColor = {
|
||||
red: 0,
|
||||
green: 0,
|
||||
|
@ -2303,8 +2355,6 @@ var PopupMenu = function () {
|
|||
}
|
||||
};
|
||||
|
||||
var visible = false;
|
||||
|
||||
self.setVisible = function (newVisible) {
|
||||
if (newVisible !== visible) {
|
||||
visible = newVisible;
|
||||
|
@ -2358,7 +2408,7 @@ propertyMenu.onSelectMenuItem = function (name) {
|
|||
var showMenuItem = propertyMenu.addMenuItem("Show in Marketplace");
|
||||
|
||||
var propertiesTool = new PropertiesTool();
|
||||
var particleExplorerTool = new ParticleExplorerTool();
|
||||
var particleExplorerTool = new ParticleExplorerTool(createToolsWindow);
|
||||
var selectedParticleEntityID = null;
|
||||
|
||||
function selectParticleEntity(entityID) {
|
||||
|
@ -2375,11 +2425,16 @@ function selectParticleEntity(entityID) {
|
|||
particleExplorerTool.setActiveParticleEntity(entityID);
|
||||
|
||||
// Switch to particle explorer
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
tablet.sendToQml({method: 'selectTab', params: {id: 'particle'}});
|
||||
var selectTabMethod = { method: 'selectTab', params: { id: 'particle' } };
|
||||
if (HMD.active) {
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
tablet.sendToQml(selectTabMethod);
|
||||
} else {
|
||||
createToolsWindow.sendToQml(selectTabMethod);
|
||||
}
|
||||
}
|
||||
|
||||
entityListTool.webView.webEventReceived.connect(function (data) {
|
||||
entityListTool.webView.webEventReceived.connect(function(data) {
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
} catch(e) {
|
||||
|
|
|
@ -11,27 +11,64 @@
|
|||
/* global EntityListTool, Tablet, selectionManager, Entities, Camera, MyAvatar, Vec3, Menu, Messages,
|
||||
cameraManager, MENU_EASE_ON_FOCUS, deleteSelectedEntities, toggleSelectedEntitiesLocked, toggleSelectedEntitiesVisible */
|
||||
|
||||
EntityListTool = function(opts) {
|
||||
EntityListTool = function() {
|
||||
var that = {};
|
||||
|
||||
var CreateWindow = Script.require('../modules/createWindow.js');
|
||||
|
||||
var TITLE_OFFSET = 60;
|
||||
var ENTITY_LIST_WIDTH = 495;
|
||||
var MAX_DEFAULT_CREATE_TOOLS_HEIGHT = 778;
|
||||
var entityListWindow = new CreateWindow(
|
||||
Script.resourcesPath() + "qml/hifi/tablet/EditEntityList.qml",
|
||||
'Entity List',
|
||||
'com.highfidelity.create.entityListWindow',
|
||||
function () {
|
||||
var windowHeight = Window.innerHeight - TITLE_OFFSET;
|
||||
if (windowHeight > MAX_DEFAULT_CREATE_TOOLS_HEIGHT) {
|
||||
windowHeight = MAX_DEFAULT_CREATE_TOOLS_HEIGHT;
|
||||
}
|
||||
return {
|
||||
size: {
|
||||
x: ENTITY_LIST_WIDTH,
|
||||
y: windowHeight
|
||||
},
|
||||
position: {
|
||||
x: Window.x,
|
||||
y: Window.y + TITLE_OFFSET
|
||||
}
|
||||
};
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
var webView = null;
|
||||
webView = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
webView.setVisible = function(value) {};
|
||||
webView.setVisible = function(value){ };
|
||||
|
||||
var filterInView = false;
|
||||
var searchRadius = 100;
|
||||
|
||||
var visible = false;
|
||||
|
||||
webView.setVisible(visible);
|
||||
|
||||
that.webView = webView;
|
||||
|
||||
that.setVisible = function(newVisible) {
|
||||
visible = newVisible;
|
||||
webView.setVisible(visible);
|
||||
webView.setVisible(HMD.active && visible);
|
||||
entityListWindow.setVisible(!HMD.active && visible);
|
||||
};
|
||||
|
||||
that.setVisible(false);
|
||||
|
||||
function emitJSONScriptEvent(data) {
|
||||
var dataString = JSON.stringify(data);
|
||||
webView.emitScriptEvent(dataString);
|
||||
if (entityListWindow.window) {
|
||||
entityListWindow.window.emitScriptEvent(dataString);
|
||||
}
|
||||
}
|
||||
|
||||
that.toggleVisible = function() {
|
||||
that.setVisible(!visible);
|
||||
};
|
||||
|
@ -43,18 +80,16 @@ EntityListTool = function(opts) {
|
|||
selectedIDs.push(selectionManager.selections[i]);
|
||||
}
|
||||
|
||||
var data = {
|
||||
emitJSONScriptEvent({
|
||||
type: 'selectionUpdate',
|
||||
selectedIDs: selectedIDs,
|
||||
};
|
||||
webView.emitScriptEvent(JSON.stringify(data));
|
||||
selectedIDs: selectedIDs
|
||||
});
|
||||
});
|
||||
|
||||
that.clearEntityList = function () {
|
||||
var data = {
|
||||
that.clearEntityList = function() {
|
||||
emitJSONScriptEvent({
|
||||
type: 'clearEntityList'
|
||||
};
|
||||
webView.emitScriptEvent(JSON.stringify(data));
|
||||
});
|
||||
};
|
||||
|
||||
that.removeEntities = function (deletedIDs, selectedIDs) {
|
||||
|
@ -87,9 +122,9 @@ EntityListTool = function(opts) {
|
|||
|
||||
if (!filterInView || Vec3.distance(properties.position, cameraPosition) <= searchRadius) {
|
||||
var url = "";
|
||||
if (properties.type == "Model") {
|
||||
if (properties.type === "Model") {
|
||||
url = properties.modelURL;
|
||||
} else if (properties.type == "Material") {
|
||||
} else if (properties.type === "Material") {
|
||||
url = properties.materialURL;
|
||||
}
|
||||
entities.push({
|
||||
|
@ -107,7 +142,7 @@ EntityListTool = function(opts) {
|
|||
valueIfDefined(properties.renderInfo.texturesSize) : ""),
|
||||
hasTransparent: (properties.renderInfo !== undefined ?
|
||||
valueIfDefined(properties.renderInfo.hasTransparent) : ""),
|
||||
isBaked: properties.type == "Model" ? url.toLowerCase().endsWith(".baked.fbx") : false,
|
||||
isBaked: properties.type === "Model" ? url.toLowerCase().endsWith(".baked.fbx") : false,
|
||||
drawCalls: (properties.renderInfo !== undefined ?
|
||||
valueIfDefined(properties.renderInfo.drawCalls) : ""),
|
||||
hasScript: properties.script !== ""
|
||||
|
@ -120,12 +155,11 @@ EntityListTool = function(opts) {
|
|||
selectedIDs.push(selectionManager.selections[j]);
|
||||
}
|
||||
|
||||
var data = {
|
||||
emitJSONScriptEvent({
|
||||
type: "update",
|
||||
entities: entities,
|
||||
selectedIDs: selectedIDs,
|
||||
};
|
||||
webView.emitScriptEvent(JSON.stringify(data));
|
||||
});
|
||||
};
|
||||
|
||||
function onFileSaveChanged(filename) {
|
||||
|
@ -138,15 +172,15 @@ EntityListTool = function(opts) {
|
|||
}
|
||||
}
|
||||
|
||||
webView.webEventReceived.connect(function(data) {
|
||||
var onWebEventReceived = function(data) {
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
} catch(e) {
|
||||
print("entityList.js: Error parsing JSON: " + e.name + " data " + data)
|
||||
print("entityList.js: Error parsing JSON: " + e.name + " data " + data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.type == "selectionUpdate") {
|
||||
if (data.type === "selectionUpdate") {
|
||||
var ids = data.entityIds;
|
||||
var entityIDs = [];
|
||||
for (var i = 0; i < ids.length; i++) {
|
||||
|
@ -159,20 +193,20 @@ EntityListTool = function(opts) {
|
|||
selectionManager.worldDimensions,
|
||||
Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
|
||||
}
|
||||
} else if (data.type == "refresh") {
|
||||
} else if (data.type === "refresh") {
|
||||
that.sendUpdate();
|
||||
} else if (data.type == "teleport") {
|
||||
} else if (data.type === "teleport") {
|
||||
if (selectionManager.hasSelection()) {
|
||||
MyAvatar.position = selectionManager.worldPosition;
|
||||
}
|
||||
} else if (data.type == "export") {
|
||||
} else if (data.type === "export") {
|
||||
if (!selectionManager.hasSelection()) {
|
||||
Window.notifyEditError("No entities have been selected.");
|
||||
} else {
|
||||
Window.saveFileChanged.connect(onFileSaveChanged);
|
||||
Window.saveAsync("Select Where to Save", "", "*.json");
|
||||
}
|
||||
} else if (data.type == "pal") {
|
||||
} else if (data.type === "pal") {
|
||||
var sessionIds = {}; // Collect the sessionsIds of all selected entitities, w/o duplicates.
|
||||
selectionManager.selections.forEach(function (id) {
|
||||
var lastEditedBy = Entities.getEntityProperties(id, 'lastEditedBy').lastEditedBy;
|
||||
|
@ -189,24 +223,21 @@ EntityListTool = function(opts) {
|
|||
// No need to subscribe if we're just sending.
|
||||
Messages.sendMessage('com.highfidelity.pal', JSON.stringify({method: 'select', params: [dedupped, true, false]}), 'local');
|
||||
}
|
||||
} else if (data.type == "delete") {
|
||||
} else if (data.type === "delete") {
|
||||
deleteSelectedEntities();
|
||||
} else if (data.type == "toggleLocked") {
|
||||
} else if (data.type === "toggleLocked") {
|
||||
toggleSelectedEntitiesLocked();
|
||||
} else if (data.type == "toggleVisible") {
|
||||
} else if (data.type === "toggleVisible") {
|
||||
toggleSelectedEntitiesVisible();
|
||||
} else if (data.type === "filterInView") {
|
||||
filterInView = data.filterInView === true;
|
||||
} else if (data.type === "radius") {
|
||||
searchRadius = data.radius;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// webView.visibleChanged.connect(function () {
|
||||
// if (webView.visible) {
|
||||
// that.sendUpdate();
|
||||
// }
|
||||
// });
|
||||
webView.webEventReceived.connect(onWebEventReceived);
|
||||
entityListWindow.webEventReceived.addListener(onWebEventReceived);
|
||||
|
||||
return that;
|
||||
};
|
||||
|
|
|
@ -240,6 +240,7 @@ GridTool = function(opts) {
|
|||
|
||||
var horizontalGrid = opts.horizontalGrid;
|
||||
var verticalGrid = opts.verticalGrid;
|
||||
var createToolsWindow = opts.createToolsWindow;
|
||||
var listeners = [];
|
||||
|
||||
var webView = null;
|
||||
|
@ -247,13 +248,15 @@ GridTool = function(opts) {
|
|||
webView.setVisible = function(value) { };
|
||||
|
||||
horizontalGrid.addListener(function(data) {
|
||||
webView.emitScriptEvent(JSON.stringify(data));
|
||||
var dataString = JSON.stringify(data);
|
||||
webView.emitScriptEvent(dataString);
|
||||
createToolsWindow.emitScriptEvent(dataString);
|
||||
if (selectionDisplay) {
|
||||
selectionDisplay.updateHandles();
|
||||
}
|
||||
});
|
||||
|
||||
webView.webEventReceived.connect(function(data) {
|
||||
var webEventReceived = function(data) {
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
} catch (e) {
|
||||
|
@ -282,14 +285,17 @@ GridTool = function(opts) {
|
|||
grid.setPosition(newPosition);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
webView.webEventReceived.connect(webEventReceived);
|
||||
createToolsWindow.webEventReceived.addListener(webEventReceived);
|
||||
|
||||
that.addListener = function(callback) {
|
||||
listeners.push(callback);
|
||||
};
|
||||
|
||||
that.setVisible = function(visible) {
|
||||
webView.setVisible(visible);
|
||||
webView.setVisible(HMD.active && visible);
|
||||
};
|
||||
|
||||
return that;
|
||||
|
|
151
scripts/system/modules/createWindow.js
Normal file
151
scripts/system/modules/createWindow.js
Normal file
|
@ -0,0 +1,151 @@
|
|||
"use strict";
|
||||
|
||||
// createWindow.js
|
||||
//
|
||||
// Created by Thijs Wenker on 6/1/18
|
||||
//
|
||||
// Copyright 2018 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
|
||||
//
|
||||
|
||||
var getWindowRect = function(settingsKey, defaultRect) {
|
||||
var windowRect = Settings.getValue(settingsKey, defaultRect);
|
||||
return windowRect;
|
||||
};
|
||||
|
||||
var setWindowRect = function(settingsKey, position, size) {
|
||||
Settings.setValue(settingsKey, {
|
||||
position: position,
|
||||
size: size
|
||||
});
|
||||
};
|
||||
|
||||
var CallableEvent = (function() {
|
||||
function CallableEvent() {
|
||||
this.callbacks = [];
|
||||
}
|
||||
|
||||
CallableEvent.prototype = {
|
||||
callbacks: null,
|
||||
call: function () {
|
||||
var callArguments = arguments;
|
||||
this.callbacks.forEach(function(callbackObject) {
|
||||
try {
|
||||
callbackObject.callback.apply(callbackObject.context ? callbackObject.context : this, callArguments);
|
||||
} catch (e) {
|
||||
console.error('Call to CallableEvent callback failed!');
|
||||
}
|
||||
});
|
||||
},
|
||||
addListener: function(contextOrCallback, callback) {
|
||||
if (callback) {
|
||||
this.callbacks.push({
|
||||
context: contextOrCallback,
|
||||
callback: callback
|
||||
});
|
||||
} else {
|
||||
this.callbacks.push({
|
||||
callback: contextOrCallback
|
||||
});
|
||||
}
|
||||
},
|
||||
removeListener: function(callback) {
|
||||
var foundIndex = -1;
|
||||
this.callbacks.forEach(function (callbackObject, index) {
|
||||
if (callbackObject.callback === callback) {
|
||||
foundIndex = index;
|
||||
}
|
||||
});
|
||||
|
||||
if (foundIndex !== -1) {
|
||||
this.callbacks.splice(foundIndex, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return CallableEvent;
|
||||
})();
|
||||
|
||||
module.exports = (function() {
|
||||
function CreateWindow(qmlPath, title, settingsKey, defaultRect, createOnStartup) {
|
||||
this.qmlPath = qmlPath;
|
||||
this.title = title;
|
||||
this.settingsKey = settingsKey;
|
||||
this.defaultRect = defaultRect;
|
||||
this.webEventReceived = new CallableEvent();
|
||||
this.fromQml = new CallableEvent();
|
||||
if (createOnStartup) {
|
||||
this.createWindow();
|
||||
}
|
||||
}
|
||||
|
||||
CreateWindow.prototype = {
|
||||
window: null,
|
||||
createWindow: function() {
|
||||
var defaultRect = this.defaultRect;
|
||||
if (typeof this.defaultRect === "function") {
|
||||
defaultRect = this.defaultRect();
|
||||
}
|
||||
|
||||
var windowRect = getWindowRect(this.settingsKey, defaultRect);
|
||||
this.window = Desktop.createWindow(this.qmlPath, {
|
||||
title: this.title,
|
||||
flags: Desktop.ALWAYS_ON_TOP | Desktop.CLOSE_BUTTON_HIDES,
|
||||
presentationMode: Desktop.PresentationMode.NATIVE,
|
||||
size: windowRect.size,
|
||||
visible: true,
|
||||
position: windowRect.position
|
||||
});
|
||||
|
||||
var windowRectChanged = function () {
|
||||
if (this.window.visible) {
|
||||
setWindowRect(this.settingsKey, this.window.position, this.window.size);
|
||||
}
|
||||
};
|
||||
|
||||
this.window.sizeChanged.connect(this, windowRectChanged);
|
||||
this.window.positionChanged.connect(this, windowRectChanged);
|
||||
|
||||
this.window.webEventReceived.connect(this, function (data) {
|
||||
this.webEventReceived.call(data);
|
||||
});
|
||||
|
||||
this.window.fromQml.connect(this, function (data) {
|
||||
this.fromQml.call(data);
|
||||
});
|
||||
|
||||
Script.scriptEnding.connect(this, function() {
|
||||
this.window.close();
|
||||
});
|
||||
},
|
||||
setVisible: function(visible) {
|
||||
if (visible && !this.window) {
|
||||
this.createWindow();
|
||||
}
|
||||
|
||||
if (this.window) {
|
||||
if (visible) {
|
||||
this.window.show();
|
||||
} else {
|
||||
this.window.visible = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
emitScriptEvent: function(data) {
|
||||
if (this.window) {
|
||||
this.window.emitScriptEvent(data);
|
||||
}
|
||||
},
|
||||
sendToQml: function(data) {
|
||||
if (this.window) {
|
||||
this.window.sendToQml(data);
|
||||
}
|
||||
},
|
||||
webEventReceived: null,
|
||||
fromQml: null
|
||||
};
|
||||
|
||||
return CreateWindow;
|
||||
})();
|
|
@ -9,13 +9,12 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
/* global window, alert, ParticleExplorerTool, EventBridge, dat, listenForSettingsUpdates, createVec3Folder,
|
||||
createQuatFolder, writeVec3ToInterface, writeDataToInterface */
|
||||
/* global ParticleExplorerTool */
|
||||
|
||||
|
||||
var PARTICLE_EXPLORER_HTML_URL = Script.resolvePath('particleExplorer.html');
|
||||
|
||||
ParticleExplorerTool = function() {
|
||||
ParticleExplorerTool = function(createToolsWindow) {
|
||||
var that = {};
|
||||
that.activeParticleEntity = 0;
|
||||
that.updatedActiveParticleProperties = {};
|
||||
|
@ -24,8 +23,15 @@ ParticleExplorerTool = function() {
|
|||
that.webView = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
that.webView.setVisible = function(value) {};
|
||||
that.webView.webEventReceived.connect(that.webEventReceived);
|
||||
createToolsWindow.webEventReceived.addListener(this, that.webEventReceived);
|
||||
};
|
||||
|
||||
function emitScriptEvent(data) {
|
||||
var messageData = JSON.stringify(data);
|
||||
that.webView.emitScriptEvent(messageData);
|
||||
createToolsWindow.emitScriptEvent(messageData);
|
||||
}
|
||||
|
||||
that.destroyWebView = function() {
|
||||
if (!that.webView) {
|
||||
return;
|
||||
|
@ -33,17 +39,16 @@ ParticleExplorerTool = function() {
|
|||
that.activeParticleEntity = 0;
|
||||
that.updatedActiveParticleProperties = {};
|
||||
|
||||
var messageData = {
|
||||
emitScriptEvent({
|
||||
messageType: "particle_close"
|
||||
};
|
||||
that.webView.emitScriptEvent(JSON.stringify(messageData));
|
||||
});
|
||||
};
|
||||
|
||||
function sendParticleProperties(properties) {
|
||||
that.webView.emitScriptEvent(JSON.stringify({
|
||||
emitScriptEvent({
|
||||
messageType: "particle_settings",
|
||||
currentProperties: properties
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
function sendActiveParticleProperties() {
|
||||
|
|
Loading…
Reference in a new issue