I am learning to build a surface using JMonkey api. The class Surface has a method
createNurbsSurface(controlPoints, nurbKnots, uSegments, vSegments, basisUFunctionDegree, basisVFunctionDegree).
I am trying to make a simple example to understand the meaning of the arguments. However, I can't initialize the second argument:
List<Float>[] nurbKnots
I tried:
List<Float>[] nurbKnots = {new ArrayList<Float>()};
but it complains that you cannot create a generic array of List<Float>.
Could someone show me how to initialize this nurbKnots.
It works for non-generic List:
List[] listNonGeneric = new ArrayList[10];
But this won't work:
List<Float>[] listGeneric = new ArrayList<Float>[10];
You have to use:
List<List<Float>> nurbKnots = new ArrayList<>();
and pass the argument as
(List<Float>[])nurbKnots.toArray();
One friend helped. He told me:
In Java, it's not really possible to have arrays of generic types (safely). You have to allow unchecked assignment. Something like:
#SuppressWarnings("unchecked")
List<Float>[] f = new List[2];
f[0] = new ArrayList<Float>();
f[0].add(0.1);
f[1] = new ArrayList<Float>();
f[1].add(0.2);
But, it worked!
Related
I am attempting to implement a solution from How to set canBecomeKeyWindow? Into my native C application using Objective-C runtime (The app is already written with objective C Runtime). Is there a way to create a subclass purely in Objective-C Runtime?
Right now I just create NSWindow object but need to be able to create my own so I can override the function specified in that question.
objc_msgSend((id)objc_getClass("NSWindow"), sel_registerName("alloc"));
The signature of can_become_key_window_true is slightly incorrect. According to the documentation (https://developer.apple.com/documentation/objectivec/objective-c_runtime/imp?language=objc) the function should have at least two arguments: "self" and "_cmd". So the signature should be like:
static bool can_become_key_window_true(__unused id _self, __unused SEL _cmd) {
return true;
}
You could also use #encode to construct the type encoding for the function.
char encoding[10]; // should be enough
snprintf(encoding, 10, "%s%s%s", #encode(BOOL), #encode(id), #encode(SEL));
... or you could get a method from UIWindow and get its type encoding like:
Method m = class_getInstanceMethod(objc_lookUpClass("UIWindow"), sel_getUid("canBecomeKeyWindow"));
const char *encoding = method_getTypeEncoding(m);
And as you might have noticed you could use sel_getUid() instead of sel_registerName as you expect this selector to be already registered by this time (because you are about to override an existing method).
To allocate a new instance you could use
window = class_createInstance(__UIWindow);
Figured it out after a lot of code searching:
// Subclass NSWindow with overridden function
Class __NSWindow =
objc_allocateClassPair(objc_getClass("NSWindow"), "__NSWindow", 0);
class_addMethod(__NSWindow,
sel_registerName("canBecomeKeyWindow"),
(IMP)can_become_key_window_true, "B#:");
objc_registerClassPair(__NSWindow);
// Allocate a new __NSWindow
window = objc_msgSend((id)__NSWindow, sel_registerName("alloc"));
And then can_become_key_window_true is defined as:
static bool can_become_key_window_true() {
return true;
}
I use objc_allocateClassPair to subclass the object and return a Class of that object. Then I use class_addMethod to override the method canBecomeKeyWindow. And finally use objc_registerClassPair to register my new class before using it as I would a normal NSWindow.
I have many class in my library almost 300, and I want to generate instance name by loop. In other words I wanna instead of this approach(witch has many code line):
X:This is my problem:
var cm1: Cm1 = new Cm1();
var cm2: Cm2 = new Cm2();
var cm3: Cm3 = new Cm3();
...
use like this approach (less than 10 code lines):
Y:I think this is solution:
for (var i: uint = 1; i < 4; i++)
{
var getChildByName("cm" + i): getChildByName("Cm" + i) = new getChildByName("Cm" + i);
}
but I know above code does not work, is there any way to make them !
-What am I actually trying to solve?
Make many variable by a few line code and save time and size app!
-Why do I have ~300 classes and why are you trying to create them in a loop at once?
This is about to data of request application!
-What do these classes do that you unconditionally need one of each all at the same time?
Because those data would show at first time!
First, it is better to store the classes in an Array or Object rather than an external variable for each item. if you want to access them by name, better to use object:
var classList:Object=new Object();
Then in your loop:
for(var i:uint=1;i<NumberOfClasses;i++){
classList["cm"+i.toString()]=new (getDefinitionByName("Cm"+i.toString()) as Class)();
}
getDefinitionByName is used to make Constructors using String;
Note: if your classes contain a package directory, you should include it. for example:
getDefinitionByName("myclasses.cm.Cm123")();
Then you can access them using Bracket syntax:
classList["cm123"].prop=val;
And don't forget to:
import flash.utils.getDefinitionByName;
I Hope it will help.
EDIT
to use Array instead of object, the loop should be:
for(var i:uint=1;i<NumberOfClasses;i++){
classList[i]=new (getDefinitionByName("Cm"+i.toString()) as Class)();
}
then to access them:
addChild(classList[0]);//0 or any other index;
I need to split string to an array. And I get object reference not set to an instance of an object when I try to add new object to the array:
array<d3^> ^pr_d3; //d3 - class
parts = sr->ReadLine()->Split(
(array<String^>^)nullptr,
StringSplitOptions::RemoveEmptyEntries); //array<String ^> ^parts;
pr_d3[0] = gcnew d3(
parts[0], parts[1],
parts[2],
Convert::ToInt16(parts[3]), Convert::ToInt16(parts[4])); //error
Code on Ideon
You're not initializing the array pr_d3.
Removing the correct code, you currently have this:
array<d3^> ^pr_d3;
pr_d3[0] = gcnew d3(...);
The error is trying to access [0] of pr_d3, but pr_d3 is still null.
You need to initialize pr_d3 with gcnew array<d3^>(<some array size>), or if you're not sure of the size you'll need, use a List<d3^> instead.
How can you reverse an array without using the reverse() method?
public class Main extends Sprite
{
private var _reversedList:Array = new Array();
public function Main()
{
var yourShoppingList:Array = ["Milk","Bread","Eggs","Cereal","Cheese","Ham"];
shoppingList(yourShoppingList);
trace("The original array was " + yourShoppingList + " and now it is reversed as " + _reversedList + ".");
}
private function shoppingList(items:Array):Array {
while(items.length){
var lastItem:String = items.pop();
_reversedList.unshift(lastItem);
}
return _reversedList;
}
}
This is what I have so far. I tried using _reversedList.unshift(items.pop()); but it was giving me an error, so I ended up creating a variable, and now it seems fine? But regardless, it's not reversing the Array, and I'm not sure why.
Thank you for your time and help. I really appreciate it.
*NOTE: For those of you who are Full Sail students, feel free to reference this, but don't copy / paste, as the teachers know about this post and you'll probably be penalized for cheating. Just a friendly warning.
Changing
_reversedList.unshift(lastItem);
to
_reversedList.push(lastItem);
works for me. Taking the last item and pushing it in as the first item on the new array.
Let's say I have an array, each item in the array has a corresponding library item.
I'd like to do something like :
var rando = Math.round(Math.random()*3)
var myArray = new Array ["ball", "wall", "fall"]
var i:myArray[rando] = myArray[rando] new myArray[rando]()
addChild(i)
But, this doesn't work. What's the secret?
Thank You,
Victor Hugo
Surprised no one mentioned getDefinitionByName() here.
Here's some complete code to get your example working:
var myArray = ["ball", "wall", "fall"];
/**
* Creates a random instance based on an input array containing class names as Strings.
* #param The input array containing aforementioned Strings.
* #return The newly created instance.
*/
function createRandom(typeArray:Array):*
{
// Select random String from typeArray.
var selection:String = typeArray[ int(Math.random() * typeArray.length) ];
// Create instance of relevant class.
var Type:Class = getDefinitionByName(selection) as Class;
// Return created instance.
return new Type();
}
// Randomly create and add instance.
var instance:DisplayObject = createRandom(myArray);
addChild(instance);
Ok so there are a bunch of problems with this.
A large one being var i:myArray[rando] = myArray[rando] new myArray[rando]() not really too sure what you're trying to do here.
Anyway I'm going to assume ball, wall and fall are instance names of MovieClips you have in your library. I think you're going to want something like this
var rando:int = Math.floor(Math.random()*3); //As the comments point out this should give you a random
//int between 0 and 2, arrays are 0 indexed so this is what we want if we have 3 items
Now for your array, you're current putting strings in there. Flash has no idea what "ball", etc are.
Try something like this
var myArray:Array = new Array [new ball(), new wall(), new fall()]; //this creates a new instance of your library object and stores it in your array
Now to add one of these to your stage:
addChild(myArray[rando]); //this uses the random number to pull one of the items out of your array
What you're trying to do with var i:myArray[rando] doesn't really make sense. There is no type of myArray[rando] this slot should be holding a MovieClip
If you only have a few choices, it's easier to use a switch-case.
switch (rando) {
case 0:
i = new ball();
break;
case 1:
i = new wall();
break;
case 2:
i = new fall();
break;
}
addChild(i);
I suggest you define the variable i as a MovieClip, in which case it can be instantiated as both ball, wall, fall.
Given that ball, wall and fall are in the library exported to actionscript.
Just guessing off your limited information but give this a shot.
private function myFunction():void{
var rando = Math.round(Math.random()*3);
var myArray= new Array ["ball", "wall", "fall"];
}
private function generateItem(item:String):void{
switch(item){
case "ball" : generateBall(); break;
case "wall" : generateWall(); break;
case "fall" : generateFall(); break;
}
private function generateBall():void{
//code to generate ball
addChild(ball);
}
private function generateFall():void{
//code to generate fall
addChild(fall);
}
private function generateWall():void{
//code to generate wall
addChild(wall);
}
Change your arrary line to:
var myArray = new Array [ball, wall, fall];
This should work. :)
Marty Wallace gets big praise for steering me down the path of getDefinitionByName(). The example he posted was good, but this example does exactly what I was going for.
http://www.emanueleferonato.com/2011/03/31/understanding-as3-getdefinitionbyname-for-all-eval-maniacs/