diff --git a/android/app/build.gradle b/android/app/build.gradle
index ba3d16ad4d..97267258e2 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -23,8 +23,8 @@ android {
'-DRELEASE_NUMBER=' + RELEASE_NUMBER,
'-DRELEASE_TYPE=' + RELEASE_TYPE,
'-DBUILD_BRANCH=' + BUILD_BRANCH,
- '-DDISABLE_QML=ON',
- '-DDISABLE_KTX_CACHE=ON'
+ '-DDISABLE_QML=OFF',
+ '-DDISABLE_KTX_CACHE=OFF'
}
}
}
diff --git a/android/build.gradle b/android/build.gradle
index 9e5e76f0e3..22273f9059 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -77,8 +77,8 @@ if (Os.isFamily(Os.FAMILY_MAC)) {
qtVersionId='HygCmtMLPYioyil0DfXckGVzhw2SXZA9'
} else if (Os.isFamily(Os.FAMILY_WINDOWS)) {
qtFile = 'qt-5.9.3_win_armv8-libcpp_openssl.tgz'
- qtChecksum='a93d22c0c59aa112fda18c4c6d157d17'
- qtVersionId='0Bl9NSUWb5CBKLT_NXaxTt75SNBBZ9sB'
+ qtChecksum='c3e25db64002d0f43cf565e0ef708911'
+ qtVersionId='HeVObSVLCBoc7yY7He1oBMvPIH0VkClT'
}
def packages = [
@@ -112,6 +112,13 @@ def packages = [
versionId: 'UTberAIFraEfF9IVjoV66u1DTPTopgeY',
checksum: '57fd02baa069176ba18597a29b6b4fc7',
],
+ nvtt: [
+ file: 'nvtt_armv8-libcpp.zip',
+ versionId: 'vLqrqThvpq4gp75BHMAqO6HhfTXaa0An',
+ checksum: 'eb46d0b683e66987190ed124aabf8910',
+ sharedLibFolder: 'lib',
+ includeLibs: ['libnvtt.so', 'libnvmath.so', 'libnvimage.so', 'libnvcore.so'],
+ ],
openssl: [
file: 'openssl-1.1.0g_armv8.tgz',
versionId: 'DmahmSGFS4ltpHyTdyQvv35WOeUOiib9',
diff --git a/cmake/macros/TargetNvtt.cmake b/cmake/macros/TargetNvtt.cmake
new file mode 100644
index 0000000000..b8198c0cf0
--- /dev/null
+++ b/cmake/macros/TargetNvtt.cmake
@@ -0,0 +1,26 @@
+#
+# Copyright 2015 High Fidelity, Inc.
+# Created by Bradley Austin Davis on 2015/10/10
+#
+# Distributed under the Apache License, Version 2.0.
+# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+#
+macro(TARGET_NVTT)
+ if (ANDROID)
+ set(NVTT_INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/nvtt)
+ set(NVTT_LIB_DIR "${NVTT_INSTALL_DIR}/lib")
+ set(NVTT_INCLUDE_DIRS "${NVTT_INSTALL_DIR}/include" CACHE TYPE INTERNAL)
+ list(APPEND NVTT_LIBS "${NVTT_LIB_DIR}/libnvcore.so")
+ list(APPEND NVTT_LIBS "${NVTT_LIB_DIR}/libnvmath.so")
+ list(APPEND NVTT_LIBS "${NVTT_LIB_DIR}/libnvimage.so")
+ list(APPEND NVTT_LIBS "${NVTT_LIB_DIR}/libnvtt.so")
+ set(NVTT_LIBRARIES ${NVTT_LIBS} CACHE TYPE INTERNAL)
+ else()
+ add_dependency_external_projects(nvtt)
+ find_package(NVTT REQUIRED)
+ add_paths_to_fixup_libs(${NVTT_DLL_PATH})
+ endif()
+
+ target_include_directories(${TARGET_NAME} PRIVATE ${NVTT_INCLUDE_DIRS})
+ target_link_libraries(${TARGET_NAME} ${NVTT_LIBRARIES})
+endmacro()
diff --git a/interface/resources/controllers/touchscreenvirtualpad.json b/interface/resources/controllers/touchscreenvirtualpad.json
new file mode 100644
index 0000000000..8c21044c3b
--- /dev/null
+++ b/interface/resources/controllers/touchscreenvirtualpad.json
@@ -0,0 +1,12 @@
+{
+ "name": "TouchscreenVirtualPad to Actions",
+ "channels": [
+ { "from": "TouchscreenVirtualPad.LY", "when": "!Application.CameraIndependent", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Actions.TranslateZ" },
+
+ { "from": "TouchscreenVirtualPad.LX", "when": "!Application.CameraIndependent", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Actions.TranslateX" },
+
+ { "from": "TouchscreenVirtualPad.RX", "when": "!Application.CameraIndependent", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Actions.Yaw" },
+
+ { "from": "TouchscreenVirtualPad.RY", "when": "!Application.CameraIndependent", "to": "Actions.Pitch" }
+ ]
+}
diff --git a/interface/resources/icons/+android/backward.svg b/interface/resources/icons/+android/backward.svg
new file mode 100644
index 0000000000..ae0893fc66
--- /dev/null
+++ b/interface/resources/icons/+android/backward.svg
@@ -0,0 +1,70 @@
+
+
+
+
\ No newline at end of file
diff --git a/interface/resources/icons/+android/forward.svg b/interface/resources/icons/+android/forward.svg
new file mode 100644
index 0000000000..d03c4097d7
--- /dev/null
+++ b/interface/resources/icons/+android/forward.svg
@@ -0,0 +1,71 @@
+
+
+
+
\ No newline at end of file
diff --git a/interface/resources/icons/+android/go-a.svg b/interface/resources/icons/+android/go-a.svg
new file mode 100755
index 0000000000..faecb15292
--- /dev/null
+++ b/interface/resources/icons/+android/go-a.svg
@@ -0,0 +1,40 @@
+
+
+
+
diff --git a/interface/resources/icons/+android/go-i.svg b/interface/resources/icons/+android/go-i.svg
new file mode 100644
index 0000000000..0f1298d573
--- /dev/null
+++ b/interface/resources/icons/+android/go-i.svg
@@ -0,0 +1,40 @@
+
+
+
+
diff --git a/interface/resources/icons/+android/goto-a.svg b/interface/resources/icons/+android/goto-a.svg
new file mode 100755
index 0000000000..5fb3e52e4c
--- /dev/null
+++ b/interface/resources/icons/+android/goto-a.svg
@@ -0,0 +1,28 @@
+
+
+
+
diff --git a/interface/resources/icons/+android/goto-i.svg b/interface/resources/icons/+android/goto-i.svg
new file mode 100644
index 0000000000..7613beb9e7
--- /dev/null
+++ b/interface/resources/icons/+android/goto-i.svg
@@ -0,0 +1,28 @@
+
+
+
+
diff --git a/interface/resources/icons/+android/hide.svg b/interface/resources/icons/+android/hide.svg
new file mode 100644
index 0000000000..e09d517b08
--- /dev/null
+++ b/interface/resources/icons/+android/hide.svg
@@ -0,0 +1,947 @@
+
+
+
+
diff --git a/interface/resources/icons/+android/home.svg b/interface/resources/icons/+android/home.svg
new file mode 100644
index 0000000000..414c179e79
--- /dev/null
+++ b/interface/resources/icons/+android/home.svg
@@ -0,0 +1,82 @@
+
+
+
+
\ No newline at end of file
diff --git a/interface/resources/icons/+android/mic-mute-a.svg b/interface/resources/icons/+android/mic-mute-a.svg
new file mode 100644
index 0000000000..73555ce21b
--- /dev/null
+++ b/interface/resources/icons/+android/mic-mute-a.svg
@@ -0,0 +1,18 @@
+
+
+
diff --git a/interface/resources/icons/+android/mic-mute-i.svg b/interface/resources/icons/+android/mic-mute-i.svg
new file mode 100644
index 0000000000..56e33eab6b
--- /dev/null
+++ b/interface/resources/icons/+android/mic-mute-i.svg
@@ -0,0 +1,21 @@
+
+
+
diff --git a/interface/resources/icons/+android/mic-unmute-a.svg b/interface/resources/icons/+android/mic-unmute-a.svg
new file mode 100644
index 0000000000..bb28dc0f2b
--- /dev/null
+++ b/interface/resources/icons/+android/mic-unmute-a.svg
@@ -0,0 +1,70 @@
+
+
+
+
\ No newline at end of file
diff --git a/interface/resources/icons/+android/mic-unmute-i.svg b/interface/resources/icons/+android/mic-unmute-i.svg
new file mode 100644
index 0000000000..76f98d7f0c
--- /dev/null
+++ b/interface/resources/icons/+android/mic-unmute-i.svg
@@ -0,0 +1,22 @@
+
+
+
diff --git a/interface/resources/icons/+android/myview-a.svg b/interface/resources/icons/+android/myview-a.svg
new file mode 100755
index 0000000000..307b559c95
--- /dev/null
+++ b/interface/resources/icons/+android/myview-a.svg
@@ -0,0 +1,56 @@
+
+
+
+
\ No newline at end of file
diff --git a/interface/resources/icons/+android/myview-hover.svg b/interface/resources/icons/+android/myview-hover.svg
new file mode 100755
index 0000000000..49656ad294
--- /dev/null
+++ b/interface/resources/icons/+android/myview-hover.svg
@@ -0,0 +1,54 @@
+
+
+
+
\ No newline at end of file
diff --git a/interface/resources/icons/+android/myview-i.svg b/interface/resources/icons/+android/myview-i.svg
new file mode 100755
index 0000000000..574f51c615
--- /dev/null
+++ b/interface/resources/icons/+android/myview-i.svg
@@ -0,0 +1,56 @@
+
+
+
+
\ No newline at end of file
diff --git a/interface/resources/icons/+android/radar-a.svg b/interface/resources/icons/+android/radar-a.svg
new file mode 100755
index 0000000000..e4b157f827
--- /dev/null
+++ b/interface/resources/icons/+android/radar-a.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/interface/resources/icons/+android/radar-hover.svg b/interface/resources/icons/+android/radar-hover.svg
new file mode 100755
index 0000000000..e4b157f827
--- /dev/null
+++ b/interface/resources/icons/+android/radar-hover.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/interface/resources/icons/+android/radar-i.svg b/interface/resources/icons/+android/radar-i.svg
new file mode 100755
index 0000000000..3994a775d3
--- /dev/null
+++ b/interface/resources/icons/+android/radar-i.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/interface/resources/icons/+android/show-up.svg b/interface/resources/icons/+android/show-up.svg
new file mode 100644
index 0000000000..0736b9a794
--- /dev/null
+++ b/interface/resources/icons/+android/show-up.svg
@@ -0,0 +1,8 @@
+
+
+
+
diff --git a/interface/resources/images/analog_stick.png b/interface/resources/images/analog_stick.png
new file mode 100644
index 0000000000..e9457c7307
Binary files /dev/null and b/interface/resources/images/analog_stick.png differ
diff --git a/interface/resources/images/analog_stick_base.png b/interface/resources/images/analog_stick_base.png
new file mode 100644
index 0000000000..3b7b8aa8a9
Binary files /dev/null and b/interface/resources/images/analog_stick_base.png differ
diff --git a/interface/resources/meshes/+gles/defaultAvatar_full.fst b/interface/resources/meshes/+gles/defaultAvatar_full.fst
deleted file mode 100644
index 7d917318dd..0000000000
--- a/interface/resources/meshes/+gles/defaultAvatar_full.fst
+++ /dev/null
@@ -1,135 +0,0 @@
-name = being_of_light
-type = body+head
-scale = 1
-filename = being_of_light/being_of_light.fbx
-texdir = being_of_light/textures
-joint = jointRoot = Hips
-joint = jointLeftHand = LeftHand
-joint = jointHead = HeadTop_End
-joint = jointLean = Spine
-joint = jointEyeLeft = LeftEye
-joint = jointRightHand = RightHand
-joint = jointNeck = Head
-joint = jointEyeRight = RightEye
-freeJoint = LeftArm
-freeJoint = LeftForeArm
-freeJoint = RightArm
-freeJoint = RightForeArm
-bs = MouthFrown_L = Frown_Left = 1
-bs = MouthLeft = Midmouth_Left = 1
-bs = BrowsU_R = BrowsUp_Right = 1
-bs = ChinUpperRaise = UpperLipUp_Right = 0.5
-bs = ChinUpperRaise = UpperLipUp_Left = 0.5
-bs = MouthSmile_R = Smile_Right = 1
-bs = MouthDimple_L = Smile_Left = 0.25
-bs = EyeBlink_L = Blink_Left = 1
-bs = BrowsD_L = BrowsDown_Left = 1
-bs = MouthFrown_R = Frown_Right = 1
-bs = MouthDimple_R = Smile_Right = 0.25
-bs = Sneer = Squint_Right = 0.5
-bs = Sneer = Squint_Left = 0.5
-bs = Sneer = NoseScrunch_Right = 0.75
-bs = Sneer = NoseScrunch_Left = 0.75
-bs = EyeSquint_L = Squint_Left = 1
-bs = EyeBlink_R = Blink_Right = 1
-bs = JawLeft = JawRotateY_Left = 0.5
-bs = BrowsD_R = BrowsDown_Right = 1
-bs = EyeSquint_R = Squint_Right = 1
-bs = Puff = CheekPuff_Right = 1
-bs = Puff = CheekPuff_Left = 1
-bs = LipsUpperClose = UpperLipIn = 1
-bs = JawOpen = MouthOpen = 0.69999999999999996
-bs = LipsUpperUp = UpperLipUp_Right = 0.69999999999999996
-bs = LipsUpperUp = UpperLipUp_Left = 0.69999999999999996
-bs = LipsLowerDown = LowerLipDown_Right = 0.69999999999999996
-bs = LipsLowerDown = LowerLipDown_Left = 0.69999999999999996
-bs = LipsLowerOpen = LowerLipOut = 1
-bs = EyeOpen_L = EyesWide_Left = 1
-bs = LipsPucker = MouthNarrow_Right = 1
-bs = LipsPucker = MouthNarrow_Left = 1
-bs = EyeOpen_R = EyesWide_Right = 1
-bs = JawRight = Jaw_Right = 1
-bs = MouthRight = Midmouth_Right = 1
-bs = ChinLowerRaise = Jaw_Up = 1
-bs = LipsUpperOpen = UpperLipOut = 1
-bs = BrowsU_C = BrowsUp_Right = 1
-bs = BrowsU_C = BrowsUp_Left = 1
-bs = JawFwd = JawForeward = 1
-bs = BrowsU_L = BrowsUp_Left = 1
-bs = MouthSmile_L = Smile_Left = 1
-bs = LipsLowerClose = LowerLipIn = 1
-bs = LipsFunnel = TongueUp = 1
-bs = LipsFunnel = MouthWhistle_NarrowAdjust_Right = 0.5
-bs = LipsFunnel = MouthWhistle_NarrowAdjust_Left = 0.5
-bs = LipsFunnel = MouthNarrow_Right = 1
-bs = LipsFunnel = MouthNarrow_Left = 1
-bs = LipsFunnel = Jaw_Down = 0.35999999999999999
-bs = LipsFunnel = JawForeward = 0.39000000000000001
-jointIndex = LeftHandIndex1 = 50
-jointIndex = LeftHandIndex2 = 51
-jointIndex = LeftHandIndex3 = 52
-jointIndex = LeftHandIndex4 = 53
-jointIndex = Spine1 = 12
-jointIndex = Spine2 = 13
-jointIndex = RightHandThumb1 = 18
-jointIndex = RightHandThumb2 = 19
-jointIndex = RightHandThumb3 = 20
-jointIndex = RightHandThumb4 = 21
-jointIndex = LeftFoot = 8
-jointIndex = LeftForeArm = 40
-jointIndex = Neck = 62
-jointIndex = Head = 63
-jointIndex = Hips = 0
-jointIndex = RightHandPinky1 = 30
-jointIndex = RightHandPinky2 = 31
-jointIndex = RightHandPinky3 = 32
-jointIndex = RightHandPinky4 = 33
-jointIndex = RightLeg = 2
-jointIndex = RightForeArm = 16
-jointIndex = LeftHandRing1 = 46
-jointIndex = LeftHandRing2 = 47
-jointIndex = LeftHandRing3 = 48
-jointIndex = LeftHandRing4 = 49
-jointIndex = LeftHandThumb1 = 54
-jointIndex = LeftHandThumb2 = 55
-jointIndex = LeftHandThumb3 = 56
-jointIndex = LeftHandThumb4 = 57
-jointIndex = HeadTop_End = 66
-jointIndex = LeftUpLeg = 6
-jointIndex = LeftToeBase = 9
-jointIndex = LeftHandPinky1 = 42
-jointIndex = LeftHandPinky2 = 43
-jointIndex = LeftHandPinky3 = 44
-jointIndex = LeftHandPinky4 = 45
-jointIndex = LeftLeg = 7
-jointIndex = RightEye = 65
-jointIndex = RightHand = 17
-jointIndex = RightToeBase = 4
-jointIndex = RightUpLeg = 1
-jointIndex = RightArm = 15
-jointIndex = RightHandRing1 = 26
-jointIndex = RightHandRing2 = 27
-jointIndex = RightHandRing3 = 28
-jointIndex = RightHandRing4 = 29
-jointIndex = RightHandIndex1 = 22
-jointIndex = RightHandIndex2 = 23
-jointIndex = RightHandIndex3 = 24
-jointIndex = RightHandIndex4 = 25
-jointIndex = LeftToe_End = 10
-jointIndex = LeftHandMiddle1 = 58
-jointIndex = LeftHandMiddle2 = 59
-jointIndex = LeftHandMiddle3 = 60
-jointIndex = LeftShoulder = 38
-jointIndex = LeftHandMiddle4 = 61
-jointIndex = RightFoot = 3
-jointIndex = LeftHand = 41
-jointIndex = RightHandMiddle1 = 34
-jointIndex = RightHandMiddle2 = 35
-jointIndex = RightHandMiddle3 = 36
-jointIndex = RightShoulder = 14
-jointIndex = LeftEye = 64
-jointIndex = RightHandMiddle4 = 37
-jointIndex = Body = 67
-jointIndex = LeftArm = 39
-jointIndex = RightToe_End = 5
-jointIndex = Spine = 11
diff --git a/interface/resources/meshes/being_of_light/being_of_light.fbx b/interface/resources/meshes/being_of_light/being_of_light.fbx
deleted file mode 100644
index 20e71abd6d..0000000000
Binary files a/interface/resources/meshes/being_of_light/being_of_light.fbx and /dev/null differ
diff --git a/interface/resources/meshes/being_of_light/textures/BaseMesh_BeingofLight_DiffuseMap.png b/interface/resources/meshes/being_of_light/textures/BaseMesh_BeingofLight_DiffuseMap.png
deleted file mode 100644
index 8fcf588643..0000000000
Binary files a/interface/resources/meshes/being_of_light/textures/BaseMesh_BeingofLight_DiffuseMap.png and /dev/null differ
diff --git a/interface/resources/meshes/being_of_light/textures/BaseMesh_BeingofLight_EmissiveMap.png b/interface/resources/meshes/being_of_light/textures/BaseMesh_BeingofLight_EmissiveMap.png
deleted file mode 100644
index d836aebde8..0000000000
Binary files a/interface/resources/meshes/being_of_light/textures/BaseMesh_BeingofLight_EmissiveMap.png and /dev/null differ
diff --git a/interface/resources/meshes/being_of_light/textures/BaseMesh_BeingofLight_NormalMap.png b/interface/resources/meshes/being_of_light/textures/BaseMesh_BeingofLight_NormalMap.png
deleted file mode 100644
index f5000b86e9..0000000000
Binary files a/interface/resources/meshes/being_of_light/textures/BaseMesh_BeingofLight_NormalMap.png and /dev/null differ
diff --git a/interface/resources/meshes/mannequin/+gles/Eyes.ktx b/interface/resources/meshes/mannequin/+gles/Eyes.ktx
new file mode 100644
index 0000000000..0cccc03dc5
Binary files /dev/null and b/interface/resources/meshes/mannequin/+gles/Eyes.ktx differ
diff --git a/interface/resources/meshes/mannequin/+gles/lambert1_Base_Color.ktx b/interface/resources/meshes/mannequin/+gles/lambert1_Base_Color.ktx
new file mode 100644
index 0000000000..b0baa696d5
Binary files /dev/null and b/interface/resources/meshes/mannequin/+gles/lambert1_Base_Color.ktx differ
diff --git a/interface/resources/meshes/mannequin/+gles/lambert1_Normal_OpenGL.ktx b/interface/resources/meshes/mannequin/+gles/lambert1_Normal_OpenGL.ktx
new file mode 100644
index 0000000000..0960d30ce6
Binary files /dev/null and b/interface/resources/meshes/mannequin/+gles/lambert1_Normal_OpenGL.ktx differ
diff --git a/interface/resources/meshes/mannequin/+gles/lambert1_Roughness.ktx b/interface/resources/meshes/mannequin/+gles/lambert1_Roughness.ktx
new file mode 100644
index 0000000000..6d87e6e337
Binary files /dev/null and b/interface/resources/meshes/mannequin/+gles/lambert1_Roughness.ktx differ
diff --git a/interface/resources/qml/+android/AddressBarDialog.qml b/interface/resources/qml/+android/AddressBarDialog.qml
new file mode 100644
index 0000000000..0b12301561
--- /dev/null
+++ b/interface/resources/qml/+android/AddressBarDialog.qml
@@ -0,0 +1,230 @@
+//
+// AddressBarDialog.qml
+//
+// Created by Austin Davis on 2015/04/14
+// 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
+//
+
+import Hifi 1.0
+import QtQuick 2.4
+import "../controls"
+import "../styles"
+import "../hifi" as QmlHifi
+import "../hifi/toolbars"
+import "../styles-uit" as HifiStyles
+import "../controls-uit" as HifiControls
+
+Item {
+ QmlHifi.HifiConstants { id: android }
+
+ width: parent ? parent.width - android.dimen.windowLessWidth : 0
+ height: parent ? parent.height - android.dimen.windowLessHeight : 0
+ z: android.dimen.windowZ
+ anchors { horizontalCenter: parent.horizontalCenter; bottom: parent.bottom }
+
+ id: bar
+ property bool isCursorVisible: false // Override default cursor visibility.
+ property bool shown: true
+
+ onShownChanged: {
+ bar.visible = shown;
+ sendToScript({method: 'shownChanged', params: { shown: shown }});
+ if (shown) {
+ updateLocationText(false);
+ }
+ }
+
+ function hide() {
+ shown = false;
+ sendToScript ({ type: "hide" });
+ }
+
+ Component.onCompleted: {
+ updateLocationText(false);
+ }
+
+ HifiConstants { id: hifi }
+ HifiStyles.HifiConstants { id: hifiStyleConstants }
+
+ signal sendToScript(var message);
+
+ AddressBarDialog {
+ id: addressBarDialog
+ }
+
+
+ Rectangle {
+ id: background
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: android.color.gradientTop }
+ GradientStop { position: 1.0; color: android.color.gradientBottom }
+ }
+ anchors {
+ fill: parent
+ }
+
+ QmlHifi.WindowHeader {
+ id: header
+ iconSource: "../../../icons/goto-i.svg"
+ titleText: "GO TO"
+ }
+
+ HifiStyles.RalewayRegular {
+ id: notice
+ text: "YOUR LOCATION"
+ font.pixelSize: hifi.fonts.pixelSize * 2.15;
+ color: "#2CD7FF"
+ anchors {
+ bottom: addressBackground.top
+ bottomMargin: 45
+ left: addressBackground.left
+ leftMargin: 60
+ }
+
+ }
+
+ property int inputAreaHeight: 210
+ property int inputAreaStep: (height - inputAreaHeight) / 2
+
+ ToolbarButton {
+ id: homeButton
+ y: 280
+ imageURL: "../../icons/home.svg"
+ onClicked: {
+ addressBarDialog.loadHome();
+ bar.shown = false;
+ }
+ anchors {
+ leftMargin: 75
+ left: parent.left
+ }
+ size: 150
+ }
+
+ ToolbarButton {
+ id: backArrow;
+ imageURL: "../../icons/backward.svg";
+ onClicked: addressBarDialog.loadBack();
+ anchors {
+ left: homeButton.right
+ leftMargin: 70
+ verticalCenter: homeButton.verticalCenter
+ }
+ size: 150
+ }
+ ToolbarButton {
+ id: forwardArrow;
+ imageURL: "../../icons/forward.svg";
+ onClicked: addressBarDialog.loadForward();
+ anchors {
+ left: backArrow.right
+ leftMargin: 60
+ verticalCenter: homeButton.verticalCenter
+ }
+ size: 150
+ }
+
+ HifiStyles.FiraSansRegular {
+ id: location;
+ font.pixelSize: addressLine.font.pixelSize;
+ color: "gray";
+ clip: true;
+ anchors.fill: addressLine;
+ visible: addressLine.text.length === 0
+ z: 1
+ }
+
+ Rectangle {
+ id: addressBackground
+ x: 780
+ y: 280
+ width: 1440
+ height: 150
+ color: "#FFFFFF"
+ }
+
+ TextInput {
+ id: addressLine
+ focus: true
+ x: 870
+ y: 450
+ width: 1350
+ height: 120
+ inputMethodHints: Qt.ImhNoPredictiveText
+ //helperText: "Hint is here"
+ anchors {
+ verticalCenter: homeButton.verticalCenter
+ }
+ font.pixelSize: hifi.fonts.pixelSize * 3.75
+ onTextChanged: {
+ //filterChoicesByText();
+ updateLocationText(addressLine.text.length > 0);
+ if (!isCursorVisible && text.length > 0) {
+ isCursorVisible = true;
+ cursorVisible = true;
+ }
+ }
+
+ onActiveFocusChanged: {
+ //cursorVisible = isCursorVisible && focus;
+ }
+ }
+
+
+
+ function toggleOrGo() {
+ if (addressLine.text !== "") {
+ addressBarDialog.loadAddress(addressLine.text);
+ }
+ bar.shown = false;
+ }
+
+ Keys.onPressed: {
+ switch (event.key) {
+ case Qt.Key_Escape:
+ case Qt.Key_Back:
+ clearAddressLineTimer.start();
+ event.accepted = true
+ bar.shown = false;
+ break
+ case Qt.Key_Enter:
+ case Qt.Key_Return:
+ toggleOrGo();
+ clearAddressLineTimer.start();
+ event.accepted = true
+ break
+ }
+ }
+
+ }
+
+ Timer {
+ // Delay clearing address line so as to avoid flicker of "not connected" being displayed after entering an address.
+ id: clearAddressLineTimer
+ running: false
+ interval: 100 // ms
+ repeat: false
+ onTriggered: {
+ addressLine.text = "";
+ isCursorVisible = false;
+ }
+ }
+
+ function updateLocationText(enteringAddress) {
+ if (enteringAddress) {
+ notice.text = "Go to a place, @user, path or network address";
+ notice.color = "#ffffff"; // hifiStyleConstants.colors.baseGrayHighlight;
+ location.visible = false;
+ } else {
+ notice.text = AddressManager.isConnected ? "YOUR LOCATION:" : "NOT CONNECTED";
+ notice.color = AddressManager.isConnected ? hifiStyleConstants.colors.blueHighlight : hifiStyleConstants.colors.redHighlight;
+ // Display hostname, which includes ip address, localhost, and other non-placenames.
+ location.text = (AddressManager.placename || AddressManager.hostname || '') + (AddressManager.pathname ? AddressManager.pathname.match(/\/[^\/]+/)[0] : '');
+ location.visible = true;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/interface/resources/qml/hifi/+android/AudioBar.qml b/interface/resources/qml/hifi/+android/AudioBar.qml
new file mode 100644
index 0000000000..f524595ef5
--- /dev/null
+++ b/interface/resources/qml/hifi/+android/AudioBar.qml
@@ -0,0 +1,71 @@
+import QtQuick 2.5
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Layouts 1.3
+import Qt.labs.settings 1.0
+import "../../styles-uit"
+import "../../controls-uit" as HifiControlsUit
+import "../../controls" as HifiControls
+import ".."
+
+Item {
+ id: bar
+ x:0
+ y:0
+ width: 300
+ height: 300
+ z: -1
+
+ signal sendToScript(var message);
+ signal windowClosed();
+
+ property bool shown: true
+
+ onShownChanged: {
+ bar.visible = shown;
+ }
+
+ Rectangle {
+ anchors.fill : parent
+ color: "transparent"
+ Flow {
+ id: flowMain
+ spacing: 10
+ flow: Flow.TopToBottom
+ layoutDirection: Flow.TopToBottom
+ anchors.fill: parent
+ anchors.margins: 4
+ }
+ }
+
+ Component.onCompleted: {
+ // put on bottom
+ x = 0;
+ y = 0;
+ width = 300;
+ height = 300;
+ }
+
+ function addButton(properties) {
+ var component = Qt.createComponent("button.qml");
+ if (component.status == Component.Ready) {
+ var button = component.createObject(flowMain);
+ // copy all properites to button
+ var keys = Object.keys(properties).forEach(function (key) {
+ button[key] = properties[key];
+ });
+ return button;
+ } else if( component.status == Component.Error) {
+ console.log("Load button errors " + component.errorString());
+ }
+ }
+
+ function urlHelper(src) {
+ if (src.match(/\bhttp/)) {
+ return src;
+ } else {
+ return "../../../" + src;
+ }
+ }
+
+}
diff --git a/interface/resources/qml/hifi/+android/HifiConstants.qml b/interface/resources/qml/hifi/+android/HifiConstants.qml
new file mode 100644
index 0000000000..ee6d92ed38
--- /dev/null
+++ b/interface/resources/qml/hifi/+android/HifiConstants.qml
@@ -0,0 +1,54 @@
+//
+// HifiAndroidConstants.qml
+// interface/resources/qml/+android
+//
+// Created by Gabriel Calero & Cristian Duarte on 23 Oct 2017
+// Copyright 2017 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
+//
+
+import QtQuick 2.4
+
+Item {
+
+ id: android
+
+ readonly property alias dimen: dimen
+ readonly property alias color: color
+
+ Item {
+ id: dimen
+ readonly property real windowLessWidth: 126
+ readonly property real windowLessHeight: 64
+
+ readonly property real windowZ: 100
+
+ readonly property real headerHeight: 276
+
+ readonly property real headerIconPosX: 90
+ readonly property real headerIconPosY: 108
+ readonly property real headerIconWidth: 111
+ readonly property real headerIconHeight: 111
+ readonly property real headerIconTitleDistance: 151
+
+ readonly property real headerHideWidth: 150
+ readonly property real headerHideHeight: 150
+ readonly property real headerHideRightMargin: 110
+ readonly property real headerHideTopMargin: 90
+ readonly property real headerHideIconWidth: 70
+ readonly property real headerHideIconHeight: 45
+ readonly property real headerHideTextTopMargin: 36
+
+ readonly property real botomHudWidth: 366
+ readonly property real botomHudHeight: 180
+
+ }
+
+ Item {
+ id: color
+ readonly property color gradientTop: "#4E4E4E"
+ readonly property color gradientBottom: "#242424"
+ }
+}
diff --git a/interface/resources/qml/hifi/+android/WindowHeader.qml b/interface/resources/qml/hifi/+android/WindowHeader.qml
new file mode 100644
index 0000000000..4ec0a0c6e6
--- /dev/null
+++ b/interface/resources/qml/hifi/+android/WindowHeader.qml
@@ -0,0 +1,113 @@
+//
+// WindowHeader.qml
+// interface/resources/qml/android
+//
+// Created by Gabriel Calero & Cristian Duarte on 23 Oct 2017
+// Copyright 2017 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
+//
+
+import QtQuick 2.5
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Layouts 1.3
+import Qt.labs.settings 1.0
+import "."
+import "../styles" as HifiStyles
+import "../styles-uit"
+import "../controls-uit" as HifiControlsUit
+import "../controls" as HifiControls
+import ".."
+
+
+// header
+Rectangle {
+ id: header
+
+ // properties
+ property string iconSource: ""
+ property string titleText: ""
+ property var extraItemInCenter: Item {}
+
+ HifiStyles.HifiConstants { id: hifiStylesConstants }
+
+ /*property var mockRectangle: Rectangle {
+ anchors.fill: parent
+ color: "#44FFFF00"
+ }*/
+ color: "#00000000"
+ //color: "#55FF0000"
+ width: parent.width
+ height: android.dimen.headerHeight
+ anchors.top : parent.top
+
+ Image {
+ id: windowIcon
+ source: iconSource
+ x: android.dimen.headerIconPosX
+ y: android.dimen.headerIconPosY
+ width: android.dimen.headerIconWidth
+ height: android.dimen.headerIconHeight
+ }
+
+ /*HifiStylesUit.*/FiraSansSemiBold {
+ id: windowTitle
+ x: windowIcon.x + android.dimen.headerIconTitleDistance
+ anchors.verticalCenter: windowIcon.verticalCenter
+ text: titleText
+ color: "#FFFFFF"
+ font.letterSpacing: 2
+ font.pixelSize: hifiStylesConstants.fonts.headerPixelSize * 2.15
+ }
+ Item {
+ height: 60
+ anchors {
+ left: windowTitle.right
+ right: hideButton.left
+ verticalCenter: windowIcon.verticalCenter
+ }
+ children: [ extraItemInCenter/*, mockRectangle */]
+ }
+
+ Rectangle {
+ id: hideButton
+ height: android.dimen.headerHideWidth
+ width: android.dimen.headerHideHeight
+ color: "#00000000"
+ //color: "#CC00FF00"
+ anchors {
+ top: parent.top
+ right: parent.right
+ rightMargin: android.dimen.headerHideRightMargin
+ topMargin: android.dimen.headerHideTopMargin
+ }
+ Image {
+ id: hideIcon
+ source: "../../../icons/hide.svg"
+ width: android.dimen.headerHideIconWidth
+ height: android.dimen.headerHideIconHeight
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ }
+ }
+ /*HifiStyles.*/FiraSansRegular {
+ anchors {
+ top: hideIcon.bottom
+ horizontalCenter: hideIcon.horizontalCenter
+ topMargin: android.dimen.headerHideTextTopMargin
+ }
+ text: "HIDE"
+ color: "#FFFFFF"
+ font.pixelSize: hifiStylesConstants.fonts.pixelSize * 2.15
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ hide();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/interface/resources/qml/hifi/+android/bottomHudOptions.qml b/interface/resources/qml/hifi/+android/bottomHudOptions.qml
new file mode 100644
index 0000000000..860298149f
--- /dev/null
+++ b/interface/resources/qml/hifi/+android/bottomHudOptions.qml
@@ -0,0 +1,89 @@
+//
+// bottomHudOptions.qml
+// interface/resources/qml/android
+//
+// Created by Cristian Duarte & Gabriel Calero on 24 Nov 2017
+// Copyright 2017 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
+//
+
+import Hifi 1.0
+import QtQuick 2.5
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Layouts 1.3
+import Qt.labs.settings 1.0
+import "../../styles" as HifiStyles
+import "../../styles-uit"
+import "../../controls-uit" as HifiControlsUit
+import "../../controls" as HifiControls
+import ".."
+import "."
+
+Item {
+ id: bottomHud
+
+ property bool shown: false
+
+ signal sendToScript(var message);
+
+ HifiConstants { id: android }
+
+ onShownChanged: {
+ bottomHud.visible = shown;
+ }
+
+ function hide() {
+ shown = false;
+ }
+
+ Rectangle {
+ anchors.fill : parent
+ color: "transparent"
+ Flow {
+ id: flowMain
+ spacing: 0
+ flow: Flow.LeftToRight
+ layoutDirection: Flow.LeftToRight
+ anchors.fill: parent
+ anchors.margins: 12
+
+ Rectangle {
+ id: hideButton
+ height: android.dimen.headerHideWidth
+ width: android.dimen.headerHideHeight
+ color: "#00000000"
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ }
+ Image {
+ id: hideIcon
+ source: "../../../icons/show-up.svg"
+ width: android.dimen.headerHideIconWidth
+ height: android.dimen.headerHideIconHeight
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ verticalCenter: parent.verticalCenter
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ sendToScript ({ method: "showUpBar" });
+ }
+ }
+ }
+ }
+ }
+
+ Component.onCompleted: {
+ width = android.dimen.botomHudWidth;
+ height = android.dimen.botomHudHeight;
+ x=Window.innerWidth - width;
+ y=Window.innerHeight - height;
+ }
+
+}
diff --git a/interface/resources/qml/hifi/+android/bottombar.qml b/interface/resources/qml/hifi/+android/bottombar.qml
new file mode 100644
index 0000000000..2a34b7fe19
--- /dev/null
+++ b/interface/resources/qml/hifi/+android/bottombar.qml
@@ -0,0 +1,135 @@
+//
+// bottomHudOptions.qml
+// interface/resources/qml/android
+//
+// Created by Gabriel Calero & Cristian Duarte on 19 Jan 2018
+// 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
+//
+
+import Hifi 1.0
+import QtQuick 2.5
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Layouts 1.3
+import Qt.labs.settings 1.0
+import "../../styles" as Styles
+import "../../styles-uit"
+import "../../controls-uit" as HifiControlsUit
+import "../../controls" as HifiControls
+import ".."
+import "."
+
+Item {
+ id: bar
+ x:0
+
+ property bool shown: true
+
+ signal sendToScript(var message);
+
+ onShownChanged: {
+ bar.visible = shown;
+ }
+
+ function hide() {
+ //shown = false;
+ sendToScript({ method: "hide" });
+ }
+
+ Styles.HifiConstants { id: hifi }
+ HifiConstants { id: android }
+
+ Rectangle {
+ id: background
+ anchors.fill : parent
+ color: "#FF000000"
+ border.color: "#FFFFFF"
+ anchors.bottomMargin: -1
+ anchors.leftMargin: -1
+ anchors.rightMargin: -1
+ Flow {
+ id: flowMain
+ spacing: 10
+ anchors.fill: parent
+ anchors.topMargin: 12
+ anchors.bottomMargin: 12
+ anchors.rightMargin: 12
+ anchors.leftMargin: 72
+ }
+
+
+ Rectangle {
+ id: hideButton
+ height: android.dimen.headerHideWidth
+ width: android.dimen.headerHideHeight
+ color: "#00000000"
+ anchors {
+ right: parent.right
+ rightMargin: android.dimen.headerHideRightMargin
+ top: parent.top
+ topMargin: android.dimen.headerHideTopMargin
+ }
+
+ Image {
+ id: hideIcon
+ source: "../../../icons/hide.svg"
+ width: android.dimen.headerHideIconWidth
+ height: android.dimen.headerHideIconHeight
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ top: parent.top
+ }
+ }
+ FiraSansRegular {
+ anchors {
+ top: hideIcon.bottom
+ horizontalCenter: hideIcon.horizontalCenter
+ topMargin: 12
+ }
+ text: "HIDE"
+ color: "#FFFFFF"
+ font.pixelSize: hifi.fonts.pixelSize * 2.5;
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ hide();
+ }
+ }
+ }
+ }
+
+ Component.onCompleted: {
+ // put on bottom
+ width = Window.innerWidth;
+ height = 255;
+ y = Window.innerHeight - height;
+ }
+
+ function addButton(properties) {
+ var component = Qt.createComponent("button.qml");
+ if (component.status == Component.Ready) {
+ var button = component.createObject(flowMain);
+ // copy all properites to button
+ var keys = Object.keys(properties).forEach(function (key) {
+ button[key] = properties[key];
+ });
+ return button;
+ } else if( component.status == Component.Error) {
+ console.log("Load button errors " + component.errorString());
+ }
+ }
+
+ function urlHelper(src) {
+ if (src.match(/\bhttp/)) {
+ return src;
+ } else {
+ return "../../../" + src;
+ }
+ }
+
+}
diff --git a/interface/resources/qml/hifi/+android/button.qml b/interface/resources/qml/hifi/+android/button.qml
new file mode 100644
index 0000000000..ec7af2ab92
--- /dev/null
+++ b/interface/resources/qml/hifi/+android/button.qml
@@ -0,0 +1,230 @@
+import QtQuick 2.5
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Layouts 1.3
+
+Item {
+ id: button
+ property string icon: "icons/edit-icon.svg"
+ property string hoverIcon: button.icon
+ property string activeIcon: button.icon
+ property string activeHoverIcon: button.activeIcon
+ property int stableOrder: 0
+
+ property int iconSize: 165
+ property string text: "."
+ property string hoverText: button.text
+ property string activeText: button.text
+ property string activeHoverText: button.activeText
+
+ property string bgColor: "#ffffff"
+ property string hoverBgColor: button.bgColor
+ property string activeBgColor: button.bgColor
+ property string activeHoverBgColor: button.bgColor
+
+ property real bgOpacity: 0
+ property real hoverBgOpacity: 1
+ property real activeBgOpacity: 0.5
+ property real activeHoverBgOpacity: 1
+
+ property string textColor: "#ffffff"
+ property int textSize: 54
+ property string hoverTextColor: "#ffffff"
+ property string activeTextColor: "#ffffff"
+ property string activeHoverTextColor: "#ffffff"
+ property int bottomMargin: 30
+
+ property bool isEntered: false
+ property double sortOrder: 100
+
+ property bool isActive: false
+
+ signal clicked()
+
+ onIsActiveChanged: {
+ if (button.isEntered) {
+ button.state = (button.isActive) ? "hover active state" : "hover state";
+ } else {
+ button.state = (button.isActive) ? "active state" : "base state";
+ }
+ }
+
+ function editProperties(props) {
+ for (var prop in props) {
+ button[prop] = props[prop];
+ }
+ }
+
+
+ width: 300
+ height: 300
+
+ Rectangle {
+ id: buttonBg
+ color: bgColor
+ opacity: bgOpacity
+ anchors.right: parent.right
+ anchors.rightMargin: 0
+ anchors.left: parent.left
+ anchors.leftMargin: 0
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 0
+ anchors.top: parent.top
+ anchors.topMargin: 0
+ }
+ Image {
+ id: icon
+ width: iconSize
+ height: iconSize
+ anchors.bottom: text.top
+ anchors.bottomMargin: 6
+ anchors.horizontalCenter: parent.horizontalCenter
+ fillMode: Image.Stretch
+ source: urlHelper(button.icon)
+ }
+ FontLoader {
+ id: firaSans
+ source: "../../../fonts/FiraSans-Regular.ttf"
+ }
+ Text {
+ id: text
+ color: "#ffffff"
+ text: button.text
+ font.family: "FiraSans"
+ //font.bold: true
+ font.pixelSize: textSize
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: bottomMargin
+ anchors.horizontalCenter: parent.horizontalCenter
+ horizontalAlignment: Text.AlignHCenter
+ }
+ MouseArea {
+ anchors.fill: parent
+ hoverEnabled: true
+ enabled: true
+ onClicked: {
+ console.log("Bottom bar button clicked!!");
+ /*if (tabletButton.inDebugMode) {
+ if (tabletButton.isActive) {
+ tabletButton.isActive = false;
+ } else {
+ tabletButton.isActive = true;
+ }
+ }*/
+ button.clicked();
+ /*if (tabletRoot) {
+ tabletRoot.playButtonClickSound();
+ }*/
+ }
+ onEntered: {
+ button.isEntered = true;
+ if (button.isActive) {
+ button.state = "hover active state";
+ } else {
+ button.state = "hover state";
+ }
+ }
+ onExited: {
+ button.isEntered = false;
+ if (button.isActive) {
+ button.state = "active state";
+ } else {
+ button.state = "base state";
+ }
+ }
+ }
+ states: [
+ State {
+ name: "hover state"
+
+ PropertyChanges {
+ target: buttonBg
+ //color: "#cfcfcf"
+ //opacity: 1
+ color: button.hoverBgColor
+ opacity: button.hoverBgOpacity
+ }
+
+ PropertyChanges {
+ target: text
+ //color: "#ffffff"
+ color: button.hoverTextColor
+ text: button.hoverText
+ }
+
+ PropertyChanges {
+ target: icon
+ source: urlHelper(button.hoverIcon)
+ }
+ },
+ State {
+ name: "active state"
+
+ PropertyChanges {
+ target: buttonBg
+ //color: "#1fc6a6"
+ //opacity: 1
+ color: button.activeBgColor
+ opacity: button.activeBgOpacity
+ }
+
+ PropertyChanges {
+ target: text
+ //color: "#333333"
+ color: button.activeTextColor
+ text: button.activeText
+ }
+
+ PropertyChanges {
+ target: icon
+ source: urlHelper(button.activeIcon)
+ }
+ },
+ State {
+ name: "hover active state"
+
+ PropertyChanges {
+ target: buttonBg
+ //color: "#ff0000"
+ //opacity: 1
+ color: button.activeHoverBgColor
+ opacity: button.activeHoverBgOpacity
+ }
+
+ PropertyChanges {
+ target: text
+ //color: "#333333"
+ color: button.activeHoverTextColor
+ text: button.activeHoverText
+ }
+
+ PropertyChanges {
+ target: icon
+ source: urlHelper(button.activeHoverIcon)
+ }
+ },
+ State {
+ name: "base state"
+
+ PropertyChanges {
+ target: buttonBg
+ //color: "#9A9A9A"
+ //opacity: 0.1
+ color: button.bgColor
+ opacity: button.bgOpacity
+ }
+
+ PropertyChanges {
+ target: text
+ //color: "#ffffff"
+ color: button.textColor
+ text: button.text
+ }
+
+ PropertyChanges {
+ target: icon
+ source: urlHelper(button.icon)
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/interface/resources/qml/hifi/+android/modesbar.qml b/interface/resources/qml/hifi/+android/modesbar.qml
new file mode 100644
index 0000000000..8ce455c2c1
--- /dev/null
+++ b/interface/resources/qml/hifi/+android/modesbar.qml
@@ -0,0 +1,73 @@
+import QtQuick 2.5
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Layouts 1.3
+import Qt.labs.settings 1.0
+import "../../styles-uit"
+import "../../controls-uit" as HifiControlsUit
+import "../../controls" as HifiControls
+import ".."
+
+Item {
+ id: modesbar
+ y:60
+ Rectangle {
+ anchors.fill : parent
+ color: "transparent"
+ Flow {
+ id: flowMain
+ spacing: 0
+ flow: Flow.TopToBottom
+ layoutDirection: Flow.TopToBottom
+ anchors.fill: parent
+ anchors.margins: 4
+ }
+ }
+
+ Component.onCompleted: {
+ width = 330;
+ height = 330;
+ x=Window.innerWidth - width;
+ }
+
+ function addButton(properties) {
+ var component = Qt.createComponent("button.qml");
+ console.log("load button");
+ if (component.status == Component.Ready) {
+ console.log("load button 2");
+ var button = component.createObject(flowMain);
+ // copy all properites to button
+ var keys = Object.keys(properties).forEach(function (key) {
+ button[key] = properties[key];
+ });
+ return button;
+ } else if( component.status == Component.Error) {
+ console.log("Load button errors " + component.errorString());
+ }
+ }
+
+ function removeButton(name) {
+ }
+
+ function urlHelper(src) {
+ if (src.match(/\bhttp/)) {
+ return src;
+ } else {
+ return "../../../" + src;
+ }
+ }
+
+ function fromScript(message) {
+ switch (message.type) {
+ case "allButtonsShown":
+ modesbar.height = flowMain.children.length * 100 + 10;
+ break;
+ case "inactiveButtonsHidden":
+ modesbar.height = 100 + 10;
+ break;
+ default:
+ break;
+ }
+ }
+
+}
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index a373926361..7ba545114b 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -69,6 +69,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -137,6 +138,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -777,6 +779,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
DependencyManager::set();
DependencyManager::set();
DependencyManager::set();
+ DependencyManager::set();
DependencyManager::set();
DependencyManager::set(std::bind(&Application::getUserAgent, qApp));
DependencyManager::set();
@@ -1522,12 +1525,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
return DependencyManager::get()->navigationFocused() ? 1 : 0;
});
- // Setup the _keyboardMouseDevice, _touchscreenDevice and the user input mapper with the default bindings
+ // Setup the _keyboardMouseDevice, _touchscreenDevice, _touchscreenVirtualPadDevice and the user input mapper with the default bindings
userInputMapper->registerDevice(_keyboardMouseDevice->getInputDevice());
// if the _touchscreenDevice is not supported it will not be registered
if (_touchscreenDevice) {
userInputMapper->registerDevice(_touchscreenDevice->getInputDevice());
}
+ if (_touchscreenVirtualPadDevice) {
+ userInputMapper->registerDevice(_touchscreenVirtualPadDevice->getInputDevice());
+ }
// this will force the model the look at the correct directory (weird order of operations issue)
scriptEngines->reloadLocalFiles();
@@ -2615,6 +2621,9 @@ void Application::initializeUi() {
if (TouchscreenDevice::NAME == inputPlugin->getName()) {
_touchscreenDevice = std::dynamic_pointer_cast(inputPlugin);
}
+ if (TouchscreenVirtualPadDevice::NAME == inputPlugin->getName()) {
+ _touchscreenVirtualPadDevice = std::dynamic_pointer_cast(inputPlugin);
+ }
}
auto compositorHelper = DependencyManager::get();
@@ -3021,7 +3030,9 @@ void Application::handleSandboxStatus(QNetworkReply* reply) {
// If this is a first run we short-circuit the address passed in
if (firstRun.get()) {
+#if !defined(Q_OS_ANDROID)
showHelp();
+#endif
if (sandboxIsRunning) {
qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
DependencyManager::get()->goToLocalSandbox();
@@ -3805,6 +3816,9 @@ void Application::touchUpdateEvent(QTouchEvent* event) {
if (_touchscreenDevice && _touchscreenDevice->isActive()) {
_touchscreenDevice->touchUpdateEvent(event);
}
+ if (_touchscreenVirtualPadDevice && _touchscreenVirtualPadDevice->isActive()) {
+ _touchscreenVirtualPadDevice->touchUpdateEvent(event);
+ }
}
void Application::touchBeginEvent(QTouchEvent* event) {
@@ -3826,6 +3840,9 @@ void Application::touchBeginEvent(QTouchEvent* event) {
if (_touchscreenDevice && _touchscreenDevice->isActive()) {
_touchscreenDevice->touchBeginEvent(event);
}
+ if (_touchscreenVirtualPadDevice && _touchscreenVirtualPadDevice->isActive()) {
+ _touchscreenVirtualPadDevice->touchBeginEvent(event);
+ }
}
@@ -3846,7 +3863,9 @@ void Application::touchEndEvent(QTouchEvent* event) {
if (_touchscreenDevice && _touchscreenDevice->isActive()) {
_touchscreenDevice->touchEndEvent(event);
}
-
+ if (_touchscreenVirtualPadDevice && _touchscreenVirtualPadDevice->isActive()) {
+ _touchscreenVirtualPadDevice->touchEndEvent(event);
+ }
// put any application specific touch behavior below here..
}
@@ -3854,6 +3873,9 @@ void Application::touchGestureEvent(QGestureEvent* event) {
if (_touchscreenDevice && _touchscreenDevice->isActive()) {
_touchscreenDevice->touchGestureEvent(event);
}
+ if (_touchscreenVirtualPadDevice && _touchscreenVirtualPadDevice->isActive()) {
+ _touchscreenVirtualPadDevice->touchGestureEvent(event);
+ }
}
void Application::wheelEvent(QWheelEvent* event) const {
@@ -5336,7 +5358,9 @@ void Application::update(float deltaTime) {
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::update()");
+#if !defined(Q_OS_ANDROID)
updateLOD(deltaTime);
+#endif
// TODO: break these out into distinct perfTimers when they prove interesting
{
@@ -6065,6 +6089,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
scriptEngine->registerFunction("OverlayWebWindow", QmlWebWindowClass::constructor);
#endif
scriptEngine->registerFunction("OverlayWindow", QmlWindowClass::constructor);
+ scriptEngine->registerFunction("QmlFragment", QmlFragmentClass::constructor);
scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance());
scriptEngine->registerGlobalObject("DesktopPreviewProvider", DependencyManager::get().data());
diff --git a/interface/src/Application.h b/interface/src/Application.h
index 8a0d3c2351..1214ca4df4 100644
--- a/interface/src/Application.h
+++ b/interface/src/Application.h
@@ -33,6 +33,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -554,6 +555,7 @@ private:
std::shared_ptr _applicationStateDevice; // Default ApplicationDevice reflecting the state of different properties of the session
std::shared_ptr _keyboardMouseDevice; // Default input device, the good old keyboard mouse and maybe touchpad
std::shared_ptr _touchscreenDevice; // the good old touchscreen
+ std::shared_ptr _touchscreenVirtualPadDevice;
SimpleMovingAverage _avatarSimsPerSecond {10};
int _avatarSimsPerSecondReport {0};
quint64 _lastAvatarSimsPerSecondUpdate {0};
diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp
index 4848531de7..95be7b29e9 100644
--- a/interface/src/scripting/ControllerScriptingInterface.cpp
+++ b/interface/src/scripting/ControllerScriptingInterface.cpp
@@ -16,6 +16,7 @@
#include
#include "Application.h"
+#include "VirtualPadManager.h"
bool ControllerScriptingInterface::isKeyCaptured(QKeyEvent* event) const {
return isKeyCaptured(KeyEvent(*event));
@@ -83,6 +84,11 @@ QVariant ControllerScriptingInterface::getRecommendedHUDRect() const {
return qRectToVariant(rect);
}
+void ControllerScriptingInterface::setVPadEnabled(const bool enable) {
+ auto& virtualPadManager = VirtualPad::Manager::instance();
+ virtualPadManager.enable(enable);
+}
+
void ControllerScriptingInterface::emitKeyPressEvent(QKeyEvent* event) { emit keyPressEvent(KeyEvent(*event)); }
void ControllerScriptingInterface::emitKeyReleaseEvent(QKeyEvent* event) { emit keyReleaseEvent(KeyEvent(*event)); }
diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h
index 7a2c964622..1f223814a3 100644
--- a/interface/src/scripting/ControllerScriptingInterface.h
+++ b/interface/src/scripting/ControllerScriptingInterface.h
@@ -65,6 +65,8 @@ public slots:
virtual glm::vec2 getViewportDimensions() const;
virtual QVariant getRecommendedHUDRect() const;
+ virtual void setVPadEnabled(bool enable);
+
signals:
void keyPressEvent(const KeyEvent& event);
void keyReleaseEvent(const KeyEvent& event);
diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp
index 8379151d1c..873d294303 100644
--- a/libraries/audio-client/src/AudioClient.cpp
+++ b/libraries/audio-client/src/AudioClient.cpp
@@ -53,10 +53,16 @@
#include "AudioClient.h"
const int AudioClient::MIN_BUFFER_FRAMES = 1;
+
const int AudioClient::MAX_BUFFER_FRAMES = 20;
static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 100;
+#if defined(Q_OS_ANDROID)
+static const int CHECK_INPUT_READS_MSECS = 2000;
+static const int MIN_READS_TO_CONSIDER_INPUT_ALIVE = 100;
+#endif
+
static const auto DEFAULT_POSITION_GETTER = []{ return Vectors::ZERO; };
static const auto DEFAULT_ORIENTATION_GETTER = [] { return Quaternions::IDENTITY; };
@@ -197,6 +203,9 @@ AudioClient::AudioClient() :
_audioOutputIODevice(_localInjectorsStream, _receivedAudioStream, this),
_stats(&_receivedAudioStream),
_positionGetter(DEFAULT_POSITION_GETTER),
+#if defined(Q_OS_ANDROID)
+ _checkInputTimer(this),
+#endif
_orientationGetter(DEFAULT_ORIENTATION_GETTER) {
// avoid putting a lock in the device callback
assert(_localSamplesAvailable.is_lock_free());
@@ -278,6 +287,9 @@ void AudioClient::cleanupBeforeQuit() {
return;
}
+#if defined(Q_OS_ANDROID)
+ _shouldRestartInputSetup = false;
+#endif
stop();
_checkDevicesTimer->stop();
_checkPeakValuesTimer->stop();
@@ -622,6 +634,12 @@ void AudioClient::start() {
qCDebug(audioclient) << "Unable to set up audio output because of a problem with output format.";
qCDebug(audioclient) << "The closest format available is" << outputDeviceInfo.nearestFormat(_desiredOutputFormat);
}
+#if defined(Q_OS_ANDROID)
+ connect(&_checkInputTimer, &QTimer::timeout, [this] {
+ checkInputTimeout();
+ });
+ _checkInputTimer.start(CHECK_INPUT_READS_MSECS);
+#endif
}
void AudioClient::stop() {
@@ -631,6 +649,9 @@ void AudioClient::stop() {
qCDebug(audioclient) << "AudioClient::stop(), requesting switchOutputToAudioDevice() to shut down";
switchOutputToAudioDevice(QAudioDeviceInfo(), true);
+#if defined(Q_OS_ANDROID)
+ _checkInputTimer.stop();
+#endif
}
void AudioClient::handleAudioEnvironmentDataPacket(QSharedPointer message) {
@@ -1090,6 +1111,10 @@ void AudioClient::handleMicAudioInput() {
return;
}
+#if defined(Q_OS_ANDROID)
+ _inputReadsSinceLastCheck++;
+#endif
+
// input samples required to produce exactly NETWORK_FRAME_SAMPLES of output
const int inputSamplesRequired = (_inputToNetworkResampler ?
_inputToNetworkResampler->getMinInput(AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL) :
@@ -1434,6 +1459,10 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf
// NOTE: device start() uses the Qt internal device list
Lock lock(_deviceMutex);
+#if defined(Q_OS_ANDROID)
+ _shouldRestartInputSetup = false; // avoid a double call to _audioInput->start() from audioInputStateChanged
+#endif
+
// cleanup any previously initialized device
if (_audioInput) {
// The call to stop() causes _inputDevice to be destructed.
@@ -1514,7 +1543,10 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf
#if defined(Q_OS_ANDROID)
if (_audioInput) {
- connect(_audioInput, SIGNAL(stateChanged(QAudio::State)), this, SLOT(audioInputStateChanged(QAudio::State)));
+ _shouldRestartInputSetup = true;
+ connect(_audioInput, &QAudioInput::stateChanged, [this](QAudio::State state) {
+ audioInputStateChanged(state);
+ });
}
#endif
_inputDevice = _audioInput->start();
@@ -1555,14 +1587,14 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf
return supportedFormat;
}
-#if defined(Q_OS_ANDROID)
void AudioClient::audioInputStateChanged(QAudio::State state) {
+#if defined(Q_OS_ANDROID)
switch (state) {
case QAudio::StoppedState:
if (!_audioInput) {
break;
}
- // Stopped on purpose
+ // Stopped on purpose
if (_shouldRestartInputSetup) {
Lock lock(_deviceMutex);
_inputDevice = _audioInput->start();
@@ -1577,8 +1609,18 @@ void AudioClient::audioInputStateChanged(QAudio::State state) {
default:
break;
}
-}
#endif
+}
+
+void AudioClient::checkInputTimeout() {
+#if defined(Q_OS_ANDROID)
+ if (_audioInput && _inputReadsSinceLastCheck < MIN_READS_TO_CONSIDER_INPUT_ALIVE) {
+ _audioInput->stop();
+ } else {
+ _inputReadsSinceLastCheck = 0;
+ }
+#endif
+}
void AudioClient::outputNotify() {
int recentUnfulfilled = _audioOutputIODevice.getRecentUnfulfilledReads();
diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h
index 0643b8e52a..3e6e83b598 100644
--- a/libraries/audio-client/src/AudioClient.h
+++ b/libraries/audio-client/src/AudioClient.h
@@ -26,7 +26,6 @@
#include
#include
#include
-
#include
#include
#include
@@ -183,9 +182,8 @@ public slots:
void sendDownstreamAudioStatsPacket() { _stats.publish(); }
void handleMicAudioInput();
-#if defined(Q_OS_ANDROID)
void audioInputStateChanged(QAudio::State state);
-#endif
+ void checkInputTimeout();
void handleDummyAudioInput();
void handleRecordedAudioInput(const QByteArray& audio);
void reset();
@@ -276,6 +274,11 @@ private:
float azimuthForSource(const glm::vec3& relativePosition);
float gainForSource(float distance, float volume);
+#ifdef Q_OS_ANDROID
+ QTimer _checkInputTimer;
+ long _inputReadsSinceLastCheck = 0l;
+#endif
+
class Gate {
public:
Gate(AudioClient* audioClient);
diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp
index 588c43d534..1a1714ad56 100644
--- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp
+++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp
@@ -6,6 +6,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "Basic2DWindowOpenGLDisplayPlugin.h"
+#include "CompositorHelper.h"
+#include "VirtualPadManager.h"
#include
@@ -14,13 +16,65 @@
#include
#include
+#include
const QString Basic2DWindowOpenGLDisplayPlugin::NAME("Desktop");
static const QString FULLSCREEN = "Fullscreen";
+void Basic2DWindowOpenGLDisplayPlugin::customizeContext() {
+ auto iconPath = PathUtils::resourcesPath() + "images/analog_stick.png";
+ auto image = QImage(iconPath);
+ if (image.format() != QImage::Format_ARGB32) {
+ image = image.convertToFormat(QImage::Format_ARGB32);
+ }
+ if ((image.width() > 0) && (image.height() > 0)) {
+
+ _virtualPadStickTexture = gpu::Texture::createStrict(
+ gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA),
+ image.width(), image.height(),
+ gpu::Texture::MAX_NUM_MIPS,
+ gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR));
+ _virtualPadStickTexture->setSource("virtualPad stick");
+ auto usage = gpu::Texture::Usage::Builder().withColor().withAlpha();
+ _virtualPadStickTexture->setUsage(usage.build());
+ _virtualPadStickTexture->setStoredMipFormat(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
+ _virtualPadStickTexture->assignStoredMip(0, image.byteCount(), image.constBits());
+ _virtualPadStickTexture->setAutoGenerateMips(true);
+ }
+
+ iconPath = PathUtils::resourcesPath() + "images/analog_stick_base.png";
+ image = QImage(iconPath);
+ if (image.format() != QImage::Format_ARGB32) {
+ image = image.convertToFormat(QImage::Format_ARGB32);
+ }
+ if ((image.width() > 0) && (image.height() > 0)) {
+ _virtualPadStickBaseTexture = gpu::Texture::createStrict(
+ gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA),
+ image.width(), image.height(),
+ gpu::Texture::MAX_NUM_MIPS,
+ gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR));
+ _virtualPadStickBaseTexture->setSource("virtualPad base");
+ auto usage = gpu::Texture::Usage::Builder().withColor().withAlpha();
+ _virtualPadStickBaseTexture->setUsage(usage.build());
+ _virtualPadStickBaseTexture->setStoredMipFormat(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
+ _virtualPadStickBaseTexture->assignStoredMip(0, image.byteCount(), image.constBits());
+ _virtualPadStickBaseTexture->setAutoGenerateMips(true);
+ }
+
+
+ Parent::customizeContext();
+}
+
+void Basic2DWindowOpenGLDisplayPlugin::uncustomizeContext() {
+ Parent::uncustomizeContext();
+}
+
bool Basic2DWindowOpenGLDisplayPlugin::internalActivate() {
_framerateActions.clear();
+#if defined(Q_OS_ANDROID)
+ _container->setFullscreen(nullptr, true);
+#endif
_container->addMenuItem(PluginType::DISPLAY_PLUGIN, MENU_PATH(), FULLSCREEN,
[this](bool clicked) {
if (clicked) {
@@ -33,6 +87,37 @@ bool Basic2DWindowOpenGLDisplayPlugin::internalActivate() {
return Parent::internalActivate();
}
+void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() {
+ auto& virtualPadManager = VirtualPad::Manager::instance();
+ if(virtualPadManager.getLeftVirtualPad()->isBeingTouched()) {
+ // render stick base
+ auto stickBaseTransform = DependencyManager::get()->getPoint2DTransform(virtualPadManager.getLeftVirtualPad()->getFirstTouch());
+ render([&](gpu::Batch& batch) {
+ batch.enableStereo(false);
+ batch.setProjectionTransform(mat4());
+ batch.setPipeline(_cursorPipeline);
+ batch.setResourceTexture(0, _virtualPadStickBaseTexture);
+ batch.resetViewTransform();
+ batch.setModelTransform(stickBaseTransform);
+ batch.setViewportTransform(ivec4(uvec2(0), getRecommendedRenderSize()));
+ batch.draw(gpu::TRIANGLE_STRIP, 4);
+ });
+ // render stick head
+ auto stickTransform = DependencyManager::get()->getPoint2DTransform(virtualPadManager.getLeftVirtualPad()->getCurrentTouch());
+ render([&](gpu::Batch& batch) {
+ batch.enableStereo(false);
+ batch.setProjectionTransform(mat4());
+ batch.setPipeline(_cursorPipeline);
+ batch.setResourceTexture(0, _virtualPadStickTexture);
+ batch.resetViewTransform();
+ batch.setModelTransform(stickTransform);
+ batch.setViewportTransform(ivec4(uvec2(0), getRecommendedRenderSize()));
+ batch.draw(gpu::TRIANGLE_STRIP, 4);
+ });
+ }
+ Parent::compositeExtra();
+}
+
static const uint32_t MIN_THROTTLE_CHECK_FRAMES = 60;
bool Basic2DWindowOpenGLDisplayPlugin::isThrottled() const {
diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h
index f3dd50602c..d9b942bd97 100644
--- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h
+++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h
@@ -22,10 +22,15 @@ public:
virtual float getTargetFrameRate() const override { return _framerateTarget ? (float) _framerateTarget : TARGET_FRAMERATE_Basic2DWindowOpenGL; }
+ virtual void customizeContext() override;
+ virtual void uncustomizeContext() override;
+
virtual bool internalActivate() override;
virtual bool isThrottled() const override;
+ virtual void compositeExtra() override;
+
protected:
mutable bool _isThrottled = false;
@@ -36,4 +41,7 @@ private:
QAction* _vsyncAction { nullptr };
uint32_t _framerateTarget { 0 };
int _fullscreenTarget{ -1 };
+
+ gpu::TexturePointer _virtualPadStickTexture;
+ gpu::TexturePointer _virtualPadStickBaseTexture;
};
diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp
index f3f81c0b2e..74225b5b39 100644
--- a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp
+++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp
@@ -458,6 +458,22 @@ glm::mat4 CompositorHelper::getReticleTransform(const glm::mat4& eyePose, const
return result;
}
+glm::mat4 CompositorHelper::getPoint2DTransform(const glm::vec2& point) const {
+ glm::mat4 result;
+ static const float PIXEL_SIZE = 512.0f;
+ const auto canvasSize = vec2(toGlm(_renderingWidget->size()));;
+ QPoint qPoint(point.x,point.y);
+ vec2 position = toGlm(_renderingWidget->mapFromGlobal(qPoint));
+ position /= canvasSize;
+ position *= 2.0;
+ position -= 1.0;
+ position.y *= -1.0f;
+
+ vec2 size = PIXEL_SIZE / canvasSize;
+ result = glm::scale(glm::translate(glm::mat4(), vec3(position, 0.0f)), vec3(size, 1.0f));
+ return result;
+}
+
QVariant ReticleInterface::getPosition() const {
return vec2toVariant(_compositor->getReticlePosition());
diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.h b/libraries/display-plugins/src/display-plugins/CompositorHelper.h
index 6c2acb7e62..5b65315f45 100644
--- a/libraries/display-plugins/src/display-plugins/CompositorHelper.h
+++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.h
@@ -90,6 +90,7 @@ public:
glm::vec2 getReticleMaximumPosition() const;
glm::mat4 getReticleTransform(const glm::mat4& eyePose = glm::mat4(), const glm::vec3& headPosition = glm::vec3()) const;
+ glm::mat4 getPoint2DTransform(const glm::vec2& point = glm::vec2()) const;
ReticleInterface* getReticleInterface() { return _reticleInterface; }
diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp
index 090891fe62..119a46b68f 100644
--- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp
@@ -68,7 +68,6 @@ ShapeKey MaterialEntityRenderer::getShapeKey() {
bool isTranslucent = drawMaterialKey.isTranslucent();
bool hasTangents = drawMaterialKey.isNormalMap();
- bool hasSpecular = drawMaterialKey.isMetallicMap();
bool hasLightmap = drawMaterialKey.isLightmapMap();
bool isUnlit = drawMaterialKey.isUnlit();
@@ -81,9 +80,6 @@ ShapeKey MaterialEntityRenderer::getShapeKey() {
if (hasTangents) {
builder.withTangents();
}
- if (hasSpecular) {
- builder.withSpecular();
- }
if (hasLightmap) {
builder.withLightmap();
}
diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp
index da80924184..0ed328315b 100644
--- a/libraries/entities/src/EntityTree.cpp
+++ b/libraries/entities/src/EntityTree.cpp
@@ -1516,6 +1516,12 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
}
}
+ if (isAdd && properties.getLocked() && !senderNode->isAllowedEditor()) {
+ // if a node can't change locks, don't allow them to create an already-locked entity
+ properties.setLocked(false);
+ bumpTimestamp(properties);
+ }
+
// If we got a valid edit packet, then it could be a new entity or it could be an update to
// an existing entity... handle appropriately
if (validEditPacket) {
diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp
index c432e19368..7141a7eac7 100644
--- a/libraries/gpu/src/gpu/Batch.cpp
+++ b/libraries/gpu/src/gpu/Batch.cpp
@@ -14,9 +14,12 @@
#include
+#include "GPULogging.h"
+
#if defined(NSIGHT_FOUND)
#include "nvToolsExt.h"
+
ProfileRangeBatch::ProfileRangeBatch(gpu::Batch& batch, const char *name) : _batch(batch) {
_batch.pushProfileRange(name);
}
@@ -30,6 +33,11 @@ ProfileRangeBatch::~ProfileRangeBatch() {
using namespace gpu;
+// FIXME make these backend / pipeline dependent.
+static const int MAX_NUM_UNIFORM_BUFFERS = 12;
+static const int MAX_NUM_RESOURCE_BUFFERS = 16;
+static const int MAX_NUM_RESOURCE_TEXTURES = 16;
+
size_t Batch::_commandsMax { BATCH_PREALLOCATE_MIN };
size_t Batch::_commandOffsetsMax { BATCH_PREALLOCATE_MIN };
size_t Batch::_paramsMax { BATCH_PREALLOCATE_MIN };
@@ -281,7 +289,9 @@ void Batch::setStateScissorRect(const Vec4i& rect) {
void Batch::setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size) {
ADD_COMMAND(setUniformBuffer);
-
+ if (slot >= MAX_NUM_UNIFORM_BUFFERS) {
+ qCWarning(gpulogging) << "Slot" << slot << "exceeds max uniform buffer count of" << MAX_NUM_UNIFORM_BUFFERS;
+ }
_params.emplace_back(size);
_params.emplace_back(offset);
_params.emplace_back(_buffers.cache(buffer));
@@ -294,6 +304,9 @@ void Batch::setUniformBuffer(uint32 slot, const BufferView& view) {
void Batch::setResourceBuffer(uint32 slot, const BufferPointer& buffer) {
ADD_COMMAND(setResourceBuffer);
+ if (slot >= MAX_NUM_RESOURCE_BUFFERS) {
+ qCWarning(gpulogging) << "Slot" << slot << "exceeds max resources buffer count of" << MAX_NUM_RESOURCE_BUFFERS;
+ }
_params.emplace_back(_buffers.cache(buffer));
_params.emplace_back(slot);
@@ -302,6 +315,10 @@ void Batch::setResourceBuffer(uint32 slot, const BufferPointer& buffer) {
void Batch::setResourceTexture(uint32 slot, const TexturePointer& texture) {
ADD_COMMAND(setResourceTexture);
+ if (slot >= MAX_NUM_RESOURCE_TEXTURES) {
+ qCWarning(gpulogging) << "Slot" << slot << "exceeds max texture count of" << MAX_NUM_RESOURCE_TEXTURES;
+ }
+
_params.emplace_back(_textures.cache(texture));
_params.emplace_back(slot);
}
diff --git a/libraries/graphics/src/graphics/Light.slh b/libraries/graphics/src/graphics/Light.slh
index 12ac1f3c4b..20394816c9 100644
--- a/libraries/graphics/src/graphics/Light.slh
+++ b/libraries/graphics/src/graphics/Light.slh
@@ -32,9 +32,16 @@ vec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradi
// AMbient lighting needs extra info provided from a different Buffer
<@include graphics/SphericalHarmonics.shared.slh@>
// Light Ambient
-struct LightAmbient {
- vec4 _ambient;
+#ifndef PRECISIONQ
+#ifdef GL_ES
+#define PRECISIONQ highp
+#else
+#define PRECISIONQ
+#endif
+#endif
+struct LightAmbient {
+ PRECISIONQ vec4 _ambient;
SphericalHarmonics _ambientSphere;
mat4 transform;
};
diff --git a/libraries/graphics/src/graphics/LightIrradiance.shared.slh b/libraries/graphics/src/graphics/LightIrradiance.shared.slh
index 13d6cf4b93..ff42f57fd9 100644
--- a/libraries/graphics/src/graphics/LightIrradiance.shared.slh
+++ b/libraries/graphics/src/graphics/LightIrradiance.shared.slh
@@ -12,11 +12,17 @@
#define LightIrradianceConstRef LightIrradiance
-
+#ifndef PRECISIONQ
+#ifdef GL_ES
+#define PRECISIONQ highp
+#else
+#define PRECISIONQ
+#endif
+#endif
struct LightIrradiance {
- vec4 colorIntensity;
+ PRECISIONQ vec4 colorIntensity;
// falloffRadius, cutoffRadius, falloffSpot, spare
- vec4 attenuation;
+ PRECISIONQ vec4 attenuation;
};
diff --git a/libraries/graphics/src/graphics/LightVolume.shared.slh b/libraries/graphics/src/graphics/LightVolume.shared.slh
index 3f0cb135f5..48249e766f 100644
--- a/libraries/graphics/src/graphics/LightVolume.shared.slh
+++ b/libraries/graphics/src/graphics/LightVolume.shared.slh
@@ -15,9 +15,17 @@
#define LightVolumeConstRef LightVolume
+#ifndef PRECISIONQ
+#ifdef GL_ES
+#define PRECISIONQ highp
+#else
+#define PRECISIONQ
+#endif
+#endif
+
struct LightVolume {
- vec4 positionRadius;
- vec4 directionSpotCos;
+ PRECISIONQ vec4 positionRadius;
+ PRECISIONQ vec4 directionSpotCos;
};
bool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); }
diff --git a/libraries/graphics/src/graphics/Material.slh b/libraries/graphics/src/graphics/Material.slh
index 2faf2d8569..f9f4144748 100644
--- a/libraries/graphics/src/graphics/Material.slh
+++ b/libraries/graphics/src/graphics/Material.slh
@@ -11,11 +11,21 @@
<@if not MODEL_MATERIAL_SLH@>
<@def MODEL_MATERIAL_SLH@>
-struct Material {
- vec4 _emissiveOpacity;
- vec4 _albedoRoughness;
- vec4 _fresnelMetallic;
- vec4 _scatteringSpare2Key;
+// The material values (at least the material key) must be precisely bitwise accurate
+// to what is provided by the uniform buffer, or the material key has the wrong bits
+#ifdef GL_ES
+precision highp float;
+#define BITFIELD highp int
+#define PRECISIONQ highp
+#else
+#define BITFIELD int
+#define PRECISIONQ
+#endif
+struct Material {
+ PRECISIONQ vec4 _emissiveOpacity;
+ PRECISIONQ vec4 _albedoRoughness;
+ PRECISIONQ vec4 _fresnelMetallic;
+ PRECISIONQ vec4 _scatteringSpare2Key;
};
uniform materialBuffer {
@@ -39,27 +49,29 @@ float getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); }
float getMaterialScattering(Material m) { return m._scatteringSpare2Key.x; }
-int getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }
+BITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._scatteringSpare2Key.w); }
-const int EMISSIVE_VAL_BIT = 0x00000001;
-const int UNLIT_VAL_BIT = 0x00000002;
-const int ALBEDO_VAL_BIT = 0x00000004;
-const int METALLIC_VAL_BIT = 0x00000008;
-const int GLOSSY_VAL_BIT = 0x00000010;
-const int OPACITY_VAL_BIT = 0x00000020;
-const int OPACITY_MASK_MAP_BIT = 0x00000040;
-const int OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;
-const int SCATTERING_VAL_BIT = 0x00000100;
+const BITFIELD EMISSIVE_VAL_BIT = 0x00000001;
+const BITFIELD UNLIT_VAL_BIT = 0x00000002;
+const BITFIELD ALBEDO_VAL_BIT = 0x00000004;
+const BITFIELD METALLIC_VAL_BIT = 0x00000008;
+const BITFIELD GLOSSY_VAL_BIT = 0x00000010;
+const BITFIELD OPACITY_VAL_BIT = 0x00000020;
+const BITFIELD OPACITY_MASK_MAP_BIT = 0x00000040;
+const BITFIELD OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080;
+const BITFIELD SCATTERING_VAL_BIT = 0x00000100;
-const int EMISSIVE_MAP_BIT = 0x00000200;
-const int ALBEDO_MAP_BIT = 0x00000400;
-const int METALLIC_MAP_BIT = 0x00000800;
-const int ROUGHNESS_MAP_BIT = 0x00001000;
-const int NORMAL_MAP_BIT = 0x00002000;
-const int OCCLUSION_MAP_BIT = 0x00004000;
-const int LIGHTMAP_MAP_BIT = 0x00008000;
-const int SCATTERING_MAP_BIT = 0x00010000;
-
+const BITFIELD EMISSIVE_MAP_BIT = 0x00000200;
+const BITFIELD ALBEDO_MAP_BIT = 0x00000400;
+const BITFIELD METALLIC_MAP_BIT = 0x00000800;
+const BITFIELD ROUGHNESS_MAP_BIT = 0x00001000;
+const BITFIELD NORMAL_MAP_BIT = 0x00002000;
+const BITFIELD OCCLUSION_MAP_BIT = 0x00004000;
+const BITFIELD LIGHTMAP_MAP_BIT = 0x00008000;
+const BITFIELD SCATTERING_MAP_BIT = 0x00010000;
+#ifdef GL_ES
+precision lowp float;
+#endif
<@endif@>
diff --git a/libraries/graphics/src/graphics/SphericalHarmonics.shared.slh b/libraries/graphics/src/graphics/SphericalHarmonics.shared.slh
index 312824c5a3..72a505fa25 100644
--- a/libraries/graphics/src/graphics/SphericalHarmonics.shared.slh
+++ b/libraries/graphics/src/graphics/SphericalHarmonics.shared.slh
@@ -15,16 +15,24 @@
#define SphericalHarmonicsConstRef SphericalHarmonics
+#ifndef PRECISIONQ
+#ifdef GL_ES
+#define PRECISIONQ highp
+#else
+#define PRECISIONQ
+#endif
+#endif
+
struct SphericalHarmonics {
- vec4 L00;
- vec4 L1m1;
- vec4 L10;
- vec4 L11;
- vec4 L2m2;
- vec4 L2m1;
- vec4 L20;
- vec4 L21;
- vec4 L22;
+ PRECISIONQ vec4 L00;
+ PRECISIONQ vec4 L1m1;
+ PRECISIONQ vec4 L10;
+ PRECISIONQ vec4 L11;
+ PRECISIONQ vec4 L2m2;
+ PRECISIONQ vec4 L2m1;
+ PRECISIONQ vec4 L20;
+ PRECISIONQ vec4 L21;
+ PRECISIONQ vec4 L22;
};
vec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) {
diff --git a/libraries/image/CMakeLists.txt b/libraries/image/CMakeLists.txt
index e6a1856327..8073cc2b5e 100644
--- a/libraries/image/CMakeLists.txt
+++ b/libraries/image/CMakeLists.txt
@@ -1,12 +1,4 @@
set(TARGET_NAME image)
setup_hifi_library()
link_hifi_libraries(shared gpu)
-
-if (NOT ANDROID)
- add_dependency_external_projects(nvtt)
- find_package(NVTT REQUIRED)
-
- target_include_directories(${TARGET_NAME} PRIVATE ${NVTT_INCLUDE_DIRS})
- target_link_libraries(${TARGET_NAME} ${NVTT_LIBRARIES})
- add_paths_to_fixup_libs(${NVTT_DLL_PATH})
-endif()
+target_nvtt()
diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp
index 9115dd09e2..696e311495 100644
--- a/libraries/image/src/image/Image.cpp
+++ b/libraries/image/src/image/Image.cpp
@@ -28,12 +28,8 @@
using namespace gpu;
-#if defined(Q_OS_ANDROID)
-#define CPU_MIPMAPS 1
-#else
#define CPU_MIPMAPS 1
#include
-#endif
static const glm::uvec2 SPARSE_PAGE_SIZE(128);
static const glm::uvec2 MAX_TEXTURE_SIZE(4096);
@@ -679,7 +675,6 @@ void generateLDRMips(gpu::Texture* texture, QImage&& image, const std::atomic& abortProcessing = false, int face = -1) {
#if CPU_MIPMAPS
-#if !defined(Q_OS_ANDROID)
PROFILE_RANGE(resource_parse, "generateMips");
if (image.format() == QIMAGE_HDR_FORMAT) {
@@ -687,16 +682,6 @@ void generateMips(gpu::Texture* texture, QImage&& image, const std::atomic
} else {
generateLDRMips(texture, std::move(image), abortProcessing, face);
}
-
-#else
- //texture->setAutoGenerateMips(false);
- texture->assignStoredMip(0, image.byteCount(), image.constBits());
- for (uint16 level = 1; level < texture->getNumMips(); ++level) {
- QSize mipSize(texture->evalMipWidth(level), texture->evalMipHeight(level));
- QImage mipImage = image.scaled(mipSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
- texture->assignStoredMip(level, mipImage.byteCount(), mipImage.constBits());
- }
-#endif
#else
texture->setAutoGenerateMips(true);
#endif
@@ -737,15 +722,9 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(QImage&& srcIma
bool validAlpha = image.hasAlphaChannel();
bool alphaAsMask = false;
-#if !defined(Q_OS_ANDROID)
if (image.format() != QImage::Format_ARGB32) {
image = image.convertToFormat(QImage::Format_ARGB32);
}
-#else
- if (image.format() != QImage::Format_RGBA8888) {
- image = image.convertToFormat(QImage::Format_RGBA8888);
- }
-#endif
if (validAlpha) {
processTextureAlpha(image, validAlpha, alphaAsMask);
@@ -766,7 +745,12 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(QImage&& srcIma
}
formatMip = formatGPU;
} else {
+#ifdef USE_GLES
+ // GLES does not support GL_BGRA
+ formatMip = gpu::Element::COLOR_SRGBA_32;
+#else
formatMip = gpu::Element::COLOR_SBGRA_32;
+#endif
formatGPU = gpu::Element::COLOR_SRGBA_32;
}
diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt
index b0ea13843b..b1fcc4076a 100644
--- a/libraries/input-plugins/CMakeLists.txt
+++ b/libraries/input-plugins/CMakeLists.txt
@@ -1,5 +1,5 @@
set(TARGET_NAME input-plugins)
setup_hifi_library()
-link_hifi_libraries(shared plugins ui-plugins controllers)
+link_hifi_libraries(shared plugins ui-plugins controllers ui)
GroupSources("src/input-plugins")
diff --git a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp
index acd7a20327..96f1daba8c 100644
--- a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp
+++ b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp
@@ -14,12 +14,16 @@
#include "KeyboardMouseDevice.h"
#include "TouchscreenDevice.h"
+#include "TouchscreenVirtualPadDevice.h"
// TODO migrate to a DLL model where plugins are discovered and loaded at runtime by the PluginManager class
InputPluginList getInputPlugins() {
InputPlugin* PLUGIN_POOL[] = {
new KeyboardMouseDevice(),
new TouchscreenDevice(),
+#if defined(Q_OS_ANDROID)
+ new TouchscreenVirtualPadDevice(),
+#endif
nullptr
};
diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp
new file mode 100644
index 0000000000..8e1e6c2fba
--- /dev/null
+++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp
@@ -0,0 +1,247 @@
+//
+// TouchscreenVirtualPadDevice.cpp
+// input-plugins/src/input-plugins
+//
+// Created by Triplelexx on 01/31/16.
+// Copyright 2016 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 "TouchscreenVirtualPadDevice.h"
+#include "KeyboardMouseDevice.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include "VirtualPadManager.h"
+
+const char* TouchscreenVirtualPadDevice::NAME = "TouchscreenVirtualPad";
+
+bool TouchscreenVirtualPadDevice::isSupported() const {
+ for (auto touchDevice : QTouchDevice::devices()) {
+ if (touchDevice->type() == QTouchDevice::TouchScreen) {
+ return true;
+ }
+ }
+#if defined(Q_OS_ANDROID)
+ // last chance, assume that if this is android, a touchscreen is indeed supported
+ return true;
+#endif
+ return false;
+}
+
+float clip(float n, float lower, float upper) {
+ return std::max(lower, std::min(n, upper));
+}
+
+void TouchscreenVirtualPadDevice::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
+ auto userInputMapper = DependencyManager::get();
+ userInputMapper->withLock([&, this]() {
+ _inputDevice->update(deltaTime, inputCalibrationData);
+ });
+
+ auto& virtualPadManager = VirtualPad::Manager::instance();
+ if (_validTouchLeft) {
+ float leftDistanceScaleX, leftDistanceScaleY;
+ leftDistanceScaleX = (_currentTouchLeftPoint.x - _firstTouchLeftPoint.x) / _screenDPIScale.x;
+ leftDistanceScaleY = (_currentTouchLeftPoint.y - _firstTouchLeftPoint.y) / _screenDPIScale.y;
+
+ leftDistanceScaleX = clip(leftDistanceScaleX, -STICK_RADIUS_INCHES, STICK_RADIUS_INCHES);
+ leftDistanceScaleY = clip(leftDistanceScaleY, -STICK_RADIUS_INCHES, STICK_RADIUS_INCHES);
+
+ // NOW BETWEEN -1 1
+ leftDistanceScaleX /= STICK_RADIUS_INCHES;
+ leftDistanceScaleY /= STICK_RADIUS_INCHES;
+
+ _inputDevice->_axisStateMap[controller::LX] = leftDistanceScaleX;
+ _inputDevice->_axisStateMap[controller::LY] = leftDistanceScaleY;
+
+ /* Shared variables for stick rendering (clipped to the stick radius)*/
+ // Prevent this for being done when not in first person view
+ virtualPadManager.getLeftVirtualPad()->setBeingTouched(true);
+ virtualPadManager.getLeftVirtualPad()->setFirstTouch(_firstTouchLeftPoint);
+ virtualPadManager.getLeftVirtualPad()->setCurrentTouch(
+ glm::vec2(clip(_currentTouchLeftPoint.x, -STICK_RADIUS_INCHES * _screenDPIScale.x + _firstTouchLeftPoint.x, STICK_RADIUS_INCHES * _screenDPIScale.x + _firstTouchLeftPoint.x),
+ clip(_currentTouchLeftPoint.y, -STICK_RADIUS_INCHES * _screenDPIScale.y + _firstTouchLeftPoint.y, STICK_RADIUS_INCHES * _screenDPIScale.y + _firstTouchLeftPoint.y))
+ );
+ } else {
+ virtualPadManager.getLeftVirtualPad()->setBeingTouched(false);
+ }
+
+ if (_validTouchRight) {
+ float rightDistanceScaleX, rightDistanceScaleY;
+ rightDistanceScaleX = (_currentTouchRightPoint.x - _firstTouchRightPoint.x) / _screenDPIScale.x;
+ rightDistanceScaleY = (_currentTouchRightPoint.y - _firstTouchRightPoint.y) / _screenDPIScale.y;
+
+ rightDistanceScaleX = clip(rightDistanceScaleX, -STICK_RADIUS_INCHES, STICK_RADIUS_INCHES);
+ rightDistanceScaleY = clip(rightDistanceScaleY, -STICK_RADIUS_INCHES, STICK_RADIUS_INCHES);
+
+ // NOW BETWEEN -1 1
+ rightDistanceScaleX /= STICK_RADIUS_INCHES;
+ rightDistanceScaleY /= STICK_RADIUS_INCHES;
+
+ _inputDevice->_axisStateMap[controller::RX] = rightDistanceScaleX;
+ _inputDevice->_axisStateMap[controller::RY] = rightDistanceScaleY;
+ }
+
+}
+
+void TouchscreenVirtualPadDevice::InputDevice::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
+ _axisStateMap.clear();
+}
+
+void TouchscreenVirtualPadDevice::InputDevice::focusOutEvent() {
+}
+
+void TouchscreenVirtualPadDevice::debugPoints(const QTouchEvent* event, QString who) {
+ // convert the touch points into an average
+ const QList& tPoints = event->touchPoints();
+ QVector points;
+ int touchPoints = tPoints.count();
+ for (int i = 0; i < touchPoints; ++i) {
+ glm::vec2 thisPoint(tPoints[i].pos().x(), tPoints[i].pos().y());
+ points << thisPoint;
+ }
+ QScreen* eventScreen = event->window()->screen();
+ int midScreenX = eventScreen->size().width()/2;
+ int lefties = 0;
+ int righties = 0;
+ vec2 currentPoint;
+ for (int i = 0; i < points.length(); i++) {
+ currentPoint = points.at(i);
+ if (currentPoint.x < midScreenX) {
+ lefties++;
+ } else {
+ righties++;
+ }
+ }
+}
+
+void TouchscreenVirtualPadDevice::touchBeginEvent(const QTouchEvent* event) {
+ // touch begin here is a big begin -> begins both pads? maybe it does nothing
+ debugPoints(event, " BEGIN ++++++++++++++++");
+ KeyboardMouseDevice::enableTouch(false);
+ QScreen* eventScreen = event->window()->screen();
+ _screenWidthCenter = eventScreen->size().width() / 2;
+ if (_screenDPI != eventScreen->physicalDotsPerInch()) {
+ _screenDPIScale.x = (float)eventScreen->physicalDotsPerInchX();
+ _screenDPIScale.y = (float)eventScreen->physicalDotsPerInchY();
+ _screenDPI = eventScreen->physicalDotsPerInch();
+ }
+}
+
+void TouchscreenVirtualPadDevice::touchEndEvent(const QTouchEvent* event) {
+ // touch end here is a big reset -> resets both pads
+ _touchPointCount = 0;
+ KeyboardMouseDevice::enableTouch(true);
+ debugPoints(event, " END ----------------");
+ touchLeftEnd();
+ touchRightEnd();
+ _inputDevice->_axisStateMap.clear();
+}
+
+void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) {
+ _touchPointCount = event->touchPoints().count();
+
+ const QList& tPoints = event->touchPoints();
+ bool leftTouchFound = false;
+ bool rightTouchFound = false;
+ for (int i = 0; i < _touchPointCount; ++i) {
+ glm::vec2 thisPoint(tPoints[i].pos().x(), tPoints[i].pos().y());
+ if (thisPoint.x < _screenWidthCenter) {
+ if (!leftTouchFound) {
+ leftTouchFound = true;
+ if (!_validTouchLeft) {
+ touchLeftBegin(thisPoint);
+ } else {
+ touchLeftUpdate(thisPoint);
+ }
+ }
+ } else {
+ if (!rightTouchFound) {
+ rightTouchFound = true;
+ if (!_validTouchRight) {
+ touchRightBegin(thisPoint);
+ } else {
+ touchRightUpdate(thisPoint);
+ }
+ }
+ }
+ }
+ if (!leftTouchFound) {
+ touchLeftEnd();
+ }
+ if (!rightTouchFound) {
+ touchRightEnd();
+ }
+}
+
+void TouchscreenVirtualPadDevice::touchLeftBegin(glm::vec2 touchPoint) {
+ auto& virtualPadManager = VirtualPad::Manager::instance();
+ if (virtualPadManager.isEnabled()) {
+ _firstTouchLeftPoint = touchPoint;
+ _validTouchLeft = true;
+ }
+}
+
+void TouchscreenVirtualPadDevice::touchLeftUpdate(glm::vec2 touchPoint) {
+ _currentTouchLeftPoint = touchPoint;
+}
+
+void TouchscreenVirtualPadDevice::touchLeftEnd() {
+ if (_validTouchLeft) { // do stuff once
+ _validTouchLeft = false;
+ _inputDevice->_axisStateMap[controller::LX] = 0;
+ _inputDevice->_axisStateMap[controller::LY] = 0;
+ }
+}
+
+void TouchscreenVirtualPadDevice::touchRightBegin(glm::vec2 touchPoint) {
+ auto& virtualPadManager = VirtualPad::Manager::instance();
+ if (virtualPadManager.isEnabled()) {
+ _firstTouchRightPoint = touchPoint;
+ _validTouchRight = true;
+ }
+}
+
+void TouchscreenVirtualPadDevice::touchRightUpdate(glm::vec2 touchPoint) {
+ _currentTouchRightPoint = touchPoint;
+}
+
+void TouchscreenVirtualPadDevice::touchRightEnd() {
+ if (_validTouchRight) { // do stuff once
+ _validTouchRight = false;
+ _inputDevice->_axisStateMap[controller::RX] = 0;
+ _inputDevice->_axisStateMap[controller::RY] = 0;
+ }
+}
+
+void TouchscreenVirtualPadDevice::touchGestureEvent(const QGestureEvent* event) {
+ if (QGesture* gesture = event->gesture(Qt::PinchGesture)) {
+ QPinchGesture* pinch = static_cast(gesture);
+ _pinchScale = pinch->totalScaleFactor();
+ }
+}
+
+controller::Input::NamedVector TouchscreenVirtualPadDevice::InputDevice::getAvailableInputs() const {
+ using namespace controller;
+ QVector availableInputs{
+ makePair(LX, "LX"),
+ makePair(LY, "LY"),
+ makePair(RX, "RX"),
+ makePair(RY, "RY")
+ };
+ return availableInputs;
+}
+
+QString TouchscreenVirtualPadDevice::InputDevice::getDefaultMappingConfig() const {
+ static const QString MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/touchscreenvirtualpad.json";
+ return MAPPING_JSON;
+}
diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h
new file mode 100644
index 0000000000..fd74009ee8
--- /dev/null
+++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h
@@ -0,0 +1,89 @@
+//
+// TouchscreenVirtualPadDevice.h
+// input-plugins/src/input-plugins
+//
+// Created by Triplelexx on 1/31/16.
+// Copyright 2016 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_TouchscreenVirtualPadDevice_h
+#define hifi_TouchscreenVirtualPadDevice_h
+
+#include
+#include "InputPlugin.h"
+#include
+
+class QTouchEvent;
+class QGestureEvent;
+
+const float STICK_RADIUS_INCHES = .3f;
+
+class TouchscreenVirtualPadDevice : public InputPlugin {
+Q_OBJECT
+public:
+
+ // Plugin functions
+ virtual bool isSupported() const override;
+ virtual const QString getName() const override { return NAME; }
+
+ bool isHandController() const override { return false; }
+
+ virtual void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); }
+ virtual void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override;
+
+ void touchBeginEvent(const QTouchEvent* event);
+ void touchEndEvent(const QTouchEvent* event);
+ void touchUpdateEvent(const QTouchEvent* event);
+ void touchGestureEvent(const QGestureEvent* event);
+
+ static const char* NAME;
+
+protected:
+
+ class InputDevice : public controller::InputDevice {
+ public:
+ InputDevice() : controller::InputDevice("TouchscreenVirtualPad") {}
+ private:
+ // Device functions
+ virtual controller::Input::NamedVector getAvailableInputs() const override;
+ virtual QString getDefaultMappingConfig() const override;
+ virtual void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override;
+ virtual void focusOutEvent() override;
+
+ friend class TouchscreenVirtualPadDevice;
+ };
+
+public:
+ const std::shared_ptr& getInputDevice() const { return _inputDevice; }
+
+protected:
+ qreal _lastPinchScale;
+ qreal _pinchScale;
+ qreal _screenDPI;
+ glm::vec2 _screenDPIScale;
+ bool _validTouchLeft;
+ glm::vec2 _firstTouchLeftPoint;
+ glm::vec2 _currentTouchLeftPoint;
+ bool _validTouchRight;
+ glm::vec2 _firstTouchRightPoint;
+ glm::vec2 _currentTouchRightPoint;
+ int _touchPointCount;
+ int _screenWidthCenter;
+ std::shared_ptr _inputDevice { std::make_shared() };
+
+ void touchLeftBegin(glm::vec2 touchPoint);
+ void touchLeftUpdate(glm::vec2 touchPoint);
+ void touchLeftEnd();
+ void touchRightBegin(glm::vec2 touchPoint);
+ void touchRightUpdate(glm::vec2 touchPoint);
+ void touchRightEnd();
+// just for debug
+private:
+ void debugPoints(const QTouchEvent* event, QString who);
+
+};
+
+#endif // hifi_TouchscreenVirtualPadDevice_h
diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp
index 3a29139ee7..912a44cb97 100644
--- a/libraries/model-networking/src/model-networking/TextureCache.cpp
+++ b/libraries/model-networking/src/model-networking/TextureCache.cpp
@@ -37,7 +37,7 @@
#include
#include
-
+#include
#include
#include
@@ -50,10 +50,12 @@ Q_LOGGING_CATEGORY(trace_resource_parse_image, "trace.resource.parse.image")
Q_LOGGING_CATEGORY(trace_resource_parse_image_raw, "trace.resource.parse.image.raw")
Q_LOGGING_CATEGORY(trace_resource_parse_image_ktx, "trace.resource.parse.image.ktx")
-#if !defined(DISABLE_KTX_CACHE)
-const std::string TextureCache::KTX_DIRNAME { "ktx_cache" };
-const std::string TextureCache::KTX_EXT { "ktx" };
+#if defined(USE_GLES)
+const std::string TextureCache::KTX_DIRNAME { "ktx_cache_gles" };
+#else
+const std::string TextureCache::KTX_DIRNAME{ "ktx_cache" };
#endif
+const std::string TextureCache::KTX_EXT { "ktx" };
static const QString RESOURCE_SCHEME = "resource";
static const QUrl SPECTATOR_CAMERA_FRAME_URL("resource://spectatorCameraFrame");
@@ -63,8 +65,9 @@ static const float SKYBOX_LOAD_PRIORITY { 10.0f }; // Make sure skybox loads fir
static const float HIGH_MIPS_LOAD_PRIORITY { 9.0f }; // Make sure high mips loads after skybox but before models
TextureCache::TextureCache() {
-#if !defined(DISABLE_KTX_CACHE)
_ktxCache->initialize();
+#if defined(DISABLE_KTX_CACHE)
+ _ktxCache->wipe();
#endif
setUnusedResourceCacheSize(0);
setObjectName("TextureCache");
@@ -296,6 +299,10 @@ _maxNumPixels(100)
_loaded = true;
}
+static bool isLocalUrl(const QUrl& url) {
+ auto scheme = url.scheme();
+ return (scheme == URL_SCHEME_FILE || scheme == URL_SCHEME_QRC || scheme == RESOURCE_SCHEME);
+}
NetworkTexture::NetworkTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels) :
Resource(url),
@@ -389,6 +396,21 @@ void NetworkTexture::makeRequest() {
return;
}
+ if (isLocalUrl(_url)) {
+ auto self = _self;
+ QtConcurrent::run(QThreadPool::globalInstance(), [self] {
+ auto resource = self.lock();
+ if (!resource) {
+ return;
+ }
+
+ NetworkTexture* networkTexture = static_cast(resource.data());
+ networkTexture->makeLocalRequest();
+ });
+ return;
+ }
+
+
// We special-handle ktx requests to run 2 concurrent requests right off the bat
PROFILE_ASYNC_BEGIN(resource, "Resource:" + getType(), QString::number(_requestID), { { "url", _url.toString() }, { "activeURL", _activeUrl.toString() } });
@@ -437,6 +459,74 @@ void NetworkTexture::makeRequest() {
}
+void NetworkTexture::makeLocalRequest() {
+ const QString scheme = _url.scheme();
+ QString path;
+ if (scheme == URL_SCHEME_FILE) {
+ path = _url.toLocalFile();
+ } else {
+ path = ":" + _url.path();
+ }
+
+ path = FileUtils::selectFile(path);
+
+ auto storage = std::make_shared(path);
+ std::unique_ptr ktxFile;
+ if (storage) {
+ ktxFile = ktx::KTX::create(storage);
+ }
+ std::shared_ptr ktxDescriptor;
+ if (ktxFile) {
+ ktxDescriptor = std::make_shared(ktxFile->toDescriptor());
+ }
+
+ gpu::TexturePointer texture;
+ if (ktxDescriptor) {
+ std::string hash;
+ // Create bare ktx in memory
+ auto found = std::find_if(ktxDescriptor->keyValues.begin(), ktxDescriptor->keyValues.end(), [](const ktx::KeyValue& val) -> bool {
+ return val._key.compare(gpu::SOURCE_HASH_KEY) == 0;
+ });
+
+ if (found == ktxDescriptor->keyValues.end() || found->_value.size() != gpu::SOURCE_HASH_BYTES) {
+ hash = _url.toString().toLocal8Bit().toHex().toStdString();
+ } else {
+ // at this point the source hash is in binary 16-byte form
+ // and we need it in a hexadecimal string
+ auto binaryHash = QByteArray(reinterpret_cast(found->_value.data()), gpu::SOURCE_HASH_BYTES);
+ hash = binaryHash.toHex().toStdString();
+ }
+
+ auto textureCache = DependencyManager::get();
+ texture = textureCache->getTextureByHash(hash);
+ if (!texture) {
+ texture = gpu::Texture::build(*ktxDescriptor);
+ if (texture) {
+ texture->setKtxBacking(path.toStdString());
+ texture->setSource(path.toStdString());
+ texture = textureCache->cacheTextureByHash(hash, texture);
+ }
+ }
+ }
+
+ if (!texture) {
+ qCDebug(networking).noquote() << "Failed load local KTX from" << path;
+ QMetaObject::invokeMethod(this, "setImage",
+ Q_ARG(gpu::TexturePointer, nullptr),
+ Q_ARG(int, 0),
+ Q_ARG(int, 0));
+ return;
+ }
+
+ _ktxResourceState = PENDING_MIP_REQUEST;
+ _lowestKnownPopulatedMip = texture->minAvailableMipLevel();
+ QMetaObject::invokeMethod(this, "setImage",
+ Q_ARG(gpu::TexturePointer, texture),
+ Q_ARG(int, texture->getWidth()),
+ Q_ARG(int, texture->getHeight()));
+
+}
+
bool NetworkTexture::handleFailedRequest(ResourceRequest::Result result) {
if (!_sourceIsKTX && result == ResourceRequest::Result::RedirectFail) {
auto newPath = _request->getRelativePathUrl();
@@ -752,7 +842,6 @@ void NetworkTexture::handleFinishedInitialLoad() {
gpu::TexturePointer texture = textureCache->getTextureByHash(hash);
-#if !defined(DISABLE_KTX_CACHE)
if (!texture) {
auto ktxFile = textureCache->_ktxCache->getFile(hash);
if (ktxFile) {
@@ -765,9 +854,8 @@ void NetworkTexture::handleFinishedInitialLoad() {
}
}
}
-#endif
- if (!texture) {
+ if (!texture) {
auto memKtx = ktx::KTX::createBare(*header, keyValues);
if (!memKtx) {
qWarning() << " Ktx could not be created, bailing";
@@ -780,7 +868,6 @@ void NetworkTexture::handleFinishedInitialLoad() {
// Move ktx to file
const char* data = reinterpret_cast(memKtx->_storage->data());
-#if !defined(DISABLE_KTX_CACHE)
size_t length = memKtx->_storage->size();
cache::FilePointer file;
auto& ktxCache = textureCache->_ktxCache;
@@ -792,14 +879,11 @@ void NetworkTexture::handleFinishedInitialLoad() {
Q_ARG(int, 0));
return;
}
-#endif
auto newKtxDescriptor = memKtx->toDescriptor();
texture = gpu::Texture::build(newKtxDescriptor);
-#if !defined(DISABLE_KTX_CACHE)
texture->setKtxBacking(file);
-#endif
texture->setSource(filename);
auto& images = originalKtxDescriptor->images;
@@ -942,7 +1026,6 @@ void ImageReader::read() {
// If we already have a live texture with the same hash, use it
auto texture = textureCache->getTextureByHash(hash);
-#if !defined(DISABLE_KTX_CACHE)
// If there is no live texture, check if there's an existing KTX file
if (!texture) {
auto ktxFile = textureCache->_ktxCache->getFile(hash);
@@ -955,7 +1038,6 @@ void ImageReader::read() {
}
}
}
-#endif
// If we found the texture either because it's in use or via KTX deserialization,
// set the image and return immediately.
@@ -991,7 +1073,6 @@ void ImageReader::read() {
// Save the image into a KTXFile
if (texture && textureCache) {
-#if !defined(DISABLE_KTX_CACHE)
auto memKtx = gpu::Texture::serialize(*texture);
// Move the texture into a memory mapped file
@@ -1008,7 +1089,7 @@ void ImageReader::read() {
} else {
qCWarning(modelnetworking) << "Unable to serialize texture to KTX " << _url;
}
-#endif
+
// We replace the texture with the one stored in the cache. This deals with the possible race condition of two different
// images with the same hash being loaded concurrently. Only one of them will make it into the cache by hash first and will
// be the winner
diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h
index ffa3150b43..71714f0c10 100644
--- a/libraries/model-networking/src/model-networking/TextureCache.h
+++ b/libraries/model-networking/src/model-networking/TextureCache.h
@@ -70,6 +70,7 @@ public slots:
protected:
void makeRequest() override;
+ void makeLocalRequest();
virtual bool isCacheable() const override { return _loaded; }
@@ -193,12 +194,11 @@ private:
TextureCache();
virtual ~TextureCache();
-#if !defined(DISABLE_KTX_CACHE)
static const std::string KTX_DIRNAME;
static const std::string KTX_EXT;
std::shared_ptr _ktxCache { std::make_shared(KTX_DIRNAME, KTX_EXT) };
-#endif
+
// Map from image hashes to texture weak pointers
std::unordered_map> _texturesByHashes;
std::mutex _texturesByHashesMutex;
diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp
index 9296f61ad3..a8eec66067 100644
--- a/libraries/networking/src/AddressManager.cpp
+++ b/libraries/networking/src/AddressManager.cpp
@@ -104,11 +104,17 @@ QUrl AddressManager::currentFacingShareableAddress() const {
}
void AddressManager::loadSettings(const QString& lookupString) {
+#if defined(USE_GLES) && defined(Q_OS_WIN)
+ handleUrl(QUrl("hifi://127.0.0.0"), LookupTrigger::StartupFromSettings);
+#elif defined(Q_OS_ANDROID)
+ handleUrl(QUrl("hifi://pikachu/167.11,0.745735,181.529/0,0.887027,0,-0.461717"), LookupTrigger::StartupFromSettings);
+#else
if (lookupString.isEmpty()) {
handleUrl(currentAddressHandle.get(), LookupTrigger::StartupFromSettings);
} else {
handleUrl(lookupString, LookupTrigger::StartupFromSettings);
}
+#endif
}
void AddressManager::goBack() {
diff --git a/libraries/networking/src/FileResourceRequest.cpp b/libraries/networking/src/FileResourceRequest.cpp
index b55f1839a0..7cbb401f7f 100644
--- a/libraries/networking/src/FileResourceRequest.cpp
+++ b/libraries/networking/src/FileResourceRequest.cpp
@@ -18,6 +18,7 @@
#include
#include
+#include "NetworkLogging.h"
#include "ResourceManager.h"
void FileResourceRequest::doSend() {
@@ -38,9 +39,15 @@ void FileResourceRequest::doSend() {
// Allow platform specific versions of files loaded out of a resource cache via file://
- QFileSelector fileSelector;
- fileSelector.setExtraSelectors(FileUtils::getFileSelectors());
- filename = fileSelector.select(filename);
+ {
+ QString originalFilename = filename;
+ QFileSelector fileSelector;
+ fileSelector.setExtraSelectors(FileUtils::getFileSelectors());
+ filename = fileSelector.select(filename);
+ if (filename != originalFilename) {
+ qCDebug(resourceLog) << "Using" << filename << "instead of" << originalFilename;
+ }
+ }
if (!_byteRange.isValid()) {
_result = ResourceRequest::InvalidByteRange;
diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp
index 52c56d1e7d..d8b72c8838 100644
--- a/libraries/procedural/src/procedural/Procedural.cpp
+++ b/libraries/procedural/src/procedural/Procedural.cpp
@@ -187,6 +187,10 @@ void Procedural::setProceduralData(const ProceduralData& proceduralData) {
}
bool Procedural::isReady() const {
+#if defined(USE_GLES)
+ return false;
+#endif
+
if (!_enabled) {
return false;
}
diff --git a/libraries/qml/src/qml/OffscreenSurface.cpp b/libraries/qml/src/qml/OffscreenSurface.cpp
index a84f3feb4d..56b2c13e95 100644
--- a/libraries/qml/src/qml/OffscreenSurface.cpp
+++ b/libraries/qml/src/qml/OffscreenSurface.cpp
@@ -154,17 +154,45 @@ bool OffscreenSurface::eventFilter(QObject* originalDestination, QEvent* event)
QPointF transformedPos = mapToVirtualScreen(mouseEvent->localPos());
QMouseEvent mappedEvent(mouseEvent->type(), transformedPos, mouseEvent->screenPos(), mouseEvent->button(),
mouseEvent->buttons(), mouseEvent->modifiers());
- if (event->type() == QEvent::MouseMove) {
- // TODO - this line necessary for the QML Tooltop to work (which is not currently being used), but it causes interface to crash on launch on a fresh install
- // need to investigate into why this crash is happening.
- //_qmlContext->setContextProperty("lastMousePosition", transformedPos);
- }
mappedEvent.ignore();
if (QCoreApplication::sendEvent(_sharedObject->getWindow(), &mappedEvent)) {
return mappedEvent.isAccepted();
}
break;
}
+
+#if defined(Q_OS_ANDROID)
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd: {
+ QTouchEvent *originalEvent = static_cast(event);
+ QTouchEvent fakeEvent(*originalEvent);
+ auto newTouchPoints = fakeEvent.touchPoints();
+ for (size_t i = 0; i < newTouchPoints.size(); ++i) {
+ const auto &originalPoint = originalEvent->touchPoints()[i];
+ auto &newPoint = newTouchPoints[i];
+ newPoint.setPos(originalPoint.pos());
+ }
+ fakeEvent.setTouchPoints(newTouchPoints);
+ if (QCoreApplication::sendEvent(_sharedObject->getWindow(), &fakeEvent)) {
+ qInfo() << __FUNCTION__ << "sent fake touch event:" << fakeEvent.type()
+ << "_quickWindow handled it... accepted:" << fakeEvent.isAccepted();
+ return false; //event->isAccepted();
+ }
+ break;
+ }
+ case QEvent::InputMethod:
+ case QEvent::InputMethodQuery: {
+ if (_sharedObject->getWindow() && _sharedObject->getWindow()->activeFocusItem()) {
+ event->ignore();
+ if (QCoreApplication::sendEvent(_sharedObject->getWindow()->activeFocusItem(), event)) {
+ return event->isAccepted();
+ }
+ return false;
+ }
+ break;
+ }
+#endif
default:
break;
}
diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp
index 5174126243..02ff234c01 100644
--- a/libraries/render-utils/src/AnimDebugDraw.cpp
+++ b/libraries/render-utils/src/AnimDebugDraw.cpp
@@ -7,15 +7,17 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
-#include
+#include "AnimDebugDraw.h"
#include
+#include
+
#include "AbstractViewStateInterface.h"
#include "RenderUtilsLogging.h"
-#include "GLMHelpers.h"
#include "DebugDraw.h"
-#include "AnimDebugDraw.h"
+#include "animdebugdraw_vert.h"
+#include "animdebugdraw_frag.h"
#include "animdebugdraw_vert.h"
#include "animdebugdraw_frag.h"
diff --git a/libraries/render-utils/src/AnimDebugDraw.h b/libraries/render-utils/src/AnimDebugDraw.h
index 20336ed6dd..03101c9f86 100644
--- a/libraries/render-utils/src/AnimDebugDraw.h
+++ b/libraries/render-utils/src/AnimDebugDraw.h
@@ -12,8 +12,9 @@
#include
-#include "render/Scene.h"
-#include "gpu/Pipeline.h"
+#include
+#include
+
#include "AnimNode.h"
#include "AnimSkeleton.h"
diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp
index c94fe717f1..c09aa99988 100644
--- a/libraries/render-utils/src/FadeEffect.cpp
+++ b/libraries/render-utils/src/FadeEffect.cpp
@@ -34,8 +34,12 @@ render::ShapePipeline::BatchSetter FadeEffect::getBatchSetter() const {
auto program = shapePipeline.pipeline->getProgram();
auto maskMapLocation = program->getTextures().findLocation("fadeMaskMap");
auto bufferLocation = program->getUniformBuffers().findLocation("fadeParametersBuffer");
- batch.setResourceTexture(maskMapLocation, _maskMap);
- batch.setUniformBuffer(bufferLocation, _configurations);
+ if (maskMapLocation != -1) {
+ batch.setResourceTexture(maskMapLocation, _maskMap);
+ }
+ if (bufferLocation != -1) {
+ batch.setUniformBuffer(bufferLocation, _configurations);
+ }
};
}
diff --git a/libraries/render-utils/src/ForwardBuffer.slh b/libraries/render-utils/src/ForwardBuffer.slh
deleted file mode 100644
index 4d1dc89aa4..0000000000
--- a/libraries/render-utils/src/ForwardBuffer.slh
+++ /dev/null
@@ -1,68 +0,0 @@
-
-<@if not FORWARD_BUFFER_SLH@>
-<@def FORWARD_BUFFER_SLH@>
-
-<@include gpu/PackedNormal.slh@>
-
-// Unpack the metallic-mode value
-const float FRAG_PACK_SHADED_NON_METALLIC = 0.0;
-const float FRAG_PACK_SHADED_METALLIC = 0.1;
-const float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC);
-
-const float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2;
-const float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3;
-const float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC);
-
-const float FRAG_PACK_SCATTERING_NON_METALLIC = 0.4;
-const float FRAG_PACK_SCATTERING_METALLIC = 0.5;
-const float FRAG_PACK_SCATTERING_RANGE_INV = 1.0 / (FRAG_PACK_SCATTERING_METALLIC - FRAG_PACK_SCATTERING_NON_METALLIC);
-
-const float FRAG_PACK_UNLIT = 0.6;
-
-const int FRAG_MODE_UNLIT = 0;
-const int FRAG_MODE_SHADED = 1;
-const int FRAG_MODE_LIGHTMAPPED = 2;
-const int FRAG_MODE_SCATTERING = 3;
-
-void unpackModeMetallic(float rawValue, out int mode, out float metallic) {
- if (rawValue <= FRAG_PACK_SHADED_METALLIC) {
- mode = FRAG_MODE_SHADED;
- metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0);
- } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) {
- mode = FRAG_MODE_LIGHTMAPPED;
- metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_LIGHTMAPPED_RANGE_INV, 0.0, 1.0);
- } else if (rawValue <= FRAG_PACK_SCATTERING_METALLIC) {
- mode = FRAG_MODE_SCATTERING;
- metallic = clamp((rawValue - FRAG_PACK_SCATTERING_NON_METALLIC) * FRAG_PACK_SCATTERING_RANGE_INV, 0.0, 1.0);
- } else if (rawValue >= FRAG_PACK_UNLIT) {
- mode = FRAG_MODE_UNLIT;
- metallic = 0.0;
- }
-}
-
-float packShadedMetallic(float metallic) {
- return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic);
-}
-
-float packLightmappedMetallic(float metallic) {
- return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic);
-}
-
-float packScatteringMetallic(float metallic) {
- return mix(FRAG_PACK_SCATTERING_NON_METALLIC, FRAG_PACK_SCATTERING_METALLIC, metallic);
-}
-
-float packUnlit() {
- return FRAG_PACK_UNLIT;
-}
-
-<@endif@>
diff --git a/libraries/render-utils/src/ForwardBufferWrite.slh b/libraries/render-utils/src/ForwardBufferWrite.slh
deleted file mode 100644
index 873514d51f..0000000000
--- a/libraries/render-utils/src/ForwardBufferWrite.slh
+++ /dev/null
@@ -1,63 +0,0 @@
-
-<@if not FORWARD_BUFFER_WRITE_SLH@>
-<@def FORWARD_BUFFER_WRITE_SLH@>
-
-<@include ForwardBuffer.slh@>
-
-
-layout(location = 0) out vec4 _fragColor0;
-
-// the alpha threshold
-const float alphaThreshold = 0.5;
-float evalOpaqueFinalAlpha(float alpha, float mapAlpha) {
- return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));
-}
-
-const float DEFAULT_ROUGHNESS = 0.9;
-const float DEFAULT_SHININESS = 10.0;
-const float DEFAULT_METALLIC = 0.0;
-const vec3 DEFAULT_SPECULAR = vec3(0.1);
-const vec3 DEFAULT_EMISSIVE = vec3(0.0);
-const float DEFAULT_OCCLUSION = 1.0;
-const float DEFAULT_SCATTERING = 0.0;
-const vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;
-
-void packForwardFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {
- if (alpha != 1.0) {
- discard;
- }
- _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic)));
-}
-
-void packForwardFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 lightmap) {
- if (alpha != 1.0) {
- discard;
- }
-
- _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic));
-}
-
-void packForwardFragmentUnlit(vec3 normal, float alpha, vec3 color) {
- if (alpha != 1.0) {
- discard;
- }
- _fragColor0 = vec4(color, packUnlit());
-}
-
-void packForwardFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) {
- if (alpha <= 0.0) {
- discard;
- }
- _fragColor0 = vec4(albedo.rgb, alpha);
-}
-
-<@endif@>
diff --git a/libraries/render-utils/src/ForwardGlobalLight.slh b/libraries/render-utils/src/ForwardGlobalLight.slh
index a55e2ea651..a945acb8c4 100644
--- a/libraries/render-utils/src/ForwardGlobalLight.slh
+++ b/libraries/render-utils/src/ForwardGlobalLight.slh
@@ -124,8 +124,6 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
color += ambientDiffuse;
color += ambientSpecular;
-
- // Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation
@@ -136,6 +134,12 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
color += directionalDiffuse;
color += directionalSpecular;
+ // FIXME - temporarily removed until we support it for forward...
+ // Attenuate the light if haze effect selected
+ // if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) {
+ // color = computeHazeColorKeyLightAttenuation(color, lightDirection, position);
+ // }
+
return color;
}
@@ -168,6 +172,7 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur
+<@include Haze.slh@>
<@func declareEvalGlobalLightingAlphaBlended()@>
@@ -198,6 +203,47 @@ vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, fl
return color;
}
+vec3 evalGlobalLightingAlphaBlendedWithHaze(
+ mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,
+ vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity)
+{
+ <$prepareGlobalLight()$>
+
+ SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
+
+ color += emissive * isEmissiveEnabled();
+
+ // Ambient
+ vec3 ambientDiffuse;
+ vec3 ambientSpecular;
+ evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);
+ color += ambientDiffuse;
+ color += ambientSpecular / opacity;
+
+ // Directional
+ vec3 directionalDiffuse;
+ vec3 directionalSpecular;
+ evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);
+ color += directionalDiffuse;
+ color += directionalSpecular / opacity;
+
+ // Haze
+ // FIXME - temporarily removed until we support it for forward...
+ /* if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {
+ vec4 colorV4 = computeHazeColor(
+ vec4(color, 1.0), // fragment original color
+ position, // fragment position in eye coordinates
+ fragEyeVector, // fragment position in world coordinates
+ invViewMat[3].y, // eye height in world coordinates
+ lightDirection // keylight direction vector
+ );
+
+ color = colorV4.rgb;
+ }*/
+
+ return color;
+}
+
<@endfunc@>
diff --git a/libraries/render-utils/src/LightAmbient.slh b/libraries/render-utils/src/LightAmbient.slh
index 3f52760eff..008f29da01 100644
--- a/libraries/render-utils/src/LightAmbient.slh
+++ b/libraries/render-utils/src/LightAmbient.slh
@@ -12,9 +12,14 @@ uniform samplerCube skyboxMap;
vec4 evalSkyboxLight(vec3 direction, float lod) {
// textureQueryLevels is not available until #430, so we require explicit lod
+ // float mipmapLevel = lod * textureQueryLevels(skyboxMap);
+
+#if !defined(GL_ES)
float filterLod = textureQueryLod(skyboxMap, direction).x;
// Keep texture filtering LOD as limit to prevent aliasing on specular reflection
lod = max(lod, filterLod);
+#endif
+
return textureLod(skyboxMap, direction, lod);
}
<@endfunc@>
diff --git a/libraries/render-utils/src/LightingModel.slh b/libraries/render-utils/src/LightingModel.slh
index ddcbf8229c..2280d12465 100644
--- a/libraries/render-utils/src/LightingModel.slh
+++ b/libraries/render-utils/src/LightingModel.slh
@@ -311,4 +311,14 @@ void evalFragShadingGloss(out vec3 diffuse, out vec3 specular,
specular = shading.xyz;
}
+
+<@if not GETFRESNEL0@>
+<@def GETFRESNEL0@>
+vec3 getFresnelF0(float metallic, vec3 metalF0) {
+ // Enable continuous metallness value by lerping between dielectric
+ // and metal fresnel F0 value based on the "metallic" parameter
+ return mix(vec3(0.03), metalF0, metallic);
+}
+<@endif@>
+
<@endif@>
diff --git a/libraries/render-utils/src/MaterialTextures.slh b/libraries/render-utils/src/MaterialTextures.slh
index 40709b3668..b3662385b0 100644
--- a/libraries/render-utils/src/MaterialTextures.slh
+++ b/libraries/render-utils/src/MaterialTextures.slh
@@ -154,7 +154,7 @@ vec3 fetchLightmapMap(vec2 uv) {
vec3 normalizedTangent = normalize(<$interpolatedTangent$>.xyz);
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
vec3 localNormal = <$fetchedNormal$>;
- <$normal$> = vec3(normalizedTangent * localNormal.x + normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z);
+ <$normal$> = vec3(normalizedTangent * localNormal.x + normalizedNormal * localNormal.y + normalizedBitangent * localNormal.z);
}
<@endfunc@>
diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp
index 2637d24d67..5231b3e4d0 100644
--- a/libraries/render-utils/src/MeshPartPayload.cpp
+++ b/libraries/render-utils/src/MeshPartPayload.cpp
@@ -128,9 +128,6 @@ ShapeKey MeshPartPayload::getShapeKey() const {
if (drawMaterialKey.isNormalMap()) {
builder.withTangents();
}
- if (drawMaterialKey.isMetallicMap()) {
- builder.withSpecular();
- }
if (drawMaterialKey.isLightmapMap()) {
builder.withLightmap();
}
@@ -387,14 +384,13 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, bool isWireframe
bool isTranslucent = drawMaterialKey.isTranslucent();
bool hasTangents = drawMaterialKey.isNormalMap() && _hasTangents;
- bool hasSpecular = drawMaterialKey.isMetallicMap();
bool hasLightmap = drawMaterialKey.isLightmapMap();
bool isUnlit = drawMaterialKey.isUnlit();
bool isSkinned = _isSkinned;
if (isWireframe) {
- isTranslucent = hasTangents = hasSpecular = hasLightmap = isSkinned = false;
+ isTranslucent = hasTangents = hasLightmap = isSkinned = false;
}
ShapeKey::Builder builder;
@@ -406,9 +402,6 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, bool isWireframe
if (hasTangents) {
builder.withTangents();
}
- if (hasSpecular) {
- builder.withSpecular();
- }
if (hasLightmap) {
builder.withLightmap();
}
diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp
index c201e8a106..4829e5c85b 100755
--- a/libraries/render-utils/src/RenderForwardTask.cpp
+++ b/libraries/render-utils/src/RenderForwardTask.cpp
@@ -19,9 +19,12 @@
#include
#include
+#include
+
#include "StencilMaskPass.h"
#include "ZoneRenderer.h"
#include "FadeEffect.h"
+#include "ToneMappingEffect.h"
#include "BackgroundStage.h"
#include "FramebufferCache.h"
#include "TextureCache.h"
@@ -56,6 +59,7 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend
fadeEffect->build(task, opaques);
// Prepare objects shared by several jobs
+ const auto deferredFrameTransform = task.addJob("DeferredFrameTransform");
const auto lightingModel = task.addJob("LightingModel");
// Filter zones from the general metas bucket
@@ -87,15 +91,23 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend
task.addJob("DrawTransparentBounds", transparents);
task.addJob("DrawZones", zones);
+ task.addJob("DrawZoneStack", deferredFrameTransform);
+
}
- // Layered Overlays
+ // Lighting Buffer ready for tone mapping
+ // Forward rendering on GLES doesn't support tonemapping to and from the same FBO, so we specify
+ // the output FBO as null, which causes the tonemapping to target the blit framebuffer
+ const auto toneMappingInputs = ToneMappingDeferred::Inputs(framebuffer, nullptr).asVarying();
+ task.addJob("ToneMapping", toneMappingInputs);
+ // Layered Overlays
// Composite the HUD and HUD overlays
task.addJob("HUD");
+ // Disable blit because we do tonemapping and compositing directly to the blit FBO
// Blit!
- task.addJob("Blit", framebuffer);
+ // task.addJob("Blit", framebuffer);
}
void PrepareFramebuffer::run(const RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer) {
@@ -130,40 +142,12 @@ void PrepareFramebuffer::run(const RenderContextPointer& renderContext, gpu::Fra
batch.setFramebuffer(_framebuffer);
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH |
gpu::Framebuffer::BUFFER_STENCIL,
- vec4(vec3(0, 1.0, 0.0), 0), 1.0, 0, true);
+ vec4(vec3(0), 0), 1.0, 0, true);
});
framebuffer = _framebuffer;
}
-enum ForwardShader_MapSlot {
- DEFERRED_BUFFER_COLOR_UNIT = 0,
- DEFERRED_BUFFER_NORMAL_UNIT = 1,
- DEFERRED_BUFFER_EMISSIVE_UNIT = 2,
- DEFERRED_BUFFER_DEPTH_UNIT = 3,
- DEFERRED_BUFFER_OBSCURANCE_UNIT = 4,
- SHADOW_MAP_UNIT = 5,
- SKYBOX_MAP_UNIT = SHADOW_MAP_UNIT + 4,
- DEFERRED_BUFFER_LINEAR_DEPTH_UNIT,
- DEFERRED_BUFFER_CURVATURE_UNIT,
- DEFERRED_BUFFER_DIFFUSED_CURVATURE_UNIT,
- SCATTERING_LUT_UNIT,
- SCATTERING_SPECULAR_UNIT,
-};
-enum ForwardShader_BufferSlot {
- DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT = 0,
- CAMERA_CORRECTION_BUFFER_SLOT,
- SCATTERING_PARAMETERS_BUFFER_SLOT,
- LIGHTING_MODEL_BUFFER_SLOT = render::ShapePipeline::Slot::LIGHTING_MODEL,
- LIGHT_GPU_SLOT = render::ShapePipeline::Slot::LIGHT,
- LIGHT_AMBIENT_SLOT = render::ShapePipeline::Slot::LIGHT_AMBIENT_BUFFER,
- HAZE_MODEL_BUFFER_SLOT = render::ShapePipeline::Slot::HAZE_MODEL,
- LIGHT_INDEX_GPU_SLOT,
- LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT,
- LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT,
- LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT,
-};
-
void PrepareForward::run(const RenderContextPointer& renderContext, const Inputs& inputs) {
RenderArgs* args = renderContext->args;
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
@@ -181,18 +165,14 @@ void PrepareForward::run(const RenderContextPointer& renderContext, const Inputs
}
if (keySunLight) {
- if (LIGHT_GPU_SLOT >= 0) {
- batch.setUniformBuffer(LIGHT_GPU_SLOT, keySunLight->getLightSchemaBuffer());
- }
+ batch.setUniformBuffer(render::ShapePipeline::Slot::KEY_LIGHT, keySunLight->getLightSchemaBuffer());
}
if (keyAmbiLight) {
- if (LIGHT_AMBIENT_SLOT >= 0) {
- batch.setUniformBuffer(LIGHT_AMBIENT_SLOT, keyAmbiLight->getAmbientSchemaBuffer());
- }
+ batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHT_AMBIENT_BUFFER, keyAmbiLight->getAmbientSchemaBuffer());
- if (keyAmbiLight->getAmbientMap() && (SKYBOX_MAP_UNIT >= 0)) {
- batch.setResourceTexture(SKYBOX_MAP_UNIT, keyAmbiLight->getAmbientMap());
+ if (keyAmbiLight->getAmbientMap()) {
+ batch.setResourceTexture(render::ShapePipeline::Slot::LIGHT_AMBIENT, keyAmbiLight->getAmbientMap());
}
}
});
diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp
index 3fedae1778..4cbc6ef3af 100644
--- a/libraries/render-utils/src/RenderPipelines.cpp
+++ b/libraries/render-utils/src/RenderPipelines.cpp
@@ -32,7 +32,6 @@
#include "model_lightmap_fade_vert.h"
#include "model_lightmap_normal_map_fade_vert.h"
#include "model_translucent_vert.h"
-#include "model_translucent_normal_map_vert.h"
#include "skin_model_fade_vert.h"
#include "skin_model_normal_map_fade_vert.h"
#include "skin_model_fade_dq_vert.h"
@@ -53,38 +52,26 @@
#include "model_frag.h"
#include "model_unlit_frag.h"
#include "model_normal_map_frag.h"
-#include "model_normal_specular_map_frag.h"
-#include "model_specular_map_frag.h"
-
#include "model_fade_vert.h"
#include "model_normal_map_fade_vert.h"
#include "model_fade_frag.h"
#include "model_unlit_fade_frag.h"
#include "model_normal_map_fade_frag.h"
-#include "model_normal_specular_map_fade_frag.h"
-#include "model_specular_map_fade_frag.h"
#include "forward_model_frag.h"
#include "forward_model_unlit_frag.h"
#include "forward_model_normal_map_frag.h"
-#include "forward_model_normal_specular_map_frag.h"
-#include "forward_model_specular_map_frag.h"
+#include "forward_model_translucent_frag.h"
#include "model_lightmap_frag.h"
#include "model_lightmap_normal_map_frag.h"
-#include "model_lightmap_normal_specular_map_frag.h"
-#include "model_lightmap_specular_map_frag.h"
#include "model_translucent_frag.h"
#include "model_translucent_unlit_frag.h"
-#include "model_translucent_normal_map_frag.h"
#include "model_lightmap_fade_frag.h"
#include "model_lightmap_normal_map_fade_frag.h"
-#include "model_lightmap_normal_specular_map_fade_frag.h"
-#include "model_lightmap_specular_map_fade_frag.h"
#include "model_translucent_fade_frag.h"
-#include "model_translucent_normal_map_fade_frag.h"
#include "model_translucent_unlit_fade_frag.h"
#include "overlay3D_vert.h"
@@ -124,6 +111,7 @@ void addPlumberPipeline(ShapePlumber& plumber,
void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args);
void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args);
+static bool forceLightBatchSetter{ false };
void initOverlay3DPipelines(ShapePlumber& plumber, bool depthTest) {
auto vertex = overlay3D_vert::getShader();
@@ -198,7 +186,6 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
auto modelLightmapVertex = model_lightmap_vert::getShader();
auto modelLightmapNormalMapVertex = model_lightmap_normal_map_vert::getShader();
auto modelTranslucentVertex = model_translucent_vert::getShader();
- auto modelTranslucentNormalMapVertex = model_translucent_normal_map_vert::getShader();
auto modelShadowVertex = model_shadow_vert::getShader();
auto modelLightmapFadeVertex = model_lightmap_fade_vert::getShader();
@@ -236,29 +223,19 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
auto modelPixel = model_frag::getShader();
auto modelUnlitPixel = model_unlit_frag::getShader();
auto modelNormalMapPixel = model_normal_map_frag::getShader();
- auto modelSpecularMapPixel = model_specular_map_frag::getShader();
- auto modelNormalSpecularMapPixel = model_normal_specular_map_frag::getShader();
auto modelTranslucentPixel = model_translucent_frag::getShader();
- auto modelTranslucentNormalMapPixel = model_translucent_normal_map_frag::getShader();
auto modelTranslucentUnlitPixel = model_translucent_unlit_frag::getShader();
auto modelShadowPixel = model_shadow_frag::getShader();
auto modelLightmapPixel = model_lightmap_frag::getShader();
auto modelLightmapNormalMapPixel = model_lightmap_normal_map_frag::getShader();
- auto modelLightmapSpecularMapPixel = model_lightmap_specular_map_frag::getShader();
- auto modelLightmapNormalSpecularMapPixel = model_lightmap_normal_specular_map_frag::getShader();
auto modelLightmapFadePixel = model_lightmap_fade_frag::getShader();
auto modelLightmapNormalMapFadePixel = model_lightmap_normal_map_fade_frag::getShader();
- auto modelLightmapSpecularMapFadePixel = model_lightmap_specular_map_fade_frag::getShader();
- auto modelLightmapNormalSpecularMapFadePixel = model_lightmap_normal_specular_map_fade_frag::getShader();
auto modelFadePixel = model_fade_frag::getShader();
auto modelUnlitFadePixel = model_unlit_fade_frag::getShader();
auto modelNormalMapFadePixel = model_normal_map_fade_frag::getShader();
- auto modelSpecularMapFadePixel = model_specular_map_fade_frag::getShader();
- auto modelNormalSpecularMapFadePixel = model_normal_specular_map_fade_frag::getShader();
auto modelShadowFadePixel = model_shadow_fade_frag::getShader();
auto modelTranslucentFadePixel = model_translucent_fade_frag::getShader();
- auto modelTranslucentNormalMapFadePixel = model_translucent_normal_map_fade_frag::getShader();
auto modelTranslucentUnlitFadePixel = model_translucent_unlit_fade_frag::getShader();
auto simpleFadePixel = simple_textured_fade_frag::getShader();
auto simpleUnlitFadePixel = simple_textured_unlit_fade_frag::getShader();
@@ -284,12 +261,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
addPipeline(
Key::Builder().withMaterial().withTangents(),
modelNormalMapVertex, modelNormalMapPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withSpecular(),
- modelVertex, modelSpecularMapPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withTangents().withSpecular(),
- modelNormalMapVertex, modelNormalSpecularMapPixel, nullptr, nullptr);
+
// Same thing but with Fade on
addPipeline(
Key::Builder().withMaterial().withFade(),
@@ -306,12 +278,6 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
addPipeline(
Key::Builder().withMaterial().withTangents().withFade(),
modelNormalMapFadeVertex, modelNormalMapFadePixel, batchSetter, itemSetter);
- addPipeline(
- Key::Builder().withMaterial().withSpecular().withFade(),
- modelFadeVertex, modelSpecularMapFadePixel, batchSetter, itemSetter);
- addPipeline(
- Key::Builder().withMaterial().withTangents().withSpecular().withFade(),
- modelNormalMapFadeVertex, modelNormalSpecularMapFadePixel, batchSetter, itemSetter);
// Translucents
addPipeline(
@@ -328,13 +294,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
simpleVertex, simpleTranslucentUnlitPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withTranslucent().withTangents(),
- modelTranslucentNormalMapVertex, modelTranslucentNormalMapPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withTranslucent().withSpecular(),
modelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular(),
- modelTranslucentNormalMapVertex, modelTranslucentNormalMapPixel, nullptr, nullptr);
addPipeline(
// FIXME: Ignore lightmap for translucents meshpart
Key::Builder().withMaterial().withTranslucent().withLightmap(),
@@ -354,13 +314,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
simpleFadeVertex, simpleTranslucentUnlitFadePixel, batchSetter, itemSetter);
addPipeline(
Key::Builder().withMaterial().withTranslucent().withTangents().withFade(),
- modelTranslucentNormalMapVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter);
- addPipeline(
- Key::Builder().withMaterial().withTranslucent().withSpecular().withFade(),
- modelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter);
- addPipeline(
- Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular().withFade(),
- modelTranslucentNormalMapVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter);
+ modelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter);
addPipeline(
// FIXME: Ignore lightmap for translucents meshpart
Key::Builder().withMaterial().withTranslucent().withLightmap().withFade(),
@@ -373,12 +327,6 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
addPipeline(
Key::Builder().withMaterial().withLightmap().withTangents(),
modelLightmapNormalMapVertex, modelLightmapNormalMapPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withLightmap().withSpecular(),
- modelLightmapVertex, modelLightmapSpecularMapPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withLightmap().withTangents().withSpecular(),
- modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel, nullptr, nullptr);
// Same thing but with Fade on
addPipeline(
Key::Builder().withMaterial().withLightmap().withFade(),
@@ -386,12 +334,6 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
addPipeline(
Key::Builder().withMaterial().withLightmap().withTangents().withFade(),
modelLightmapNormalMapFadeVertex, modelLightmapNormalMapFadePixel, batchSetter, itemSetter);
- addPipeline(
- Key::Builder().withMaterial().withLightmap().withSpecular().withFade(),
- modelLightmapFadeVertex, modelLightmapSpecularMapFadePixel, batchSetter, itemSetter);
- addPipeline(
- Key::Builder().withMaterial().withLightmap().withTangents().withSpecular().withFade(),
- modelLightmapNormalMapFadeVertex, modelLightmapNormalSpecularMapFadePixel, batchSetter, itemSetter);
// matrix palette skinned
addPipeline(
@@ -400,12 +342,6 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
addPipeline(
Key::Builder().withMaterial().withSkinned().withTangents(),
skinModelNormalMapVertex, modelNormalMapPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withSpecular(),
- skinModelVertex, modelSpecularMapPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withTangents().withSpecular(),
- skinModelNormalMapVertex, modelNormalSpecularMapPixel, nullptr, nullptr);
// Same thing but with Fade on
addPipeline(
Key::Builder().withMaterial().withSkinned().withFade(),
@@ -413,12 +349,6 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
addPipeline(
Key::Builder().withMaterial().withSkinned().withTangents().withFade(),
skinModelNormalMapFadeVertex, modelNormalMapFadePixel, batchSetter, itemSetter);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withSpecular().withFade(),
- skinModelFadeVertex, modelSpecularMapFadePixel, batchSetter, itemSetter);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withTangents().withSpecular().withFade(),
- skinModelNormalMapFadeVertex, modelNormalSpecularMapFadePixel, batchSetter, itemSetter);
// matrix palette skinned and translucent
addPipeline(
@@ -426,26 +356,14 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
skinModelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(),
- skinModelNormalMapTranslucentVertex, modelTranslucentNormalMapPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular(),
- skinModelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular(),
- skinModelNormalMapTranslucentVertex, modelTranslucentNormalMapPixel, nullptr, nullptr);
+ skinModelNormalMapTranslucentVertex, modelTranslucentPixel, nullptr, nullptr);
// Same thing but with Fade on
addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent().withFade(),
skinModelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter);
addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withFade(),
- skinModelNormalMapFadeVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular().withFade(),
- skinModelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular().withFade(),
- skinModelNormalMapFadeVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter);
+ skinModelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter);
// dual quaternion skinned
addPipeline(
@@ -454,12 +372,6 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
addPipeline(
Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTangents(),
skinModelNormalMapDualQuatVertex, modelNormalMapPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withSpecular(),
- skinModelDualQuatVertex, modelSpecularMapPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTangents().withSpecular(),
- skinModelNormalMapDualQuatVertex, modelNormalSpecularMapPixel, nullptr, nullptr);
// Same thing but with Fade on
addPipeline(
Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withFade(),
@@ -467,12 +379,6 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
addPipeline(
Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTangents().withFade(),
skinModelNormalMapFadeDualQuatVertex, modelNormalMapFadePixel, batchSetter, itemSetter);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withSpecular().withFade(),
- skinModelFadeDualQuatVertex, modelSpecularMapFadePixel, batchSetter, itemSetter);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTangents().withSpecular().withFade(),
- skinModelNormalMapFadeDualQuatVertex, modelNormalSpecularMapFadePixel, batchSetter, itemSetter);
// dual quaternion skinned and translucent
addPipeline(
@@ -480,26 +386,14 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
skinModelTranslucentDualQuatVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline(
Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withTangents(),
- skinModelNormalMapTranslucentDualQuatVertex, modelTranslucentNormalMapPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withSpecular(),
- skinModelTranslucentDualQuatVertex, modelTranslucentPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withTangents().withSpecular(),
- skinModelNormalMapTranslucentDualQuatVertex, modelTranslucentNormalMapPixel, nullptr, nullptr);
+ skinModelNormalMapTranslucentDualQuatVertex, modelTranslucentPixel, nullptr, nullptr);
// Same thing but with Fade on
addPipeline(
Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withFade(),
skinModelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter);
addPipeline(
Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withTangents().withFade(),
- skinModelNormalMapFadeDualQuatVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withSpecular().withFade(),
- skinModelFadeDualQuatVertex, modelTranslucentFadePixel, batchSetter, itemSetter);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withTangents().withSpecular().withFade(),
- skinModelNormalMapFadeDualQuatVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter);
+ skinModelNormalMapFadeDualQuatVertex, modelTranslucentFadePixel, batchSetter, itemSetter);
// Depth-only
addPipeline(
@@ -523,51 +417,44 @@ void initForwardPipelines(ShapePlumber& plumber, const render::ShapePipeline::Ba
auto modelNormalMapVertex = model_normal_map_vert::getShader();
auto skinModelVertex = skin_model_vert::getShader();
auto skinModelNormalMapVertex = skin_model_normal_map_vert::getShader();
- auto skinModelNormalMapFadeVertex = skin_model_normal_map_fade_vert::getShader();
// Pixel shaders
auto modelPixel = forward_model_frag::getShader();
auto modelUnlitPixel = forward_model_unlit_frag::getShader();
auto modelNormalMapPixel = forward_model_normal_map_frag::getShader();
- auto modelSpecularMapPixel = forward_model_specular_map_frag::getShader();
- auto modelNormalSpecularMapPixel = forward_model_normal_specular_map_frag::getShader();
- auto modelNormalMapFadePixel = model_normal_map_fade_frag::getShader();
+ auto modelTranslucentPixel = forward_model_translucent_frag::getShader();
using Key = render::ShapeKey;
- auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3, _4, _5);
- // Opaques
- addPipeline(
- Key::Builder().withMaterial(),
- modelVertex, modelPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withUnlit(),
- modelVertex, modelUnlitPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withTangents(),
- modelNormalMapVertex, modelNormalMapPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withSpecular(),
- modelVertex, modelSpecularMapPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withTangents().withSpecular(),
- modelNormalMapVertex, modelNormalSpecularMapPixel, nullptr, nullptr);
- // Skinned
- addPipeline(
- Key::Builder().withMaterial().withSkinned(),
- skinModelVertex, modelPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withTangents(),
- skinModelNormalMapVertex, modelNormalMapPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withSpecular(),
- skinModelVertex, modelSpecularMapPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withTangents().withSpecular(),
- skinModelNormalMapVertex, modelNormalSpecularMapPixel, nullptr, nullptr);
- addPipeline(
- Key::Builder().withMaterial().withSkinned().withTangents().withFade(),
- skinModelNormalMapFadeVertex, modelNormalMapFadePixel, batchSetter, itemSetter, nullptr, nullptr);
+ auto addPipelineBind = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3, _4, _5);
+ // Disable fade on the forward pipeline, all shaders get added twice, once with the fade key and once without
+ auto addPipeline = [&](const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel) {
+ addPipelineBind(key, vertex, pixel, nullptr, nullptr);
+ addPipelineBind(Key::Builder(key).withFade(), vertex, pixel, nullptr, nullptr);
+ };
+
+ // Forward pipelines need the lightBatchSetter for opaques and transparents
+ // forceLightBatchSetter = true;
+ forceLightBatchSetter = false;
+
+ // Opaques
+ addPipeline(Key::Builder().withMaterial(), modelVertex, modelPixel);
+ addPipeline(Key::Builder().withMaterial().withUnlit(), modelVertex, modelUnlitPixel);
+ addPipeline(Key::Builder().withMaterial().withTangents(), modelNormalMapVertex, modelNormalMapPixel);
+
+ // Skinned Opaques
+ addPipeline(Key::Builder().withMaterial().withSkinned(), skinModelVertex, modelPixel);
+ addPipeline(Key::Builder().withMaterial().withSkinned().withTangents(), skinModelNormalMapVertex, modelNormalMapPixel);
+
+ // Translucents
+ addPipeline(Key::Builder().withMaterial().withTranslucent(), modelVertex, modelTranslucentPixel);
+ addPipeline(Key::Builder().withMaterial().withTranslucent().withTangents(), modelNormalMapVertex, modelTranslucentPixel);
+
+ // Skinned Translucents
+ addPipeline(Key::Builder().withMaterial().withSkinned().withTranslucent(), skinModelVertex, modelTranslucentPixel);
+ addPipeline(Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(), skinModelNormalMapVertex, modelTranslucentPixel);
+
+ forceLightBatchSetter = false;
}
void addPlumberPipeline(ShapePlumber& plumber,
@@ -609,7 +496,7 @@ void addPlumberPipeline(ShapePlumber& plumber,
state->setDepthBiasSlopeScale(1.0f);
}
- auto baseBatchSetter = key.isTranslucent() ? &lightBatchSetter : &batchSetter;
+ auto baseBatchSetter = (forceLightBatchSetter || key.isTranslucent()) ? &lightBatchSetter : &batchSetter;
render::ShapePipeline::BatchSetter finalBatchSetter;
if (extraBatchSetter) {
finalBatchSetter = [baseBatchSetter, extraBatchSetter](const ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) {
diff --git a/libraries/render-utils/src/ToneMappingEffect.cpp b/libraries/render-utils/src/ToneMappingEffect.cpp
index e1abefd681..0cc5be5ff9 100644
--- a/libraries/render-utils/src/ToneMappingEffect.cpp
+++ b/libraries/render-utils/src/ToneMappingEffect.cpp
@@ -57,10 +57,16 @@ void ToneMappingEffect::setToneCurve(ToneCurve curve) {
}
}
-void ToneMappingEffect::render(RenderArgs* args, const gpu::TexturePointer& lightingBuffer, const gpu::FramebufferPointer& destinationFramebuffer) {
+void ToneMappingEffect::render(RenderArgs* args, const gpu::TexturePointer& lightingBuffer, const gpu::FramebufferPointer& requestedDestinationFramebuffer) {
if (!_blitLightBuffer) {
init();
}
+
+ auto destinationFramebuffer = requestedDestinationFramebuffer;
+ if (!destinationFramebuffer) {
+ destinationFramebuffer = args->_blitFramebuffer;
+ }
+
auto framebufferSize = glm::ivec2(lightingBuffer->getDimensions());
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
batch.enableStereo(false);
diff --git a/libraries/render-utils/src/ZoneRenderer.cpp b/libraries/render-utils/src/ZoneRenderer.cpp
index 1d358ff895..b6d0e61577 100644
--- a/libraries/render-utils/src/ZoneRenderer.cpp
+++ b/libraries/render-utils/src/ZoneRenderer.cpp
@@ -52,25 +52,25 @@ void ZoneRendererTask::build(JobModel& task, const Varying& input, Varying& oupu
}
void SetupZones::run(const RenderContextPointer& context, const Inputs& inputs) {
+ // Grab light, background and haze stages and clear them
+ auto lightStage = context->_scene->getStage();
+ assert(lightStage);
+ lightStage->_currentFrame.clear();
+
auto backgroundStage = context->_scene->getStage();
assert(backgroundStage);
backgroundStage->_currentFrame.clear();
- // Haze
auto hazeStage = context->_scene->getStage();
assert(hazeStage);
hazeStage->_currentFrame.clear();
- // call render in the correct order first...
+ // call render over the zones to grab their components in the correct order first...
render::renderItems(context, inputs);
// Finally add the default lights and background:
- auto lightStage = context->_scene->getStage();
- assert(lightStage);
-
lightStage->_currentFrame.pushSunLight(lightStage->getDefaultLight());
lightStage->_currentFrame.pushAmbientLight(lightStage->getDefaultLight());
-
backgroundStage->_currentFrame.pushBackground(0);
hazeStage->_currentFrame.pushHaze(0);
}
diff --git a/libraries/render-utils/src/forward_model.slf b/libraries/render-utils/src/forward_model.slf
index 65556e2939..9241503902 100644
--- a/libraries/render-utils/src/forward_model.slf
+++ b/libraries/render-utils/src/forward_model.slf
@@ -1,18 +1,16 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
+//
// forward_model.frag
// fragment shader
//
-// Created by Andrzej Kapolka on 10/14/13.
-// Copyright 2013 High Fidelity, Inc.
+// Created by Sam Gateau on 2/15/2016.
+// Copyright 2014 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 ForwardGlobalLight.slh@>
<$declareEvalSkyboxGlobalColor()$>
@@ -22,21 +20,21 @@
<$declareStandardCameraTransform()$>
<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, _SCRIBE_NULL)$>
+<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$>
in vec4 _position;
-in vec3 _normal;
-in vec3 _color;
in vec2 _texCoord0;
in vec2 _texCoord1;
+in vec3 _normal;
+in vec3 _color;
-out vec4 _fragColor;
+layout(location = 0) out vec4 _fragColor0;
void main(void) {
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$>
- !>
+ BITFIELD matKey = getMaterialKey(mat);
+ <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$>
+ <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
float opacity = 1.0;
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
@@ -46,41 +44,33 @@ void main(void) {
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
albedo *= _color;
- float metallic = getMaterialMetallic(mat);
- vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value
- if (metallic <= 0.5) {
- metallic = 0.0;
- } else {
- fresnel = albedo;
- metallic = 1.0;
- }
-
float roughness = getMaterialRoughness(mat);
<$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
+ float metallic = getMaterialMetallic(mat);
+ <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
+ vec3 fresnel = getFresnelF0(metallic, albedo);
vec3 fragPosition = _position.xyz;
+ vec3 fragNormal = normalize(_normal);
TransformCamera cam = getTransformCamera();
- vec3 fragNormal;
- <$transformEyeToWorldDir(cam, _normal, fragNormal)$>
vec4 color = vec4(evalSkyboxGlobalColor(
cam._viewInverse,
1.0,
- 1.0,
+ occlusionTex,
fragPosition,
fragNormal,
albedo,
fresnel,
metallic,
roughness),
- opacity);
- color.rgb += emissive * isEmissiveEnabled();
+ opacity);
+ color.rgb += emissive * isEmissiveEnabled();
-// _fragColor = vec4(albedo, opacity);
- _fragColor = color;
+ _fragColor0 = color;
}
diff --git a/libraries/render-utils/src/forward_model_normal_map.slf b/libraries/render-utils/src/forward_model_normal_map.slf
index d22cc667e1..b32ed862d6 100644
--- a/libraries/render-utils/src/forward_model_normal_map.slf
+++ b/libraries/render-utils/src/forward_model_normal_map.slf
@@ -5,15 +5,13 @@
// forward_model_normal_map.frag
// fragment shader
//
-// Created by Andrzej Kapolka on 10/29/13.
-// Copyright 2013 High Fidelity, Inc.
+// Created by Sam Gateau on 2/15/2016.
+// Copyright 2014 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 ForwardGlobalLight.slh@>
<$declareEvalSkyboxGlobalColor()$>
@@ -23,7 +21,7 @@
<$declareStandardCameraTransform()$>
<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, _SCRIBE_NULL, EMISSIVE, OCCLUSION, SCATTERING)$>
+<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$>
in vec4 _position;
in vec2 _texCoord0;
@@ -32,61 +30,51 @@ in vec3 _normal;
in vec3 _tangent;
in vec3 _color;
-out vec4 _fragColor;
+layout(location = 0) out vec4 _fragColor0;
void main(void) {
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex, scatteringTex)$>
+ BITFIELD matKey = getMaterialKey(mat);
+ <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex)$>
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
float opacity = 1.0;
- <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
+ <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>;
<$discardTransparent(opacity)$>;
vec3 albedo = getMaterialAlbedo(mat);
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
albedo *= _color;
- float metallic = getMaterialMetallic(mat);
- vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value
- if (metallic <= 0.5) {
- metallic = 0.0;
- } else {
- fresnel = albedo;
- metallic = 1.0;
- }
-
float roughness = getMaterialRoughness(mat);
<$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
- vec3 viewNormal;
- <$tangentToViewSpace(normalTex, _normal, _tangent, viewNormal)$>
-
- float scattering = getMaterialScattering(mat);
- <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>;
+ float metallic = getMaterialMetallic(mat);
+ <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
+ vec3 fresnel = getFresnelF0(metallic, albedo);
vec3 fragPosition = _position.xyz;
+ vec3 fragNormal;
+ <$tangentToViewSpace(normalTex, _normal, _tangent, fragNormal)$>
TransformCamera cam = getTransformCamera();
-
+
vec4 color = vec4(evalSkyboxGlobalColor(
cam._viewInverse,
1.0,
- 1.0,
+ occlusionTex,
fragPosition,
- viewNormal,
+ fragNormal,
albedo,
fresnel,
metallic,
roughness),
- opacity);
+ opacity);
color.rgb += emissive * isEmissiveEnabled();
-// _fragColor = vec4(albedo, opacity);
- _fragColor = color;
+ _fragColor0 = color;
}
diff --git a/libraries/render-utils/src/forward_model_normal_specular_map.slf b/libraries/render-utils/src/forward_model_normal_specular_map.slf
deleted file mode 100644
index 68e5b755f8..0000000000
--- a/libraries/render-utils/src/forward_model_normal_specular_map.slf
+++ /dev/null
@@ -1,91 +0,0 @@
-<@include gpu/Config.slh@>
-<$VERSION_HEADER$>
-// Generated on <$_SCRIBE_DATE$>
-//
-// forward_model_normal_specular_map.frag
-// fragment shader
-//
-// Created by Andrzej Kapolka on 5/6/14.
-// Copyright 2014 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 ForwardGlobalLight.slh@>
-<$declareEvalSkyboxGlobalColor()$>
-
-<@include graphics/Material.slh@>
-
-<@include gpu/Transform.slh@>
-<$declareStandardCameraTransform()$>
-
-<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$>
-
-in vec4 _position;
-in vec2 _texCoord0;
-in vec2 _texCoord1;
-in vec3 _normal;
-in vec3 _tangent;
-in vec3 _color;
-
-out vec4 _fragColor;
-
-void main(void) {
- Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex)$>
- <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
-
- float opacity = 1.0;
- <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>;
- <$discardTransparent(opacity)$>;
-
- vec3 albedo = getMaterialAlbedo(mat);
- <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
- albedo *= _color;
-
- float roughness = getMaterialRoughness(mat);
- <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
-
- vec3 emissive = getMaterialEmissive(mat);
- <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
-
- vec3 viewNormal;
- <$tangentToViewSpace(normalTex, _normal, _tangent, viewNormal)$>
-
- float metallic = getMaterialMetallic(mat);
- <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
- vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value
- if (metallic <= 0.5) {
- metallic = 0.0;
- }
- else {
- fresnel = albedo;
- metallic = 1.0;
- }
- vec3 fragPosition = _position.xyz;
-
- TransformCamera cam = getTransformCamera();
-
- vec4 color = vec4(evalSkyboxGlobalColor(
- cam._viewInverse,
- 1.0,
- 1.0,
- fragPosition,
- viewNormal,
- albedo,
- fresnel,
- metallic,
- roughness),
- opacity);
-
- color.rgb += emissive * isEmissiveEnabled();
-
- // _fragColor = vec4(albedo, opacity);
- _fragColor = color;
-}
diff --git a/libraries/render-utils/src/forward_model_specular_map.slf b/libraries/render-utils/src/forward_model_specular_map.slf
deleted file mode 100644
index 057ec2cf53..0000000000
--- a/libraries/render-utils/src/forward_model_specular_map.slf
+++ /dev/null
@@ -1,100 +0,0 @@
-<@include gpu/Config.slh@>
-<$VERSION_HEADER$>
-// Generated on <$_SCRIBE_DATE$>
-//
-// forward_model_specular_map.frag
-// fragment shader
-//
-// Created by Andrzej Kapolka on 5/6/14.
-// Copyright 2014 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 ForwardGlobalLight.slh@>
-<$declareEvalSkyboxGlobalColor()$>
-
-<@include graphics/Material.slh@>
-
-<@include gpu/Transform.slh@>
-<$declareStandardCameraTransform()$>
-
-<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$>
-
-in vec4 _position;
-in vec2 _texCoord0;
-in vec2 _texCoord1;
-in vec3 _normal;
-in vec3 _color;
-
-out vec4 _fragColor;
-
-void main(void) {
- Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$>
- !>
-
- float opacity = 1.0;
- <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
- <$discardTransparent(opacity)$>;
-
- vec3 albedo = getMaterialAlbedo(mat);
- <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
- albedo *= _color;
-
- float roughness = getMaterialRoughness(mat);
- <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
-
- vec3 emissive = getMaterialEmissive(mat);
- <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
-
- float metallic = getMaterialMetallic(mat);
- <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
- vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value
- if (metallic <= 0.5) {
- metallic = 0.0;
- }
- else {
- fresnel = albedo;
- metallic = 1.0;
- }/*
- float scattering = getMaterialScattering(mat);
-
- packForwardFragment(
- normalize(_normal),
- opacity,
- albedo,
- roughness,
- metallic,
- emissive,
- occlusionTex,
- scattering);
- */
- vec3 fragPosition = _position.xyz;
-
- TransformCamera cam = getTransformCamera();
- vec3 fragNormal;
- <$transformEyeToWorldDir(cam, _normal, fragNormal)$>
-
- vec4 color = vec4(evalSkyboxGlobalColor(
- cam._viewInverse,
- 1.0,
- 1.0,
- fragPosition,
- fragNormal,
- albedo,
- fresnel,
- metallic,
- roughness),
- opacity);
- color.rgb += emissive * isEmissiveEnabled();
-
- // _fragColor = vec4(albedo, opacity);
- _fragColor = color;
-}
diff --git a/libraries/render-utils/src/forward_model_translucent.slf b/libraries/render-utils/src/forward_model_translucent.slf
index 7f752d893a..2892a6bbf5 100644
--- a/libraries/render-utils/src/forward_model_translucent.slf
+++ b/libraries/render-utils/src/forward_model_translucent.slf
@@ -22,7 +22,7 @@
<$declareStandardCameraTransform()$>
<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$>
+<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$>
in vec2 _texCoord0;
in vec2 _texCoord1;
@@ -31,12 +31,12 @@ in vec3 _normal;
in vec3 _color;
in float _alpha;
-out vec4 _fragColor;
+layout(location = 0) out vec4 _fragColor0;
void main(void) {
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$>
+ BITFIELD matKey = getMaterialKey(mat);
+ <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$>
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
float opacity = getMaterialOpacity(mat) * _alpha;
@@ -50,13 +50,8 @@ void main(void) {
<$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
float metallic = getMaterialMetallic(mat);
- vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value
- if (metallic <= 0.5) {
- metallic = 0.0;
- } else {
- fresnel = albedo;
- metallic = 1.0;
- }
+ <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
+ vec3 fresnel = getFresnelF0(metallic, albedo);
vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
@@ -66,7 +61,7 @@ void main(void) {
TransformCamera cam = getTransformCamera();
- _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(
+ _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze(
cam._viewInverse,
1.0,
occlusionTex,
diff --git a/libraries/render-utils/src/forward_model_unlit.slf b/libraries/render-utils/src/forward_model_unlit.slf
index 72ee61e28c..fda001dba9 100644
--- a/libraries/render-utils/src/forward_model_unlit.slf
+++ b/libraries/render-utils/src/forward_model_unlit.slf
@@ -12,7 +12,6 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
-<@include ForwardBufferWrite.slh@>
<@include LightingModel.slh@>
<@include graphics/Material.slh@>
@@ -24,10 +23,12 @@ in vec3 _normal;
in vec3 _color;
in float _alpha;
+layout(location = 0) out vec4 _fragColor0;
+
void main(void) {
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
+ BITFIELD matKey = getMaterialKey(mat);
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$>
float opacity = 1.0;
@@ -38,8 +39,8 @@ void main(void) {
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
albedo *= _color;
- packForwardFragmentUnlit(
- normalize(_normal),
- opacity,
- albedo * isUnlitEnabled());
+ if (opacity != 1.0) {
+ discard;
+ }
+ _fragColor0 = vec4(albedo * isUnlitEnabled(), 1.0);
}
diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf
index 4747b69278..94929f4943 100644
--- a/libraries/render-utils/src/model.slf
+++ b/libraries/render-utils/src/model.slf
@@ -1,11 +1,12 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
-// model.frag
+//
+// model_specular_map.frag
// fragment shader
//
-// Created by Andrzej Kapolka on 10/14/13.
-// Copyright 2013 High Fidelity, Inc.
+// Created by Andrzej Kapolka on 5/6/14.
+// Copyright 2014 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
@@ -16,19 +17,19 @@
<@include graphics/Material.slh@>
<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$>
+<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION, SCATTERING)$>
in vec4 _position;
-in vec3 _normal;
-in vec3 _color;
in vec2 _texCoord0;
in vec2 _texCoord1;
+in vec3 _normal;
+in vec3 _color;
void main(void) {
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$>
+ BITFIELD matKey = getMaterialKey(mat);
+ <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex, scatteringTex)$>
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
float opacity = 1.0;
@@ -45,14 +46,18 @@ void main(void) {
vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
+ float metallic = getMaterialMetallic(mat);
+ <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
+
float scattering = getMaterialScattering(mat);
+ <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>;
packDeferredFragment(
- normalize(_normal.xyz),
+ normalize(_normal),
opacity,
albedo,
roughness,
- getMaterialMetallic(mat),
+ metallic,
emissive,
occlusionTex,
scattering);
diff --git a/libraries/render-utils/src/model_fade.slf b/libraries/render-utils/src/model_fade.slf
index 40c156a3a4..577324f97a 100644
--- a/libraries/render-utils/src/model_fade.slf
+++ b/libraries/render-utils/src/model_fade.slf
@@ -1,10 +1,11 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
+//
// model_fade.frag
// fragment shader
//
-// Created by Olivier Prat on 04/19/17.
+// Created by Olivier Prat on 06/05/17.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
@@ -16,18 +17,17 @@
<@include graphics/Material.slh@>
<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$>
+<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$>
<@include Fade.slh@>
<$declareFadeFragment()$>
in vec4 _position;
-in vec4 _worldPosition;
-in vec3 _normal;
-in vec3 _color;
in vec2 _texCoord0;
in vec2 _texCoord1;
-
+in vec3 _normal;
+in vec3 _color;
+in vec4 _worldPosition;
void main(void) {
vec3 fadeEmissive;
@@ -37,8 +37,8 @@ void main(void) {
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$>
+ BITFIELD matKey = getMaterialKey(mat);
+ <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$>
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
float opacity = 1.0;
@@ -54,17 +54,19 @@ void main(void) {
vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
- emissive += fadeEmissive;
+
+ float metallic = getMaterialMetallic(mat);
+ <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
float scattering = getMaterialScattering(mat);
packDeferredFragment(
- normalize(_normal.xyz),
+ normalize(_normal),
opacity,
albedo,
roughness,
- getMaterialMetallic(mat),
- emissive,
+ metallic,
+ emissive+fadeEmissive,
occlusionTex,
scattering);
}
diff --git a/libraries/render-utils/src/model_lightmap.slf b/libraries/render-utils/src/model_lightmap.slf
index b22a1029f9..33195fce00 100644
--- a/libraries/render-utils/src/model_lightmap.slf
+++ b/libraries/render-utils/src/model_lightmap.slf
@@ -2,11 +2,11 @@
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
-// model_lightmap.frag
+// model_lightmap_specular_map.frag
// fragment shader
//
// Created by Samuel Gateau on 11/19/14.
-// Copyright 2013 High Fidelity, Inc.
+// Copyright 2014 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
@@ -17,7 +17,7 @@
<@include graphics/Material.slh@>
<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS)$>
+<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$>
<$declareMaterialLightmap()$>
in vec4 _position;
@@ -28,17 +28,16 @@ in vec3 _color;
void main(void) {
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness)$>
+ BITFIELD matKey = getMaterialKey(mat);
+ <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, _SCRIBE_NULL, metallicTex)$>
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$>
-
packDeferredFragmentLightmap(
normalize(_normal),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
getMaterialAlbedo(mat) * albedo.rgb * _color,
getMaterialRoughness(mat) * roughness,
- getMaterialMetallic(mat),
- getMaterialFresnel(mat),
+ getMaterialMetallic(mat) * metallicTex,
+ /*metallicTex, // no use of */getMaterialFresnel(mat),
lightmapVal);
}
diff --git a/libraries/render-utils/src/model_lightmap_fade.slf b/libraries/render-utils/src/model_lightmap_fade.slf
index 55cb24d35d..1dfc6a1b9e 100644
--- a/libraries/render-utils/src/model_lightmap_fade.slf
+++ b/libraries/render-utils/src/model_lightmap_fade.slf
@@ -17,7 +17,7 @@
<@include graphics/Material.slh@>
<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS)$>
+<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$>
<$declareMaterialLightmap()$>
<@include Fade.slh@>
@@ -38,17 +38,16 @@ void main(void) {
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness)$>
+ BITFIELD matKey = getMaterialKey(mat);
+ <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, _SCRIBE_NULL, metallicTex)$>
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$>
-
packDeferredFragmentLightmap(
normalize(_normal),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
getMaterialAlbedo(mat) * albedo.rgb * _color,
getMaterialRoughness(mat) * roughness,
- getMaterialMetallic(mat),
- getMaterialFresnel(mat),
+ getMaterialMetallic(mat) * metallicTex,
+ /*metallicTex, // no use of */getMaterialFresnel(mat),
lightmapVal+fadeEmissive);
}
diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slf b/libraries/render-utils/src/model_lightmap_normal_map.slf
index 1510ea9ba3..8734ea74b8 100644
--- a/libraries/render-utils/src/model_lightmap_normal_map.slf
+++ b/libraries/render-utils/src/model_lightmap_normal_map.slf
@@ -6,7 +6,7 @@
// fragment shader
//
// Created by Samuel Gateau on 11/19/14.
-// Copyright 2013 High Fidelity, Inc.
+// Copyright 2014 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
@@ -17,7 +17,7 @@
<@include graphics/Material.slh@>
<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL)$>
+<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$>
<$declareMaterialLightmap()$>
in vec4 _position;
@@ -29,10 +29,10 @@ in vec3 _color;
void main(void) {
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel)$>
+ BITFIELD matKey = getMaterialKey(mat);
+ <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$>
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$>
-
+
vec3 viewNormal;
<$tangentToViewSpaceLOD(_position, normalTexel, _normal, _tangent, viewNormal)$>
@@ -40,8 +40,8 @@ void main(void) {
normalize(viewNormal.xyz),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
getMaterialAlbedo(mat) * albedo.rgb * _color,
- getMaterialRoughness(mat),
- getMaterialMetallic(mat),
- getMaterialFresnel(mat),
+ getMaterialRoughness(mat) * roughness,
+ getMaterialMetallic(mat) * metallicTex,
+ /*specular, // no use of */ getMaterialFresnel(mat),
lightmapVal);
}
diff --git a/libraries/render-utils/src/model_lightmap_normal_map_fade.slf b/libraries/render-utils/src/model_lightmap_normal_map_fade.slf
index 6b63943a9a..e6cb35ec4f 100644
--- a/libraries/render-utils/src/model_lightmap_normal_map_fade.slf
+++ b/libraries/render-utils/src/model_lightmap_normal_map_fade.slf
@@ -17,7 +17,7 @@
<@include graphics/Material.slh@>
<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL)$>
+<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$>
<$declareMaterialLightmap()$>
<@include Fade.slh@>
@@ -39,10 +39,10 @@ void main(void) {
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel)$>
+ BITFIELD matKey = getMaterialKey(mat);
+ <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$>
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$>
-
+
vec3 viewNormal;
<$tangentToViewSpaceLOD(_position, normalTexel, _normal, _tangent, viewNormal)$>
@@ -50,8 +50,8 @@ void main(void) {
normalize(viewNormal.xyz),
evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
getMaterialAlbedo(mat) * albedo.rgb * _color,
- getMaterialRoughness(mat),
- getMaterialMetallic(mat),
- getMaterialFresnel(mat),
+ getMaterialRoughness(mat) * roughness,
+ getMaterialMetallic(mat) * metallicTex,
+ /*specular, // no use of */ getMaterialFresnel(mat),
lightmapVal+fadeEmissive);
}
diff --git a/libraries/render-utils/src/model_lightmap_normal_specular_map.slf b/libraries/render-utils/src/model_lightmap_normal_specular_map.slf
deleted file mode 100644
index 3a66aaad3d..0000000000
--- a/libraries/render-utils/src/model_lightmap_normal_specular_map.slf
+++ /dev/null
@@ -1,47 +0,0 @@
-<@include gpu/Config.slh@>
-<$VERSION_HEADER$>
-// Generated on <$_SCRIBE_DATE$>
-//
-// model_lightmap_normal_specular_map.frag
-// fragment shader
-//
-// Created by Samuel Gateau on 11/19/14.
-// Copyright 2014 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 DeferredBufferWrite.slh@>
-
-<@include graphics/Material.slh@>
-
-<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$>
-<$declareMaterialLightmap()$>
-
-in vec4 _position;
-in vec2 _texCoord0;
-in vec2 _texCoord1;
-in vec3 _normal;
-in vec3 _tangent;
-in vec3 _color;
-
-void main(void) {
- Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$>
- <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$>
-
- vec3 viewNormal;
- <$tangentToViewSpaceLOD(_position, normalTexel, _normal, _tangent, viewNormal)$>
-
- packDeferredFragmentLightmap(
- normalize(viewNormal.xyz),
- evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
- getMaterialAlbedo(mat) * albedo.rgb * _color,
- getMaterialRoughness(mat) * roughness,
- getMaterialMetallic(mat) * metallicTex,
- /*specular, // no use of */ getMaterialFresnel(mat),
- lightmapVal);
-}
diff --git a/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf b/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf
deleted file mode 100644
index b785a8a6ab..0000000000
--- a/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf
+++ /dev/null
@@ -1,57 +0,0 @@
-<@include gpu/Config.slh@>
-<$VERSION_HEADER$>
-// Generated on <$_SCRIBE_DATE$>
-//
-// model_lightmap_normal_specular_map_fade.frag
-// fragment shader
-//
-// Created by Olivier Prat on 06/05/17.
-// Copyright 2017 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 DeferredBufferWrite.slh@>
-
-<@include graphics/Material.slh@>
-
-<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$>
-<$declareMaterialLightmap()$>
-
-<@include Fade.slh@>
-<$declareFadeFragment()$>
-
-in vec4 _position;
-in vec2 _texCoord0;
-in vec2 _texCoord1;
-in vec3 _normal;
-in vec3 _tangent;
-in vec3 _color;
-in vec4 _worldPosition;
-
-void main(void) {
- vec3 fadeEmissive;
- FadeObjectParams fadeParams;
-
- <$fetchFadeObjectParams(fadeParams)$>
- applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
-
- Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$>
- <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$>
-
- vec3 viewNormal;
- <$tangentToViewSpaceLOD(_position, normalTexel, _normal, _tangent, viewNormal)$>
-
- packDeferredFragmentLightmap(
- normalize(viewNormal.xyz),
- evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
- getMaterialAlbedo(mat) * albedo.rgb * _color,
- getMaterialRoughness(mat) * roughness,
- getMaterialMetallic(mat) * metallicTex,
- /*specular, // no use of */ getMaterialFresnel(mat),
- lightmapVal+fadeEmissive);
-}
diff --git a/libraries/render-utils/src/model_lightmap_specular_map.slf b/libraries/render-utils/src/model_lightmap_specular_map.slf
deleted file mode 100644
index 1c97d435bd..0000000000
--- a/libraries/render-utils/src/model_lightmap_specular_map.slf
+++ /dev/null
@@ -1,43 +0,0 @@
-<@include gpu/Config.slh@>
-<$VERSION_HEADER$>
-// Generated on <$_SCRIBE_DATE$>
-//
-// model_lightmap_specular_map.frag
-// fragment shader
-//
-// Created by Samuel Gateau on 11/19/14.
-// Copyright 2014 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 DeferredBufferWrite.slh@>
-
-<@include graphics/Material.slh@>
-
-<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$>
-<$declareMaterialLightmap()$>
-
-in vec4 _position;
-in vec2 _texCoord0;
-in vec2 _texCoord1;
-in vec3 _normal;
-in vec3 _color;
-
-void main(void) {
- Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, _SCRIBE_NULL, metallicTex)$>
- <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$>
-
- packDeferredFragmentLightmap(
- normalize(_normal),
- evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
- getMaterialAlbedo(mat) * albedo.rgb * _color,
- getMaterialRoughness(mat) * roughness,
- getMaterialMetallic(mat) * metallicTex,
- /*metallicTex, // no use of */getMaterialFresnel(mat),
- lightmapVal);
-}
diff --git a/libraries/render-utils/src/model_lightmap_specular_map_fade.slf b/libraries/render-utils/src/model_lightmap_specular_map_fade.slf
deleted file mode 100644
index 1adedb9328..0000000000
--- a/libraries/render-utils/src/model_lightmap_specular_map_fade.slf
+++ /dev/null
@@ -1,53 +0,0 @@
-<@include gpu/Config.slh@>
-<$VERSION_HEADER$>
-// Generated on <$_SCRIBE_DATE$>
-//
-// model_lightmap_specular_map_fade.frag
-// fragment shader
-//
-// Created by Olivier Prat on 06/05/17.
-// Copyright 2017 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 DeferredBufferWrite.slh@>
-
-<@include graphics/Material.slh@>
-
-<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$>
-<$declareMaterialLightmap()$>
-
-<@include Fade.slh@>
-<$declareFadeFragment()$>
-
-in vec4 _position;
-in vec2 _texCoord0;
-in vec2 _texCoord1;
-in vec3 _normal;
-in vec3 _color;
-in vec4 _worldPosition;
-
-void main(void) {
- vec3 fadeEmissive;
- FadeObjectParams fadeParams;
-
- <$fetchFadeObjectParams(fadeParams)$>
- applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
-
- Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, _SCRIBE_NULL, metallicTex)$>
- <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$>
-
- packDeferredFragmentLightmap(
- normalize(_normal),
- evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a),
- getMaterialAlbedo(mat) * albedo.rgb * _color,
- getMaterialRoughness(mat) * roughness,
- getMaterialMetallic(mat) * metallicTex,
- /*metallicTex, // no use of */getMaterialFresnel(mat),
- lightmapVal+fadeEmissive);
-}
diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf
index b41e226e23..82f667bf73 100644
--- a/libraries/render-utils/src/model_normal_map.slf
+++ b/libraries/render-utils/src/model_normal_map.slf
@@ -5,8 +5,8 @@
// model_normal_map.frag
// fragment shader
//
-// Created by Andrzej Kapolka on 10/29/13.
-// Copyright 2013 High Fidelity, Inc.
+// Created by Andrzej Kapolka on 5/6/14.
+// Copyright 2014 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
@@ -17,7 +17,7 @@
<@include graphics/Material.slh@>
<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, _SCRIBE_NULL, EMISSIVE, OCCLUSION, SCATTERING)$>
+<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION, SCATTERING)$>
in vec4 _position;
in vec2 _texCoord0;
@@ -28,12 +28,12 @@ in vec3 _color;
void main(void) {
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex, scatteringTex)$>
+ BITFIELD matKey = getMaterialKey(mat);
+ <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex, scatteringTex)$>
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
float opacity = 1.0;
- <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
+ <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>;
<$discardTransparent(opacity)$>;
vec3 albedo = getMaterialAlbedo(mat);
@@ -49,15 +49,18 @@ void main(void) {
vec3 viewNormal;
<$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$>
+ float metallic = getMaterialMetallic(mat);
+ <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
+
float scattering = getMaterialScattering(mat);
<$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>;
packDeferredFragment(
- viewNormal,
+ normalize(viewNormal.xyz),
opacity,
albedo,
roughness,
- getMaterialMetallic(mat),
+ metallic,
emissive,
occlusionTex,
scattering);
diff --git a/libraries/render-utils/src/model_normal_map_fade.slf b/libraries/render-utils/src/model_normal_map_fade.slf
index 5a166b1c2c..67bea98cf0 100644
--- a/libraries/render-utils/src/model_normal_map_fade.slf
+++ b/libraries/render-utils/src/model_normal_map_fade.slf
@@ -2,10 +2,10 @@
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
-// model_normal_map_fade.frag
+// model_normal_specular_map_fade.frag
// fragment shader
//
-// Created by Olivier Prat on 04/19/17.
+// Created by Olivier Prat on 06/05/17.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
@@ -17,18 +17,18 @@
<@include graphics/Material.slh@>
<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, _SCRIBE_NULL, EMISSIVE, OCCLUSION, SCATTERING)$>
+<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$>
<@include Fade.slh@>
<$declareFadeFragment()$>
in vec4 _position;
-in vec4 _worldPosition;
in vec2 _texCoord0;
in vec2 _texCoord1;
in vec3 _normal;
in vec3 _tangent;
in vec3 _color;
+in vec4 _worldPosition;
void main(void) {
vec3 fadeEmissive;
@@ -38,12 +38,12 @@ void main(void) {
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex, scatteringTex)$>
+ BITFIELD matKey = getMaterialKey(mat);
+ <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex)$>
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
float opacity = 1.0;
- <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
+ <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>;
<$discardTransparent(opacity)$>;
vec3 albedo = getMaterialAlbedo(mat);
@@ -57,17 +57,19 @@ void main(void) {
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
vec3 viewNormal;
- <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$>
+ <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$>
+
+ float metallic = getMaterialMetallic(mat);
+ <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
float scattering = getMaterialScattering(mat);
- <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>;
packDeferredFragment(
- viewNormal,
+ normalize(viewNormal.xyz),
opacity,
albedo,
roughness,
- getMaterialMetallic(mat),
+ metallic,
emissive+fadeEmissive,
occlusionTex,
scattering);
diff --git a/libraries/render-utils/src/model_normal_specular_map.slf b/libraries/render-utils/src/model_normal_specular_map.slf
deleted file mode 100644
index 3eb3d43fdc..0000000000
--- a/libraries/render-utils/src/model_normal_specular_map.slf
+++ /dev/null
@@ -1,66 +0,0 @@
-<@include gpu/Config.slh@>
-<$VERSION_HEADER$>
-// Generated on <$_SCRIBE_DATE$>
-//
-// model_normal_specular_map.frag
-// fragment shader
-//
-// Created by Andrzej Kapolka on 5/6/14.
-// Copyright 2014 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 DeferredBufferWrite.slh@>
-
-<@include graphics/Material.slh@>
-
-<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$>
-
-in vec4 _position;
-in vec2 _texCoord0;
-in vec2 _texCoord1;
-in vec3 _normal;
-in vec3 _tangent;
-in vec3 _color;
-
-void main(void) {
- Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex)$>
- <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
-
- float opacity = 1.0;
- <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>;
- <$discardTransparent(opacity)$>;
-
- vec3 albedo = getMaterialAlbedo(mat);
- <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
- albedo *= _color;
-
- float roughness = getMaterialRoughness(mat);
- <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
-
- vec3 emissive = getMaterialEmissive(mat);
- <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
-
- vec3 viewNormal;
- <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$>
-
- float metallic = getMaterialMetallic(mat);
- <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
-
- float scattering = getMaterialScattering(mat);
-
- packDeferredFragment(
- normalize(viewNormal.xyz),
- opacity,
- albedo,
- roughness,
- metallic,
- emissive,
- occlusionTex,
- scattering);
-}
diff --git a/libraries/render-utils/src/model_normal_specular_map_fade.slf b/libraries/render-utils/src/model_normal_specular_map_fade.slf
deleted file mode 100644
index 0985d5d493..0000000000
--- a/libraries/render-utils/src/model_normal_specular_map_fade.slf
+++ /dev/null
@@ -1,76 +0,0 @@
-<@include gpu/Config.slh@>
-<$VERSION_HEADER$>
-// Generated on <$_SCRIBE_DATE$>
-//
-// model_normal_specular_map_fade.frag
-// fragment shader
-//
-// Created by Olivier Prat on 06/05/17.
-// Copyright 2017 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 DeferredBufferWrite.slh@>
-
-<@include graphics/Material.slh@>
-
-<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$>
-
-<@include Fade.slh@>
-<$declareFadeFragment()$>
-
-in vec4 _position;
-in vec2 _texCoord0;
-in vec2 _texCoord1;
-in vec3 _normal;
-in vec3 _tangent;
-in vec3 _color;
-in vec4 _worldPosition;
-
-void main(void) {
- vec3 fadeEmissive;
- FadeObjectParams fadeParams;
-
- <$fetchFadeObjectParams(fadeParams)$>
- applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
-
- Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex)$>
- <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
-
- float opacity = 1.0;
- <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>;
- <$discardTransparent(opacity)$>;
-
- vec3 albedo = getMaterialAlbedo(mat);
- <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
- albedo *= _color;
-
- float roughness = getMaterialRoughness(mat);
- <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
-
- vec3 emissive = getMaterialEmissive(mat);
- <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
-
- vec3 viewNormal;
- <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$>
-
- float metallic = getMaterialMetallic(mat);
- <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
-
- float scattering = getMaterialScattering(mat);
-
- packDeferredFragment(
- normalize(viewNormal.xyz),
- opacity,
- albedo,
- roughness,
- metallic,
- emissive+fadeEmissive,
- occlusionTex,
- scattering);
-}
diff --git a/libraries/render-utils/src/model_specular_map.slf b/libraries/render-utils/src/model_specular_map.slf
deleted file mode 100644
index e65dbaeda6..0000000000
--- a/libraries/render-utils/src/model_specular_map.slf
+++ /dev/null
@@ -1,63 +0,0 @@
-<@include gpu/Config.slh@>
-<$VERSION_HEADER$>
-// Generated on <$_SCRIBE_DATE$>
-//
-// model_specular_map.frag
-// fragment shader
-//
-// Created by Andrzej Kapolka on 5/6/14.
-// Copyright 2014 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 DeferredBufferWrite.slh@>
-
-<@include graphics/Material.slh@>
-
-<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$>
-
-in vec4 _position;
-in vec2 _texCoord0;
-in vec2 _texCoord1;
-in vec3 _normal;
-in vec3 _color;
-
-
-void main(void) {
- Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$>
- <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
-
- float opacity = 1.0;
- <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
- <$discardTransparent(opacity)$>;
-
- vec3 albedo = getMaterialAlbedo(mat);
- <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
- albedo *= _color;
-
- float roughness = getMaterialRoughness(mat);
- <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
-
- vec3 emissive = getMaterialEmissive(mat);
- <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
-
- float metallic = getMaterialMetallic(mat);
- <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
-
- float scattering = getMaterialScattering(mat);
-
- packDeferredFragment(
- normalize(_normal),
- opacity,
- albedo,
- roughness,
- metallic,
- emissive,
- occlusionTex,
- scattering);
-}
diff --git a/libraries/render-utils/src/model_specular_map_fade.slf b/libraries/render-utils/src/model_specular_map_fade.slf
deleted file mode 100644
index 17173d8bc3..0000000000
--- a/libraries/render-utils/src/model_specular_map_fade.slf
+++ /dev/null
@@ -1,72 +0,0 @@
-<@include gpu/Config.slh@>
-<$VERSION_HEADER$>
-// Generated on <$_SCRIBE_DATE$>
-//
-// model_specular_map_fade.frag
-// fragment shader
-//
-// Created by Olivier Prat on 06/05/17.
-// Copyright 2017 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 DeferredBufferWrite.slh@>
-
-<@include graphics/Material.slh@>
-
-<@include MaterialTextures.slh@>
-<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$>
-
-<@include Fade.slh@>
-<$declareFadeFragment()$>
-
-in vec4 _position;
-in vec2 _texCoord0;
-in vec2 _texCoord1;
-in vec3 _normal;
-in vec3 _color;
-in vec4 _worldPosition;
-
-void main(void) {
- vec3 fadeEmissive;
- FadeObjectParams fadeParams;
-
- <$fetchFadeObjectParams(fadeParams)$>
- applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
-
- Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
- <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$>
- <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
-
- float opacity = 1.0;
- <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
- <$discardTransparent(opacity)$>;
-
- vec3 albedo = getMaterialAlbedo(mat);
- <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
- albedo *= _color;
-
- float roughness = getMaterialRoughness(mat);
- <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>;
-
- vec3 emissive = getMaterialEmissive(mat);
- <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
-
- float metallic = getMaterialMetallic(mat);
- <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
-
- float scattering = getMaterialScattering(mat);
-
- packDeferredFragment(
- normalize(_normal),
- opacity,
- albedo,
- roughness,
- metallic,
- emissive+fadeEmissive,
- occlusionTex,
- scattering);
-}
diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf
index 67a5651ab8..bac97f2546 100644
--- a/libraries/render-utils/src/model_translucent.slf
+++ b/libraries/render-utils/src/model_translucent.slf
@@ -38,7 +38,7 @@ out vec4 _fragColor;
void main(void) {
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
+ BITFIELD matKey = getMaterialKey(mat);
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$>
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
diff --git a/libraries/render-utils/src/model_translucent_fade.slf b/libraries/render-utils/src/model_translucent_fade.slf
index e767d0ffa5..b81ed06479 100644
--- a/libraries/render-utils/src/model_translucent_fade.slf
+++ b/libraries/render-utils/src/model_translucent_fade.slf
@@ -40,7 +40,7 @@ void main(void) {
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
+ BITFIELD matKey = getMaterialKey(mat);
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$>
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
diff --git a/libraries/render-utils/src/model_translucent_unlit.slf b/libraries/render-utils/src/model_translucent_unlit.slf
index 4c3a0f0195..ebe9901616 100644
--- a/libraries/render-utils/src/model_translucent_unlit.slf
+++ b/libraries/render-utils/src/model_translucent_unlit.slf
@@ -26,7 +26,7 @@ out vec4 _fragColor;
void main(void) {
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
+ BITFIELD matKey = getMaterialKey(mat);
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$>
float opacity = getMaterialOpacity(mat) * _alpha;
diff --git a/libraries/render-utils/src/model_translucent_unlit_fade.slf b/libraries/render-utils/src/model_translucent_unlit_fade.slf
index 210060d54d..ea8a912a86 100644
--- a/libraries/render-utils/src/model_translucent_unlit_fade.slf
+++ b/libraries/render-utils/src/model_translucent_unlit_fade.slf
@@ -36,7 +36,7 @@ void main(void) {
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
+ BITFIELD matKey = getMaterialKey(mat);
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$>
float opacity = getMaterialOpacity(mat) * _alpha;
diff --git a/libraries/render-utils/src/model_unlit.slf b/libraries/render-utils/src/model_unlit.slf
index ccfc7d4935..d786c94634 100644
--- a/libraries/render-utils/src/model_unlit.slf
+++ b/libraries/render-utils/src/model_unlit.slf
@@ -27,7 +27,7 @@ in float _alpha;
void main(void) {
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
+ BITFIELD matKey = getMaterialKey(mat);
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$>
float opacity = 1.0;
diff --git a/libraries/render-utils/src/model_unlit_fade.slf b/libraries/render-utils/src/model_unlit_fade.slf
index 65c97f9e21..50c1681c0d 100644
--- a/libraries/render-utils/src/model_unlit_fade.slf
+++ b/libraries/render-utils/src/model_unlit_fade.slf
@@ -36,7 +36,7 @@ void main(void) {
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
+ BITFIELD matKey = getMaterialKey(mat);
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$>
float opacity = 1.0;
diff --git a/libraries/render-utils/src/overlay3D_model.slf b/libraries/render-utils/src/overlay3D_model.slf
index d4de0ee69f..8e8c3e6077 100644
--- a/libraries/render-utils/src/overlay3D_model.slf
+++ b/libraries/render-utils/src/overlay3D_model.slf
@@ -33,7 +33,7 @@ out vec4 _fragColor;
void main(void) {
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
+ BITFIELD matKey = getMaterialKey(mat);
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$>
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
diff --git a/libraries/render-utils/src/overlay3D_model_translucent.slf b/libraries/render-utils/src/overlay3D_model_translucent.slf
index b66c114f4a..040b491346 100644
--- a/libraries/render-utils/src/overlay3D_model_translucent.slf
+++ b/libraries/render-utils/src/overlay3D_model_translucent.slf
@@ -32,7 +32,7 @@ out vec4 _fragColor;
void main(void) {
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
+ BITFIELD matKey = getMaterialKey(mat);
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$>
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
diff --git a/libraries/render-utils/src/overlay3D_model_translucent_unlit.slf b/libraries/render-utils/src/overlay3D_model_translucent_unlit.slf
index 3b79818cd9..6753b02a05 100644
--- a/libraries/render-utils/src/overlay3D_model_translucent_unlit.slf
+++ b/libraries/render-utils/src/overlay3D_model_translucent_unlit.slf
@@ -27,7 +27,7 @@ out vec4 _fragColor;
void main(void) {
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
+ BITFIELD matKey = getMaterialKey(mat);
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$>
float opacity = 1.0;
diff --git a/libraries/render-utils/src/overlay3D_model_unlit.slf b/libraries/render-utils/src/overlay3D_model_unlit.slf
index eab975e810..8b7eb06d41 100644
--- a/libraries/render-utils/src/overlay3D_model_unlit.slf
+++ b/libraries/render-utils/src/overlay3D_model_unlit.slf
@@ -27,7 +27,7 @@ out vec4 _fragColor;
void main(void) {
Material mat = getMaterial();
- int matKey = getMaterialKey(mat);
+ BITFIELD matKey = getMaterialKey(mat);
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$>
float opacity = 1.0;
diff --git a/libraries/render-utils/src/surfaceGeometry_downsampleDepthNormal.slf b/libraries/render-utils/src/surfaceGeometry_downsampleDepthNormal.slf
index 205dad124e..82895d4684 100644
--- a/libraries/render-utils/src/surfaceGeometry_downsampleDepthNormal.slf
+++ b/libraries/render-utils/src/surfaceGeometry_downsampleDepthNormal.slf
@@ -17,8 +17,8 @@ uniform sampler2D normalMap;
in vec2 varTexCoord0;
-out vec4 outLinearDepth;
-out vec4 outNormal;
+layout(location = 0) out vec4 outLinearDepth;
+layout(location = 1) out vec4 outNormal;
void main(void) {
// Gather 2 by 2 quads from texture and downsample
diff --git a/libraries/render-utils/src/text/Font.cpp b/libraries/render-utils/src/text/Font.cpp
index f9508b343f..d3d25431d0 100644
--- a/libraries/render-utils/src/text/Font.cpp
+++ b/libraries/render-utils/src/text/Font.cpp
@@ -368,7 +368,9 @@ void Font::drawString(gpu::Batch& batch, float x, float y, const QString& str, c
setupGPU();
batch.setPipeline(((*color).a < 1.0f || layered) ? _transparentPipeline : _pipeline);
- batch.setResourceTexture(_fontLoc, _texture);
+ if (_fontLoc >= 0) {
+ batch.setResourceTexture(_fontLoc, _texture);
+ }
if (_outlineLoc >= 0) {
batch._glUniform1i(_outlineLoc, (effectType == OUTLINE_EFFECT));
}
diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h
index f175bab99a..f6d02e1e96 100644
--- a/libraries/render/src/render/ShapePipeline.h
+++ b/libraries/render/src/render/ShapePipeline.h
@@ -29,7 +29,6 @@ public:
TRANSLUCENT,
LIGHTMAP,
TANGENTS,
- SPECULAR,
UNLIT,
SKINNED,
DUAL_QUAT_SKINNED,
@@ -78,7 +77,6 @@ public:
Builder& withTranslucent() { _flags.set(TRANSLUCENT); return (*this); }
Builder& withLightmap() { _flags.set(LIGHTMAP); return (*this); }
Builder& withTangents() { _flags.set(TANGENTS); return (*this); }
- Builder& withSpecular() { _flags.set(SPECULAR); return (*this); }
Builder& withUnlit() { _flags.set(UNLIT); return (*this); }
Builder& withSkinned() { _flags.set(SKINNED); return (*this); }
Builder& withDualQuatSkinned() { _flags.set(DUAL_QUAT_SKINNED); return (*this); }
@@ -126,9 +124,6 @@ public:
Builder& withTangents() { _flags.set(TANGENTS); _mask.set(TANGENTS); return (*this); }
Builder& withoutTangents() { _flags.reset(TANGENTS); _mask.set(TANGENTS); return (*this); }
- Builder& withSpecular() { _flags.set(SPECULAR); _mask.set(SPECULAR); return (*this); }
- Builder& withoutSpecular() { _flags.reset(SPECULAR); _mask.set(SPECULAR); return (*this); }
-
Builder& withUnlit() { _flags.set(UNLIT); _mask.set(UNLIT); return (*this); }
Builder& withoutUnlit() { _flags.reset(UNLIT); _mask.set(UNLIT); return (*this); }
@@ -172,7 +167,6 @@ public:
bool useMaterial() const { return _flags[MATERIAL]; }
bool hasLightmap() const { return _flags[LIGHTMAP]; }
bool hasTangents() const { return _flags[TANGENTS]; }
- bool hasSpecular() const { return _flags[SPECULAR]; }
bool isUnlit() const { return _flags[UNLIT]; }
bool isTranslucent() const { return _flags[TRANSLUCENT]; }
bool isSkinned() const { return _flags[SKINNED]; }
@@ -212,7 +206,6 @@ inline QDebug operator<<(QDebug debug, const ShapeKey& key) {
<< "useMaterial:" << key.useMaterial()
<< "hasLightmap:" << key.hasLightmap()
<< "hasTangents:" << key.hasTangents()
- << "hasSpecular:" << key.hasSpecular()
<< "isUnlit:" << key.isUnlit()
<< "isTranslucent:" << key.isTranslucent()
<< "isSkinned:" << key.isSkinned()
diff --git a/libraries/shared/src/shared/FileUtils.cpp b/libraries/shared/src/shared/FileUtils.cpp
index 7b88321e99..9bdd65bf11 100644
--- a/libraries/shared/src/shared/FileUtils.cpp
+++ b/libraries/shared/src/shared/FileUtils.cpp
@@ -38,6 +38,16 @@ const QStringList& FileUtils::getFileSelectors() {
}
+QString FileUtils::selectFile(const QString& path) {
+ QFileSelector fileSelector;
+ fileSelector.setExtraSelectors(FileUtils::getFileSelectors());
+ QString result = fileSelector.select(path);
+ if (path != result) {
+ qDebug() << "Using" << result << "instead of" << path;
+ }
+ return result;
+}
+
QString FileUtils::readFile(const QString& filename) {
QFile file(filename);
@@ -51,7 +61,7 @@ QStringList FileUtils::readLines(const QString& filename, QString::SplitBehavior
return readFile(filename).split(QRegularExpression("[\\r\\n]"), QString::SkipEmptyParts);
}
-void FileUtils::locateFile(QString filePath) {
+void FileUtils::locateFile(const QString& filePath) {
// adapted from
// http://stackoverflow.com/questions/3490336/how-to-reveal-in-finder-or-show-in-explorer-with-qt
diff --git a/libraries/shared/src/shared/FileUtils.h b/libraries/shared/src/shared/FileUtils.h
index 9a5e2d5aba..2f5e11f005 100644
--- a/libraries/shared/src/shared/FileUtils.h
+++ b/libraries/shared/src/shared/FileUtils.h
@@ -18,7 +18,8 @@ class FileUtils {
public:
static const QStringList& getFileSelectors();
- static void locateFile(QString fileName);
+ static QString selectFile(const QString& fileName);
+ static void locateFile(const QString& fileName);
static QString standardPath(QString subfolder);
static QString readFile(const QString& filename);
static QStringList readLines(const QString& filename, QString::SplitBehavior splitBehavior = QString::KeepEmptyParts);
diff --git a/libraries/ui/src/QmlFragmentClass.cpp b/libraries/ui/src/QmlFragmentClass.cpp
new file mode 100644
index 0000000000..c4cac73b2d
--- /dev/null
+++ b/libraries/ui/src/QmlFragmentClass.cpp
@@ -0,0 +1,87 @@
+//
+// Created by Gabriel Calero & Cristian Duarte on Aug 25, 2017
+// Copyright 2017 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 "QmlFragmentClass.h"
+
+#include
+#include
+#include
+
+#include
+
+#include "OffscreenUi.h"
+
+
+std::mutex QmlFragmentClass::_mutex;
+std::map QmlFragmentClass::_fragments;
+
+QmlFragmentClass::QmlFragmentClass(QString id) : qml(id) { }
+
+// Method called by Qt scripts to create a new bottom menu bar in Android
+QScriptValue QmlFragmentClass::constructor(QScriptContext* context, QScriptEngine* engine) {
+
+ std::lock_guard guard(_mutex);
+ auto qml = context->argument(0).toVariant().toMap().value("qml");
+ if (qml.isValid()) {
+ // look up tabletId in the map.
+ auto iter = _fragments.find(qml.toString());
+ if (iter != _fragments.end()) {
+ //qDebug() << "[QML-ANDROID] QmlFragmentClass menu already exists";
+ return iter->second;
+ }
+ } else {
+ qWarning() << "QmlFragmentClass could not build instance " << qml;
+ return QScriptValue();
+ }
+
+ auto properties = parseArguments(context);
+ auto offscreenUi = DependencyManager::get();
+ QmlFragmentClass* retVal = new QmlFragmentClass(qml.toString());
+ Q_ASSERT(retVal);
+ if (QThread::currentThread() != qApp->thread()) {
+ retVal->moveToThread(qApp->thread());
+ BLOCKING_INVOKE_METHOD(retVal, "initQml", Q_ARG(QVariantMap, properties));
+ } else {
+ retVal->initQml(properties);
+ }
+ connect(engine, &QScriptEngine::destroyed, retVal, &QmlWindowClass::deleteLater);
+ QScriptValue scriptObject = engine->newQObject(retVal);
+ _fragments[qml.toString()] = scriptObject;
+ return scriptObject;
+}
+
+void QmlFragmentClass::close() {
+ QmlWindowClass::close();
+ _fragments.erase(qml);
+}
+
+QObject* QmlFragmentClass::addButton(const QVariant& properties) {
+ QVariant resultVar;
+ Qt::ConnectionType connectionType = Qt::AutoConnection;
+
+ if (QThread::currentThread() != _qmlWindow->thread()) {
+ connectionType = Qt::BlockingQueuedConnection;
+ }
+ bool hasResult = QMetaObject::invokeMethod(_qmlWindow, "addButton", connectionType,
+ Q_RETURN_ARG(QVariant, resultVar), Q_ARG(QVariant, properties));
+ if (!hasResult) {
+ qWarning() << "QmlFragmentClass addButton has no result";
+ return NULL;
+ }
+
+ QObject* qmlButton = qvariant_cast(resultVar);
+ if (!qmlButton) {
+ qWarning() << "QmlFragmentClass addButton result not a QObject";
+ return NULL;
+ }
+
+ return qmlButton;
+}
+
+void QmlFragmentClass::removeButton(QObject* button) {
+}
diff --git a/libraries/ui/src/QmlFragmentClass.h b/libraries/ui/src/QmlFragmentClass.h
new file mode 100644
index 0000000000..87c18a49ad
--- /dev/null
+++ b/libraries/ui/src/QmlFragmentClass.h
@@ -0,0 +1,45 @@
+//
+// Created by Gabriel Calero & Cristian Duarte on Aug 25, 2017
+// Copyright 2017 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_ui_QmlFragmentClass_h
+#define hifi_ui_QmlFragmentClass_h
+
+#include "QmlWindowClass.h"
+
+class QmlFragmentClass : public QmlWindowClass {
+ Q_OBJECT
+public:
+ QmlFragmentClass(QString id);
+ static QScriptValue constructor(QScriptContext* context, QScriptEngine* engine);
+
+ /**jsdoc
+ * Creates a new button, adds it to this and returns it.
+ * @function QmlFragmentClass#addButton
+ * @param properties {Object} button properties
+ * @returns {TabletButtonProxy}
+ */
+ Q_INVOKABLE QObject* addButton(const QVariant& properties);
+
+ /*
+ * TODO - not yet implemented
+ */
+ Q_INVOKABLE void removeButton(QObject* tabletButtonProxy);
+public slots:
+ Q_INVOKABLE void close();
+
+protected:
+ QString qmlSource() const override { return qml; }
+
+ static std::mutex _mutex;
+ static std::map _fragments;
+private:
+ QString qml;
+
+};
+
+#endif
diff --git a/libraries/ui/src/VirtualPadManager.cpp b/libraries/ui/src/VirtualPadManager.cpp
new file mode 100644
index 0000000000..4c3e6ff728
--- /dev/null
+++ b/libraries/ui/src/VirtualPadManager.cpp
@@ -0,0 +1,58 @@
+//
+// Created by Gabriel Calero & Cristian Duarte on 01/16/2018
+// 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
+//
+
+#include "VirtualPadManager.h"
+
+namespace VirtualPad {
+
+ bool Instance::isBeingTouched() {
+ return _isBeingTouched;
+ }
+
+ void Instance::setBeingTouched(bool touched) {
+ _isBeingTouched = touched;
+ }
+
+ void Instance::setFirstTouch(glm::vec2 point) {
+ _firstTouch = point;
+ }
+
+ glm::vec2 Instance::getFirstTouch() {
+ return _firstTouch;
+ }
+
+ void Instance::setCurrentTouch(glm::vec2 point) {
+ _currentTouch = point;
+ }
+
+ glm::vec2 Instance::getCurrentTouch() {
+ return _currentTouch;
+ }
+
+ Manager::Manager() {
+
+ }
+
+ Manager& Manager::instance() {
+ static QSharedPointer instance = DependencyManager::get();
+ return *instance;
+ }
+
+ void Manager::enable(bool enable) {
+ _enabled = enable;
+ }
+
+ bool Manager::isEnabled() {
+ return _enabled;
+ }
+
+ Instance* Manager::getLeftVirtualPad() {
+ return &_leftVPadInstance;
+ }
+
+}
diff --git a/libraries/ui/src/VirtualPadManager.h b/libraries/ui/src/VirtualPadManager.h
new file mode 100644
index 0000000000..599954989f
--- /dev/null
+++ b/libraries/ui/src/VirtualPadManager.h
@@ -0,0 +1,46 @@
+//
+// Created by Gabriel Calero & Cristian Duarte on 01/16/2018
+// 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
+//
+
+#pragma once
+#include
+#include
+
+#include
+
+namespace VirtualPad {
+ class Instance {
+ public:
+ virtual bool isBeingTouched();
+ virtual void setBeingTouched(bool touched);
+ virtual void setFirstTouch(glm::vec2 point);
+ virtual glm::vec2 getFirstTouch();
+ virtual void setCurrentTouch(glm::vec2 point);
+ virtual glm::vec2 getCurrentTouch();
+ private:
+ bool _isBeingTouched;
+ glm::vec2 _firstTouch;
+ glm::vec2 _currentTouch;
+ };
+
+ class Manager : public QObject, public Dependency {
+ SINGLETON_DEPENDENCY
+
+ Manager();
+ Manager(const Manager& other) = delete;
+ public:
+ static Manager& instance();
+ Instance* getLeftVirtualPad();
+ bool isEnabled();
+ void enable(bool enable);
+ private:
+ Instance _leftVPadInstance;
+ bool _enabled;
+ };
+}
+
+
diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp
index 749a60a578..73d82c6b89 100644
--- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp
+++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp
@@ -28,7 +28,7 @@
#include
#include
#include
-
+#include
#include
#include
#include
diff --git a/scripts/+android/defaultScripts.js b/scripts/+android/defaultScripts.js
index a115e498da..a8f6bf42a1 100644
--- a/scripts/+android/defaultScripts.js
+++ b/scripts/+android/defaultScripts.js
@@ -12,7 +12,11 @@
//
var DEFAULT_SCRIPTS_COMBINED = [
- "system/progress.js"/*,
+ "system/progress.js",
+ "system/+android/touchscreenvirtualpad.js",
+ "system/+android/bottombar.js",
+ "system/+android/audio.js" ,
+ "system/+android/modes.js"/*,
"system/away.js",
"system/controllers/controllerDisplayManager.js",
"system/controllers/handControllerGrabAndroid.js",
diff --git a/scripts/system/+android/audio.js b/scripts/system/+android/audio.js
new file mode 100644
index 0000000000..b4f156d4bf
--- /dev/null
+++ b/scripts/system/+android/audio.js
@@ -0,0 +1,67 @@
+"use strict";
+//
+// audio.js
+// scripts/system/
+//
+// Created by Gabriel Calero & Cristian Duarte on Jan 16, 2018
+// 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
+//
+
+(function() { // BEGIN LOCAL_SCOPE
+
+var audiobar;
+var audioButton;
+
+var logEnabled = true;
+
+function printd(str) {
+ if (logEnabled)
+ print("[audio.js] " + str);
+}
+
+function init() {
+ audiobar = new QmlFragment({
+ qml: "hifi/AudioBar.qml"
+ });
+
+ audioButton = audiobar.addButton({
+ icon: "icons/mic-unmute-a.svg",
+ activeIcon: "icons/mic-mute-a.svg",
+ text: "",
+ bgOpacity: 0.0,
+ activeBgOpacity: 0.0,
+ bgColor: "#FFFFFF"
+ });
+
+ onMuteToggled();
+
+ audioButton.clicked.connect(onMuteClicked);
+ Audio.mutedChanged.connect(onMuteToggled);
+}
+
+function onMuteClicked() {
+ printd("On Mute Clicked");
+ //Menu.setIsOptionChecked("Mute Microphone", !Menu.isOptionChecked("Mute Microphone"));
+ Audio.muted = !Audio.muted;
+ onMuteToggled();
+}
+
+function onMuteToggled() {
+ printd("On Mute Toggled");
+ audioButton.isActive = Audio.muted; // Menu.isOptionChecked("Mute Microphone")
+ printd("Audio button is active: " + audioButton.isActive);
+}
+
+Script.scriptEnding.connect(function () {
+ if(audioButton) {
+ audioButton.clicked.disconnect(onMuteClicked);
+ Audio.mutedChanged.connect(onMuteToggled);
+ }
+});
+
+init();
+
+}()); // END LOCAL_SCOPE
diff --git a/scripts/system/+android/bottombar.js b/scripts/system/+android/bottombar.js
new file mode 100644
index 0000000000..e58840ad6f
--- /dev/null
+++ b/scripts/system/+android/bottombar.js
@@ -0,0 +1,159 @@
+"use strict";
+//
+// bottombar.js
+// scripts/system/
+//
+// Created by Gabriel Calero & Cristian Duarte on Jan 18, 2018
+// 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
+//
+(function() { // BEGIN LOCAL_SCOPE
+
+var bottombar;
+var bottomHudOptionsBar;
+var gotoBtn;
+
+var gotoScript = Script.require('./goto.js');
+
+var logEnabled = false;
+
+function printd(str) {
+ if (logEnabled) {
+ print("[bottombar.js] " + str);
+ }
+}
+
+function init() {
+ gotoScript.init();
+ gotoScript.setOnShownChange(function (shown) {
+ if (shown) {
+ showAddressBar();
+ } else {
+ hideAddressBar();
+ }
+ });
+
+ setupBottomBar();
+ setupBottomHudOptionsBar();
+
+ raiseBottomBar();
+
+}
+
+function shutdown() {
+}
+
+function setupBottomBar() {
+ bottombar = new QmlFragment({
+ qml: "hifi/bottombar.qml"
+ });
+
+ bottombar.fromQml.connect(function(message) {
+ switch (message.method) {
+ case 'hide':
+ lowerBottomBar();
+ break;
+ default:
+ print('[bottombar.js] Unrecognized message from bottomHud.qml:', JSON.stringify(message));
+ }
+ });
+
+
+ gotoBtn = bottombar.addButton({
+ icon: "icons/goto-i.svg",
+ activeIcon: "icons/goto-a.svg",
+ bgOpacity: 0,
+ hoverBgOpacity: 0,
+ activeBgOpacity: 0,
+ activeHoverBgOpacity: 0,
+ height: 240,
+ width: 300,
+ iconSize: 108,
+ textSize: 45,
+ text: "GO TO"
+ });
+
+ gotoBtn.clicked.connect(function() {
+ if (!gotoScript.isVisible()) {
+ showAddressBar();
+ } else {
+ hideAddressBar();
+ }
+ });
+
+ // TODO: setup all the buttons or provide a dynamic interface
+
+ raiseBottomBar();
+
+
+}
+
+var setupBottomHudOptionsBar = function() {
+ var bottomHud = new QmlFragment({
+ qml: "hifi/bottomHudOptions.qml"
+ });
+
+ bottomHudOptionsBar = {
+ show: function() {
+ bottomHud.setVisible(true);
+ },
+ hide: function() {
+ bottomHud.setVisible(false);
+ },
+ qmlFragment: bottomHud
+ };
+ bottomHud.fromQml.connect(
+ function(message) {
+ switch (message.method) {
+ case 'showUpBar':
+ printd('[bottombar.js] showUpBar message from bottomHudOptions.qml: ', JSON.stringify(message));
+ raiseBottomBar();
+ break;
+ default:
+ print('[bottombar.js] Unrecognized message from bottomHudOptions.qml:', JSON.stringify(message));
+ }
+ }
+ );
+}
+
+function lowerBottomBar() {
+ if (bottombar) {
+ bottombar.setVisible(false);
+ }
+ if (bottomHudOptionsBar) {
+ bottomHudOptionsBar.show();
+ }
+}
+
+function raiseBottomBar() {
+ print('[bottombar.js] raiseBottomBar begin');
+ if (bottombar) {
+ bottombar.setVisible(true);
+ }
+ if (bottomHudOptionsBar) {
+ bottomHudOptionsBar.hide();
+ }
+ print('[bottombar.js] raiseBottomBar end');
+}
+
+function showAddressBar() {
+ gotoScript.show();
+ gotoBtn.isActive = true;
+}
+
+function hideAddressBar() {
+ gotoScript.hide();
+ gotoBtn.isActive = false;
+}
+
+
+
+Script.scriptEnding.connect(function () {
+ shutdown();
+});
+
+init();
+
+}()); // END LOCAL_SCOPE
diff --git a/scripts/system/+android/goto.js b/scripts/system/+android/goto.js
new file mode 100644
index 0000000000..e917455128
--- /dev/null
+++ b/scripts/system/+android/goto.js
@@ -0,0 +1,96 @@
+"use strict";
+//
+// goto-android.js
+// scripts/system/
+//
+// Created by Gabriel Calero & Cristian Duarte on 12 Sep 2017
+// Copyright 2017 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 window;
+
+
+var logEnabled = false;
+function printd(str) {
+ if (logEnabled)
+ print("[goto-android.js] " + str);
+}
+
+function init() {
+}
+
+function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml.
+ switch (message.method) {
+ case 'shownChanged':
+ if (notifyShownChange) {
+ notifyShownChange(message.params.shown);
+ } ;
+ break;
+ case 'hide':
+ module.exports.hide();
+ module.exports.onHidden();
+ break;
+ default:
+ print('[goto-android.js] Unrecognized message from AddressBarDialog.qml:', JSON.stringify(message));
+ }
+}
+
+function sendToQml(message) {
+ window.sendToQml(message);
+}
+
+var isVisible = false;
+var notifyShownChange;
+module.exports = {
+ init: function() {
+ window = new QmlFragment({
+ qml: "AddressBarDialog.qml",
+ visible: false
+ });
+ },
+ show: function() {
+ Controller.setVPadEnabled(false);
+ if (window) {
+ window.fromQml.connect(fromQml);
+ window.setVisible(true);
+ isVisible = true;
+ }
+ },
+ hide: function() {
+ Controller.setVPadEnabled(true);
+ if (window) {
+ window.fromQml.disconnect(fromQml);
+ window.setVisible(false);
+ }
+ isVisible = false;
+ },
+ destroy: function() {
+ if (window) {
+ window.close();
+ window = null;
+ }
+ },
+ isVisible: function() {
+ return isVisible;
+ },
+ width: function() {
+ return window ? window.size.x : 0;
+ },
+ height: function() {
+ return window ? window.size.y : 0;
+ },
+ position: function() {
+ return window && isVisible ? window.position : null;
+ },
+ setOnShownChange: function(f) {
+ notifyShownChange = f;
+ },
+ onHidden: function() { }
+
+
+};
+
+init();
diff --git a/scripts/system/+android/modes.js b/scripts/system/+android/modes.js
new file mode 100644
index 0000000000..b29548094f
--- /dev/null
+++ b/scripts/system/+android/modes.js
@@ -0,0 +1,220 @@
+"use strict";
+//
+// modes.js
+// scripts/system/
+//
+// Created by Gabriel Calero & Cristian Duarte on Jan 23, 2018
+// 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
+//
+(function() { // BEGIN LOCAL_SCOPE
+
+var modesbar;
+var modesButtons;
+var currentSelectedBtn;
+
+var SETTING_CURRENT_MODE_KEY = 'Android/Mode';
+var MODE_VR = "VR", MODE_RADAR = "RADAR", MODE_MY_VIEW = "MY VIEW";
+var DEFAULT_MODE = MODE_RADAR;
+var logEnabled = true;
+
+var radar = Script.require('./radar.js');
+var uniqueColor = Script.require('./uniqueColor.js');
+
+function printd(str) {
+ if (logEnabled) {
+ print("[modes.js] " + str);
+ }
+}
+
+function init() {
+ radar.setUniqueColor(uniqueColor);
+ radar.init();
+ setupModesBar();
+ radar.isTouchValid = isRadarModeValidTouch;
+}
+
+function shutdown() {
+
+}
+
+function setupModesBar() {
+
+ var bar = new QmlFragment({
+ qml: "hifi/modesbar.qml"
+ });
+ var buttonRadarMode = bar.addButton({
+ icon: "icons/radar-i.svg",
+ activeIcon: "icons/radar-a.svg",
+ hoverIcon: "icons/radar-a.svg",
+ activeBgOpacity: 0.0,
+ hoverBgOpacity: 0.0,
+ activeHoverBgOpacity: 0.0,
+ text: "RADAR",
+ height:240,
+ bottomMargin: 6,
+ textSize: 45
+ });
+ var buttonMyViewMode = bar.addButton({
+ icon: "icons/myview-i.svg",
+ activeIcon: "icons/myview-a.svg",
+ hoverIcon: "icons/myview-a.svg",
+ activeBgOpacity: 0.0,
+ hoverBgOpacity: 0.0,
+ activeHoverBgOpacity: 0.0,
+ text: "MY VIEW",
+ height: 240,
+ bottomMargin: 6,
+ textSize: 45
+ });
+
+ modesButtons = [buttonRadarMode, buttonMyViewMode];
+
+ var mode = getCurrentModeSetting();
+
+ var buttonsRevealed = false;
+ bar.sendToQml({type: "inactiveButtonsHidden"});
+
+ modesbar = {
+ restoreMyViewButton: function() {
+ switchModeButtons(buttonMyViewMode);
+ saveCurrentModeSetting(MODE_MY_VIEW);
+ },
+ sendToQml: function(o) { bar.sendToQml(o); },
+ qmlFragment: bar
+ };
+
+ buttonRadarMode.clicked.connect(function() {
+ //if (connections.isVisible()) return;
+ saveCurrentModeSetting(MODE_RADAR);
+ printd("Radar clicked");
+ onButtonClicked(buttonRadarMode, function() {
+ radar.startRadarMode();
+ });
+ });
+ buttonMyViewMode.clicked.connect(function() {
+ //if (connections.isVisible()) return;
+ saveCurrentModeSetting(MODE_MY_VIEW);
+ printd("My View clicked");
+ onButtonClicked(buttonMyViewMode, function() {
+ if (currentSelectedBtn == buttonRadarMode) {
+ radar.endRadarMode();
+ }
+ });
+ });
+
+ var savedButton;
+ if (mode == MODE_MY_VIEW) {
+ savedButton = buttonMyViewMode;
+ } else {
+ savedButton = buttonRadarMode;
+ }
+ printd("[MODE] previous mode " + mode);
+
+ savedButton.clicked();
+}
+
+function saveCurrentModeSetting(mode) {
+ Settings.setValue(SETTING_CURRENT_MODE_KEY, mode);
+}
+
+function getCurrentModeSetting(mode) {
+ return Settings.getValue(SETTING_CURRENT_MODE_KEY, DEFAULT_MODE);
+}
+
+function showAllButtons() {
+ for (var i=0; i= aQmlFrag.position.x * 3 && coords.x <= aQmlFrag.position.x * 3 + aQmlFrag.size.x * 3 &&
+ coords.y >= aQmlFrag.position.y * 3 && coords.y <= aQmlFrag.position.y * 3 + aQmlFrag.size.y * 3
+ ) {
+ printd("godViewModeTouchValid- false because of qmlFragments!? idx " + i);
+ return false;
+ }
+ }
+
+ for (var i=0; i < windows.length; i++) {
+ var aWin = windows[i];
+ if (aWin != null && aWin.position() != null &&
+ coords.x >= aWin.position().x * 3 && coords.x <= aWin.position().x * 3 + aWin.width() * 3 &&
+ coords.y >= aWin.position().y * 3 && coords.y <= aWin.position().y * 3 + aWin.height() * 3
+ ) {
+ printd("godViewModeTouchValid- false because of windows!?");
+ return false;
+ }
+ }
+ printd("godViewModeTouchValid- true by default ");
+ return true;
+}
+
+Script.scriptEnding.connect(function () {
+ shutdown();
+});
+
+init();
+
+}()); // END LOCAL_SCOPE
\ No newline at end of file
diff --git a/scripts/system/+android/radar.js b/scripts/system/+android/radar.js
new file mode 100644
index 0000000000..9b9bd9c473
--- /dev/null
+++ b/scripts/system/+android/radar.js
@@ -0,0 +1,1503 @@
+"use strict";
+//
+// radar.js
+// scripts/system/+android/
+//
+// Created by Cristian Duarte & Gabriel Calero on 31 Jan 2018
+// 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 radarModeInterface = {};
+
+var logEnabled = true;
+function printd(str) {
+ if (logEnabled) {
+ print("[radar.js] " + str);
+ }
+}
+
+var radar = false;
+var radarHeight = 10; // camera position meters above the avatar
+var tablet;
+
+var RADAR_CAMERA_OFFSET = -1; // 1 meter below the avatar
+var ABOVE_GROUND_DROP = 2;
+var MOVE_BY = 1;
+
+// Swipe/Drag vars
+var PINCH_INCREMENT_FIRST = 0.4; // 0.1 meters zoom in - out
+var PINCH_INCREMENT = 0.4; // 0.1 meters zoom in - out
+var RADAR_HEIGHT_MAX_PLUS_AVATAR = 40;
+var RADAR_HEIGHT_MIN_PLUS_AVATAR = 2;
+var RADAR_CAMERA_DISTANCE_TO_ICONS = 0.5; // Icons are near the camera to
+ // prevent the LOD manager
+ // dismissing them
+var RADAR_ICONS_APPARENT_DISTANCE_TO_AVATAR_BASE = 1; // How much above the
+ // avatar base should
+ // the icon appear
+var AVATAR_DISPLAY_NAME_HEIGHT = 38;
+var AVATAR_DISPLAY_NAME_CHAR_WIDTH = 18;
+var lastDragAt;
+var lastDeltaDrag;
+
+var uniqueColor;
+
+function moveTo(position) {
+ if (radar) {
+ MyAvatar.position = position;
+ Camera.position = Vec3.sum(MyAvatar.position, {
+ x : 0,
+ y : radarHeight,
+ z : 0
+ });
+ }
+}
+
+function keyPressEvent(event) {
+ if (radar) {
+ switch (event.text) {
+ case "UP":
+ moveTo(Vec3.sum(MyAvatar.position, {
+ x : 0.0,
+ y : 0,
+ z : -1 * MOVE_BY
+ }));
+ break;
+ case "DOWN":
+ moveTo(Vec3.sum(MyAvatar.position, {
+ x : 0,
+ y : 0,
+ z : MOVE_BY
+ }));
+ break;
+ case "LEFT":
+ moveTo(Vec3.sum(MyAvatar.position, {
+ x : -1 * MOVE_BY,
+ y : 0,
+ z : 0
+ }));
+ break;
+ case "RIGHT":
+ moveTo(Vec3.sum(MyAvatar.position, {
+ x : MOVE_BY,
+ y : 0,
+ z : 0
+ }));
+ break;
+ }
+ }
+}
+
+function actionOnObjectFromEvent(event) {
+ var rayIntersection = findRayIntersection(Camera.computePickRay(event.x,
+ event.y));
+ if (rayIntersection && rayIntersection.intersects
+ && rayIntersection.overlayID) {
+ printd("found overlayID touched " + rayIntersection.overlayID);
+ if (entitiesByOverlayID[rayIntersection.overlayID]) {
+ var entity = Entities.getEntityProperties(
+ entitiesByOverlayID[rayIntersection.overlayID],
+ [ "sourceUrl" ]);
+ App.openUrl(entity.sourceUrl);
+ return true;
+ }
+ }
+ if (rayIntersection && rayIntersection.intersects
+ && rayIntersection.entityID && rayIntersection.properties) {
+ printd("found " + rayIntersection.entityID + " of type "
+ + rayIntersection.properties.type);
+ if (rayIntersection.properties.type == "Web") {
+ printd("found web element to "
+ + rayIntersection.properties.sourceUrl);
+ App.openUrl(rayIntersection.properties.sourceUrl);
+ return true;
+ }
+ }
+ return false;
+}
+
+function mousePress(event) {
+ if (!isTouchValid(coords)) {
+ currentTouchIsValid = false;
+ return;
+ } else {
+ currentTouchIsValid = true;
+ }
+ mousePressOrTouchEnd(event);
+}
+
+function mousePressOrTouchEnd(event) {
+ if (!currentTouchIsValid) {
+ return;
+ }
+ if (radar) {
+ if (actionOnObjectFromEvent(event)) {
+ return;
+ }
+ }
+}
+
+function toggleRadarMode() {
+ if (radar) {
+ endRadar();
+ } else {
+ startRadar();
+ }
+}
+
+function fakeDoubleTap(event) {
+ // CLD - temporarily disable toggling mode through double tap
+ // * As we have a new UI for toggling between modes, it may be discarded
+ // completely in the future.
+ // toggleRadarMode();
+ teleporter.dragTeleportUpdate(event);
+ teleporter.dragTeleportRelease(event);
+}
+
+var currentTouchIsValid = false; // Currently used to know if touch hasn't
+ // started on a UI overlay
+
+var DOUBLE_TAP_TIME = 300;
+var fakeDoubleTapStart = Date.now();
+var touchEndCount = 0;
+
+/*
+ * Counts touchEnds and if there were 2 in the DOUBLE_TAP_TIME lapse, it
+ * triggers a fakeDoubleTap and returns true. Otherwise, returns false (no
+ * double tap yet)
+ */
+function analyzeDoubleTap(event) {
+ var fakeDoubleTapEnd = Date.now();
+ var elapsed = fakeDoubleTapEnd - fakeDoubleTapStart;
+ if (elapsed > DOUBLE_TAP_TIME) {
+ touchEndCount = 0;
+ }
+
+ // if this is our first "up" then record time so we can
+ // later determine if second "up" is a double tap
+ if (touchEndCount == 0) {
+ fakeDoubleTapStart = Date.now();
+ }
+ touchEndCount++;
+
+ if (touchEndCount >= 2) {
+ var fakeDoubleTapEnd = Date.now();
+ var elapsed = fakeDoubleTapEnd - fakeDoubleTapStart;
+ printd("-- fakeDoubleTapEnd:" + fakeDoubleTapEnd + "-- elapsed:"
+ + elapsed)
+ if (elapsed <= DOUBLE_TAP_TIME) {
+ touchEndCount = 0;
+ fakeDoubleTap(event);
+ return true; // don't do the normal touch end processing
+ }
+
+ touchEndCount = 0;
+ }
+ return false;
+}
+
+function touchEnd(event) {
+ printd("touchEnd received " + JSON.stringify(event));
+ // Clean up touch variables
+ lastDragAt = null;
+ lastDeltaDrag = null;
+ touchStartingCoordinates = null; // maybe in special cases it should be
+ // setup later?
+ startedDraggingCamera = false;
+ prevTouchPinchRadius = null;
+ draggingCamera = false;
+
+ if (movingCamera) {
+ // if camera was indeed moving, we should not further process, it was
+ // just dragging
+ movingCamera = false;
+ dragModeFunc = null;
+ return;
+ }
+
+ // teleport release analysis
+ if (teleporter && teleporter.dragTeleportUpdate == dragModeFunc) {
+ teleporter.dragTeleportRelease(event);
+ dragModeFunc = null;
+ return;
+ }
+ dragModeFunc = null;
+
+ // if pinching or moving is still detected, cancel
+ if (event.isPinching) {
+ printd("touchEnd fail because isPinching");
+ return;
+ }
+ if (event.isPinchOpening) {
+ printd("touchEnd fail because isPinchingOpening");
+ return;
+ }
+ if (event.isMoved) {
+ printd("touchEnd fail because isMoved");
+ return;
+ }
+
+ // if touch is invalid, cancel
+ if (!currentTouchIsValid) {
+ printd("touchEnd fail because !currentTouchIsValid");
+ return;
+ }
+
+ if (analyzeDoubleTap(event))
+ return; // double tap detected, finish
+
+ if (radar) {
+ mousePressOrTouchEnd(event);
+ }
+}
+
+/**
+ * Polyfill for sign(x)
+ */
+if (!Math.sign) {
+ Math.sign = function(x) {
+ // If x is NaN, the result is NaN.
+ // If x is -0, the result is -0.
+ // If x is +0, the result is +0.
+ // If x is negative and not -0, the result is -1.
+ // If x is positive and not +0, the result is +1.
+ x = +x; // convert to a number
+ if (x === 0 || isNaN(x)) {
+ return Number(x);
+ }
+ return x > 0 ? 1 : -1;
+ };
+}
+
+/*******************************************************************************
+ * Line and Plane intersection methods
+ ******************************************************************************/
+
+/**
+ * findLinePlaneIntersection Given points p {x: y: z:} and q that define a line,
+ * and the plane of formula ax+by+cz+d = 0, returns the intersection point or
+ * null if none.
+ */
+function findLinePlaneIntersection(p, q, a, b, c, d) {
+ return findLinePlaneIntersectionCoords(p.x, p.y, p.z, q.x, q.y, q.z, a, b,
+ c, d);
+}
+
+/**
+ * findLineToHeightIntersection Given points p {x: y: z:} and q that define a
+ * line, and a planeY value that defines a plane paralel to 'the floor' xz
+ * plane, returns the intersection to that plane or null if none.
+ */
+function findLineToHeightIntersection(p, q, planeY) {
+ return findLinePlaneIntersection(p, q, 0, 1, 0, -planeY);
+}
+
+/**
+ * findLinePlaneIntersectionCoords (to avoid requiring unnecessary
+ * instantiation) Given points p with px py pz and q that define a line, and the
+ * plane of formula ax+by+cz+d = 0, returns the intersection point or null if
+ * none.
+ */
+function findLinePlaneIntersectionCoords(px, py, pz, qx, qy, qz, a, b, c, d) {
+ var tDenom = a * (qx - px) + b * (qy - py) + c * (qz - pz);
+ if (tDenom == 0)
+ return null;
+
+ var t = -(a * px + b * py + c * pz + d) / tDenom;
+
+ return {
+ x : (px + t * (qx - px)),
+ y : (py + t * (qy - py)),
+ z : (pz + t * (qz - pz))
+ };
+}
+
+/**
+ * findLineToHeightIntersection Given points p with px py pz and q that define a
+ * line, and a planeY value that defines a plane paralel to 'the floor' xz
+ * plane, returns the intersection to that plane or null if none.
+ */
+function findLineToHeightIntersectionCoords(px, py, pz, qx, qy, qz, planeY) {
+ return findLinePlaneIntersectionCoords(px, py, pz, qx, qy, qz, 0, 1, 0,
+ -planeY);
+}
+
+function findRayIntersection(pickRay) {
+ // Check 3D overlays and entities. Argument is an object with origin and
+ // direction.
+ var result = Overlays.findRayIntersection(pickRay);
+ if (!result.intersects) {
+ result = Entities.findRayIntersection(pickRay, true);
+ }
+ return result;
+}
+
+/**
+ * Given a 2d point (x,y) this function returns the intersection (x, y, z) of
+ * the computedPickRay for that point with the plane y = py
+ */
+function computePointAtPlaneY(x, y, py) {
+ var ray = Camera.computePickRay(x, y);
+ var p1 = ray.origin;
+ var p2 = Vec3.sum(p1, Vec3.multiply(ray.direction, 1));
+ return findLineToHeightIntersectionCoords(p1.x, p1.y, p1.z, p2.x, p2.y,
+ p2.z, py);
+}
+
+/*******************************************************************************
+ *
+ ******************************************************************************/
+
+function isTouchValid(coords) {
+ // TODO: Extend to the detection of touches on new menu bars
+ var radarModeTouchValid = radarModeInterface.isTouchValid(coords);
+
+ // getItemAtPoint does not exist anymore, look for another way to know if we
+ // are touching buttons
+ // is it still needed?
+ return /* !tablet.getItemAtPoint(coords) && */radarModeTouchValid;
+}
+
+/*******************************************************************************
+ *
+ ******************************************************************************/
+
+var touchStartingCoordinates = null;
+
+var KEEP_PRESSED_FOR_TELEPORT_MODE_TIME = 750;
+var touchBeginTime;
+
+function touchBegin(event) {
+ var coords = {
+ x : event.x,
+ y : event.y
+ };
+ if (!isTouchValid(coords)) {
+ printd("analyze touch - RADAR_TOUCH - INVALID");
+ currentTouchIsValid = false;
+ touchStartingCoordinates = null;
+ } else {
+ printd("analyze touch - RADAR_TOUCH - ok");
+ currentTouchIsValid = true;
+ touchStartingCoordinates = coords;
+ touchBeginTime = Date.now();
+ }
+}
+
+var startedDraggingCamera = false; // first time
+var draggingCamera = false; // is trying
+var movingCamera = false; // definitive
+
+var MIN_DRAG_DISTANCE_TO_CONSIDER = 100; // distance by axis, not real
+ // distance
+
+var prevTouchPinchRadius = null;
+
+function pinchUpdate(event) {
+ if (!event.isMoved)
+ return;
+ if (event.radius <= 0)
+ return;
+
+ // pinch management
+ var avatarY = MyAvatar.position.y;
+ var pinchIncrement;
+ if (!!prevTouchPinchRadius) {
+ // no prev value
+ pinchIncrement = PINCH_INCREMENT
+ * Math.abs(event.radius - prevTouchPinchRadius) * 0.1;
+ } else {
+ pinchIncrement = PINCH_INCREMENT_FIRST;
+ }
+
+ if (event.isPinching) {
+ if (radarHeight + pinchIncrement > RADAR_HEIGHT_MAX_PLUS_AVATAR
+ + avatarY) {
+ radarHeight = RADAR_HEIGHT_MAX_PLUS_AVATAR + avatarY;
+ } else {
+ radarHeight += pinchIncrement;
+ }
+ } else if (event.isPinchOpening) {
+ if (radarHeight - pinchIncrement < RADAR_HEIGHT_MIN_PLUS_AVATAR
+ + avatarY) {
+ radarHeight = RADAR_HEIGHT_MIN_PLUS_AVATAR + avatarY;
+ } else {
+ radarHeight -= pinchIncrement;
+ }
+ }
+ var deltaHeight = avatarY + radarHeight - Camera.position.y;
+ Camera.position = Vec3.sum(Camera.position, {
+ x : 0,
+ y : deltaHeight,
+ z : 0
+ });
+ if (!draggingCamera) {
+ startedDraggingCamera = true;
+ draggingCamera = true;
+ }
+
+ prevTouchPinchRadius = event.radius;
+}
+
+function isInsideSquare(coords0, coords1, halfside) {
+ return Math.abs(coords0.x - coords1.x) <= halfside
+ && Math.abs(coords0.y - coords1.y) <= halfside;
+}
+
+function dragScrollUpdate(event) {
+ if (!event.isMoved)
+ return;
+
+ // drag management
+ var pickRay = Camera.computePickRay(event.x, event.y);
+ var dragAt = Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction,
+ radarHeight));
+
+ if (lastDragAt === undefined || lastDragAt === null) {
+ lastDragAt = dragAt;
+ return;
+ }
+
+ var deltaDrag = {
+ x : (lastDragAt.x - dragAt.x),
+ y : 0,
+ z : (lastDragAt.z - dragAt.z)
+ };
+
+ lastDragAt = dragAt;
+ if (lastDeltaDrag === undefined || lastDeltaDrag === null) {
+ lastDeltaDrag = deltaDrag;
+ return;
+ }
+
+ if (!draggingCamera) {
+ startedDraggingCamera = true;
+ draggingCamera = true;
+ } else {
+ if (!movingCamera) {
+ if (!isInsideSquare(touchStartingCoordinates, event,
+ MIN_DRAG_DISTANCE_TO_CONSIDER)) {
+ movingCamera = true;
+ }
+ }
+
+ if (movingCamera) {
+ if (Math.sign(deltaDrag.x) == Math.sign(lastDeltaDrag.x)
+ && Math.sign(deltaDrag.z) == Math.sign(lastDeltaDrag.z)) {
+ // Process movement if direction of the movement is the same
+ // than the previous frame
+ // process delta
+ var moveCameraTo = Vec3.sum(Camera.position, deltaDrag);
+ // move camera
+ Camera.position = moveCameraTo;
+ } else {
+ // Do not move camera if it's changing direction in this case,
+ // wait until the next direction confirmation..
+ }
+ lastDeltaDrag = deltaDrag; // save last
+ }
+ }
+}
+
+/*******************************************************************************
+ * Teleport feature
+ ******************************************************************************/
+
+function Teleporter() {
+
+ var SURFACE_DETECTION_FOR_TELEPORT = true; // true if uses teleport.js
+ // similar logic to detect
+ // surfaces. false if uses plain
+ // teleport to avatar same
+ // height.
+
+ var TELEPORT_TARGET_MODEL_URL = Script
+ .resolvePath("../assets/models/teleport-destination.fbx");
+ var TELEPORT_TOO_CLOSE_MODEL_URL = Script
+ .resolvePath("../assets/models/teleport-cancel.fbx");
+
+ var TELEPORT_MODEL_DEFAULT_DIMENSIONS = {
+ x : 0.10,
+ y : 0.00001,
+ z : 0.10
+ };
+
+ var teleportOverlay = Overlays.addOverlay("model", {
+ url : TELEPORT_TARGET_MODEL_URL,
+ dimensions : TELEPORT_MODEL_DEFAULT_DIMENSIONS,
+ orientation : Quat.fromPitchYawRollDegrees(0, 180, 0),
+ visible : false
+ });
+
+ var teleportCancelOverlay = Overlays.addOverlay("model", {
+ url : TELEPORT_TOO_CLOSE_MODEL_URL,
+ dimensions : TELEPORT_MODEL_DEFAULT_DIMENSIONS,
+ orientation : Quat.fromPitchYawRollDegrees(0, 180, 0),
+ visible : false
+ });
+
+ var TELEPORT_COLOR = {
+ red : 0,
+ green : 255,
+ blue : 255
+ };
+ var TELEPORT_CANCEL_COLOR = {
+ red : 255,
+ green : 255,
+ blue : 0
+ };
+
+ var teleportLine = Overlays.addOverlay("line3d", {
+ start : {
+ x : 0,
+ y : 0,
+ z : 0
+ },
+ end : {
+ x : 0,
+ y : 0,
+ z : 0
+ },
+ color : TELEPORT_COLOR,
+ alpha : 1,
+ lineWidth : 2,
+ dashed : false,
+ visible : false
+ });
+
+ // code from teleport.js
+ var TELEPORT_TARGET = {
+ NONE : 'none', // Not currently targetting anything
+ INVISIBLE : 'invisible', // The current target is an invvsible
+ // surface
+ INVALID : 'invalid', // The current target is invalid (wall, ceiling,
+ // etc.)
+ SURFACE : 'surface', // The current target is a valid surface
+ SEAT : 'seat', // The current target is a seat
+ }
+
+ var TELEPORT_CANCEL_RANGE = 1;
+ var teleportTargetType = TELEPORT_TARGET.NONE;
+
+ function parseJSON(json) {
+ try {
+ return JSON.parse(json);
+ } catch (e) {
+ return undefined;
+ }
+ }
+
+ /*
+ * Enhanced with intersection with terrain instead of using current avatar y
+ * position if SURFACE_DETECTION_FOR_TELEPORT is true
+ */
+ function computeDestination(touchEventPos, avatarPosition, cameraPosition,
+ radarH) {
+ if (SURFACE_DETECTION_FOR_TELEPORT) {
+ var pickRay = Camera.computePickRay(touchEventPos.x,
+ touchEventPos.y);
+ printd("newTeleportDetect - pickRay " + JSON.stringify(pickRay));
+ var destination = Entities.findRayIntersection(pickRay, true, [],
+ [], false, true);
+ printd("newTeleportDetect - destination "
+ + JSON.stringify(destination));
+ return destination;
+ } else {
+ var pickRay = Camera.computePickRay(touchEventPos.x,
+ touchEventPos.y);
+ var pointingAt = Vec3.sum(pickRay.origin, Vec3.multiply(
+ pickRay.direction, radarH));
+ var destination = {
+ x : pointingAt.x,
+ y : avatarPosition.y,
+ z : pointingAt.z
+ };
+ return destination;
+ }
+ }
+
+ function renderTeleportOverlays(destination) {
+ var overlayPosition = findLineToHeightIntersection(destination,
+ Camera.position, Camera.position.y
+ - RADAR_CAMERA_DISTANCE_TO_ICONS);
+ printd("[newTeleport] TELEPORT ! render overlay at "
+ + JSON.stringify(overlayPosition));
+
+ // CLD note Oct 11, 2017
+ // Version of teleport.js 3c109f294f88ba7573bd1221f907f2605893c509
+ // doesn't allow invisible surfaces, let's allow it for now
+ if (teleportTargetType == TELEPORT_TARGET.SURFACE
+ || teleportTargetType == TELEPORT_TARGET.INVISIBLE) {
+ Overlays.editOverlay(teleportOverlay, {
+ visible : true,
+ position : overlayPosition
+ });
+ Overlays.editOverlay(teleportCancelOverlay, {
+ visible : false
+ });
+ Overlays.editOverlay(teleportLine, {
+ start : MyAvatar.position,
+ end : destination,
+ color : TELEPORT_COLOR,
+ visible : true
+ });
+ } else if (teleportTargetType == TELEPORT_TARGET.INVALID) {
+ Overlays.editOverlay(teleportOverlay, {
+ visible : false
+ });
+ Overlays.editOverlay(teleportCancelOverlay, {
+ visible : true,
+ position : overlayPosition
+ });
+ Overlays.editOverlay(teleportLine, {
+ start : MyAvatar.position,
+ end : destination,
+ color : TELEPORT_CANCEL_COLOR,
+ visible : true
+ });
+ } else { // TELEPORT_TARGET:NONE?
+ Overlays.editOverlay(teleportOverlay, {
+ visible : false
+ });
+ Overlays.editOverlay(teleportCancelOverlay, {
+ visible : false
+ });
+ Overlays.editOverlay(teleportLine, {
+ visible : false
+ });
+ }
+ }
+
+ var BORDER_DISTANCE_PX = 100;
+ var border_top = 0;
+ var border_left = 0;
+ var border_right = Window.innerWidth;
+ var border_bottom = Window.innerHeight;
+
+ function moveOnBorders(event) {
+ var xDelta = 0;
+ var zDelta = 0;
+
+ if (event.y <= border_top + BORDER_DISTANCE_PX) {
+ zDelta = -0.1;
+ } else if (event.y >= border_bottom - BORDER_DISTANCE_PX) {
+ zDelta = 0.1;
+ }
+ if (event.x <= border_left + BORDER_DISTANCE_PX) {
+ xDelta = -0.1;
+ } else if (event.x >= border_right - BORDER_DISTANCE_PX) {
+ xDelta = 0.1;
+ }
+ if (xDelta == 0 && zDelta == 0) {
+ draggingCamera = false;
+ return;
+ }
+
+ Camera.position = Vec3.sum(Camera.position, {
+ x : xDelta,
+ y : 0,
+ z : zDelta
+ });
+ draggingCamera = true;
+ }
+
+ // When determininig whether you can teleport to a location, the normal of
+ // the
+ // point that is being intersected with is looked at. If this normal is more
+ // than MAX_ANGLE_FROM_UP_TO_TELEPORT degrees from <0, 1, 0> (straight up),
+ // then
+ // you can't teleport there.
+ const MAX_ANGLE_FROM_UP_TO_TELEPORT = 70;
+ function getTeleportTargetType(intersection) {
+ if (SURFACE_DETECTION_FOR_TELEPORT) {
+ if (!intersection.intersects) {
+ return TELEPORT_TARGET.NONE;
+ }
+ var props = Entities.getEntityProperties(intersection.entityID, [
+ 'userData', 'visible' ]);
+ var data = parseJSON(props.userData);
+ if (data !== undefined && data.seat !== undefined) {
+ return TELEPORT_TARGET.SEAT;
+ }
+
+ if (!props.visible) {
+ return TELEPORT_TARGET.INVISIBLE;
+ }
+
+ var surfaceNormal = intersection.surfaceNormal;
+ var adj = Math.sqrt(surfaceNormal.x * surfaceNormal.x
+ + surfaceNormal.z * surfaceNormal.z);
+ var angleUp = Math.atan2(surfaceNormal.y, adj) * (180 / Math.PI);
+
+ if (angleUp < (90 - MAX_ANGLE_FROM_UP_TO_TELEPORT)
+ || angleUp > (90 + MAX_ANGLE_FROM_UP_TO_TELEPORT)
+ || Vec3.distance(MyAvatar.position,
+ intersection.intersection) <= TELEPORT_CANCEL_RANGE) {
+ return TELEPORT_TARGET.INVALID;
+ } else {
+ return TELEPORT_TARGET.SURFACE;
+ }
+ } else {
+ var destination = intersection;
+ if (Vec3.distance(MyAvatar.position, destination) <= TELEPORT_CANCEL_RANGE) {
+ return TELEPORT_TARGET.INVALID;
+ } else {
+ return TELEPORT_TARGET.SURFACE;
+ }
+ }
+ }
+ ;
+
+ function moveToFromEvent(event) {
+ var destination = computeDestination(event, MyAvatar.position,
+ Camera.position, radarHeight);
+ moveTo(SURFACE_DETECTION_FOR_TELEPORT ? Vec3.sum(
+ destination.intersection, {
+ y : 1
+ }) : destination);
+ return true;
+ }
+
+ return {
+ dragTeleportBegin : function(event) {
+ printd("[newTeleport] TELEPORT began");
+ var overlayDimensions = entityIconModelDimensions();
+ // var destination = computeDestination(event, MyAvatar.position,
+ // Camera.position, radarHeight);
+ // Dimension teleport and cancel overlays (not show them yet)
+ Overlays.editOverlay(teleportOverlay, {
+ dimensions : overlayDimensions
+ });
+ Overlays.editOverlay(teleportCancelOverlay, {
+ dimensions : overlayDimensions
+ });
+ // Position line
+ Overlays.editOverlay(teleportLine, {
+ visible : true,
+ start : 0,
+ end : 0
+ });
+ },
+
+ dragTeleportUpdate : function(event) {
+ // if in border, move camera
+ moveOnBorders(event);
+
+ var destination = computeDestination(event, MyAvatar.position,
+ Camera.position, radarHeight);
+
+ teleportTargetType = getTeleportTargetType(destination);
+ renderTeleportOverlays(SURFACE_DETECTION_FOR_TELEPORT ? destination.intersection
+ : destination);
+ },
+
+ dragTeleportRelease : function(event) {
+ printd("[newTeleport] TELEPORT released at "
+ + JSON.stringify(event));
+ // CLD note Oct 11, 2017
+ // Version of teleport.js 3c109f294f88ba7573bd1221f907f2605893c509
+ // doesn't allow invisible surfaces, let's allow it for now
+ if (teleportTargetType == TELEPORT_TARGET.SURFACE
+ || teleportTargetType == TELEPORT_TARGET.INVISIBLE) {
+ moveToFromEvent(event);
+ }
+ teleportTargetType = TELEPORT_TARGET.NONE;
+
+ Overlays.editOverlay(teleportOverlay, {
+ visible : false
+ });
+ Overlays.editOverlay(teleportLine, {
+ visible : false
+ });
+ Overlays.editOverlay(teleportCancelOverlay, {
+ visible : false
+ });
+ }
+ };
+
+}
+
+var teleporter = Teleporter();
+
+/*******************************************************************************
+ *
+ ******************************************************************************/
+
+var dragModeFunc = null; // by default is nothing
+
+function oneFingerTouchUpdate(event) {
+ if (dragModeFunc) {
+ dragModeFunc(event);
+ } else {
+ if (!isInsideSquare(touchStartingCoordinates, event,
+ MIN_DRAG_DISTANCE_TO_CONSIDER)) {
+ dragModeFunc = dragScrollUpdate;
+ dragModeFunc(event);
+ } else {
+ var now = Date.now(); // check time
+ if (now - touchBeginTime >= KEEP_PRESSED_FOR_TELEPORT_MODE_TIME) {
+ teleporter.dragTeleportBegin(event);
+ dragModeFunc = teleporter.dragTeleportUpdate;
+ dragModeFunc(event);
+ } else {
+ // not defined yet, let's wait for time or movement to happen
+ }
+ }
+ }
+}
+
+function touchUpdate(event) {
+ if (!currentTouchIsValid) {
+ return; // avoid moving and zooming when tap is over UI entities
+ }
+ if (event.isPinching || event.isPinchOpening) {
+ pinchUpdate(event);
+ } else {
+ oneFingerTouchUpdate(event);
+ }
+}
+
+/*******************************************************************************
+ * Avatar cache structure for showing avatars markers
+ ******************************************************************************/
+
+// by QUuid
+var avatarsData = {};
+var avatarsIcons = []; // a parallel list of icons (overlays) to easily run
+ // through
+var avatarsNames = []; // a parallel list of names (overlays) to easily run
+ // through
+
+function getAvatarIconForUser(uid) {
+ var color = uniqueColor.getColor(uid);
+ if (color.charAt(0) == '#') {
+ color = color.substring(1, color.length);
+ }
+ // FIXME: this is a temporary solution until we can use circle3d with
+ // lineWidth
+ return Script.resolvePath("assets/images/circle-" + color + ".svg");
+}
+
+var avatarIconDimensionsVal = {
+ x : 0,
+ y : 0,
+ z : 0.00001
+};
+function avatarIconPlaneDimensions() {
+ // given the current height, give a size
+ var xy = -0.003531 * radarHeight + 0.1;
+ avatarIconDimensionsVal.x = Math.abs(xy);
+ avatarIconDimensionsVal.y = Math.abs(xy);
+ // reuse object
+ return avatarIconDimensionsVal;
+}
+
+function currentOverlayIconForAvatar(QUuid) {
+ if (avatarsData[QUuid] != undefined) {
+ return avatarsData[QUuid].icon;
+ } else {
+ return null;
+ }
+}
+
+function currentOverlayNameForAvatar(QUuid) {
+ if (avatarsData[QUuid] != undefined) {
+ return avatarsData[QUuid].name;
+ } else {
+ return null;
+ }
+}
+
+function saveAvatarData(QUuid) {
+ if (QUuid == null)
+ return;
+ var avat = AvatarList.getAvatar(QUuid);
+ printd("avatar added save avatar " + QUuid);
+
+ if (!avat)
+ return;
+
+ if (avatarsData[QUuid] != undefined) {
+ avatarsData[QUuid].position = avat.position;
+ } else {
+ var avatarIcon = Overlays.addOverlay("image3d", {
+ subImage : {
+ x : 0,
+ y : 0,
+ width : 150,
+ height : 142
+ },
+ url : getAvatarIconForUser(QUuid),
+ dimensions : ICON_ENTITY_DEFAULT_DIMENSIONS,
+ visible : false,
+ ignoreRayIntersection : false,
+ orientation : Quat.fromPitchYawRollDegrees(-90, 0, 0)
+ });
+
+ var needRefresh = !avat || !avat.displayName;
+ var displayName = avat && avat.displayName ? avat.displayName
+ : "Unknown";
+ var textWidth = displayName.length * AVATAR_DISPLAY_NAME_CHAR_WIDTH;
+ var avatarName = Overlays.addOverlay("text", {
+ width : textWidth,
+ height : AVATAR_DISPLAY_NAME_HEIGHT,
+ color : {
+ red : 255,
+ green : 255,
+ blue : 255
+ },
+ backgroundAlpha : 0.0,
+ textRaiseColor : {
+ red : 0,
+ green : 0,
+ blue : 0
+ },
+ font : {
+ size : 68,
+ bold : true
+ },
+ visible : false,
+ text : displayName,
+ textAlignCenter : true
+ });
+ avatarsIcons.push(avatarIcon);
+ avatarsNames.push(avatarName);
+ avatarsData[QUuid] = {
+ position : avat.position,
+ icon : avatarIcon,
+ name : avatarName,
+ textWidth : textWidth,
+ needRefresh : needRefresh
+ };
+ }
+}
+
+function removeAvatarData(QUuid) {
+ if (QUuid == null)
+ return;
+
+ var itsOverlay = currentOverlayIconForAvatar(QUuid);
+ if (itsOverlay != null) {
+ Overlays.deleteOverlay(itsOverlay);
+ }
+ var itsNameOverlay = currentOverlayNameForAvatar(QUuid);
+ if (itsNameOverlay != null) {
+ Overlays.deleteOverlay(itsNameOverlay);
+ }
+
+ var idx = avatarsIcons.indexOf(itsOverlay);
+ avatarsIcons.splice(idx, 1);
+ idx = avatarsNames.indexOf(itsNameOverlay);
+ avatarsNames.splice(idx, 1);
+
+ delete avatarsData[QUuid];
+}
+
+function saveAllOthersAvatarsData() {
+ var avatarIds = AvatarList.getAvatarIdentifiers();
+ var len = avatarIds.length;
+ for (var i = 0; i < len; i++) {
+ if (avatarIds[i]) {
+ saveAvatarData(avatarIds[i]);
+ }
+ }
+}
+
+function avatarAdded(QUuid) {
+ printd("avatar added " + QUuid);// + " at " +
+ // JSON.stringify(AvatarList.getAvatar(QUuid).position));
+ saveAvatarData(QUuid);
+}
+
+function avatarRemoved(QUuid) {
+ printd("avatar removed " + QUuid);
+ removeAvatarData(QUuid);
+}
+
+/*******************************************************************************
+ * Avatar Icon/Markers rendering
+ ******************************************************************************/
+var myAvatarIcon;
+var myAvatarName;
+
+function renderMyAvatarIcon() {
+ var iconPos = findLineToHeightIntersectionCoords(MyAvatar.position.x,
+ MyAvatar.position.y + RADAR_ICONS_APPARENT_DISTANCE_TO_AVATAR_BASE,
+ MyAvatar.position.z, Camera.position.x, Camera.position.y,
+ Camera.position.z, Camera.position.y
+ - RADAR_CAMERA_DISTANCE_TO_ICONS);
+ if (!iconPos) {
+ printd("avatarmy icon pos null");
+ return;
+ }
+ var iconDimensions = avatarIconPlaneDimensions();
+
+ var avatarPos = MyAvatar.position;
+ var cameraPos = Camera.position;
+ var commonY = Camera.position.y - RADAR_CAMERA_DISTANCE_TO_ICONS;
+ var borderPoints = [
+ computePointAtPlaneY(0, 0, commonY),
+ computePointAtPlaneY(Window.innerWidth, Window.innerHeight, commonY) ];
+
+ var p1 = findLineToHeightIntersectionCoords(avatarPos.x, avatarPos.y,
+ avatarPos.z, cameraPos.x, cameraPos.y, cameraPos.z, commonY);
+ var x = (p1.x - borderPoints[0].x) * (Window.innerWidth)
+ / (borderPoints[1].x - borderPoints[0].x);
+ var y = (p1.z - borderPoints[0].z) * (Window.innerHeight)
+ / (borderPoints[1].z - borderPoints[0].z);
+
+ if (!myAvatarIcon && MyAvatar.sessionUUID) {
+ myAvatarIcon = Overlays.addOverlay("image3d", {
+ subImage : {
+ x : 0,
+ y : 0,
+ width : 150,
+ height : 142
+ },
+ url : getAvatarIconForUser(MyAvatar.sessionUUID),
+ dimensions : ICON_ENTITY_DEFAULT_DIMENSIONS,
+ visible : false,
+ ignoreRayIntersection : false,
+ orientation : Quat.fromPitchYawRollDegrees(-90, 0, 0)
+ });
+ }
+
+ if (!myAvatarName) {
+ myAvatarName = Overlays.addOverlay("text", {
+ width : 40,
+ height : AVATAR_DISPLAY_NAME_HEIGHT,
+ textAlignCenter : true,
+ color : {
+ red : 255,
+ green : 255,
+ blue : 255
+ },
+ backgroundAlpha : 0.0,
+ font : {
+ size : 68,
+ bold : true
+ },
+ textRaiseColor : {
+ red : 0,
+ green : 0,
+ blue : 0
+ },
+ visible : false,
+ text : "Me"
+ });
+ }
+
+ if (myAvatarIcon) {
+ Overlays.editOverlay(myAvatarIcon, {
+ visible : true,
+ dimensions : iconDimensions,
+ position : iconPos
+ });
+
+ }
+ var textSize = (14 + (iconDimensions.y - 0.03) * 15 / 0.06);
+
+ Overlays.editOverlay(myAvatarName, {
+ visible : true,
+ x : x - 18 + (iconDimensions.y - 0.03) * 2 / 0.06,
+ y : y + iconDimensions.y * 550,
+ font : {
+ size : textSize,
+ bold : true
+ },
+ });
+
+}
+
+function hideAllAvatarIcons() {
+ var len = avatarsIcons.length;
+ for (var i = 0; i < len; i++) {
+ Overlays.editOverlay(avatarsIcons[i], {
+ visible : false
+ });
+ }
+ len = avatarsNames.length;
+ for (var j = 0; j < len; j++) {
+ Overlays.editOverlay(avatarsNames[j], {
+ visible : false
+ });
+ }
+ if (myAvatarIcon) {
+ Overlays.editOverlay(myAvatarIcon, {
+ visible : false
+ });
+ }
+ Overlays.editOverlay(myAvatarName, {
+ visible : false
+ })
+}
+
+function renderAllOthersAvatarIcons() {
+ var avatarPos;
+ var iconDimensions = avatarIconPlaneDimensions();
+ var commonY = Camera.position.y - RADAR_CAMERA_DISTANCE_TO_ICONS;
+ var borderPoints = [
+ computePointAtPlaneY(0, 0, commonY),
+ computePointAtPlaneY(Window.innerWidth, Window.innerHeight, commonY) ];
+
+ for ( var QUuid in avatarsData) {
+ if (avatarsData.hasOwnProperty(QUuid)) {
+ if (AvatarList.getAvatar(QUuid) != null) {
+ avatarPos = AvatarList.getAvatar(QUuid).position;
+
+ var cameraPos = Camera.position;
+ var p1 = findLineToHeightIntersectionCoords(avatarPos.x,
+ avatarPos.y, avatarPos.z, cameraPos.x, cameraPos.y,
+ cameraPos.z, commonY);
+
+ var x = (p1.x - borderPoints[0].x) * (Window.innerWidth)
+ / (borderPoints[1].x - borderPoints[0].x);
+ var y = (p1.z - borderPoints[0].z) * (Window.innerHeight)
+ / (borderPoints[1].z - borderPoints[0].z);
+
+ if (avatarsData[QUuid].icon != undefined) {
+ var iconPos = findLineToHeightIntersectionCoords(
+ avatarPos.x,
+ avatarPos.y
+ + RADAR_ICONS_APPARENT_DISTANCE_TO_AVATAR_BASE,
+ avatarPos.z, Camera.position.x, Camera.position.y,
+ Camera.position.z, Camera.position.y
+ - RADAR_CAMERA_DISTANCE_TO_ICONS);
+ if (!iconPos) {
+ print("avatar icon pos bad for " + QUuid);
+ continue;
+ }
+ if (avatarsData[QUuid].needRefresh) {
+ var avat = AvatarList.getAvatar(QUuid);
+ if (avat && avat.displayName) {
+ Overlays.editOverlay(avatarsData[QUuid].name, {
+ width : avat.displayName.length
+ * AVATAR_DISPLAY_NAME_CHAR_WIDTH,
+ text : avat.displayName,
+ textAlignCenter : true
+ });
+ avatarsData[QUuid].needRefresh = false;
+ }
+ }
+ var textSize = (14 + (iconDimensions.y - 0.03) * 15 / 0.06);
+ Overlays.editOverlay(avatarsData[QUuid].icon, {
+ visible : true,
+ dimensions : iconDimensions,
+ position : iconPos
+ });
+ Overlays.editOverlay(avatarsData[QUuid].name, {
+ visible : true,
+ x : x - avatarsData[QUuid].textWidth * 0.5,
+ y : y + iconDimensions.y * 550,
+ font : {
+ size : textSize,
+ bold : true
+ }
+ });
+ }
+ }
+ }
+ }
+}
+
+function entityAdded(entityID) {
+ printd("Entity added " + entityID);
+ var props = Entities.getEntityProperties(entityID, [ "type" ]);
+ printd("Entity added " + entityID + " PROPS " + JSON.stringify(props));
+ if (props && props.type == "Web") {
+ printd("Entity Web added " + entityID);
+ saveEntityData(entityID, true);
+ }
+}
+
+function entityRemoved(entityID) {
+ printd("Entity removed " + entityID);
+ var props = Entities.getEntityProperties(entityID, [ "type" ]);
+ if (props && props.type == "Web") {
+ print("Entity Web removed " + entityID);
+ removeEntityData(entityID);
+ }
+}
+
+/*******************************************************************************
+ * Entities (to remark) cache structure for showing entities markers
+ ******************************************************************************/
+
+var entitiesData = {}; // by entityID
+var entitiesByOverlayID = {}; // by overlayID
+var entitiesIcons = []; // a parallel list of icons (overlays) to easily run
+ // through
+
+var ICON_ENTITY_WEB_MODEL_URL = Script.resolvePath("../assets/images/web.svg");
+var ICON_ENTITY_IMG_MODEL_URL = Script
+ .resolvePath("../assets/models/teleport-cancel.fbx"); // FIXME - use
+ // correct
+ // model&texture
+var ICON_ENTITY_DEFAULT_DIMENSIONS = {
+ x : 0.10,
+ y : 0.00001,
+ z : 0.10
+};
+
+var entityIconModelDimensionsVal = {
+ x : 0,
+ y : 0.00001,
+ z : 0
+};
+function entityIconModelDimensions() {
+ // given the current height, give a size
+ var xz = -0.002831 * radarHeight + 0.1;
+ entityIconModelDimensionsVal.x = xz;
+ entityIconModelDimensionsVal.z = xz;
+ // reuse object
+ return entityIconModelDimensionsVal;
+}
+/*
+ * entityIconPlaneDimensions: similar to entityIconModelDimensions but using xy
+ * plane
+ */
+function entityIconPlaneDimensions() {
+ var dim = entityIconModelDimensions();
+ var z = dim.z;
+ dim.z = dim.y;
+ dim.y = z;
+ return dim;
+}
+
+function currentOverlayForEntity(QUuid) {
+ if (entitiesData[QUuid] != undefined) {
+ return entitiesData[QUuid].icon;
+ } else {
+ return null;
+ }
+}
+
+function saveEntityData(QUuid, planar) {
+ if (QUuid == null)
+ return;
+ var entity = Entities.getEntityProperties(QUuid, [ "position" ]);
+ printd("entity added save entity " + QUuid);
+ if (entitiesData[QUuid] != undefined) {
+ entitiesData[QUuid].position = entity.position;
+ } else {
+ var entityIcon = Overlays.addOverlay("image3d", {
+ subImage : {
+ x : 0,
+ y : 0,
+ width : 150,
+ height : 150
+ },
+ url : ICON_ENTITY_WEB_MODEL_URL,
+ dimensions : ICON_ENTITY_DEFAULT_DIMENSIONS,
+ visible : false,
+ ignoreRayIntersection : false,
+ orientation : Quat.fromPitchYawRollDegrees(-90, 0, 0)
+ });
+
+ entitiesIcons.push(entityIcon);
+ entitiesData[QUuid] = {
+ position : entity.position,
+ icon : entityIcon
+ };
+ entitiesByOverlayID[entityIcon] = QUuid;
+ }
+}
+
+function removeEntityData(QUuid) {
+ if (QUuid == null)
+ return;
+
+ var itsOverlay = currentOverlayForEntity(QUuid);
+ if (itsOverlay != null) {
+ Overlays.deleteOverlay(itsOverlay);
+ delete entitiesByOverlayID[itsOverlay];
+ }
+ var idx = entitiesIcons.indexOf(itsOverlay);
+ entitiesIcons.splice(idx, 1);
+
+ delete entitiesData[QUuid];
+}
+
+/*******************************************************************************
+ * Entities to remark Icon/Markers rendering
+ ******************************************************************************/
+
+function hideAllEntitiesIcons() {
+ var len = entitiesIcons.length;
+ for (var i = 0; i < len; i++) {
+ Overlays.editOverlay(entitiesIcons[i], {
+ visible : false
+ });
+ }
+}
+
+function renderAllEntitiesIcons() {
+ var entityPos;
+ var entityProps;
+ var iconDimensions = entityIconModelDimensions();
+ var planeDimensions = entityIconPlaneDimensions(); // plane overlays uses
+ // xy instead of xz
+ for ( var QUuid in entitiesData) {
+ if (entitiesData.hasOwnProperty(QUuid)) {
+ entityProps = Entities.getEntityProperties(QUuid, [ "position",
+ "visible" ]);
+ if (entityProps != null) {
+ entityPos = entityProps.position;
+ if (entitiesData[QUuid].icon != undefined && entityPos) {
+ var iconPos = findLineToHeightIntersectionCoords(
+ entityPos.x,
+ entityPos.y
+ + RADAR_ICONS_APPARENT_DISTANCE_TO_AVATAR_BASE,
+ entityPos.z, Camera.position.x, Camera.position.y,
+ Camera.position.z, Camera.position.y
+ - RADAR_CAMERA_DISTANCE_TO_ICONS);
+ if (!iconPos) {
+ printd("entity icon pos bad for " + QUuid);
+ continue;
+ }
+ var dimensions = entitiesData[QUuid].planar ? planeDimensions
+ : iconDimensions;
+ Overlays.editOverlay(entitiesData[QUuid].icon, {
+ visible : entityProps.visible,
+ dimensions : dimensions,
+ position : iconPos
+ });
+ }
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+ *
+ ******************************************************************************/
+
+function startRadar() {
+ printd("avatar added my avatar is " + MyAvatar.sessionUUID);
+ saveAllOthersAvatarsData();
+ Camera.mode = "independent";
+
+ Camera.position = Vec3.sum(MyAvatar.position, {
+ x : 0,
+ y : radarHeight,
+ z : 0
+ });
+ Camera.orientation = Quat.fromPitchYawRollDegrees(-90, 0, 0);
+ radar = true;
+
+ connectRadarModeEvents();
+}
+
+function endRadar() {
+ printd("-- endRadar");
+ Camera.mode = "first person";
+ radar = false;
+
+ disconnectRadarModeEvents();
+ hideAllEntitiesIcons();
+ hideAllAvatarIcons();
+}
+
+function onRadarModeClicked() {
+ startRadar();
+}
+
+function onMyViewModeClicked() {
+ endRadar();
+}
+
+radarModeInterface.startRadarMode = function() {
+ startRadar();
+};
+
+radarModeInterface.endRadarMode = function() {
+ endRadar();
+};
+
+radarModeInterface.init = function() {
+ init();
+}
+
+radarModeInterface.setUniqueColor = function(c) {
+ uniqueColor = c;
+};
+
+module.exports = radarModeInterface;
+
+function updateRadar() {
+ // Update avatar icons
+ if (startedDraggingCamera) {
+ hideAllAvatarIcons();
+ hideAllEntitiesIcons();
+ startedDraggingCamera = false;
+ } else if (!draggingCamera) {
+ renderMyAvatarIcon();
+ renderAllOthersAvatarIcons();
+ renderAllEntitiesIcons();
+ }
+}
+
+function valueIfDefined(value) {
+ return value !== undefined ? value : "";
+}
+
+function entitiesAnalysis() {
+ var ids = Entities.findEntitiesInFrustum(Camera.frustum);
+ var entities = [];
+ for (var i = 0; i < ids.length; i++) {
+ var id = ids[i];
+ var properties = Entities.getEntityProperties(id);
+ entities.push({
+ id : id,
+ name : properties.name,
+ type : properties.type,
+ url : properties.type == "Model" ? properties.modelURL : "",
+ sourceUrl : properties.sourceUrl,
+ locked : properties.locked,
+ visible : properties.visible,
+ drawCalls : valueIfDefined(properties.renderInfo.drawCalls),
+ hasScript : properties.script !== ""
+ });
+ }
+}
+
+function connectRadarModeEvents() {
+ Script.update.connect(updateRadar); // 60Hz loop
+ Controller.keyPressEvent.connect(keyPressEvent);
+ Controller.mousePressEvent.connect(mousePress); // single click/touch
+ Controller.touchUpdateEvent.connect(touchUpdate);
+ MyAvatar.positionGoneTo.connect(positionGoneTo);
+}
+
+function positionGoneTo() {
+ Camera.position = Vec3.sum(MyAvatar.position, {
+ x : 0,
+ y : radarHeight,
+ z : 0
+ });
+}
+
+function disconnectRadarModeEvents() {
+ Script.update.disconnect(updateRadar);
+ Controller.keyPressEvent.disconnect(keyPressEvent);
+ Controller.mousePressEvent.disconnect(mousePress);
+ Controller.touchUpdateEvent.disconnect(touchUpdate);
+ MyAvatar.positionGoneTo.disconnect(positionGoneTo);
+}
+
+function init() {
+ tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
+
+ Controller.touchBeginEvent.connect(touchBegin);
+ Controller.touchEndEvent.connect(touchEnd);
+
+ AvatarList.avatarAddedEvent.connect(avatarAdded);
+ AvatarList.avatarRemovedEvent.connect(avatarRemoved);
+
+ Entities.addingEntity.connect(entityAdded);
+ Entities.deletingEntity.connect(entityRemoved);
+}
diff --git a/scripts/system/+android/touchscreenvirtualpad.js b/scripts/system/+android/touchscreenvirtualpad.js
new file mode 100644
index 0000000000..fa41a2b5e0
--- /dev/null
+++ b/scripts/system/+android/touchscreenvirtualpad.js
@@ -0,0 +1,21 @@
+"use strict";
+//
+// touchscreenvirtualpad.js
+// scripts/system/
+//
+// Created by Gabriel Calero & Cristian Duarte on Jan 16, 2018
+// 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
+//
+
+(function() { // BEGIN LOCAL_SCOPE
+
+function init() {
+ Controller.setVPadEnabled(true);
+}
+
+init();
+
+}()); // END LOCAL_SCOPE
diff --git a/scripts/system/+android/uniqueColor.js b/scripts/system/+android/uniqueColor.js
new file mode 100644
index 0000000000..c296b6c87d
--- /dev/null
+++ b/scripts/system/+android/uniqueColor.js
@@ -0,0 +1,46 @@
+"use strict";
+//
+// uniqueColor.js
+// scripts/system/
+//
+// Created by Gabriel Calero & Cristian Duarte on 17 Oct 2017
+// Copyright 2017 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 colorsMap = {};
+var colorsCount = 0;
+ // 'red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'magenta'
+var baseColors = [ '#EB3345', '#F0851F', '#FFCD29', '#94C338', '#11A6C5', '#294C9F', '#C01D84' ];
+
+function getNextColor(n) {
+ var N = baseColors.length;
+ /*if (n < baseColors.length) {
+ return baseColors[n];
+ } else {
+ var baseColor = baseColors[n % N];
+ var d = (n / N) % 10;
+ var c2 = "" + Qt.lighter(baseColor, 1 + d / 10);
+ return c2;
+ }*/
+ return baseColors[n%N];
+}
+
+function getColorForId(uuid) {
+ if (colorsMap == undefined) {
+ colorsMap = {};
+ }
+ if (!colorsMap.hasOwnProperty(uuid)) {
+ colorsMap[uuid] = getNextColor(colorsCount);
+ colorsCount = colorsCount + 1;
+ }
+ return colorsMap[uuid];
+}
+
+module.exports = {
+ getColor: function(id) {
+ return getColorForId(id);
+ }
+};
diff --git a/server-console/package-lock.json b/server-console/package-lock.json
index ba8ef3c720..e25fd3cded 100644
--- a/server-console/package-lock.json
+++ b/server-console/package-lock.json
@@ -151,7 +151,8 @@
"balanced-match": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.3.0.tgz",
- "integrity": "sha1-qRzdHr7xqGZZ5w/03vAWJfwtZ1Y="
+ "integrity": "sha1-qRzdHr7xqGZZ5w/03vAWJfwtZ1Y=",
+ "dev": true
},
"base64-js": {
"version": "1.2.0",
@@ -220,6 +221,7 @@
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.3.tgz",
"integrity": "sha1-Rr/1ARXUf8mriYVKu4fZgHihCZE=",
+ "dev": true,
"requires": {
"balanced-match": "0.3.0",
"concat-map": "0.0.1"
@@ -345,7 +347,8 @@
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
},
"concat-stream": {
"version": "1.5.0",
@@ -886,17 +889,21 @@
}
},
"fs-extra": {
- "version": "0.26.7",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz",
- "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=",
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz",
+ "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=",
"requires": {
"graceful-fs": "4.1.3",
"jsonfile": "2.2.3",
- "klaw": "1.1.3",
- "path-is-absolute": "1.0.0",
- "rimraf": "2.5.2"
+ "klaw": "1.3.1"
}
},
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
"generate-function": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz",
@@ -1003,15 +1010,44 @@
"dev": true
},
"glob": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.3.tgz",
- "integrity": "sha1-CqI1kxpKlqwT1g/6wvuHe9btT1g=",
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+ "dev": true,
"requires": {
+ "fs.realpath": "1.0.0",
"inflight": "1.0.4",
"inherits": "2.0.1",
- "minimatch": "3.0.0",
+ "minimatch": "3.0.4",
"once": "1.3.3",
"path-is-absolute": "1.0.0"
+ },
+ "dependencies": {
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "1.1.11"
+ }
+ }
}
},
"graceful-fs": {
@@ -1144,6 +1180,7 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz",
"integrity": "sha1-bLtFIevVHODsCpNr/XZX736bFyo=",
+ "dev": true,
"requires": {
"once": "1.3.3",
"wrappy": "1.0.1"
@@ -1303,9 +1340,20 @@
}
},
"klaw": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.1.3.tgz",
- "integrity": "sha1-faM8a0L5s9yc7ADRfxOvAX/MJyE="
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
+ "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=",
+ "requires": {
+ "graceful-fs": "4.1.11"
+ },
+ "dependencies": {
+ "graceful-fs": {
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+ "optional": true
+ }
+ }
},
"lcid": {
"version": "1.0.0",
@@ -1417,6 +1465,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.0.tgz",
"integrity": "sha1-UjYVelHk8ATBd/s8Un/33Xjw74M=",
+ "dev": true,
"requires": {
"brace-expansion": "1.1.3"
}
@@ -1529,6 +1578,19 @@
"mime-types": "2.1.17"
}
},
+ "fs-extra": {
+ "version": "0.26.7",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz",
+ "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.3",
+ "jsonfile": "2.2.3",
+ "klaw": "1.3.1",
+ "path-is-absolute": "1.0.0",
+ "rimraf": "2.6.2"
+ }
+ },
"har-validator": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
@@ -1912,7 +1974,8 @@
"path-is-absolute": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz",
- "integrity": "sha1-Jj2tpmqz8vsQv3+dJN2PPlcO+RI="
+ "integrity": "sha1-Jj2tpmqz8vsQv3+dJN2PPlcO+RI=",
+ "dev": true
},
"path-parse": {
"version": "1.0.5",
@@ -2184,11 +2247,12 @@
}
},
"rimraf": {
- "version": "2.5.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.2.tgz",
- "integrity": "sha1-YrqUf6TAtDY4Oa7+zU8PutYFlyY=",
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+ "dev": true,
"requires": {
- "glob": "7.0.3"
+ "glob": "7.1.2"
}
},
"safe-buffer": {
diff --git a/server-console/package.json b/server-console/package.json
index 9f47d0e4cc..0b13eeb2a8 100644
--- a/server-console/package.json
+++ b/server-console/package.json
@@ -26,7 +26,7 @@
"always-tail": "0.2.0",
"cheerio": "^0.19.0",
"extend": "^3.0.0",
- "fs-extra": "^0.26.4",
+ "fs-extra": "^1.0.0",
"node-notifier": "^5.2.1",
"os-homedir": "^1.0.1",
"request": "^2.67.0",
diff --git a/tests/animation/src/AnimInverseKinematicsTests.cpp b/tests/animation/src/AnimInverseKinematicsTests.cpp
index f36b8891ff..eba74726bb 100644
--- a/tests/animation/src/AnimInverseKinematicsTests.cpp
+++ b/tests/animation/src/AnimInverseKinematicsTests.cpp
@@ -93,6 +93,9 @@ void makeTestFBXJoints(FBXGeometry& geometry) {
}
void AnimInverseKinematicsTests::testSingleChain() {
+
+ AnimContext context(false, false, false, glm::mat4(), glm::mat4());
+
FBXGeometry geometry;
makeTestFBXJoints(geometry);
@@ -108,14 +111,14 @@ void AnimInverseKinematicsTests::testSingleChain() {
//
// A------>B------>C------>D
AnimPose pose;
- pose.scale = glm::vec3(1.0f);
- pose.rot = identity;
- pose.trans = origin;
+ pose.scale() = glm::vec3(1.0f);
+ pose.rot() = identity;
+ pose.trans() = origin;
AnimPoseVec poses;
poses.push_back(pose);
- pose.trans = xAxis;
+ pose.trans() = xAxis;
for (int i = 1; i < (int)geometry.joints.size(); ++i) {
poses.push_back(pose);
}
@@ -133,8 +136,13 @@ void AnimInverseKinematicsTests::testSingleChain() {
AnimVariantMap varMap;
varMap.set("positionD", targetPosition);
varMap.set("rotationD", targetRotation);
- varMap.set("targetType", (int)IKTarget::Type::RotationAndPosition);
- ikDoll.setTargetVars(QString("D"), QString("positionD"), QString("rotationD"), QString("targetType"));
+ varMap.set("targetTypeD", (int)IKTarget::Type::RotationAndPosition);
+ varMap.set("poleVectorEnabledD", false);
+
+ std::vector flexCoefficients = {1.0f, 1.0f, 1.0f, 1.0f};
+ ikDoll.setTargetVars(QString("D"), QString("positionD"), QString("rotationD"), QString("targetTypeD"),
+ QString("weightD"), 1.0f, flexCoefficients, QString("poleVectorEnabledD"),
+ QString("poleReferenceVectorD"), QString("poleVectorD"));
AnimNode::Triggers triggers;
// the IK solution should be:
@@ -147,14 +155,12 @@ void AnimInverseKinematicsTests::testSingleChain() {
// iterate several times
float dt = 1.0f;
- ikDoll.overlay(varMap, dt, triggers, poses);
- ikDoll.overlay(varMap, dt, triggers, poses);
- ikDoll.overlay(varMap, dt, triggers, poses);
- ikDoll.overlay(varMap, dt, triggers, poses);
- ikDoll.overlay(varMap, dt, triggers, poses);
- ikDoll.overlay(varMap, dt, triggers, poses);
- const AnimPoseVec& relativePoses = ikDoll.overlay(varMap, dt, triggers, poses);
+ const int NUM_FRAMES = 10;
+ for (int i = 0; i < NUM_FRAMES; i++) {
+ poses = ikDoll.overlay(varMap, context, dt, triggers, poses);
+ }
+ const AnimPoseVec& relativePoses = ikDoll.overlay(varMap, context, dt, triggers, poses);
// verify absolute results
// NOTE: since we expect this solution to converge very quickly (one loop)
@@ -164,28 +170,30 @@ void AnimInverseKinematicsTests::testSingleChain() {
absolutePoses.push_back(pose);
}
ikDoll.computeAbsolutePoses(absolutePoses);
+
const float acceptableAngleError = 0.001f;
- QCOMPARE_QUATS(absolutePoses[0].rot, identity, acceptableAngleError);
- QCOMPARE_QUATS(absolutePoses[1].rot, identity, acceptableAngleError);
- QCOMPARE_QUATS(absolutePoses[2].rot, quaterTurnAroundZ, acceptableAngleError);
- QCOMPARE_QUATS(absolutePoses[3].rot, quaterTurnAroundZ, acceptableAngleError);
+ QCOMPARE_QUATS(absolutePoses[0].rot(), identity, acceptableAngleError);
+ QCOMPARE_QUATS(absolutePoses[1].rot(), identity, acceptableAngleError);
+ QCOMPARE_QUATS(absolutePoses[2].rot(), quaterTurnAroundZ, acceptableAngleError);
+ QCOMPARE_QUATS(absolutePoses[3].rot(), quaterTurnAroundZ, acceptableAngleError);
const float acceptableTranslationError = 0.025f;
- QCOMPARE_WITH_ABS_ERROR(absolutePoses[0].trans, origin, acceptableTranslationError);
- QCOMPARE_WITH_ABS_ERROR(absolutePoses[1].trans, xAxis, acceptableTranslationError);
- QCOMPARE_WITH_ABS_ERROR(absolutePoses[2].trans, 2.0f * xAxis, acceptableTranslationError);
- QCOMPARE_WITH_ABS_ERROR(absolutePoses[3].trans, targetPosition, acceptableTranslationError);
+ QCOMPARE_WITH_ABS_ERROR(absolutePoses[0].trans(), origin, acceptableTranslationError);
+ QCOMPARE_WITH_ABS_ERROR(absolutePoses[1].trans(), xAxis, acceptableTranslationError);
+ QCOMPARE_WITH_ABS_ERROR(absolutePoses[2].trans(), 2.0f * xAxis, acceptableTranslationError);
+ QCOMPARE_WITH_ABS_ERROR(absolutePoses[3].trans(), targetPosition, acceptableTranslationError);
// verify relative results
- QCOMPARE_QUATS(relativePoses[0].rot, identity, acceptableAngleError);
- QCOMPARE_QUATS(relativePoses[1].rot, identity, acceptableAngleError);
- QCOMPARE_QUATS(relativePoses[2].rot, quaterTurnAroundZ, acceptableAngleError);
- QCOMPARE_QUATS(relativePoses[3].rot, identity, acceptableAngleError);
+ QCOMPARE_QUATS(relativePoses[0].rot(), identity, acceptableAngleError);
+ QCOMPARE_QUATS(relativePoses[1].rot(), identity, acceptableAngleError);
+ QCOMPARE_QUATS(relativePoses[2].rot(), quaterTurnAroundZ, acceptableAngleError);
+ QCOMPARE_QUATS(relativePoses[3].rot(), identity, acceptableAngleError);
+
+ QCOMPARE_WITH_ABS_ERROR(relativePoses[0].trans(), origin, acceptableTranslationError);
+ QCOMPARE_WITH_ABS_ERROR(relativePoses[1].trans(), xAxis, acceptableTranslationError);
+ QCOMPARE_WITH_ABS_ERROR(relativePoses[2].trans(), xAxis, acceptableTranslationError);
+ QCOMPARE_WITH_ABS_ERROR(relativePoses[3].trans(), xAxis, acceptableTranslationError);
- QCOMPARE_WITH_ABS_ERROR(relativePoses[0].trans, origin, acceptableTranslationError);
- QCOMPARE_WITH_ABS_ERROR(relativePoses[1].trans, xAxis, acceptableTranslationError);
- QCOMPARE_WITH_ABS_ERROR(relativePoses[2].trans, xAxis, acceptableTranslationError);
- QCOMPARE_WITH_ABS_ERROR(relativePoses[3].trans, xAxis, acceptableTranslationError);
}
{ // hard test IK of joint C
// load intial poses that look like this:
@@ -196,15 +204,15 @@ void AnimInverseKinematicsTests::testSingleChain() {
// A------>B
//
AnimPose pose;
- pose.scale = glm::vec3(1.0f);
- pose.rot = identity;
- pose.trans = origin;
+ pose.scale() = glm::vec3(1.0f);
+ pose.rot() = identity;
+ pose.trans() = origin;
AnimPoseVec poses;
poses.push_back(pose);
- pose.trans = xAxis;
+ pose.trans() = xAxis;
- pose.rot = quaterTurnAroundZ;
+ pose.rot() = quaterTurnAroundZ;
poses.push_back(pose);
poses.push_back(pose);
poses.push_back(pose);
@@ -222,8 +230,12 @@ void AnimInverseKinematicsTests::testSingleChain() {
AnimVariantMap varMap;
varMap.set("positionD", targetPosition);
varMap.set("rotationD", targetRotation);
- varMap.set("targetType", (int)IKTarget::Type::RotationAndPosition);
- ikDoll.setTargetVars(QString("D"), QString("positionD"), QString("rotationD"), QString("targetType"));
+ varMap.set("targetTypeD", (int)IKTarget::Type::RotationAndPosition);
+ varMap.set("poleVectorEnabledD", false);
+ std::vector flexCoefficients = {1.0f, 1.0f, 1.0f, 1.0f};
+ ikDoll.setTargetVars(QString("D"), QString("positionD"), QString("rotationD"), QString("targetTypeD"),
+ QString("weightD"), 1.0f, flexCoefficients, QString("poleVectorEnabledD"),
+ QString("poleReferenceVectorD"), QString("poleVectorD"));
AnimNode::Triggers triggers;
// the IK solution should be:
@@ -233,15 +245,11 @@ void AnimInverseKinematicsTests::testSingleChain() {
// iterate several times
float dt = 1.0f;
- ikDoll.overlay(varMap, dt, triggers, poses);
- ikDoll.overlay(varMap, dt, triggers, poses);
- ikDoll.overlay(varMap, dt, triggers, poses);
- ikDoll.overlay(varMap, dt, triggers, poses);
- ikDoll.overlay(varMap, dt, triggers, poses);
- ikDoll.overlay(varMap, dt, triggers, poses);
- ikDoll.overlay(varMap, dt, triggers, poses);
- ikDoll.overlay(varMap, dt, triggers, poses);
- const AnimPoseVec& relativePoses = ikDoll.overlay(varMap, dt, triggers, poses);
+ const int NUM_FRAMES = 50;
+ for (int i = 0; i < NUM_FRAMES; i++) {
+ poses = ikDoll.overlay(varMap, context, dt, triggers, poses);
+ }
+ const AnimPoseVec& relativePoses = ikDoll.overlay(varMap, context, dt, triggers, poses);
// verify absolute results
// NOTE: the IK algorithm doesn't converge very fast for full-reach targets,
@@ -255,28 +263,29 @@ void AnimInverseKinematicsTests::testSingleChain() {
absolutePoses.push_back(pose);
}
ikDoll.computeAbsolutePoses(absolutePoses);
- float acceptableAngle = 0.01f; // radians
- QCOMPARE_QUATS(absolutePoses[0].rot, identity, acceptableAngle);
- QCOMPARE_QUATS(absolutePoses[1].rot, identity, acceptableAngle);
- QCOMPARE_QUATS(absolutePoses[2].rot, identity, acceptableAngle);
- QCOMPARE_QUATS(absolutePoses[3].rot, identity, acceptableAngle);
- float acceptableDistance = 0.03f;
- QCOMPARE_WITH_ABS_ERROR(absolutePoses[0].trans, origin, acceptableDistance);
- QCOMPARE_WITH_ABS_ERROR(absolutePoses[1].trans, xAxis, acceptableDistance);
- QCOMPARE_WITH_ABS_ERROR(absolutePoses[2].trans, 2.0f * xAxis, acceptableDistance);
- QCOMPARE_WITH_ABS_ERROR(absolutePoses[3].trans, 3.0f * xAxis, acceptableDistance);
+ float acceptableAngle = 0.01f; // radians
+ QCOMPARE_QUATS(absolutePoses[0].rot(), identity, acceptableAngle);
+ QCOMPARE_QUATS(absolutePoses[1].rot(), identity, acceptableAngle);
+ QCOMPARE_QUATS(absolutePoses[2].rot(), identity, acceptableAngle);
+ QCOMPARE_QUATS(absolutePoses[3].rot(), identity, acceptableAngle);
+
+ float acceptableDistance = 0.1f;
+ QCOMPARE_WITH_ABS_ERROR(absolutePoses[0].trans(), origin, acceptableDistance);
+ QCOMPARE_WITH_ABS_ERROR(absolutePoses[1].trans(), xAxis, acceptableDistance);
+ QCOMPARE_WITH_ABS_ERROR(absolutePoses[2].trans(), 2.0f * xAxis, acceptableDistance);
+ QCOMPARE_WITH_ABS_ERROR(absolutePoses[3].trans(), 3.0f * xAxis, acceptableDistance);
// verify relative results
- QCOMPARE_QUATS(relativePoses[0].rot, identity, acceptableAngle);
- QCOMPARE_QUATS(relativePoses[1].rot, identity, acceptableAngle);
- QCOMPARE_QUATS(relativePoses[2].rot, identity, acceptableAngle);
- QCOMPARE_QUATS(relativePoses[3].rot, identity, acceptableAngle);
+ QCOMPARE_QUATS(relativePoses[0].rot(), identity, acceptableAngle);
+ QCOMPARE_QUATS(relativePoses[1].rot(), identity, acceptableAngle);
+ QCOMPARE_QUATS(relativePoses[2].rot(), identity, acceptableAngle);
+ QCOMPARE_QUATS(relativePoses[3].rot(), identity, acceptableAngle);
- QCOMPARE_WITH_ABS_ERROR(relativePoses[0].trans, origin, acceptableDistance);
- QCOMPARE_WITH_ABS_ERROR(relativePoses[1].trans, xAxis, acceptableDistance);
- QCOMPARE_WITH_ABS_ERROR(relativePoses[2].trans, xAxis, acceptableDistance);
- QCOMPARE_WITH_ABS_ERROR(relativePoses[3].trans, xAxis, acceptableDistance);
+ QCOMPARE_WITH_ABS_ERROR(relativePoses[0].trans(), origin, acceptableDistance);
+ QCOMPARE_WITH_ABS_ERROR(relativePoses[1].trans(), xAxis, acceptableDistance);
+ QCOMPARE_WITH_ABS_ERROR(relativePoses[2].trans(), xAxis, acceptableDistance);
+ QCOMPARE_WITH_ABS_ERROR(relativePoses[3].trans(), xAxis, acceptableDistance);
}
}
@@ -293,6 +302,6 @@ void AnimInverseKinematicsTests::testBar() {
AnimPose poseC = poseA * poseB;
glm::vec3 expectedTransC = transA + transB;
- QCOMPARE_WITH_ABS_ERROR(expectedTransC, poseC.trans, EPSILON);
+ QCOMPARE_WITH_ABS_ERROR(expectedTransC, poseC.trans(), EPSILON);
}
diff --git a/tests/animation/src/AnimTests.cpp b/tests/animation/src/AnimTests.cpp
index 8e67bda2d3..fe54ac3781 100644
--- a/tests/animation/src/AnimTests.cpp
+++ b/tests/animation/src/AnimTests.cpp
@@ -15,7 +15,11 @@
#include
#include
#include
-
+#include
+#include
+#include
+#include
+#include
#include <../QTestExtensions.h>
QTEST_MAIN(AnimTests)
@@ -23,12 +27,18 @@ QTEST_MAIN(AnimTests)
const float EPSILON = 0.001f;
void AnimTests::initTestCase() {
- auto animationCache = DependencyManager::set();
- auto resourceCacheSharedItems = DependencyManager::set();
+ DependencyManager::registerInheritance();
+ DependencyManager::set();
+ DependencyManager::set();
+ DependencyManager::set(NodeType::Agent);
+ DependencyManager::set();
+ DependencyManager::set();
+ DependencyManager::set();
+ DependencyManager::set();
}
void AnimTests::cleanupTestCase() {
- DependencyManager::destroy();
+ //DependencyManager::destroy();
}
void AnimTests::testClipInternalState() {
@@ -59,6 +69,7 @@ static float framesToSec(float secs) {
}
void AnimTests::testClipEvaulate() {
+ AnimContext context(false, false, false, glm::mat4(), glm::mat4());
QString id = "myClipNode";
QString url = "https://hifi-public.s3.amazonaws.com/ozan/support/FightClubBotTest1/Animations/standard_idle.fbx";
float startFrame = 2.0f;
@@ -73,12 +84,12 @@ void AnimTests::testClipEvaulate() {
AnimClip clip(id, url, startFrame, endFrame, timeScale, loopFlag, mirrorFlag);
AnimNode::Triggers triggers;
- clip.evaluate(vars, framesToSec(10.0f), triggers);
+ clip.evaluate(vars, context, framesToSec(10.0f), triggers);
QCOMPARE_WITH_ABS_ERROR(clip._frame, 12.0f, EPSILON);
// does it loop?
triggers.clear();
- clip.evaluate(vars, framesToSec(12.0f), triggers);
+ clip.evaluate(vars, context, framesToSec(12.0f), triggers);
QCOMPARE_WITH_ABS_ERROR(clip._frame, 3.0f, EPSILON); // Note: frame 3 and not 4, because extra frame between start and end.
// did we receive a loop trigger?
@@ -87,7 +98,7 @@ void AnimTests::testClipEvaulate() {
// does it pause at end?
triggers.clear();
clip.setLoopFlagVar("FalseVar");
- clip.evaluate(vars, framesToSec(20.0f), triggers);
+ clip.evaluate(vars, context, framesToSec(20.0f), triggers);
QCOMPARE_WITH_ABS_ERROR(clip._frame, 22.0f, EPSILON);
// did we receive a done trigger?
@@ -95,6 +106,7 @@ void AnimTests::testClipEvaulate() {
}
void AnimTests::testClipEvaulateWithVars() {
+ AnimContext context(false, false, false, glm::mat4(), glm::mat4());
QString id = "myClipNode";
QString url = "https://hifi-public.s3.amazonaws.com/ozan/support/FightClubBotTest1/Animations/standard_idle.fbx";
float startFrame = 2.0f;
@@ -121,7 +133,7 @@ void AnimTests::testClipEvaulateWithVars() {
clip.setLoopFlagVar("loopFlag2");
AnimNode::Triggers triggers;
- clip.evaluate(vars, framesToSec(0.1f), triggers);
+ clip.evaluate(vars, context, framesToSec(0.1f), triggers);
// verify that the values from the AnimVariantMap made it into the clipNode's
// internal state
@@ -132,7 +144,7 @@ void AnimTests::testClipEvaulateWithVars() {
}
void AnimTests::testLoader() {
- auto url = QUrl("https://gist.githubusercontent.com/hyperlogic/857129fe04567cbe670f/raw/0c54500f480fd7314a5aeb147c45a8a707edcc2e/test.json");
+ auto url = QUrl("https://gist.githubusercontent.com/hyperlogic/756e6b7018c96c9778dba4ffb959c3c7/raw/4b37f10c9d2636608916208ba7b415c1a3f842ff/test.json");
// NOTE: This will warn about missing "test01.fbx", "test02.fbx", etc. if the resource loading code doesn't handle relative pathnames!
// However, the test will proceed.
AnimNodeLoader loader(url);
@@ -173,14 +185,22 @@ void AnimTests::testLoader() {
QVERIFY(nodes[2]->getChildCount() == 0);
auto test01 = std::static_pointer_cast(nodes[0]);
- QVERIFY(test01->_url == "test01.fbx");
+
+ QUrl relativeUrl01("test01.fbx");
+ QString url01 = url.resolved(relativeUrl01).toString();
+
+ QVERIFY(test01->_url == url01);
QVERIFY(test01->_startFrame == 1.0f);
QVERIFY(test01->_endFrame == 20.0f);
QVERIFY(test01->_timeScale == 1.0f);
QVERIFY(test01->_loopFlag == false);
auto test02 = std::static_pointer_cast(nodes[1]);
- QVERIFY(test02->_url == "test02.fbx");
+
+ QUrl relativeUrl02("test02.fbx");
+ QString url02 = url.resolved(relativeUrl02).toString();
+
+ QVERIFY(test02->_url == url02);
QVERIFY(test02->_startFrame == 2.0f);
QVERIFY(test02->_endFrame == 21.0f);
QVERIFY(test02->_timeScale == 0.9f);
diff --git a/tests/animation/src/RigTests.cpp b/tests/animation/src/RigTests.cpp
deleted file mode 100644
index d5de9226c0..0000000000
--- a/tests/animation/src/RigTests.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-//
-// RigTests.cpp
-// tests/rig/src
-//
-// Created by Howard Stearns on 6/16/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
-//
-/* FIXME/TBD:
-
- The following lower level functionality might be separated out into a separate class, covered by a separate test case class:
- - With no input, initial pose is standing, arms at side
- - Some single animation produces correct results at a given keyframe time.
- - Some single animation produces correct results at a given interpolated time.
- - Blend between two animations, started at separate times, produces correct result at a given interpolated time.
- - Head orientation can be overridden to produce change that doesn't come from the playing animation.
- - Hand position/orientation can be overridden to produce change that doesn't come from the playing animation.
- - Hand position/orientation can be overrridden to produce elbow change that doesn't come from the playing animation.
- - Respect scaling? (e.g., so that MyAvatar.increase/decreaseSize can alter rig, such that anti-scating and footfalls-on-stairs works)
-
- Higher level functionality:
- - start/stopAnimation adds the animation to that which is playing, blending/fading as needed.
- - thrust causes walk role animation to be used.
- - turning causes turn role animation to be used. (two tests, correctly symmetric left & right)
- - walk/turn do not skate (footfalls match over-ground velocity)
- - (Later?) walk up stairs / hills have proper footfall for terrain
- - absence of above causes return to idle role animation to be used
- - (later?) The lower-level head/hand placements respect previous state. E.g., actual hand movement can be slower than requested.
- - (later) The lower-level head/hand placements can move whole skeleton. E.g., turning head past a limit may turn whole body. Reaching up can move shoulders and hips.
-
- Backward-compatability operations. We should think of this behavior as deprecated:
- - clearJointData return to standing. TBD: presumably with idle and all other animations NOT playing, until explicitly reenabled with a new TBD method?
- - setJointData applies the given data. Same TBD.
- These can be defined true or false, but the tests document the behavior and tells us if something's changed:
- - An external change to the original skeleton IS/ISN'T seen by the rig.
- - An external change to the original skeleton's head orientation IS/ISN'T seen by the rig.
- - An external change to the original skeleton's hand orientiation IS/ISN'T seen by the rig.
- */
-
-#include
-
-#include "FBXReader.h"
-#include "OBJReader.h"
-
-#include
-#include "RigTests.h"
-
-static void reportJoint(const Rig& rig, int index) { // Handy for debugging
- std::cout << "\n";
- std::cout << index << " " << rig->getAnimSkeleton()->getJointName(index).toUtf8().data() << "\n";
- glm::vec3 pos;
- rig->getJointPosition(index, pos);
- glm::quat rot;
- rig->getJointRotation(index, rot);
- std::cout << " pos:" << pos << "\n";
- std::cout << " rot:" << safeEulerAngles(rot) << "\n";
- std::cout << "\n";
-}
-static void reportByName(const Rig& rig, const QString& name) {
- int jointIndex = rig->indexOfJoint(name);
- reportJoint(rig, jointIndex);
-}
-static void reportAll(const Rig& rig) {
- for (int i = 0; i < rig->getJointStateCount(); i++) {
- reportJoint(rig, i);
- }
-}
-static void reportSome(const Rig& rig) {
- QString names[] = {"Head", "Neck", "RightShoulder", "RightArm", "RightForeArm", "RightHand", "Spine2", "Spine1", "Spine", "Hips", "RightUpLeg", "RightLeg", "RightFoot", "RightToeBase", "RightToe_End"};
- for (auto name : names) {
- reportByName(rig, name);
- }
-}
-
-QTEST_MAIN(RigTests)
-
-void RigTests::initTestCase() {
-//#define FROM_FILE "/Users/howardstearns/howardHiFi/Zack.fbx"
-#ifdef FROM_FILE
- QFile file(FROM_FILE);
- QCOMPARE(file.open(QIODevice::ReadOnly), true);
- FBXGeometry* geometry = readFBX(file.readAll(), QVariantHash());
-#else
- QUrl fbxUrl("https://s3.amazonaws.com/hifi-public/models/skeletons/Zack/Zack.fbx");
- QNetworkReply* reply = OBJReader().request(fbxUrl, false); // Just a convenience hack for synchronoud http request
- auto fbxHttpCode = !reply->isFinished() ? -1 : reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
- QCOMPARE(fbxHttpCode, 200);
- FBXGeometry* geometry = readFBX(reply->readAll(), QVariantHash());
-#endif
- QVERIFY((bool)geometry);
-
- _rig.initJointStates(*geometry, glm::mat4());
- std::cout << "Rig is ready " << geometry->joints.count() << " joints " << std::endl;
- reportAll(_rig);
-}
-
-void RigTests::initialPoseArmsDown() {
- reportSome(_rig);
-}
diff --git a/tests/animation/src/RigTests.h b/tests/animation/src/RigTests.h
deleted file mode 100644
index 3242c27b99..0000000000
--- a/tests/animation/src/RigTests.h
+++ /dev/null
@@ -1,55 +0,0 @@
-//
-// RigTests.h
-// tests/rig/src
-//
-// Created by Howard Stearns on 6/16/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_RigTests_h
-#define hifi_RigTests_h
-
-#include
-#include
-
-//#include "../QTestExtensions.h"
-
-
-// The QTest terminology is not consistent with itself or with industry:
-// The whole directory, and the rig-tests target, doesn't seem to be a QTest concept, an corresponds roughly to a toplevel suite of suites.
-// The directory can contain any number of classes like this one. (Don't forget to wipe your build dir, and rerun cmake when you add one.):
-// QTest doc (http://doc.qt.io/qt-5/qtest-overview.html) calls this a "test case".
-// The output of QTest's 'ctest' runner calls this a "test" when run in the whole directory (e.g., when reporting success/failure counts).
-// The test case (like this class) can contain any number of test slots:
-// QTest doc calls these "test functions"
-// When you run a single test case executable (e.g., "rig-RigTests"), the (unlabeled) count includes these test functions and also the before method, which is auto generated as initTestCase.
-
-// To build and run via make:
-// make help | grep tests # shows all test targets, including all-tests and rig-tests.
-// make all-tests # will compile and then die as soon as any test case dies, even if its not in your directory
-// make rig-tests # will compile and run `ctest .` in the tests/rig directory, running all the test cases found there.
-// Alas, only summary output is shown on stdout. The real results, including any stdout that your code does, is in tests/rig/Testing/Temporary/LastTest.log, or...
-// tests/rig/rig-RigTests (or the executable corresponding to any test case you define here) will run just that case and give output directly.
-//
-// To build and run via Xcode:
-// On some machines, xcode can't find cmake on the path it uses. I did, effectively: sudo ln -s `which cmake` /usr/bin
-// Note the above make instructions.
-// all-tests, rig-tests, and rig-RigTests are all targets:
-// The first two of these show no output at all, but if there's a failure you can see it by clicking on the red failure in the "issue navigator" (or by externally viewing the .log above).
-// The last (or any other individual test case executable) does show output in the Xcode output display.
-
-class RigTests : public QObject {
- Q_OBJECT
-
- private slots:
- void initTestCase();
- void initialPoseArmsDown();
-
- private:
- Rig _rig;
-};
-
-#endif // hifi_RigTests_h
diff --git a/tests/shaders/src/main.cpp b/tests/shaders/src/main.cpp
index a3b4196031..cce5b0678b 100644
--- a/tests/shaders/src/main.cpp
+++ b/tests/shaders/src/main.cpp
@@ -50,12 +50,8 @@
#include
#include
#include
-#include
-#include
#include
#include
-#include
-#include
#include
#include
@@ -180,19 +176,13 @@ void QTestWindow::draw() {
testShaderBuild(model_vert::getSource(), model_frag::getSource());
testShaderBuild(model_normal_map_vert::getSource(), model_normal_map_frag::getSource());
- testShaderBuild(model_vert::getSource(), model_specular_map_frag::getSource());
- testShaderBuild(model_normal_map_vert::getSource(), model_normal_specular_map_frag::getSource());
testShaderBuild(model_vert::getSource(), model_translucent_frag::getSource());
testShaderBuild(model_normal_map_vert::getSource(), model_translucent_frag::getSource());
testShaderBuild(model_lightmap_vert::getSource(), model_lightmap_frag::getSource());
testShaderBuild(model_lightmap_normal_map_vert::getSource(), model_lightmap_normal_map_frag::getSource());
- testShaderBuild(model_lightmap_vert::getSource(), model_lightmap_specular_map_frag::getSource());
- testShaderBuild(model_lightmap_normal_map_vert::getSource(), model_lightmap_normal_specular_map_frag::getSource());
testShaderBuild(skin_model_vert::getSource(), model_frag::getSource());
testShaderBuild(skin_model_normal_map_vert::getSource(), model_normal_map_frag::getSource());
- testShaderBuild(skin_model_vert::getSource(), model_specular_map_frag::getSource());
- testShaderBuild(skin_model_normal_map_vert::getSource(), model_normal_specular_map_frag::getSource());
testShaderBuild(skin_model_vert::getSource(), model_translucent_frag::getSource());
testShaderBuild(skin_model_normal_map_vert::getSource(), model_translucent_frag::getSource());
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 53d7fc2836..1c36306410 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -18,6 +18,9 @@ if (BUILD_TOOLS)
add_subdirectory(ice-client)
set_target_properties(ice-client PROPERTIES FOLDER "Tools")
+ add_subdirectory(ktx-tool)
+ set_target_properties(ktx-tool PROPERTIES FOLDER "Tools")
+
add_subdirectory(ac-client)
set_target_properties(ac-client PROPERTIES FOLDER "Tools")
diff --git a/tools/ktx-tool/CMakeLists.txt b/tools/ktx-tool/CMakeLists.txt
new file mode 100644
index 0000000000..9daf8e0a1a
--- /dev/null
+++ b/tools/ktx-tool/CMakeLists.txt
@@ -0,0 +1,14 @@
+set(TARGET_NAME ktx-tool)
+
+setup_hifi_project(Quick Gui Concurrent)
+
+link_hifi_libraries(shared networking image gl gpu ktx)
+
+target_gli()
+
+setup_memory_debugger()
+
+if (WIN32)
+ package_libraries_for_deployment()
+endif()
+
diff --git a/tools/ktx-tool/src/main.cpp b/tools/ktx-tool/src/main.cpp
new file mode 100644
index 0000000000..803b08c115
--- /dev/null
+++ b/tools/ktx-tool/src/main.cpp
@@ -0,0 +1,125 @@
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+
+
+
+
+void stripKtxKeyValues(const std::string& sourceFile, const std::string& destFile) {
+ auto sourceStorage = std::make_shared(sourceFile.c_str());
+ auto ktx = ktx::KTX::create(sourceStorage);
+ auto newStorageSize = ktx::KTX::evalStorageSize(ktx->_header, ktx->_images);
+ storage::FileStorage::create(destFile.c_str(), newStorageSize, nullptr);
+ storage::FileStorage destStorage(destFile.c_str());
+ ktx::KTX::write(destStorage.mutableData(), newStorageSize, ktx->_header, ktx->_images);
+}
+
+#if DEV_BUILD
+const QDir SOURCE_FOLDER{ PathUtils::projectRootPath() + "/interface/resources/meshes/mannequin" };
+const QDir DEST_FOLDER{ PathUtils::projectRootPath() + "/interface/resources/meshes/mannequin/+gles" };
+#else
+const QDir SOURCE_FOLDER{ PathUtils::resourcesPath() + "/interface/resources/meshes/mannequin" };
+const QDir DEST_FOLDER{ PathUtils::resourcesPath() + "/interface/resources/meshes/mannequin/+gles" };
+#endif
+
+
+void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) {
+#ifdef Q_OS_WIN
+ OutputDebugStringA(message.toStdString().c_str());
+ OutputDebugStringA("\n");
+#endif
+ std::cout << message.toStdString() << std::endl;
+}
+
+void processKtxFile(const QFileInfo& inputFileInfo) {
+ const QString inputFileName = inputFileInfo.absoluteFilePath();
+ const QString compressedFileName = DEST_FOLDER.absoluteFilePath(inputFileInfo.fileName());
+ const QString finalFilename = compressedFileName + ".new.ktx";
+ if (QFileInfo(finalFilename).exists()) {
+ return;
+ }
+ qDebug() << inputFileName;
+ qDebug() << compressedFileName;
+ auto uncomrpessedKtx = ktx::KTX::create(std::make_shared(compressedFileName));
+ if (!uncomrpessedKtx) {
+ throw std::runtime_error("Unable to load texture using hifi::ktx");
+ }
+
+ auto compressedKtx = ktx::KTX::create(std::make_shared(inputFileName));
+ if (!compressedKtx) {
+ throw std::runtime_error("Unable to load texture using hifi::ktx");
+ }
+
+
+ auto outputKtx = ktx::KTX::create(uncomrpessedKtx->getHeader(), uncomrpessedKtx->_images, compressedKtx->_keyValues);
+ auto outputStorage = outputKtx->getStorage();
+
+ storage::FileStorage::create(finalFilename, outputStorage->size(), outputStorage->data());
+}
+
+void scanDir(const QDir& dir) {
+
+ auto entries = dir.entryInfoList();
+ for (const auto& entry : entries) {
+ if (entry.isDir()) {
+ scanDir(QDir(entry.absoluteFilePath()));
+ } else {
+ qDebug() << entry.absoluteFilePath();
+ }
+ }
+}
+
+int main(int argc, char** argv) {
+ qInstallMessageHandler(messageHandler);
+ {
+ QDir destFolder(DEST_FOLDER);
+ if (!destFolder.exists() && !destFolder.mkpath(".")) {
+ throw std::runtime_error("failed to create output directory");
+ }
+ for (const auto ktxFile : SOURCE_FOLDER.entryInfoList(QStringList() << "*.ktx")) {
+ processKtxFile(ktxFile);
+ }
+ qDebug() << "Done";
+ }
+
+ return 0;
+}