// Scanner Class Definition // // Scanner handles moving a 3D cursor near/over target objects and displaying information about them // Uses HudPanel class to display information about target derived from pd_ecoTargets.js Script.include(["pd_utils.js", "pd_hudPanel.js", "pd_ecoTargets.js"]); // Returns HudPanel object function createHudPanel() { var frameUrl = pd_path("images/scannerFrame.png"); var panelWidth = 300; var xPos = (Window.innerWidth - panelWidth*1.1); var hudPanel = new HudPanel({x:xPos, y:30}, {x:300, y:420}, {x:10,y:0}); var titleColor = {red:150, green:150, blue:255}; var headingsColor = {red:255, green:40, blue:40}; var textColor = {red:40, green:200, blue:40 }; hudPanel.addRectangle("bgRectangle", {x:0, y:0}, hudPanel.size.x, hudPanel.size.y, {red:20, green:20, blue:20} ); hudPanel.addStaticText("lbl_scanData", "SCAN DATA", {x:0, y:0}, hudPanel.size.x, titleColor ); hudPanel.addStaticText("lbl_shortName", "SHORT NAME:", {x:0, y:30}, hudPanel.size.x, headingsColor ); hudPanel.addStaticText("lbl_localName", "LOCAL NAME:", {x:0, y:50}, hudPanel.size.x, headingsColor ); hudPanel.addStaticText("lbl_description", "DESCRIPTION:", {x:0, y:70}, hudPanel.size.x, headingsColor ); hudPanel.addStaticText("lbl_notes", "NOTES:", {x:0, y:190}, hudPanel.size.x, headingsColor ); hudPanel.addImageFrame("frame", {x:-23, y:-21}, hudPanel.size.x + 47, hudPanel.size.y + 43, frameUrl ); hudPanel.addDynamicText("shortName", "Short Latin Name", {x:110, y:30}, hudPanel.size.x, textColor ); hudPanel.addDynamicText("slangName", "Local Name Here!", {x:110, y:50}, hudPanel.size.x, textColor ); var desc = "This is the long description of something that could go on and on.\nIt can have breaks too!\nReally!"; hudPanel.addDynamicText("longDesc", desc, {x:0, y:90}, hudPanel.size.x, textColor ); var notes = "This is some animated text that goes on and on."; hudPanel.addDynamicText("notes", notes, {x:0, y:210}, hudPanel.size.x, textColor ); return hudPanel; } function createHistoryPanel() { var frameUrl = pd_path("images/historyFrame.png"); var titleColor = {red:150, green:150, blue:255}; var headingsColor = {red:255, green:40, blue:40}; var textColor = {red:40, green:200, blue:40 }; var hudPanel = new HudPanel({x:20, y:45}, {x:200, y:200}, {x:10,y:0}); hudPanel.addRectangle("bgRectangle", {x:0, y:0}, hudPanel.size.x, hudPanel.size.y, {red:20, green:20, blue:20} ); hudPanel.addImageFrame("frame", {x:-13, y:-12}, hudPanel.size.x + 26, hudPanel.size.y + 24, frameUrl ); hudPanel.addStaticText("lbl_title", "SCAN HISTORY", {x:0, y:0}, hudPanel.size.x, titleColor ); hudPanel.addDynamicText("history", "", {x:0, y:20}, hudPanel.size.x, textColor ); return hudPanel; } // Stores pdType and entityID of scanned objects ScannedTarget = function (pdType) { this.pdType = pdType; this.entityIds = []; } Scanner = function() { print("Scanner - CONSTRUCTOR"); this.scanCallback = null; // This function is called when new items are scanned this.pos = {x:120, y:20}; this.range = 3.0; // Search range for nearby entity this.targets = []; // Target entities found in latest radar ping. this.analyzedDict = {}; // What's been analyzed already //this.hitText = "Eco Targets Found: "; //this.uiTitle = createOverlay("SCANNER", {x:this.pos.x, y:this.pos.y}, 16, 0.8); this.hudMain = createHudPanel(); this.hudHistory = createHistoryPanel(); this.markerResetPos = {x:0, y:0.2, z:-3.6}; this.markerLocalPos = {x:0, y:0, z:0}; // Relative to MyAvatar this.targetMarkerUrl = "http://nerdchallenge.com/hifi/props/radar_target.fbx"; this.targetMarkerDims = { x:1.12, y:2.43, z:1.12 }; this.targetMarkerSpeed = 0.2; this.marker = createModelEntity(this.targetMarkerUrl, MyAvatar.position, "scanner_target", this.targetMarkerDims, -1 ); entity_show(this.marker, false); this.snd_activate = SoundCache.getSound(pd_path("sounds/ramp1.wav")); this.snd_analyze = SoundCache.getSound(pd_path("sounds/flutter.wav")); this.hudMain.hide(); this.hudHistory.hide(); this.controlKeys = { "w" : new KeyInfo({x: 0.0, y: 0.0, z:-1}), "s" : new KeyInfo({x: 0.0, y: 0.0, z: 1}), "a" : new KeyInfo({x: -1, y: 0.0, z: 0.0}), "d" : new KeyInfo({x: 1, y: 0.0, z: 0.0}) }; }; Scanner.prototype.deconstruct = function() { this.hudMain.deconstruct(); this.hudHistory.deconstruct(); Entities.deleteEntity(this.marker); } Scanner.prototype.clearHistory = function() { this.analyzedDict = {}; } Scanner.prototype.updateHistory = function() { this.hudHistory.removeAllDynamicText(); var allScans = Object.keys(this.analyzedDict); var displayString = ""; for (var i =0; i < allScans.length; i++) { var scannedTarget = this.analyzedDict[allScans[i]]; var numScans = scannedTarget.entityIds.length; var targetDef = eval(allScans[i]); displayString += targetDef.shortName + " [" + numScans + "]\n"; } //displayString = "Item1\nItem2\nItem3\n"; this.hudHistory.setDisplayText("history", displayString); } // Activate scanner mode. Show reticle, etc. Scanner.prototype.activate = function() { //this.marker = createModelEntity(this.targetMarkerUrl, MyAvatar.position, "scanner_target", this.targetMarkerDims, -1 ); this.markerLocalPos = this.markerResetPos; this.moveMarkerToLocalPos(this.markerLocalPos); Audio.playSound(this.snd_activate, { position: MyAvatar.position, volume: 0.25 }); entity_show(this.marker, true); this.updateHistory(); this.hudMain.show(); this.hudHistory.show(); this.hudHistory.startAnimation(); } // Turn off scanner functions/displays Scanner.prototype.deactivate = function() { //Entities.deleteEntity(this.marker); entity_show(this.marker, false); this.hudMain.stopAnimation(); this.hudMain.hide(); this.hudHistory.stopAnimation(); this.hudHistory.hide(); } Scanner.prototype.moveMarkerToLocalPos = function(newPos) { var orientation = Quat.fromPitchYawRollDegrees(0, MyAvatar.bodyYaw, 0); var markerWorldPos = Vec3.multiplyQbyV( orientation, newPos ); markerWorldPos = Vec3.sum(markerWorldPos, MyAvatar.position); var props = Entities.getEntityProperties( this.marker ); Entities.editEntity(this.marker, { position:markerWorldPos }); }; Scanner.prototype.onKeyPress = function(event) { var keyName = event.text; var key = this.controlKeys[keyName]; var posDelta = {x:0, y:0, z:0}; if (key != undefined) { posDelta = Vec3.multiply(this.targetMarkerSpeed, key.motorContribution); } // Modify marker position this.markerLocalPos = Vec3.sum(this.markerLocalPos, posDelta); this.moveMarkerToLocalPos(this.markerLocalPos); if (event.key == SPACEBAR_CHARCODE) { this.analyzeTarget(); } } // Analyze object under targeting marker and provide description Scanner.prototype.analyzeTarget = function() { var DEFAULT_ETD = "etd_unknown"; var targetPos = entity_pos(this.marker); Audio.playSound(this.snd_analyze, { position: MyAvatar.position, volume: 0.5 }); // following returns array = [entityID, entityProps, userData struct] var closestTarget = pd_findClosestEcoTargetInRange(targetPos, this.range); var highPos = Vec3.sum(targetPos, {x:0,y:2,z:0}); var lowPos = Vec3.sum(targetPos, {x:0,y:-2,z:0}); if (closestTarget == null) { this.hudMain.removeAllDynamicText(); this.hudMain.clearAllDynamicText(); this.hudMain.setDisplayText("shortName", "[ No Target in Range ]"); this.hudMain.startAnimation(); return; } entity_moveToPos(this.marker, closestTarget[1].position); var pdType = closestTarget[2].pdType; var targetDef = eval(pdType); // Evaluates type name as eco-target definition object and creates object if (targetDef != null) { // Add new ScannedTarget for type if not already scanned if (!(pdType in this.analyzedDict)) this.analyzedDict[pdType] = new ScannedTarget(pdType); var scannedTarget = this.analyzedDict[pdType]; // Prevent recording scan of same entity twice if (scannedTarget.entityIds.indexOf(closestTarget[0]) == -1) { scannedTarget.entityIds.push(closestTarget[0]); this.scanCallback(); } var allTypes = Object.keys(this.analyzedDict); //printDebug("Num scanned objects:" + allTypes.length); } this.hudMain.setDisplayText("shortName", targetDef.shortName); this.hudMain.setDisplayText("slangName", targetDef.slangName); this.hudMain.setDisplayText("longDesc", targetDef.longDesc); this.hudMain.setDisplayText("notes", targetDef.notes); this.hudMain.startAnimation(); //print("END Scanner.prototype.onKeyPress complete."); }; // Needs to be called via update from owner object Scanner.prototype.scriptUpdate = function(deltaTime) { this.hudMain.scriptUpdate(deltaTime); this.hudHistory.scriptUpdate(deltaTime); }