Image gets rotated 90 degrees when taking portrait photo - windows
When I'm taking an photo with my Windows Phone the landscape mode, it's perfect. The problem occurs when I'm taking a photo in portrait mode.
The photo gets rotated 90 degrees. It even occurs in the simulator as shown below.
Now this doesn't occur on Android or iOS so I assume this is because Windows is using the CameraProxy.js instead of/from cordova-plugin-camera.
My entire CameraProxy.js (Giant file, does contain 'rotate' stuff but method names are only about videos)
cordova.define("cordova-plugin-camera.CameraProxy", function(require, exports, module) {
var Camera = require('./Camera');
var getAppData = function () {
return Windows.Storage.ApplicationData.current;
};
var encodeToBase64String = function (buffer) {
return Windows.Security.Cryptography.CryptographicBuffer.encodeToBase64String(buffer);
};
var OptUnique = Windows.Storage.CreationCollisionOption.generateUniqueName;
var CapMSType = Windows.Media.Capture.MediaStreamType;
var webUIApp = Windows.UI.WebUI.WebUIApplication;
var fileIO = Windows.Storage.FileIO;
var pickerLocId = Windows.Storage.Pickers.PickerLocationId;
module.exports = {
// args will contain :
// ... it is an array, so be careful
// 0 quality:50,
// 1 destinationType:Camera.DestinationType.FILE_URI,
// 2 sourceType:Camera.PictureSourceType.CAMERA,
// 3 targetWidth:-1,
// 4 targetHeight:-1,
// 5 encodingType:Camera.EncodingType.JPEG,
// 6 mediaType:Camera.MediaType.PICTURE,
// 7 allowEdit:false,
// 8 correctOrientation:false,
// 9 saveToPhotoAlbum:false,
// 10 popoverOptions:null
// 11 cameraDirection:0
takePicture: function (successCallback, errorCallback, args) {
var sourceType = args[2];
if (sourceType != Camera.PictureSourceType.CAMERA) {
takePictureFromFile(successCallback, errorCallback, args);
} else {
takePictureFromCamera(successCallback, errorCallback, args);
}
}
};
// https://msdn.microsoft.com/en-us/library/windows/apps/ff462087(v=vs.105).aspx
var windowsVideoContainers = [".avi", ".flv", ".asx", ".asf", ".mov", ".mp4", ".mpg", ".rm", ".srt", ".swf", ".wmv", ".vob"];
var windowsPhoneVideoContainers = [".avi", ".3gp", ".3g2", ".wmv", ".3gp", ".3g2", ".mp4", ".m4v"];
// Default aspect ratio 1.78 (16:9 hd video standard)
var DEFAULT_ASPECT_RATIO = '1.8';
// Highest possible z-index supported across browsers. Anything used above is converted to this value.
var HIGHEST_POSSIBLE_Z_INDEX = 2147483647;
// Resize method
function resizeImage(successCallback, errorCallback, file, targetWidth, targetHeight, encodingType) {
var tempPhotoFileName = "";
var targetContentType = "";
if (encodingType == Camera.EncodingType.PNG) {
tempPhotoFileName = "camera_cordova_temp_return.png";
targetContentType = "image/png";
} else {
tempPhotoFileName = "camera_cordova_temp_return.jpg";
targetContentType = "image/jpeg";
}
var storageFolder = getAppData().localFolder;
file.copyAsync(storageFolder, file.name, Windows.Storage.NameCollisionOption.replaceExisting)
.then(function (storageFile) {
return fileIO.readBufferAsync(storageFile);
})
.then(function(buffer) {
var strBase64 = encodeToBase64String(buffer);
var imageData = "data:" + file.contentType + ";base64," + strBase64;
var image = new Image();
image.src = imageData;
image.onload = function() {
var ratio = Math.min(targetWidth / this.width, targetHeight / this.height);
var imageWidth = ratio * this.width;
var imageHeight = ratio * this.height;
var canvas = document.createElement('canvas');
var storageFileName;
canvas.width = imageWidth;
canvas.height = imageHeight;
canvas.getContext("2d").drawImage(this, 0, 0, imageWidth, imageHeight);
var fileContent = canvas.toDataURL(targetContentType).split(',')[1];
var storageFolder = getAppData().localFolder;
storageFolder.createFileAsync(tempPhotoFileName, OptUnique)
.then(function (storagefile) {
var content = Windows.Security.Cryptography.CryptographicBuffer.decodeFromBase64String(fileContent);
storageFileName = storagefile.name;
return fileIO.writeBufferAsync(storagefile, content);
})
.done(function () {
successCallback("ms-appdata:///local/" + storageFileName);
}, errorCallback);
};
})
.done(null, function(err) {
errorCallback(err);
}
);
}
function takePictureFromFile(successCallback, errorCallback, args) {
// Detect Windows Phone
if (navigator.appVersion.indexOf('Windows Phone 8.1') >= 0) {
takePictureFromFileWP(successCallback, errorCallback, args);
} else {
takePictureFromFileWindows(successCallback, errorCallback, args);
}
}
function takePictureFromFileWP(successCallback, errorCallback, args) {
var mediaType = args[6],
destinationType = args[1],
targetWidth = args[3],
targetHeight = args[4],
encodingType = args[5];
var filePickerActivationHandler = function(eventArgs) {
if (eventArgs.kind === Windows.ApplicationModel.Activation.ActivationKind.pickFileContinuation) {
var file = eventArgs.files[0];
if (!file) {
errorCallback("User didn't choose a file.");
webUIApp.removeEventListener("activated", filePickerActivationHandler);
return;
}
if (destinationType == Camera.DestinationType.FILE_URI || destinationType == Camera.DestinationType.NATIVE_URI) {
if (targetHeight > 0 && targetWidth > 0) {
resizeImage(successCallback, errorCallback, file, targetWidth, targetHeight, encodingType);
}
else {
var storageFolder = getAppData().localFolder;
file.copyAsync(storageFolder, file.name, Windows.Storage.NameCollisionOption.replaceExisting).done(function (storageFile) {
if(destinationType == Camera.DestinationType.NATIVE_URI) {
successCallback("ms-appdata:///local/" + storageFile.name);
}
else {
successCallback(URL.createObjectURL(storageFile));
}
}, function () {
errorCallback("Can't access localStorage folder.");
});
}
}
else {
if (targetHeight > 0 && targetWidth > 0) {
resizeImageBase64(successCallback, errorCallback, file, targetWidth, targetHeight);
} else {
fileIO.readBufferAsync(file).done(function (buffer) {
var strBase64 =encodeToBase64String(buffer);
successCallback(strBase64);
}, errorCallback);
}
}
webUIApp.removeEventListener("activated", filePickerActivationHandler);
}
};
var fileOpenPicker = new Windows.Storage.Pickers.FileOpenPicker();
if (mediaType == Camera.MediaType.PICTURE) {
fileOpenPicker.fileTypeFilter.replaceAll([".png", ".jpg", ".jpeg"]);
fileOpenPicker.suggestedStartLocation = pickerLocId.picturesLibrary;
}
else if (mediaType == Camera.MediaType.VIDEO) {
fileOpenPicker.fileTypeFilter.replaceAll(windowsPhoneVideoContainers);
fileOpenPicker.suggestedStartLocation = pickerLocId.videosLibrary;
}
else {
fileOpenPicker.fileTypeFilter.replaceAll(["*"]);
fileOpenPicker.suggestedStartLocation = pickerLocId.documentsLibrary;
}
webUIApp.addEventListener("activated", filePickerActivationHandler);
fileOpenPicker.pickSingleFileAndContinue();
}
function takePictureFromFileWindows(successCallback, errorCallback, args) {
var mediaType = args[6],
destinationType = args[1],
targetWidth = args[3],
targetHeight = args[4],
encodingType = args[5];
var fileOpenPicker = new Windows.Storage.Pickers.FileOpenPicker();
if (mediaType == Camera.MediaType.PICTURE) {
fileOpenPicker.fileTypeFilter.replaceAll([".png", ".jpg", ".jpeg"]);
fileOpenPicker.suggestedStartLocation = pickerLocId.picturesLibrary;
}
else if (mediaType == Camera.MediaType.VIDEO) {
fileOpenPicker.fileTypeFilter.replaceAll(windowsVideoContainers);
fileOpenPicker.suggestedStartLocation = pickerLocId.videosLibrary;
}
else {
fileOpenPicker.fileTypeFilter.replaceAll(["*"]);
fileOpenPicker.suggestedStartLocation = pickerLocId.documentsLibrary;
}
fileOpenPicker.pickSingleFileAsync().done(function (file) {
if (!file) {
errorCallback("User didn't choose a file.");
return;
}
if (destinationType == Camera.DestinationType.FILE_URI || destinationType == Camera.DestinationType.NATIVE_URI) {
if (targetHeight > 0 && targetWidth > 0) {
resizeImage(successCallback, errorCallback, file, targetWidth, targetHeight, encodingType);
}
else {
var storageFolder = getAppData().localFolder;
file.copyAsync(storageFolder, file.name, Windows.Storage.NameCollisionOption.replaceExisting).done(function (storageFile) {
if(destinationType == Camera.DestinationType.NATIVE_URI) {
successCallback("ms-appdata:///local/" + storageFile.name);
}
else {
successCallback(URL.createObjectURL(storageFile));
}
}, function () {
errorCallback("Can't access localStorage folder.");
});
}
}
else {
if (targetHeight > 0 && targetWidth > 0) {
resizeImageBase64(successCallback, errorCallback, file, targetWidth, targetHeight);
} else {
fileIO.readBufferAsync(file).done(function (buffer) {
var strBase64 =encodeToBase64String(buffer);
successCallback(strBase64);
}, errorCallback);
}
}
}, function () {
errorCallback("User didn't choose a file.");
});
}
function takePictureFromCamera(successCallback, errorCallback, args) {
// Check if necessary API available
if (!Windows.Media.Capture.CameraCaptureUI) {
takePictureFromCameraWP(successCallback, errorCallback, args);
} else {
takePictureFromCameraWindows(successCallback, errorCallback, args);
}
}
function takePictureFromCameraWP(successCallback, errorCallback, args) {
// We are running on WP8.1 which lacks CameraCaptureUI class
// so we need to use MediaCapture class instead and implement custom UI for camera
var destinationType = args[1],
targetWidth = args[3],
targetHeight = args[4],
encodingType = args[5],
saveToPhotoAlbum = args[9],
cameraDirection = args[11],
capturePreview = null,
cameraCaptureButton = null,
cameraCancelButton = null,
capture = null,
captureSettings = null,
CaptureNS = Windows.Media.Capture,
sensor = null;
}
function continueVideoOnFocus() {
// if preview is defined it would be stuck, play it
if (capturePreview) {
capturePreview.play();
}
}
function startCameraPreview() {
// Search for available camera devices
// This is necessary to detect which camera (front or back) we should use
var DeviceEnum = Windows.Devices.Enumeration;
var expectedPanel = cameraDirection === 1 ? DeviceEnum.Panel.front : DeviceEnum.Panel.back;
// Add focus event handler to capture the event when user suspends the app and comes back while the preview is on
window.addEventListener("focus", continueVideoOnFocus);
DeviceEnum.DeviceInformation.findAllAsync(DeviceEnum.DeviceClass.videoCapture).then(function (devices) {
if (devices.length <= 0) {
destroyCameraPreview();
errorCallback('Camera not found');
return;
}
devices.forEach(function(currDev) {
if (currDev.enclosureLocation.panel && currDev.enclosureLocation.panel == expectedPanel) {
captureSettings.videoDeviceId = currDev.id;
}
});
captureSettings.photoCaptureSource = Windows.Media.Capture.PhotoCaptureSource.photo;
return capture.initializeAsync(captureSettings);
}).then(function () {
// create focus control if available
var VideoDeviceController = capture.videoDeviceController;
var FocusControl = VideoDeviceController.focusControl;
if (FocusControl.supported === true) {
capturePreview.addEventListener('click', function () {
// Make sure function isn't called again before previous focus is completed
if (this.getAttribute('clicked') === '1') {
return false;
} else {
this.setAttribute('clicked', '1');
}
var preset = Windows.Media.Devices.FocusPreset.autoNormal;
var parent = this;
FocusControl.setPresetAsync(preset).done(function () {
// set the clicked attribute back to '0' to allow focus again
parent.setAttribute('clicked', '0');
});
});
}
// msdn.microsoft.com/en-us/library/windows/apps/hh452807.aspx
capturePreview.msZoom = true;
capturePreview.src = URL.createObjectURL(capture);
capturePreview.play();
// Bind events to controls
sensor = Windows.Devices.Sensors.SimpleOrientationSensor.getDefault();
if (sensor !== null) {
sensor.addEventListener("orientationchanged", onOrientationChange);
}
// add click events to capture and cancel buttons
cameraCaptureButton.addEventListener('click', onCameraCaptureButtonClick);
cameraCancelButton.addEventListener('click', onCameraCancelButtonClick);
// Change default orientation
if (sensor) {
setPreviewRotation(sensor.getCurrentOrientation());
} else {
setPreviewRotation(Windows.Graphics.Display.DisplayInformation.getForCurrentView().currentOrientation);
}
// Get available aspect ratios
var aspectRatios = getAspectRatios(capture);
// Couldn't find a good ratio
if (aspectRatios.length === 0) {
destroyCameraPreview();
errorCallback('There\'s not a good aspect ratio available');
return;
}
// add elements to body
document.body.appendChild(capturePreview);
document.body.appendChild(cameraCaptureButton);
document.body.appendChild(cameraCancelButton);
if (aspectRatios.indexOf(DEFAULT_ASPECT_RATIO) > -1) {
return setAspectRatio(capture, DEFAULT_ASPECT_RATIO);
} else {
// Doesn't support 16:9 - pick next best
return setAspectRatio(capture, aspectRatios[0]);
}
}).done(null, function (err) {
destroyCameraPreview();
errorCallback('Camera intitialization error ' + err);
});
}
function destroyCameraPreview() {
// If sensor is available, remove event listener
if (sensor !== null) {
sensor.removeEventListener('orientationchanged', onOrientationChange);
}
// Pause and dispose preview element
capturePreview.pause();
capturePreview.src = null;
// Remove event listeners from buttons
cameraCaptureButton.removeEventListener('click', onCameraCaptureButtonClick);
cameraCancelButton.removeEventListener('click', onCameraCancelButtonClick);
// Remove the focus event handler
window.removeEventListener("focus", continueVideoOnFocus);
// Remove elements
[capturePreview, cameraCaptureButton, cameraCancelButton].forEach(function (elem) {
if (elem /* && elem in document.body.childNodes */) {
document.body.removeChild(elem);
}
});
// Stop and dispose media capture manager
if (capture) {
capture.stopRecordAsync();
capture = null;
}
}
function getAspectRatios(capture) {
var videoDeviceController = capture.videoDeviceController;
var photoAspectRatios = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.photo).map(function (element) {
return (element.width / element.height).toFixed(1);
}).filter(function (element, index, array) { return (index === array.indexOf(element)); });
var videoAspectRatios = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.videoRecord).map(function (element) {
return (element.width / element.height).toFixed(1);
}).filter(function (element, index, array) { return (index === array.indexOf(element)); });
var videoPreviewAspectRatios = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.videoPreview).map(function (element) {
return (element.width / element.height).toFixed(1);
}).filter(function (element, index, array) { return (index === array.indexOf(element)); });
var allAspectRatios = [].concat(photoAspectRatios, videoAspectRatios, videoPreviewAspectRatios);
var aspectObj = allAspectRatios.reduce(function (map, item) {
if (!map[item]) {
map[item] = 0;
}
map[item]++;
return map;
}, {});
return Object.keys(aspectObj).filter(function (k) {
return aspectObj[k] === 3;
});
}
function setAspectRatio(capture, aspect) {
// Max photo resolution with desired aspect ratio
var videoDeviceController = capture.videoDeviceController;
var photoResolution = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.photo)
.filter(function (elem) {
return ((elem.width / elem.height).toFixed(1) === aspect);
})
.reduce(function (prop1, prop2) {
return (prop1.width * prop1.height) > (prop2.width * prop2.height) ? prop1 : prop2;
});
// Max video resolution with desired aspect ratio
var videoRecordResolution = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.videoRecord)
.filter(function (elem) {
return ((elem.width / elem.height).toFixed(1) === aspect);
})
.reduce(function (prop1, prop2) {
return (prop1.width * prop1.height) > (prop2.width * prop2.height) ? prop1 : prop2;
});
// Max video preview resolution with desired aspect ratio
var videoPreviewResolution = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.videoPreview)
.filter(function (elem) {
return ((elem.width / elem.height).toFixed(1) === aspect);
})
.reduce(function (prop1, prop2) {
return (prop1.width * prop1.height) > (prop2.width * prop2.height) ? prop1 : prop2;
});
return videoDeviceController.setMediaStreamPropertiesAsync(CapMSType.photo, photoResolution)
.then(function () {
return videoDeviceController.setMediaStreamPropertiesAsync(CapMSType.videoPreview, videoPreviewResolution);
})
.then(function () {
return videoDeviceController.setMediaStreamPropertiesAsync(CapMSType.videoRecord, videoRecordResolution);
});
}
/**
* When the phone orientation change, get the event and change camera preview rotation
* #param {Object} e - SimpleOrientationSensorOrientationChangedEventArgs
*/
function onOrientationChange(e) {
setPreviewRotation(e.orientation);
}
/**
* Converts SimpleOrientation to a VideoRotation to remove difference between camera sensor orientation
* and video orientation
* #param {number} orientation - Windows.Devices.Sensors.SimpleOrientation
* #return {number} - Windows.Media.Capture.VideoRotation
*/
function orientationToRotation(orientation) {
// VideoRotation enumerable and BitmapRotation enumerable have the same values
// https://msdn.microsoft.com/en-us/library/windows/apps/windows.media.capture.videorotation.aspx
// https://msdn.microsoft.com/en-us/library/windows/apps/windows.graphics.imaging.bitmaprotation.aspx
switch (orientation) {
// portrait
case Windows.Devices.Sensors.SimpleOrientation.notRotated:
return Windows.Media.Capture.VideoRotation.clockwise90Degrees;
// landscape
case Windows.Devices.Sensors.SimpleOrientation.rotated90DegreesCounterclockwise:
return Windows.Media.Capture.VideoRotation.none;
// portrait-flipped (not supported by WinPhone Apps)
case Windows.Devices.Sensors.SimpleOrientation.rotated180DegreesCounterclockwise:
// Falling back to portrait default
return Windows.Media.Capture.VideoRotation.clockwise90Degrees;
// landscape-flipped
case Windows.Devices.Sensors.SimpleOrientation.rotated270DegreesCounterclockwise:
return Windows.Media.Capture.VideoRotation.clockwise180Degrees;
// faceup & facedown
default:
// Falling back to portrait default
return Windows.Media.Capture.VideoRotation.clockwise90Degrees;
}
}
/**
* Rotates the current MediaCapture's video
* #param {number} orientation - Windows.Devices.Sensors.SimpleOrientation
*/
function setPreviewRotation(orientation) {
capture.setPreviewRotation(orientationToRotation(orientation));
}
try {
createCameraUI();
startCameraPreview();
} catch (ex) {
errorCallback(ex);
}
}
function takePictureFromCameraWindows(successCallback, errorCallback, args) {
var destinationType = args[1],
targetWidth = args[3],
targetHeight = args[4],
encodingType = args[5],
allowCrop = !!args[7],
saveToPhotoAlbum = args[9],
WMCapture = Windows.Media.Capture,
cameraCaptureUI = new WMCapture.CameraCaptureUI();
cameraCaptureUI.photoSettings.allowCropping = allowCrop;
if (encodingType == Camera.EncodingType.PNG) {
cameraCaptureUI.photoSettings.format = WMCapture.CameraCaptureUIPhotoFormat.png;
} else {
cameraCaptureUI.photoSettings.format = WMCapture.CameraCaptureUIPhotoFormat.jpeg;
}
// decide which max pixels should be supported by targetWidth or targetHeight.
var maxRes = null;
var UIMaxRes = WMCapture.CameraCaptureUIMaxPhotoResolution;
var totalPixels = targetWidth * targetHeight;
if (targetWidth == -1 && targetHeight == -1) {
maxRes = UIMaxRes.highestAvailable;
}
// Temp fix for CB-10539
/*else if (totalPixels <= 320 * 240) {
maxRes = UIMaxRes.verySmallQvga;
}*/
else if (totalPixels <= 640 * 480) {
maxRes = UIMaxRes.smallVga;
} else if (totalPixels <= 1024 * 768) {
maxRes = UIMaxRes.mediumXga;
} else if (totalPixels <= 3 * 1000 * 1000) {
maxRes = UIMaxRes.large3M;
} else if (totalPixels <= 5 * 1000 * 1000) {
maxRes = UIMaxRes.veryLarge5M;
} else {
maxRes = UIMaxRes.highestAvailable;
}
cameraCaptureUI.photoSettings.maxResolution = maxRes;
var cameraPicture;
// define focus handler for windows phone 10.0
var savePhotoOnFocus = function () {
window.removeEventListener("focus", savePhotoOnFocus);
// call only when the app is in focus again
savePhoto(cameraPicture, {
destinationType: destinationType,
targetHeight: targetHeight,
targetWidth: targetWidth,
encodingType: encodingType,
saveToPhotoAlbum: saveToPhotoAlbum
}, successCallback, errorCallback);
};
cameraCaptureUI.captureFileAsync(WMCapture.CameraCaptureUIMode.photo).done(function (picture) {
if (!picture) {
errorCallback("User didn't capture a photo.");
// Remove the focus handler if present
window.removeEventListener("focus", savePhotoOnFocus);
return;
}
cameraPicture = picture;
// If not windows 10, call savePhoto() now. If windows 10, wait for the app to be in focus again
if (navigator.appVersion.indexOf('Windows Phone 10.0') < 0) {
savePhoto(cameraPicture, {
destinationType: destinationType,
targetHeight: targetHeight,
targetWidth: targetWidth,
encodingType: encodingType,
saveToPhotoAlbum: saveToPhotoAlbum
}, successCallback, errorCallback);
}
}, function () {
errorCallback("Fail to capture a photo.");
window.removeEventListener("focus", savePhotoOnFocus);
});
}
require("cordova/exec/proxy").add("Camera",module.exports);
});
Does anyone know how I can keep my image rotation in Windows?
In your CameraProxy.js make changes in orientationToRotation function line number 569.
case Windows.Devices.Sensors.SimpleOrientation.notRotated:
if (cameraDirection == 0) {
return Windows.Media.Capture.VideoRotation.clockwise90Degrees;
}
else {
return Windows.Media.Capture.VideoRotation.clockwise270Degrees;
}
For More Info you can refer this Solution
Related
Discord Bot on Heroku not online
Hello everyone I have looked up this issue but can't find an answer to my specific problem. So basically the bot is not turning on, it is offline. I don't know where to put the token or how to put the token. Please let me know of the problem or if you need more code/details. Thank you. Code URL: https://github.com/Verggz/Electrolite main.bot.js "use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const discord_js_1 = __importDefault(require("discord.js")); const builders_1 = require("#discordjs/builders"); const SlashCommand_model_1 = require("./model/SlashCommand.model"); const HelpCommand_command_1 = require("./commands/HelpCommand.command"); const fs_extra_1 = __importDefault(require("fs-extra")); const BINFlipCommand_command_1 = require("./commands/flip/BINFlipCommand.command"); var client = new discord_js_1.default.Client({ "intents": [discord_js_1.default.Intents.FLAGS.GUILDS, discord_js_1.default.Intents.FLAGS.GUILD_MEMBERS, discord_js_1.default.Intents.FLAGS.GUILD_MESSAGES] }); client.on('ready', () => __awaiter(void 0, void 0, void 0, function* () { var helpcommandbuilder = new builders_1.SlashCommandBuilder() .setName("help") .setDescription("Get the list of commands that Project: Scyll has."); var binflipcommandbuilder = new builders_1.SlashCommandBuilder() .setName("binflip") .setDescription("Finds a BIN snipe on the auction house based on the amount of profit you can make.") .addIntegerOption(option => option.setName("profit") .setDescription("the amount of profit you would like to make.").setRequired(true)); SlashCommand_model_1.SlashCommand.CreateSlashCommands([helpcommandbuilder, binflipcommandbuilder]); })); client.on('interactionCreate', function (interaction) { return __awaiter(this, void 0, void 0, function* () { if (!interaction.isCommand()) return; new HelpCommand_command_1.HelpCommand(interaction); new BINFlipCommand_command_1.BINFlipCommand(interaction); }); }); client.login(fs_extra_1.default.readJSONSync("./config.json").SERVER_BOT_KEY); Another file: "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SlashCommand = void 0; const discord_js_1 = require("discord.js"); const axios = __importStar(require("axios")); const rest_1 = require("#discordjs/rest"); const v9_1 = require("discord-api-types/v9"); const fs_extra_1 = __importDefault(require("fs-extra")); var token = fs_extra_1.default.readJSONSync("./config.json").SERVER_BOT_KEY; class SlashCommand { constructor(interaction) { this.http = axios.default; this.interaction = interaction; this.command = interaction.commandName; this.purple = "#BA55D3"; this.backtick = "`"; this.gold = "#d4af37"; this.red = "#C70039"; } CreateEmbed() { return new discord_js_1.MessageEmbed() .setAuthor("Project: Scyll", this.interaction.client.user.avatarURL()).setFooter("Project:Scyll 0.1.0").setTimestamp(); } static CreateSlashCommands(commands) { return __awaiter(this, void 0, void 0, function* () { var clientid = (yield fs_extra_1.default.readJSON("./config.json")).SERVER_CLIENT_ID; yield SlashCommand.REST.put(v9_1.Routes.applicationCommands(clientid), { "body": commands }); }); } } exports.SlashCommand = SlashCommand; SlashCommand.REST = new rest_1.REST({ "version": "9" }).setToken(token);
Look for a config.json file and put you token there
Drag&Drop element into canvas from HTML
I've got a very trivial task to drag&drop the element from a gallery into the Three.js canvas. Nothing seems tricky until I face the problem that when I drag the item and add it to the scene I cannot update the item's coordinates until I finish the drag&drop event I already played around with all events that watch the mouse event mousemove, drag, dragover but the element is just stuck at the initial coordinates, the ones I applied in the dragenter event export const params = { devicePixelRatio: Math.min(window.devicePixelRatio, 2), size: getSizeParams(), grid: { size: 20, divisions: 20, }, } const itemProtos = ['Box', 'Sphere', 'Cone'] export const canvas = document.querySelector(`#canvas`) const raycaster = new Raycaster() const pointer = new Vector2() const scene = new Scene() const camera = new PerspectiveCamera(75, params.size.width / params.size.height, 0.1, 100) camera.position.z = 5 camera.position.y = 2 /** * Variable for Drag&Drop - just created object that's being moved around */ let newObjectType = null let newObject = null /** * Groups */ export const itemGroup = new Group() scene.add(itemGroup) /** * Grid */ export const gridHelper = new GridHelper(params.grid.size, params.grid.divisions) scene.add(gridHelper) /** * Renderer */ const renderer = new WebGLRenderer({ canvas, antialias: true, }) renderer.setSize(params.size.width, params.size.height) renderer.setPixelRatio(params.devicePixelRatio) /** * Resizing updates to fit the screen */ window.addEventListener('resize', () => { params.size = getSizeParams() camera.aspect = params.size.width / params.size.height camera.updateProjectionMatrix() renderer.setSize(params.size.width, params.size.height) renderer.setPixelRatio() }) canvas.addEventListener('mouseenter', () => { canvas.style.cursor = 'grab' }) /** * Controls */ const orbitControls = new OrbitControls(camera, canvas) orbitControls.enableDamping = true orbitControls.addEventListener('start', () => { canvas.style.cursor = 'grabbing' }) orbitControls.addEventListener('end', () => { canvas.style.cursor = 'grab' }) const tick = () => { orbitControls.update() requestAnimationFrame(tick) renderer.render(scene, camera) } window.onload = tick /** * Raycaster functions */ const refreshMouseCoords = (event) => { pointer.x = (event.clientX / params.size.width) * 2 - 1 pointer.y = -(event.clientY / params.size.height) * 2 + 1 } let currentIntersect = null let currentPick = null canvas.addEventListener('mousemove', (event) => { refreshMouseCoords(event) raycaster.setFromCamera(pointer, camera) const intersects = raycaster.intersectObjects(itemGroup.children, false) if(intersects.length && intersects[0].object instanceof Mesh) { if(!currentIntersect) { canvas.style.cursor = 'all-scroll' intersects[0].object.material.color.set('red') console.log(`mouse enter`) } if(currentIntersect && currentIntersect !== intersects[0].object) { currentIntersect.material.color.set('blue') intersects[0].object.material.color.set('red') } currentIntersect = intersects[0].object } else { if(currentIntersect) { console.log(`mouse leave`) currentIntersect.material.color.set('blue') canvas.style.cursor = 'grab' } currentIntersect = null } moveItem(currentPick) }) /** * Function to move items around GridHelper */ const moveItem = (item) => { const intersectsGround = raycaster.intersectObject(gridHelper, false) if(item && intersectsGround[0]) { item.position.z = intersectsGround[0].point.z item.position.x = intersectsGround[0].point.x } } canvas.addEventListener('mousedown', (event) => { event.preventDefault() refreshMouseCoords(event) raycaster.setFromCamera(pointer, camera) const intersects = raycaster.intersectObjects(itemGroup.children, false) if(intersects.length && intersects[0].object instanceof Mesh) { currentPick = intersects[0].object } if(currentIntersect) { canvas.style.cursor = 'all-scroll' orbitControls.enabled = false } }) canvas.addEventListener('mouseup', () => { if(currentIntersect) { canvas.style.cursor = 'all-scroll' orbitControls.enabled = true } if(currentPick) { currentPick = null } }) // *** Drag&Drop *** // const gallery = document.querySelector(`#gallery`) setGallery(itemProtos, gallery) canvas.addEventListener('dragenter', (event) => { event.preventDefault() console.log('Drag&Drop: dragenter') refreshMouseCoords(event) raycaster.setFromCamera(pointer, camera) const intersects = raycaster.intersectObject(gridHelper) if (intersects.length && newObjectType) { add3DEl(intersects[0].point, newObjectType, itemGroup) } }) canvas.addEventListener('dragover', (event) => { event.preventDefault() event.stopPropagation() if(newObject) { moveItem(newObject) } }) function setGallery(itemProtos, gallery) { for (let i of itemProtos) { const el = createProto() gallery.appendChild(el) el.addEventListener('dragstart', function (event) { event.dataTransfer.setData('text/plain', i) newObjectType = i }) el.addEventListener('dragend', function () { newObjectType = null newObject = null }) } } function add3DEl({ x, z }, type = 'Box', scene) { const geometry = new itemObjects[`${type}Geometry`]() const material = new MeshBasicMaterial({ color: 0x0000ff }) // Shared material for all items material.wireframe = true const el = new Mesh(geometry, material) el.position.x = x el.position.y = type == 'Sphere' ? 1 : .5 el.position.z = z el.userData.name = `${type}_${Date.now()}` newObject = el scene.add(el) } Here you can find a playgroud with what I've got so far: Playground
How to make Compass in nativescript when i am unable to find north direction?
I am working on nativescript , but There are serious lack of libraries in it. I am not able to find north direction. i have tried plugin import * as geolocation from "nativescript-geolocation"; import { Accuracy } from "tns-core-modules/ui/enums"; test:function() { var a = geolocation.getCurrentLocation({ desiredAccuracy: Accuracy.high, maximumAge: 5000, timeout: 20000 }) ; a.then( return_a => { console.log("this------------------------------->",return_a); //distance(return_a,); var degree = angleFromCoordinate(return_a.latitude,return_a.longitude , 21.4225,39.8262); console.log(degree); this.gaugeValue = degree;//return_a.verticalAccuracy }); } }); function angleFromCoordinate( lat1, long1, lat2, long2) { var dLon = (long2 - long1); var y = Math.sin(dLon) * Math.cos(lat2); var x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon); var brng = Math.atan2(y, x); brng = brng * 180 / Math.PI; brng = (brng + 360) % 360; brng = 360 - brng; // count degrees counter-clockwise - remove to make clockwise return brng; } There is direction property also available.but it is always -1 . i am using Typescript , javascript as template language.
Here I found the solution. You need to do it manually. import * as app from "tns-core-modules/application"; import { isAndroid, isIOS } from "tns-core-modules/platform"; declare const android: any; declare const CLLocationManager: any; export class MyClass { private sensorUpdate: any; private sensorManager: any; startHeadingUpdates() { if (this.sensorManager || this.sensorUpdate) { return; } if (isIOS) { this.sensorManager = CLLocationManager.alloc().init(); if (this.sensorManager.headingAvailable) { this.sensorManager.startUpdatingHeading(); this.sensorUpdate = setInterval(() => { console.log(this.sensorManager.heading.trueHeading); }, 100); } else { console.log("Heading not available."); } return; } if (isAndroid) { this.sensorManager = app.android.foregroundActivity.getSystemService( android.content.Context.SENSOR_SERVICE ); this.sensorUpdate = new android.hardware.SensorEventListener({ onAccuracyChanged: (sensor: any, accuracy: any) => { // console.log(accuracy) }, onSensorChanged: (event: any) => { console.log(event.values[0]); } }); const orientationSensor = this.sensorManager.getDefaultSensor( android.hardware.Sensor.TYPE_ORIENTATION ); this.sensorManager.registerListener( this.sensorUpdate, orientationSensor, android.hardware.SensorManager.SENSOR_DELAY_UI ); } } stopUpdatingHeading() { if (!this.sensorManager || !this.sensorUpdate) { return; } if (isIOS) { this.sensorManager.stopUpdatingHeading(); clearInterval(this.sensorUpdate); this.sensorManager = null; return; } if (isAndroid) { this.sensorManager.unregisterListener(this.sensorUpdate); this.sensorManager = null; } } }
local storage value gets overwritten
I have initiated 2 localstorage variables within a typescript function. The second variable holding the value overwrites the first variable. How do I fix it? OnSelectedOppPropStatsChange(TypeId: string, StrSelectedValue: string): void { this.appService.SetLoadingShow(true); var url = this.configs.DashboardDemandStatsURL(); var Input = { "TypeId": TypeId, "PS_No": this.user.PS_No, "StrSelectedValue": StrSelectedValue }; localStorage.setItem(this.strTypeSelected, StrSelectedValue); localStorage.setItem(this.strTypeIdValue, TypeId); this.appService.GetDataFromAPIPost(url, Input) .then(response => { this.appService.SetLoadingShow(false); if (response.ResponseCode == this.configs.RetCodeFailure()) { this.ShowDemandDetails = false; this.errorMessage = response.ResponseData; this.appService.ShowMessagePopup(this.configs.MESSAGETYPEERROR(), this.errorMessage); } else { this.OpenDemandStatsDetails = JSON.parse(response.ResponseData.strDemandStatsOpen); this.TeamFulfilledStatsDetails = JSON.parse(response.ResponseData.strDemandStatsTeam); this.RPMFulfilledStatsDetails = JSON.parse(response.ResponseData.strDemandStatsRPM); this.TotalRRCount = this.OpenDemandStatsDetails.length + this.TeamFulfilledStatsDetails.length + this.RPMFulfilledStatsDetails.length; } }, error => { this.errorMessage = <string>error; this.appService.SetLoadingShow(false) }); } OnClickOpenRRNavigate(): void { let SelectedItem = localStorage.getItem(this.strTypeSelected); let SelectedType = localStorage.getItem(this.strTypeIdValue); this.appService.SetLoadingShow(true); var url = this.configs.DashboardDemandStatsTableURL(); var Input = { "TypeId": SelectedType, "PS_No": this.user.PS_No, "StrSelectedValue": SelectedItem, "strRRAllocationValue": this.StrOpenValue }; this.appService.GetDataFromAPIPost(url, Input) .then(response => { this.appService.SetLoadingShow(false); if (response.ResponseCode == this.configs.RetCodeFailure()) { this.errorMessage = response.ResponseData; this.appService.ShowMessagePopup(this.configs.MESSAGETYPEERROR(), this.errorMessage); } else { this.DemandTableDetails = JSON.parse(response.ResponseData.strDemandStatsTable); this.ShowDemandTable = true; } }, error => { this.errorMessage = <string>error; this.appService.SetLoadingShow(false) }); } In the function OnClickOpenRRNavigate() , the SelectedType and SelectedItem holds the same value. How can I fix it?
Hide actionbar on scroll listview
I have an app that has an action bar and a Tabview. Inside the tabview there is a listview. What I want is the actionbar to hide when the user is scrolling down the list and pop up when the user is scrolling up and do it nicely. As an example youtube app for android is doing this. I have tried this code https://gist.github.com/vakrilov/6edc783b49df1f5ffda5 but as I hide the bar a white space appears on the bottom of the screen so not really useful in this case. I tried and fail to modify it and increase the height as I hide the bar using: var params = userList.android.getLayoutParams(); params.height = 500; userList.android.setLayoutParams(params); userList.android.requestLayout(); Also this var LayoutParams= android.view.ViewGroup.LayoutParams; var params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); Finally I came out with a kind of working thing but it is too sudden no animation on the hiding/appearing var isChangingBar = false; var isBarHidden = false; userList.on("pan", function(args) { var delta = args.deltaY; console.log("deltaY: " + delta); if (!isChangingBar) { if (delta > 0 && isBarHidden === true) { isChangingBar = true; isBarHidden = false; page.actionBarHidden = false; isBarHidden = false; setTimeout(function() { isChangingBar = false; }, 250); } else if (delta < 0 && isBarHidden === false) { isChangingBar = true; page.actionBarHidden = true; isBarHidden = true; setTimeout(function() { isChangingBar = false; }, 250); } } } Some idea if there is a better way?
You can add actionbar animation on hide/show: declare const java: any; declare const android: any; export enum LayoutTransitionTypes { CHANGE_APPEARING = 0, CHANGE_DISAPPEARING, APPEARING, DISAPPEARING, CHANGING } export function initPageActionBarVisibilityAnimations(page) { if (!page.actionBar) { return; } const actionBarH = page.actionBar.getMeasuredHeight(); if (actionBarH < 1) { return; } const lt = new android.animation.LayoutTransition(); lt.setAnimator(LayoutTransitionTypes.APPEARING, (function () { const a = new android.animation.ObjectAnimator(); a.setPropertyName('translationY'); a.setFloatValues([0.0]); a.setDuration(lt.getDuration(2)); return a; })()); lt.setAnimator(LayoutTransitionTypes.DISAPPEARING, (function () { const a = new android.animation.ObjectAnimator(); a.setPropertyName('translationY'); a.setFloatValues([-actionBarH]); a.setDuration(lt.getDuration(3)); return a; })()); lt.setStartDelay(LayoutTransitionTypes.CHANGE_APPEARING, 0); lt.setStartDelay(LayoutTransitionTypes.CHANGE_DISAPPEARING, 0); lt.setStartDelay(LayoutTransitionTypes.APPEARING, 0); lt.setStartDelay(LayoutTransitionTypes.DISAPPEARING, 0); lt.setStartDelay(LayoutTransitionTypes.CHANGING, 0); page.nativeView.setLayoutTransition(lt); } Now we may use page pan event to automatically hide/show action bar on scroll pan up/down events. Every change of page.actionBarHidden will start smooth actionbar hide/show transition. export function onScrollPan(ev: PanGestureEventData) { const actionBar = page.actionBar; const scrollView: ScrollView = <ScrollView>page.getViewById('mainScrollView'); const voffset = scrollView.verticalOffset; const dh = 50; if (page.actionBarHidden && ev.deltaY > dh * 5) { initPageActionBarVisibilityAnimations(page); page.actionBarHidden = false; } else if (!page.actionBarHidden && ev.deltaY < -dh && voffset > 0 && voffset > 2 * actionBar.getMeasuredHeight()) { initPageActionBarVisibilityAnimations(page); page.actionBarHidden = true; } }