Flex 4/Air setting bounds for WindowedApplication - apache-flex

for some reason this flex 4 code gives me an error but I can't figure out why. In my WindowedApplication I have:
var prefs:Object = fs.readObject();
fs.close();
var rect:Rectangle = new Rectangle();
rect = prefs.bounds as Rectangle;
this.bounds = rect; // error here
Error message:
ArgumentError: Error #2007: Parameter rect must be non-null.
I originally also tried it without the rect object and just did:
this.bounds = prefs.bounds as Rectangle;
which gives me the following error:
TypeError: Error #1034: Type Coercion failed: cannot convert Object#1dbbe1f1 to flash.geom.Rectangle.
That seems like a bogus error since I can assign pref.bounds to rect without an error. I don't know why this isn't working. It works under flex 3 compatibility mode but that also breaks a lot of my spark components so I can't use it.

rect = prefs.bounds as Rectangle;
rect ends up as null because prefs.bounds is not an instance of Rectangle class. Casting with as keywords returns null if it fails.
Just give a trace(prefs.bounds); after the call to readObject to see what it contains.
Update:
The fact that the value in prefs.bounds have x, y, width and height properties, doesn't make it a Rectangle object - it is just an object with those four properties. The easy solution is to create a Rectangle object from those values and use that:
var prefs:Object = fs.readObject();
var rect:Rectangle = new Rectangle(prefs.bounds.x, prefs.bounds.y, prefs.width, prefs.height);
this.bounds = rect;
If you call registerClassAlias before writing the rectangle object to the file stream, the readObject would return an object of appropriate type instead of a generic one.
registerClassAlias("flash.geom.Rectangle", Rectangle);
fs.writeObject(this.bounds);
//later...
//Casting with () will throw an error if the read object is not a Rectangle
var rect:Rectangle = Rectangle(fs.readObject());
trace(rect);

Related

Unable to assign [undefined] to double

I am Learning QML newly and am trying to resolve the following warning:
[warning] main.qml:392:25: Unable to assign [undefined] to double
main.qml
Rectangle{
id: rect
...
readonly property real scale0: (rotateRepeater.yPointM - rotateRepeater.yPointT) / height
readonly property real scale1: (rotateRepeater.yPointB - rotateRepeater.yPointM) / height
readonly property real yScale: [scale0, scale1][index] // Warning is in this line
}
The error is being show for property yScale.
Method 1 that I tried was -
readonly property real yScale: Binding {
when: onScale0Changed && onScale1Changed
yScale: [scale0, scale1][index]
}
and got the following error :
"cannot assign to non-existent property "yScale"
I tried Googling and found out two possible answers
-https://stackoverflow.com/questions/52290153/qml-unable-to-assign-undefined-to
-https://stackoverflow.com/questions/73306793/qml-failure-accessing-properties-with-error-unable-to-assign-undefined-to
but, I was unable to solve the warning.
Any help here is much appreciated.
Thanks in Advance.
Some further explorative testing is required for you to narrow down the cause of the undefined values. Here's one way how you can achieve further debugging:
Rectangle{
id: rect
...
readonly property real scale0: (rotateRepeater.yPointM - rotateRepeater.yPointT) / height
readonly property real scale1: (rotateRepeater.yPointB - rotateRepeater.yPointM) / height
readonly property real yScale: getYScale(scale0, scale1, index)
function getYScale(scale0, scale1, index) {
console.log("scale0: ", scale0, "scale1: ", scale1, "index: ", index);
return [scale0, scale1][index];
}
}
I made an assumption that I believe one of your inputs has an undefined value, and that undefined value was, possibly momentary. Doing the above code will not only help you see which parameter it is but, that function may get triggered multiple times so you can see it transition from an undefined state to a defined state. Then, you can build error handling in your function, e.g.
function getYScale(scale0, scale1, index) {
console.log("scale0: ", scale0, "scale1: ", scale1, "index: ", index);
if (scale0 === undefined) scale0 = 0;
if (scale1 === undefined) scale1 = 0;
if (index === undefined) index = 0;
let result = [scale0, scale1][index];
if (result === undefined) result = 0;
return result;
}
Doing the above actually has a lot of paranoid edge case handling, but, it should give you a deeper understanding of the intermediate values used in your property binding and help tailor a fix. Once you get the problem solved, you can discard the above function and incorporate the result back into a 1 line solution, perhaps something like:
Rectangle{
id: rect
...
readonly property real scale0: (rotateRepeater.yPointM - rotateRepeater.yPointT) / height
readonly property real scale1: (rotateRepeater.yPointB - rotateRepeater.yPointM) / height
readonly property real yScale: [scale0 ?? 0, scale1 ?? 0][index ?? 0] ?? 0
}
As I said above, you probably set incorrect index that is out of range. Check this code:
Item {
id: item
property int index: 0
property double value: [1.0, 2.0, 3.0][index]
onValueChanged: {
console.log(value)
}
Timer {
interval: 1000;
running: true;
repeat: true
onTriggered: item.index = Math.round(Math.random() * 3)
}
}
The output is possible will be:
qml: 1
qml: 3
qml: 2
main.qml:18:9: Unable to assign [undefined] to double
qml: 3
qml: 2
qml: 3
main.qml:18:9: Unable to assign [undefined] to double
Do this:
Rectangle{
id: rect
...
readonly property real scales: [(rotateRepeater.yPointM - rotateRepeater.yPointT) / height ,
(rotateRepeater.yPointB - rotateRepeater.yPointM) / height]
readonly property real yScale: scales[index] // Warning is in this line
}
Property evaluations are arbitrarily ordered, so the eval of yScale may happen when either scale0 or scale1 are not evaluated yet. There is also a possibility that the index value is out of range, as mentioned in other answers.
Quote from the Qt documentation:
Syntactically, bindings are allowed to be of arbitrary complexity. However, if a binding is overly complex - such as involving multiple lines, or imperative loops - it could indicate that the binding is being used for more than describing property relationships. Complex bindings can reduce code performance, readability, and maintainability. It may be a good idea to redesign components that have complex bindings, or at least factor the binding out into a separate function. As a general rule, users should not rely on the evaluation order of bindings.

Rotate object and fit to screen

I have raw obj and mtl files from photogrammetry.
They have different sizes and orientation.
The goal is to change the size and orientation for it to fill the screen.
Orientation is to be calculated assuming that the flattest area is defined as ground and anomalies from there, ie bumps, which are likely the desired objects, are to be aligned with the Y-axis point up.
The first approach was to use a bounding box
var el = document.querySelector('#aentity');
var object = el.getObject3D('tree-obj');
// compute bounding box
var bbox = new THREE.Box3().setFromObject(object);
console.log(bbox.min, bbox.max)
to get the size and scale it accordingly.
This already fails with
three.js:3819
Uncaught TypeError: Cannot read properties of undefined (reading 'updateWorldMatrix')
at Box3.expandByObject (three.js:3819:1)
at Box3.setFromObject (three.js:3766:1)
at file.html:25:29
line 25:
var bbox = new THREE.Box3().setFromObject(object);

Tiled MapObject size

I am loading Tiled map via TmxMapLoader and I have no trouble getting tiles, etc. But when I want to extract values from Object Layer, I am only able to get x, y with this code:
MapProperties props = layer.getObjects().get(i).getProperties();
float x = (float) props.get("x");
float y = (float) props.get("y");
Which gets me the right values, but when I try to add this:
float width = (float) props.get("width");
float height = (float) props.get("height");
It throws me this error:
Exception in thread "LWJGL Application" java.lang.NullPointerException
at cz.vilix.managers.MapManager.<init>(MapManager.java:67)
at cz.vilix.main.Game.create(Game.java:50)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:136)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:114)
(Line 67 in MapManager is where I try to get the width value.) It seems a bit ood to me, because I though, that I can get anything from the properties of an object, which is listed in the properties window:
Also using "Width" & "Height" instead of "width" & "height" doesn't work.
Changing the type to Object like this:
Object width = props.get("Width");
Object height = props.get("Height");
System.out.println(width + " " + height);
Prints: null null.
The solution that works is to get RectangleMapObject (or any other shape), and the get the basic Rectangle with this code: Rectangle r = rect.getRectangle() and the you can use parameters of the Rectangle.
Or you can skip the step of creating a new Rectangle object and use it as in this code:
RectangleMapObject rect = (RectangleMapObject) layer.getObjects().get(i);
float x = (float) rect.getRectangle().x;
float y = (float) rect.getRectangle().y;
float width = rect.getRectangle().width;
float height = rect.getRectangle().height;

box2d CreateFixture with b2FixtureDef gives pure virtual function call

i have this code that gives me run time error in the line :
body->CreateFixture(&boxDef)
im using cocos2d-x 2.1.5 with box2d 2.2.1 in windows
CCSprite *sprite = CCSprite::create(imageName.c_str());
this->addChild(sprite,1);
b2BodyDef bodyDef;
bodyDef.type = isStatic?b2_staticBody:b2_dynamicBody;
bodyDef.position.Set((position.x+sprite->getContentSize().width/2.0f)/PTM_RATIO,
(position.y+sprite->getContentSize().height/2.0f)/PTM_RATIO);
bodyDef.angle = CC_DEGREES_TO_RADIANS(rotation);
bodyDef.userData = sprite;
b2Body *body = world->CreateBody(&bodyDef);
b2FixtureDef boxDef;
if (isCircle)
{
b2CircleShape circle;
circle.m_radius = sprite->getContentSize().width/2.0f/PTM_RATIO;
boxDef.shape = &circle;
}
else
{
b2PolygonShape box;
box.SetAsBox(sprite->getContentSize().width/2.0f/PTM_RATIO, sprite->getContentSize().height/2.0f/PTM_RATIO);
boxDef.shape = &box;
}
if (isEnemy)
{
boxDef.userData = (void*)1;
enemies->insert(body);
}
boxDef.density = 0.5f;
body->CreateFixture(&boxDef) //<-- HERE IS THE RUN TIME ERROR
;
when i debug the box2d code im getting to b2Fixture.cpp
in the method :
void b2Fixture::Create(b2BlockAllocator* allocator, b2Body* body, const b2FixtureDef* def)
in the line :
m_shape = def->shape->Clone(allocator);
getting the runtime error :
R6025 pure virtual function call
Tricky one. I ran into this myself a couple times. It has to do with variable scope.
The boxDef.shape is the problem. You create the shapes as local variables in the if/else blocks and then assign them to boxDef. As soon as execution leaves the if/else block scope those local variables will be garbage. The boxDef.shape now points to freed memory.
The solution is to keep the shape variables in scope by moving the circle and box shape declarations before the if/else block.

Mystery coordinate offset on getCharBoundaries

I've ran into a weird problem with getCharBoundaries, I could not figure out what coordinate space the coordinates returned from the function was in. What ever I tried I could not get it to match up with what I expected.
So I made a new project and and added simple code to highlight the last charater in a textfield, and all of a sudden it worked fine. I then tried to copy over the TextField that had been causing me problems, into the new project. And now the same weird offset appeared 50px on the x axis. Everything else was spot on.
So after some headscracthing comparing the two TextFields, I simply can not see a difference in their properties or transformation.
So I was hoping that someone might now what property might affect the coordinates returned by getCharBoundaries.
I am using Flash CS4.
I've just had exactly the same problem and thought I'd help out by offering what my findings are. With a help from this thread, I tried to find everything that wasn't 'default' about the textfield I was using. I found that when I had switched my TextFormatAlign (or 'align' in the IDE) and TextFieldAutoSize properties to 'LEFT' as opposed to 'CENTER', it solved the problem.
A little late in the game perhaps, but worth knowing for anyone running into the same problem. This was the only thread I could find that raised the right flag...
Well the getCharBoundaries returns the boundaries in the textfield coordinate system. Where the origin is topleft corner of the textfield.
getCharBoundaries does not take into consideration the scrolling. you need to check if there are scrollbars on its parent (textarea) and if so relocate. One quick way of doing it is using localtoglobal and globaltolocal. Use the first to translate from the textfield coordinate system to the application coordinate system and then use the second to translate from the app coordinate system to the coordinate system of the parent of the textfield which is the textarea. I'm fine tuning a my method to get char boundaries i will publish it today on my blog
http://flexbuzz.blogspot.com/
Works For Me(tm) (Flex Builder AS3 project):
[Embed(systemFont="Segoe UI", fontWeight="bold", fontName="emb",
mimeType="application/x-font")]
private var EmbeddedFont:Class;
public function ScratchAs3()
{
stage.scaleMode = 'noScale';
stage.align = 'tl';
var m:Matrix = new Matrix(.8, .1, -.1, 1.1, 26, 78);
var t:TextField = new TextField();
t.autoSize = 'left';
t.wordWrap = false;
t.embedFonts = true;
t.defaultTextFormat = new TextFormat("emb", 100, 0, true);
t.transform.matrix = m;
t.text = "TEST STRING.";
addChild(t);
var r:Rectangle = t.getCharBoundaries(8);
var tl:Point = m.transformPoint(r.topLeft);
var tr:Point = m.transformPoint(new Point(r.right, r.top));
var bl:Point = m.transformPoint(new Point(r.left, r.bottom));
var br:Point = m.transformPoint(r.bottomRight);
graphics.beginFill(0xFF, .6);
graphics.moveTo(tl.x, tl.y);
graphics.lineTo(tr.x, tr.y);
graphics.lineTo(br.x, br.y);
graphics.lineTo(bl.x, bl.y);
graphics.lineTo(tl.x, tl.y);
}
To literally answer your question, it returns the coordinates in the TextField's coordinate system, not it's parent, and it is affected by DisplayObject.transform.matrix, which is the backing for the .x, .y, .scaleX, .scaleY, .width, .height, and .rotation properties.
What ever it was the solution was simple to add a new TextField, never found out what property screwed everything up.
The first answer is correct in most cases. However if your field is parented to another movie clip it may still return the wrong y coordinate. try this code:
//if this doesn't work:
myTextFormat = new TextFormat();
myTextFormat.align = TextFormatAlign.LEFT;
myFieldsParent.myField.autoSize = TextFieldAutoSize.LEFT;
myFieldsParent.myField.setTextFormat( myTextFormat);
//try this:
var x = myFieldsParent.myField.getCharBoundaries(o).x;
var y = myFieldsParent.myField.getCharBoundaries(o).y;
var myPoint:Point = new Point(myField.getCharBoundaries(o).x,myField.getCharBoundaries(o).y);
var pt:Point = new Point(myFieldsParent.myField.getCharBoundaries(o).x, myFieldsParent.myField.getCharBoundaries(o).y);
pt = myFieldsParent.myField.localToGlobal(pt);
//pt is the variable containing the coordinates of the char in the stage's coordinate space. You may still need to offset it with a fixed value but it should be constant.
I didn't test this code as I have adapted this example from code that is embedded into my project so I apologize if I'm missing something...

Resources