/* Sign Chat System V1 Created by Matti 'Menithal' Lahtinen on 22/4/2017 With - Fix for RELEASE-7124 breakages by humbletim 2017.09.20 Scripts Released Under CC Attribution 4.0 http://creativecommons.org/licenses/by/4.0/ */ (function () { const COMMS_HTML = "comms-panel.html"; const COMMS_BUTTON = "com.highfidelity.comms"; const ROOT = "http://mpassets.highfidelity.com/5dbbcccc-2b88-444d-bff3-9ae5d407bb84-v1/"; const PAGE = Script.resolvePath("./panel.html?fox2"); const SOUND_URL = Script.resolvePath(ROOT + "annoyingSound.wav"); const SOUND = SoundCache.getSound(SOUND_URL); var TEXT_COLOR = Settings.getValue(COMMS_BUTTON + ".textColor"); var BACKGROUND_COLOR = Settings.getValue(COMMS_BUTTON + ".backgroundColor"); if (TEXT_COLOR === undefined || TEXT_COLOR === null) { TEXT_COLOR = { red: 255, blue: 255, green: 255 }; Settings.setValue(COMMS_BUTTON + ".textColor", TEXT_COLOR); } if (BACKGROUND_COLOR === undefined || BACKGROUND_COLOR === null) { BACKGROUND_COLOR = { red: 0, blue: 0, green: 0 }; Settings.setValue(COMMS_BUTTON + ".backgroundColor", BACKGROUND_COLOR); } var colors = { "textColor": TEXT_COLOR, "backgroundColor": BACKGROUND_COLOR }; var commsPanel = new OverlayWebWindow({ title: "Sign", source: PAGE, width: 645, height: 145, visible: false }); var throttleTimer = -1; function throttle(callback, val) { if (throttleTimer !== -1) { Script.clearTimeout(throttleTimer); } throttleTimer = Script.setTimeout(function () { throttleTimer = -1; callback(); }, val); } // Doing it this way instead of override as I only want to animate the hands and shoulders. const SIGN_HOLD_OVERRIDE = Script.require("./animation.json"); function setJoints(map) { Object.keys(map).forEach(function (bone, index) { // Tim's Hotfix if (~MyAvatar.getJointIndex(bone)) { MyAvatar.setJointRotation(MyAvatar.getJointIndex(bone), map[bone].rotation); } }); } function cleanUpSigns() { // SignBoard MyAvatar.clearJointsData(); var legacy = Entities.getEntityProperties(sign, ["text"]); if (legacy) { // variable is used because I am lazy to send a message from the page back to the entity on startup to show what it has. legacyText = legacy.text; } else { legacyText = ""; } Entities.deleteEntity(sign); sign = false; var entities = Entities.findEntities(MyAvatar.position, 10); entities.forEach(function (id) { var props = Entities.getEntityProperties(id, ["parentID", "name"]); if (props.name === "SignBoard" && props.parentID === MyAvatar.sessionUUID) { Entities.deleteEntity(id); } }); }; var sign = false; var date = new Date(); var frontCamera = false; var oldCamera = { entity: null, cameraEntity: "" }; var scriptVisible = false; var legacyText = ""; commsPanel.webEventReceived.connect(function (data) { var currentDate = new Date(); var difference = currentDate - date; var message = JSON.parse(data); if (message.type === "textUpdate") { if (Entities.getEntityProperties(sign)) { Entities.editEntity(sign, { text: message.message }); } else { Entities.editEntity(sign, { text: message.message }); } } else if (message.type === "textScale") { Entities.editEntity(sign, { lineHeight: parseInt(message.message) / 1000 }); } else if (message.type === "returnHit" && difference > 5000) { date = currentDate; Audio.playSound(SOUND, { volume: 0.25, position: MyAvatar.position }); } else if (message.type === "clearSign") { if (isActive) { toggleVisibility(); } } else if (message.type === "textColorUpdate") { throttle(function () { var payload = {}; colors[message.message.id] = payload[message.message.id] = message.message.color; Entities.editEntity(sign, payload); Settings.setValue(COMMS_BUTTON + "." + message.message.id, message.message.color); }, 25); } else if (message.type === "altCamera") { frontCamera = !frontCamera; if (frontCamera) { oldCamera.mode = Camera.getModeString(); oldCamera.cameraEntity = Camera.cameraEntity; var offset = Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 2, z: -3 }); var position = Vec3.sum(MyAvatar.position, offset); Camera.setModeString("independent"); Camera.setPosition(position); Camera.lookAt(MyAvatar.position); //Camera.cameraEntity = this.cameraEntity.id; } else { Camera.setModeString(oldCamera.mode); //var camera = Camera.cameraEntity; Camera.cameraEntity = oldCamera.cameraEntity; // Entities.deleteEntity(camera); } } }); var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var icon = Script.resolvePath(ROOT + "speech-bubble-white.svg?4fsd3f5133"); var activeIcon = Script.resolvePath(ROOT + "speech-bubble-outline.svg?33dssff134"); var activeButton = tablet.addButton({ icon: icon, activeIcon: activeIcon, text: "SIGN", isActive: false, sortOrder: 11 }); var isActive = false; var scriptVisible = false; var createOrUpdateSign = function (timeout) { setJoints(SIGN_HOLD_OVERRIDE); Script.setTimeout(function () { var leftHandPosition = Vec3.subtract(MyAvatar.position, MyAvatar.getJointPosition("LeftHand")); var rightHandPosition = Vec3.subtract(MyAvatar.position, MyAvatar.getJointPosition("RightHand")); var between = Vec3.mix(leftHandPosition, rightHandPosition, 0.5) between.y = between.y + 0.20; var signEntity = { type: "Text", name: "SignBoard", text: legacyText, backgroundColor: colors["backgroundColor"], textColor: colors["textColor"], parentID: MyAvatar.sessionUUID, parentJointIndex: MyAvatar.getJointIndex("Spine2"), position: Vec3.sum(Vec3.subtract(MyAvatar.position, between), Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -0.085 })), dimensions: { x: 1, y: .5, z: 0.1 }, orientation: MyAvatar.orientation, lineHeight: 0.10 }; if (sign) { Entities.editEntity(sign, signEntity); } else { sign = Entities.addEntity(signEntity, true); } }, timeout); var payload = { type: "setColors", colors: colors } commsPanel.emitScriptEvent(JSON.stringify(payload)); } var onSkeletonChanged = function () { createOrUpdateSign(1000); } var toggleVisibility = function () { isActive = !isActive; commsPanel.setVisible(isActive); } commsPanel.visibleChanged.connect(function () { isActive = commsPanel.isVisible(); // This should be turn offable, some may want to keep it visible while moving. activeButton.editProperties({ isActive: isActive }); try { if (isActive) { createOrUpdateSign(100); MyAvatar.skeletonChanged.connect(onSkeletonChanged); } else { cleanUpSigns(); MyAvatar.skeletonChanged.disconnect(onSkeletonChanged); } } catch (e) { console.warn("No Skeleton change defined", e) } }); activeButton.clicked.connect(toggleVisibility); Script.scriptEnding.connect(function () { console.log("cleaning up comms") tablet.removeButton(activeButton) if (frontCamera) { Camera.setModeString(oldCamera.mode); Camera.cameraEntity = oldCamera.cameraEntity; } activeButton.clicked.disconnect(toggleVisibility); commsPanel.setVisible(false); commsPanel.close(); cleanUpSigns(); }); })();