I saw some similar post but not for NV12 format, so here is my code:
void MyClass::loadPreviewTexture(){
ID3D11Texture2D* textureBuf;
D3D11_TEXTURE2D_DESC textureDesc;
ComPtr<ID3D11Texture2D> tempTexture = this->c_PreviewTexture;
D3D11_TEXTURE2D_DESC tempDesc;
if (tempTexture != nullptr){
tempTexture->GetDesc(&tempDesc);
ComPtr<ID3D11Device> device;
ComPtr<ID3D11DeviceContext> context;
ZeroMemory(&textureDesc, sizeof(textureDesc));
textureDesc.Width = tempDesc.Width;
textureDesc.Height = tempDesc.Height;
textureDesc.MipLevels = tempDesc.MipLevels;
textureDesc.ArraySize = tempDesc.ArraySize;
textureDesc.Format = tempDesc.Format; // NV12
textureDesc.SampleDesc = tempDesc.SampleDesc;
textureDesc.Usage = D3D11_USAGE_STAGING;
textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
textureDesc.MiscFlags = tempDesc.MiscFlags;
tempTexture->GetDevice(&device);
device->GetImmediateContext(&context);
device->GetImmediateContext(&context);
device->CreateTexture2D(&textureDesc, NULL, &textureBuf);
context->CopyResource(textureBuf, tempTexture.Get());
D3D11_MAPPED_SUBRESOURCE mapResource;
HRESULT hr = context->Map(textureBuf, 0, D3D11_MAP_READ, NULL, &mapResource);
//data = new byte[(mapResource.RowPitch / sizeof(byte)) * textureDesc.Height];
//this->size = (mapResource.RowPitch / sizeof(byte)) * textureDesc.Height;
this->size = textureDesc.Width * textureDesc.Height * 3 * sizeof(byte);
data = new byte[this->size];
//memcpy(data, mapResource.pData, mapResource.RowPitch* textureDesc.Height);
memcpy(data, mapResource.pData, this->size);
printf("");
}
}
c_PreviewTexture is a ComPtr and contains the data I need.
I'm not sure about the size of data[] and the allocation. The size for NV12 format is suppose to be 1280*720*3 for a resolution of 1280 * 720. I'm missing something because it worked if I copy like this:
memcpy(data, mapResource.pData, mapResource.RowPitch* textureDesc.Height); // 1280*720
Related
I'd like to ask about my program bcs it doesn't work correctly. I want to recall a set of variable in two different Sequence Array. Here is my code.
// Array of Arrays
var SequenceGo:Array =
\[
{dt:dt1, P:P1, s0:s01, s:s1},
{dt:dt2, P:P2, s0:s02, s:s2},
{dt:dt3, P:P3, s0:s03, s:s3},
{dt:dt4, P:P4, s0:s04, s:s4},
{dt:dt5, P:P5, s0:s05, s:s5},
{dt:dt6, P:P6, s0:s06, s:s6},
{dt:dt7, P:P7, s0:s07, s:s7},
{dt:dt8, P:P8, s0:s08, s:s8},
{dt:dt9, P:P9, s0:s09, s:s9},
{dt:dt10, P:P10, s0:s010, s:s10},
\];
var SequenceBack:Array =
\[
{dtback:dt10back, P:P10, s0:s010, sback:s10back},
{dtback:dt9back, P:P9, s0:s09, sback:s9back},
{dtback:dt8back, P:P8, s0:s08, sback:s8back},
{dtback:dt7back, P:P7, s0:s07, sback:s7back},
{dtback:dt6back, P:P6, s0:s06, sback:s6back},
{dtback:dt5back, P:P5, s0:s05, sback:s5back},
{dtback:dt4back, P:P4, s0:s04, sback:s4back},
{dtback:dt3back, P:P3, s0:s03, sback:s3back},
{dtback:dt2back, P:P2, s0:s02, sback:s2back},
{dtback:dt1back, P:P1, s0:s01, sback:s1back}
\];
function onNext(index:int = 0):void
{
if (index >= SequenceGo.length)
{
return;
}
var aDataGo:Object = SequenceGo[index];
var aDataBack:Object = SequenceBack[index];
//variables
F = s_teganganst.value;
m = s_masjenst.value/10000;
v = Math.sqrt(F/m);
tp = 5000/v;
f = s_frekuensist.value;
w = 2*Math.PI*f;
aDataGo.dt += t;
aDataGo.s = aDataGo.s0 - A * Math.sin(w * aDataGo.dt);
aDataGo.P.y = aDataGo.s;
if(P10.y < 607){
aDataBack.dtback += t;
aDataBack.sback = - A * Math.sin(w * aDataBack.dtBack);
aDataBack.P.y = aDataGo.s + aDataBack.sback;
}
setTimeout(onNext, tp, index + 1);
}
Actually, code
aDataBack.P.y = aDataGo.s + aDataBack.sback;
is not a fit code for the animation because aDataBack is ordered inversely from aDataGo (we have to stay this inverse order for the proper animation in my program). I want to recall the variables based on its number, so each variable will match with another variable. For example,
P1.y = s1 + s1back;
P2.y = s2 + s2back;
P3.y = s3 + s3back;
P4.y = s4 + s4back;
//and so on
I've tried the code above, but it also doesn't work. Any other expression for calling some couples of variables just like my code above? Thanks!
I want to recall the variables based on its number, so each variable will match with another variable
Ok, there are two options.
Option one, simple and straightforward: compose a method to find the correspondent back object on spot:
function findBack(P:Object):Object
{
for each (var aDataBack:Object in SequenceBack)
{
if (aDataBack.P == P)
{
return aDataBack;
}
}
}
So, that piece of code would be
var aDataGo:Object = SequenceGo[index];
var aDataBack:Object = findBack(aDataGo.P);
The possible problem here is the performance. It is fine on the scale of 10 or 100 objects, but as (I suppose) you devise a particle system, the object count easily scales to thousands, and the amount of loop-searching might become cumbersome.
So I advise to prepare a pre-indexed hash so that you won't need to search each single time.
var SequenceBack:Array =
[
// ...
];
// Dictionary is a storage of key:value data, just like Object,
// but Dictionary allows Object keys.
var HashBack:Dictionary = new Dictionary;
for each (var aDataBack:Object in SequenceBack)
{
HashBack[aDataBack.P] = aDataBack;
}
I encourage you to read more about Dictionary class.
And so that piece of code would be
var aDataGo:Object = SequenceGo[index];
var aDataBack:Object = HashBack[aDataGo.P];
I used this package (https://github.com/petrbroz/forge-iot-extensions-demo). After that, I added my own extension code (RobotExt.js). The Control panel and Icon of the my extension were added to the Autodesk Forge website. But unfortunately, the control panel doesn't work.
There are these errors:
This is the source code of the my extension file:
class RobotExtension extends Autodesk.Viewing.Extension {
constructor(viewer, options) {
super(viewer, options);
this.viewer = viewer;
//this.tree = null;
this.tree = this.viewer.model.getData().instanceTree;
this.defaultState = null;
this.customize = this.customize.bind(this);
this.createUI = this.createUI.bind(this);
this.setTransformation = this.setTransformation.bind(this);
this.getFragmentWorldMatrixByNodeId = this.getFragmentWorldMatrixByNodeId.bind(this);
this.assignTransformations = this.assignTransformations.bind(this);
this.findNodeIdbyName = this.findNodeIdbyName.bind(this);
}
load() {
console.log('RobotExtension is loaded!');
this.createUI();
this.setTransformation();
return true;
}
unload() {
console.log('RobotExtension is now unloaded!');
this.viewer.restoreState(this.defaultState);
return true;
}
setTransformation() {
let tree = this.tree;
/* ====================== right 0 ================= */
let ID_BaseRod = 4806;
let ID_LowerArmBody = 4806;
let Pivot_BaseRod = new THREE.Mesh(new THREE.BoxGeometry(20, 20, 20), new THREE.MeshBasicMaterial({ color: 0xff0000 }));
let Position_BaseRod = this.getFragmentWorldMatrixByNodeId(ID_BaseRod).matrix[0].getPosition().clone();
//print the returned value from getFragmentWorldMatrixByNodeId method and using this we can inspect the....
// output of the fucntion(method) whether working or not
console.log(Position_BaseRod);
//console.log(position);
Pivot_BaseRod.position.x = 0;
Pivot_BaseRod.position.y = Position_BaseRod.y;
Pivot_BaseRod.position.z = Position_BaseRod.z-2.84;
viewer.impl.scene.add(Pivot_BaseRod);
let Helper_LowerArmBody = new THREE.Mesh();
let Position_LowerArmBody = this.getFragmentWorldMatrixByNodeId(ID_LowerArmBody).matrix[0].getPosition().clone();
Helper_LowerArmBody.position.x = - Position_LowerArmBody.x + Math.abs(Position_LowerArmBody.x - Pivot_BaseRod.position.x);
Helper_LowerArmBody.position.y = - Position_LowerArmBody.y + Math.abs(Position_LowerArmBody.y - Pivot_BaseRod.position.y);
Helper_LowerArmBody.position.z = - Position_LowerArmBody.z + Math.abs(Position_LowerArmBody.z - Pivot_BaseRod.position.z);
Pivot_BaseRod.add(Helper_LowerArmBody);
console.log(Position_LowerArmBody);
// // /* ====================== left 0 ================= */
let ID_BaseRod10 = 4851;
let ID_LowerArmBody10 = 4851;
let Pivot_BaseRod10 = new THREE.Mesh(new THREE.BoxGeometry(0.1, 0.1, 0.1), new THREE.MeshBasicMaterial({ color: 0xff0000 }));
let Position_BaseRod10 = this.getFragmentWorldMatrixByNodeId(ID_BaseRod10).matrix[0].getPosition().clone();
//print the returned value from getFragmentWorldMatrixByNodeId method and using this we can inspect the....
// output of the fucntion(method) whether working or not
console.log(Position_BaseRod10);
Pivot_BaseRod10.position.x = 0;
Pivot_BaseRod10.position.y = Position_BaseRod10.y;
Pivot_BaseRod10.position.z = Position_BaseRod10.z-2.84;
viewer.impl.scene.add(Pivot_BaseRod10);
console.log(Pivot_BaseRod10);
let Helper_LowerArmBody10 = new THREE.Mesh();
let Position_LowerArmBody10 = this.getFragmentWorldMatrixByNodeId(ID_LowerArmBody10).matrix[0].getPosition().clone();
Helper_LowerArmBody10.position.x = Position_LowerArmBody10.x + Math.abs(Position_LowerArmBody10.x - Pivot_BaseRod10.position.x);
Helper_LowerArmBody10.position.y = -Position_LowerArmBody10.y + Math.abs(Position_LowerArmBody10.y - Pivot_BaseRod10.position.y);
Helper_LowerArmBody10.position.z = -Position_LowerArmBody10.z + Math.abs(Position_LowerArmBody10.z - Pivot_BaseRod10.position.z);
Pivot_BaseRod10.add(Helper_LowerArmBody10);
console.log(Position_LowerArmBody10);
let ID_BaseRod15 = 4886;
let ID_LowerArmBody15 = 4886;
let Pivot_BaseRod15= new THREE.Mesh(new THREE.BoxGeometry(0.1, 0.1, 0.1), new THREE.MeshBasicMaterial({ color: 0xff0000 }));
let Position_BaseRod15 = this.getFragmentWorldMatrixByNodeId(ID_BaseRod15).matrix[0].getPosition().clone();
//print the returned value from getFragmentWorldMatrixByNodeId method and using this we can inspect the....
// output of the fucntion(method) whether working or not
console.log(Position_BaseRod15);
Pivot_BaseRod15.position.x = 0;
Pivot_BaseRod15.position.y = Position_BaseRod15.y;
Pivot_BaseRod15.position.z = Position_BaseRod15.z-2.84;
viewer.impl.scene.add(Pivot_BaseRod15);
console.log(Pivot_BaseRod15);
let Helper_LowerArmBody15 = new THREE.Mesh();
let Position_LowerArmBody15 = this.getFragmentWorldMatrixByNodeId(ID_LowerArmBody15).matrix[0].getPosition().clone();
Helper_LowerArmBody15.position.x = Position_LowerArmBody15.x + Math.abs(Position_LowerArmBody15.x - Pivot_BaseRod15.position.x);
Helper_LowerArmBody15.position.y = -Position_LowerArmBody15.y + Math.abs(Position_LowerArmBody15.y - Pivot_BaseRod15.position.y);
Helper_LowerArmBody15.position.z = -Position_LowerArmBody15.z + Math.abs(Position_LowerArmBody15.z - Pivot_BaseRod15.position.z);
Pivot_BaseRod15.add(Helper_LowerArmBody15);
console.log(Position_LowerArmBody15);
There was an error for limitation character in Stackoverflow I had to delete some parts of my code.
[![enter image description here][2]][2]
In the setTransformation method of your extension class, you have the following line of code:
viewer.impl.scene.add(Pivot_BaseRod1);
The viewer variable is not defined, however. The line of code should instead look like this:
this.viewer.impl.scene.add(Pivot_BaseRod1);
I am following the instructions (https://mlr.mlr-org.com/articles/tutorial/create_learner.html) to create a parametric survival learner to use with MLR. My code is below.
When I try to make the MakeLearner(id = "AFT", "surv.parametric"), I get an error
dist is missing and no default is set even though I already specified the dist default in my code to be "weibull".
makeRLearner.surv.parametric = function() {
makeRLearnerSurv(
cl = "surv.parametric",
package = "survival",
par.set = makeParamSet(
makeDiscreteLearnerParam(id = "dist", default = "weibull",
values = c("weibull", "exponential", "lognormal", "loglogistic")),
),
properties = c("numerics", "factors", "weights", "prob", "rcens"),
name = "Parametric Survival Model",
short.name = "Parametric",
note = "This is created based on MLR3 surv.parametric learner"
)
}
trainLearner.surv.parametric = function (.learner, .task, .subset, .weights = NULL, ...)
{
f = getTaskFormula(.task)
data = getTaskData(.task, subset = .subset)
if (is.null(.weights)) {
mod = survival::survreg(formula = f, data = data, ...)
}
else {
mod = survival::survreg(formula = f, data = data, weights = .weights, ...)
}
mod
}
predictLearner.surv.parametric = function (.learner, .model, .newdata, ...)
{
survival::predict.survreg(.model$learner.model, newdata = .newdata, type = "response", ...)
}
Based on here, the prediction function needs to return linear predictors and that would be lp not response. Also, the cindex function of MLR does not seem to be consistent with the output of SurvReg. Based on this discussion, adding a minus seems to resolve the issue. So the prediction function would be as below.
predictLearner.surv.reg = function(.learner, .model, .newdata, ...) {
-predict(.model$learner.model, newdata = .newdata, type = "lp", ...)
}
What is the correct way of using a Vulkan VkImage as a CUDA cuArray?
I've been trying to follow some examples, however I get a CUDA_ERROR_INVALID_VALUE on a call to cuExternalMemoryGetMappedMipmappedArray()
To provide the information in an ordered way.
I'm using CUDA 10.1
Base code comes from https://github.com/SaschaWillems/Vulkan, in particular I'm using the 01 - Vulkan Gears demo, enriched with the saveScreenshot method 09 - Capturing screenshots
Instead of saving the snapshot image to a file, I'll be sending the snapshot image into CUDA as a CUarray.
I've enabled the following instance and device extensions:
std::vector<const char*> instanceExtensions = {
VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME };
std::vector<const char*> deviceExtensions = { VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME };
I have a VkImage, created as follows:
// Create the linear tiled destination image to copy to and to read the memory from
VkImageCreateInfo imageCreateCI(vks::initializers::imageCreateInfo());
imageCreateCI.imageType = VK_IMAGE_TYPE_2D;
// Note that vkCmdBlitImage (if supported) will also do format conversions if the swapchain color format would differ
imageCreateCI.format = VK_FORMAT_R8G8B8A8_UNORM;
imageCreateCI.extent.width = width;
imageCreateCI.extent.height = height;
imageCreateCI.extent.depth = 1;
imageCreateCI.arrayLayers = 1;
imageCreateCI.mipLevels = 1;
imageCreateCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageCreateCI.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateCI.tiling = VK_IMAGE_TILING_LINEAR;
imageCreateCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageCreateCI.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
VkExternalMemoryImageCreateInfoKHR extImageCreateInfo = {};
/*
* Indicate that the memory backing this image will be exported in an
* fd. In some implementations, this may affect the call to
* GetImageMemoryRequirements() with this image.
*/
extImageCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR;
extImageCreateInfo.handleTypes |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
imageCreateCI.pNext = &extImageCreateInfo;
// Create the image
VkImage dstImage;
VK_CHECK_RESULT(vkCreateImage(device, &imageCreateCI, nullptr, &dstImage));
// Create memory to back up the image
VkMemoryRequirements memRequirements;
VkMemoryAllocateInfo memAllocInfo(vks::initializers::memoryAllocateInfo());
VkDeviceMemory dstImageMemory;
vkGetImageMemoryRequirements(device, dstImage, &memRequirements);
memAllocInfo.allocationSize = memRequirements.size;
// Memory must be host visible to copy from
memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
VkExportMemoryAllocateInfoKHR exportInfo = {};
exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;
exportInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
memAllocInfo.pNext = &exportInfo;
VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &dstImageMemory));
VK_CHECK_RESULT(vkBindImageMemory(device, dstImage, dstImageMemory, 0));
From there I'll:
Get the Vulkan Memory Handler:
int CuEncoderImpl::getVulkanMemoryHandle(VkDevice device,
VkDeviceMemory memory) {
// Get handle to memory of the VkImage
int fd = -1;
VkMemoryGetFdInfoKHR fdInfo = { };
fdInfo.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR;
fdInfo.memory = memory;
fdInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
auto func = (PFN_vkGetMemoryFdKHR) vkGetDeviceProcAddr(device,
"vkGetMemoryFdKHR");
if (!func) {
printf("Failed to locate function vkGetMemoryFdKHR\n");
return -1;
}
VkResult r = func(device, &fdInfo, &fd);
if (r != VK_SUCCESS) {
printf("Failed executing vkGetMemoryFdKHR [%d]\n", r);
return -1;
}
return fd;
}
Import the memory:
CUDA_EXTERNAL_MEMORY_HANDLE_DESC memDesc = { };
memDesc.type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD;
memDesc.handle.fd = getVulkanMemoryHandle(device, memory);
memDesc.size = extent.width*extent.height*4;
CUDA_DRVAPI_CALL(cuImportExternalMemory(&externalMem, &memDesc));
And map the memory: This is the step that it is failing.
CUarray CuEncoderImpl::getCUDAArrayFromExternalMemory(const VkExtent3D &extent,const CUexternalMemory &m_extMem) {
CUmipmappedArray m_mipmapArray;
CUresult result = CUDA_SUCCESS;
CUarray array;
CUDA_ARRAY3D_DESCRIPTOR arrayDesc = { };
arrayDesc.Width = extent.width;
arrayDesc.Height = extent.height;
arrayDesc.Depth = 0;
arrayDesc.Format = CU_AD_FORMAT_UNSIGNED_INT32;
arrayDesc.NumChannels = 4;
arrayDesc.Flags = CUDA_ARRAY3D_SURFACE_LDST;
CUDA_EXTERNAL_MEMORY_MIPMAPPED_ARRAY_DESC mipmapArrayDesc = { };
mipmapArrayDesc.arrayDesc = arrayDesc;
mipmapArrayDesc.numLevels = 1;
mipmapArrayDesc.offset = 0;
CUDA_DRVAPI_CALL(cuExternalMemoryGetMappedMipmappedArray(&m_mipmapArray, m_extMem, &mipmapArrayDesc));
CUDA_DRVAPI_CALL(cuMipmappedArrayGetLevel(&array, m_mipmapArray, 0));
return array;
}
I've been trying multiple combinations of the parameters, but failed so far. The error point to an invalid parameter, but I'm not sure how to find what's wrong.
Only thing that had worked is to map the Vulkan image memory to a host buffer and then copying it into the CUDA array... but I guess that's expensive and I'd like to avoid it if possible.
For the record, I finally got this to work.
Some notes and the modifications I had to do to the code listed in the question:
Vulkan-CUDA interoperability is advertised as a feature of CUDA 10, see CUDA 10 Features revealed
The tiling of the image that is going to be mapped had to be `VK_IMAGE_TILING_OPTIMAL
imageCreateCI.tiling = VK_IMAGE_TILING_OPTIMAL;
The memory for that image must be allocated with the VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
The memory descriptor when importing the memory should use the memory size that was returned in the memory requirements (size below is memRequirements.size from the code creating the image):
CUDA_EXTERNAL_MEMORY_HANDLE_DESC memDesc = { };
memDesc.type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD;
memDesc.handle.fd = getVulkanMemoryHandle(device, memory);
memDesc.size = size;
CUDA_DRVAPI_CALL(cuImportExternalMemory(&externalMem, &memDesc));
Finally the mapped array is described as being CU_AD_FORMAT_UNSIGNED_INT8 with four channels and with a CUDA_ARRAY3D_COLOR_ATTACHMENT
CUDA_ARRAY3D_DESCRIPTOR arrayDesc = { };
arrayDesc.Width = extent.width;
arrayDesc.Height = extent.height;
arrayDesc.Depth = 0;
arrayDesc.Format = CU_AD_FORMAT_UNSIGNED_INT8;
arrayDesc.NumChannels = 4;
arrayDesc.Flags = CUDA_ARRAY3D_COLOR_ATTACHMENT;
CUDA_EXTERNAL_MEMORY_MIPMAPPED_ARRAY_DESC mipmapArrayDesc = { };
mipmapArrayDesc.arrayDesc = arrayDesc;
mipmapArrayDesc.numLevels = 1;
mipmapArrayDesc.offset = 0;
CUDA_DRVAPI_CALL(cuExternalMemoryGetMappedMipmappedArray(&m_mipmapArray, m_extMem, &mipmapArrayDesc));
After those changes, I was able to get it to work.
I few the changes were glaring mistakes on my side (like the size), a few things I found carefully re-reading the documentation for the 100th time, others were guesses at hints in the documentation and, finally, a lot of trial and error.
i have created a formula sheet, with basically 1 input field which will return 4 results, and a calculate button.
on a right input, right results, which i have no problem.
on a blank input, the results should remain blank with error message at the bottom. but right now the results somehow returned a "a", and the calculate button does not work when the right input is in. my codes' below, appreciate advice.
import flash.events.MouseEvent;
calculate_btn.addEventListener(MouseEvent.CLICK,calculateClick);
var inputNum:String;
var tRes:Number;
var mRes: Number;
var sRes: Number;
function calculateClick(event:MouseEvent):void{
if (inputNum != ""){
inputNum = inputTxt.text;
tRes = Math.round((parseInt(inputNum) * 10000 / 3600)*10)/10;
tRes.toString();
tCal.text = String(tRes);
mRes = tRes * 20;
mCal.text = String(mRes);
sRes = mRes - 556;
sCal.text = String(sRes);
} else if (inputNum == "") {
tCal.text = "";
mCal.text = "";
sCal.text = "";
warningTxt.text = "Error! Please input!";
}
}
Ok I think I have it working. I did change the calc on the line "tRes = Math.round(inputNum * 10000 / 3600)" but you should be able to change it back to what you had without any problems.
calculate_btn.addEventListener(MouseEvent.CLICK,calculateClick);
var inputNum:Number;
var tRes:Number;
var mRes: Number;
var sRes: Number;
function calculateClick(event:MouseEvent):void{
inputNum = Number(inputTxt.text);
if (!isNaN(inputNum)){
tRes = Math.round(inputNum * 10000 / 3600)
tCal.text = String(tRes);
mRes = tRes * 20;
mCal.text = String(mRes);
sRes = mRes - 556;
sCal.text = String(sRes);
warningTxt.text = "";
} else {
tCal.text = "";
mCal.text = "";
sCal.text = "";
warningTxt.text = "Error! Please input!";
}
}