I have a qx.ui.indicator.ProgressBar , is there any way I can reverse the direction of progress bar (i.e. fill the bar from right to left) ?
Here is my code:
var pbar = new qx.ui.indicator.ProgressBar();
pbar.setDecorator(null);
pbar.setValue(30);
pbar.setWidth(400);
There is no public API for that. Just rotating the indicator would be a hack but could work.
Related
I have a SCNPlane that I created in the SceneKit editor and I want 1 side of the plane to have a certain image and the other side of the plane to have another image. How do I do that in the Scenekit editor
So far what I've tried to do is adding 2 materials to the plane. I tried adding 2 materials and unchecking double-sided but that doesn't work.
Any help would be appreciated!
Per the SCNPlane docs:
The surface is one-sided. Its surface normal vectors point in the positive z-axis direction of its local coordinate space, so it is only visible from that direction by default. To render both sides of a plane, ether set the isDoubleSided property of its material to true or create two plane geometries and orient them back to back.
That implies a plane has only one material — isDoubleSided is a property of a material, letting that one material render on both sides of a surface, but there's nothing you can do to one material to turn it into two.
If you want a flat surface with two materials, you can arrange two planes back to back as the doc suggests. Make them both children of a containing node and you can then use that to move them together. Or you could perhaps make an SCNBox that's very thin in one dimension.
Very easy to do in 2022.
It's very easy and common to do this, you just add the rear as a child.
To be clear the node (and the rear you add) should both use the single-sided shader.
Obviously, the rear you add points in the other direction!
Do note that they are indeed in "exactly the same place". Sometimes folks new to 3D mesh think the two meshes would need to be "a little apart", not so.
public var rear = SCNNode()
private var theRearPlane = SCNPlane()
private func addRear() {
addChildNode(rear)
rear.eulerAngles = SCNVector3(0, CGFloat.pi, 0)
theRearPlane. ... set width, height etc
theRearPlane.firstMaterial?.isDoubleSided = false
rear.geometry = theRearPlane
rear.geometry?.firstMaterial!.diffuse.contents = .. your rear image/etc
}
So ...
///Double-sided sprite
class SCNTwoSidedNode: SCNNode {
public var rear = SCNNode()
private var thePlane = SCNPlane()
override init() {
super.init()
thePlane. .. set size, etc
thePlane.firstMaterial?.isDoubleSided = false
thePlane.firstMaterial?.transparencyMode = .aOne
geometry = thePlane
addRear()
}
Consuming code can just refer to .rear , for example,
playerNode. ... the drawing of the Druid
playerNode.rear. ... Druid rules and abilities text
enemyNode. ... the drawing of the Mage
enemyNode.rear. ... Mage rules and abilities text
If you want to do this in the visual editor - very easy
It's trivial. Simply add the rear as a child. Rotate the child 180 degrees on Y.
It's that easy.
Make them both single-sided and put anything you want on the front and rear.
Simply move the main one (the front) normally and everything works.
I have this set up in my main.lua file
images = {
display.newImageRect("images/player3.png", 45,35),
display.newImageRect("images/player4.png", 45,35),
display.newImageRect("images/player5.png", 45,35)
}
and call it from my game.lua file with this code:
bird = images[math.random(1,3)]
bird.x, bird.y = -80, 140
bird.name = "bird"
physics.addBody( bird, "static")
bird.isFixedRotation = true
birdIntro = transition.to(bird,{time=1000, x=100, onComplete= birdReady})
A random image spawns (where it should, in the middle) but the issue is that a second image spawns and sits in the top left corner of the screen (slightly off screen). I can't seem to remove it and keep the one correct image only, any solutions?
Your help is greatly appreciated.
Thanks
I think the problem is your images array. I've found by calling the display.newImageRect it will create the object and plop it on the screen. Even if you don't want it to show the object right then. Usually I see this when I should be putting it in a display group (not sure if you are doing that).
I think the solution might be to have the array of images be the image paths and then you can set bird equal to a new image rect at that point, thus only creating 1 image rectangle instead of 3.
images = {
"images/player3.png",
"images/player4.png",
"images/player5.png",
}
bird = display.newImageRect(images[math.random(1,3)],45,35)
Let me know if that works.
I'm building an app where the first view has a menu panel, and I want this panel to stick around for the life of the app. The only places the user can "go" are reachable via buttons on this panel (a UICollectionView). In case it matters, this app is landscape-only, and iOS 6-only.
In order to make this work I created a custom segue, which removes everything from the view except for the menu panel, then adds the new view controller's view as a subview, sets the new view's frame to the bounds of the superview, and sends the new view to the back (so it's behind the menu panel). I call viewWill/DidDisappear from prepareForSegue, because otherwise they don't get called.
It may sound kludgy (it does to me), but it works fine except for one thing - the new view comes up from the bottom. It looks funny.
I then tried adding my own animation block - I initially locate the view off to the left, then animate it into place. I send it to the back in the completion block for the animation. This seems perfectly logical, and the frame values are all what they should be. But this one is worse - the view comes in from the lower left corner.
Can anyone suggest a way to make this work? Here's my current perform method:
- (void)perform {
MainMenuViewController *sourceVC = (MainMenuViewController *)self.sourceViewController;
UIViewController *destinationVC = (UIViewController *)self.destinationViewController;
for (UIView *subview in [sourceVC.mainView subviews]) {
// don't remove the menu panel or the tab
if (![subview isKindOfClass:[UICollectionView class]] && [subview.gestureRecognizers count] == 0) {
[subview removeFromSuperview];
}
}
[sourceVC.mainView addSubview:destinationVC.view];
CGRect finalFrame = sourceVC.mainView.bounds;
CGRect frame = finalFrame;
frame.origin.x = finalFrame.origin.x - finalFrame.size.width;
destinationVC.view.frame = frame;
[UIView animateWithDuration:0.5 animations:^{
destinationVC.view.frame = finalFrame;
} completion:^(BOOL finished) {
// make sure it ends up behind the main menu panel
[sourceVC.mainView sendSubviewToBack:destinationVC.view];
}];
}
It turned out to be a simple error - I needed to set destinationVC's frame before calling addSubview. Setting it afterwards was triggering the unwanted animation.
I'm struggling with the best way of changing the center point of a 3D object (Model3DGroup) in WPF.
I've exported a model from SketchUp and everything is fine, but the centers got off position, causing me trouble in rotating the objects.
Now I need to make some rotations around each object own center and have no idea on how to do it...
Any suggestions would be appreciated.
Thanks
Using Jackson Pope suggestion, I used the code below to get the center point of an object:
var bounds = this.My3DObject.Bounds;
var x = bounds.X + (bounds.SizeX / 2);
var y = bounds.Y + (bounds.SizeY / 2);
var z = bounds.Z + (bounds.SizeZ / 2);
var centerPoint = new Point3D(x, y, z);
Meanwhile I'll try find a better solution to try and move all the points to the desired offset...
To rotate an object around it's centre you need to first translate it so that its centre is at the origin. Then rotate it (and then potentially translate it back to its original position).
Find the minimum and maximum extent of the object, calculate its centre = min + (max-min)/2. Translate by (-centreX, -centreY, -centreZ), rotate and then translate by (centreX, centreY, centreZ).
Im trying to apply a material to my GeometryModel3D at runtime like so:
var model3D = ShardModelVisual.Content as GeometryModel3D;
var materialGroup = model3D.Material as MaterialGroup;
BitmapImage image;
ResourceLoader.TryLoadImage("pack://application:,,,/AnzSurface;component/path file/img.png", out image, ".png");
var iceBrush = new ImageBrush(image);
var grp = new TransformGroup();
grp.Children.Add(new ScaleTransform(0.25, 0.65, 0.5, 0.5));
grp.Children.Add(new TranslateTransform(0.0, 0.0));
iceBrush.Transform = grp;
var iceMat = new DiffuseMaterial(iceBrush);
materialGroup.Children.Add(iceMat);
Which all works fine, and the material gets added.
What I dont understand is how I can map the users click on the screen to the offsets that need to be applied to the TranslateTransform.
I.e. at the moment, x: -0.25 moves the material backwards along the X axis, but I have NO IDEA how to get that type of a coordinate from the users mouse click...
when I do:
e.MouseDevice.GetPosition(ShardsViewPort3D);
that gives me normal X/Y corrds of the mouse click...
Thanks for any help you can give!
It sounds like you want to slide the material around on your geometry when you click on it. Here's how:
Use hit testing to translate your X/Y coordinates from the mouse click into a RayMeshGeometry3DHitTestResult as described in my earlier answer. This will give you the MeshGeometry3D that was hit, the vertices of the triangle that was hit, and the relative position on that triangle.
Look up each vertex index (VertexIndex1, VertexIndex2, VertexIndex2) in the MeshGeometry3D.TextureCoordinates to get the texture coordinates. This will give you three (u,v) pairs as Point objects. Multiply each the (u,v) pairs by the corresponding weight from the hit test result (VertexWeight1, VertexWeight2, VertexWeight3) and add the pairs together, ie:
uMouse = u1 * VertexWeight1 + u2 * VertexWeight2 + u3 * VertexWeight3
vMouse = v1 * VertexWeight1 + v2 * VertexWeight2 + v3 * VertexWeight3
Now you have a point (uMouse, vMouse) that indicates where on your material your mouse was clicked.
If you want a particular point on your texture to move to exactly where the mouse was clicked, just subtract the (uMouse, vMouse) where the mouse was clicked from the (u,v) coordinate of the location in the material you want to appear under the mouse, and set this as your TranslateTransform. If you want to handle dragging, store the computed (uMouse,vMouse) where the drag started and the transform as of the drag start, then as dragging progresses compute the new transform as:
translate = (uMouse,vMouse) - (uMouseDragStart, vMouseDragStart) + origTranslate
In code you'll write this as Point additions. I spelled it out as (u,v) in this explanation because I thought it was easier to understand if I did so. In actuality the code to compute (uMouse, vMouse) will look more like this:
var uv1 = hit.MeshHit.TextureCoordinates[hit.VertexIndex1];
var uv2 = hit.MeshHit.TextureCoordinates[hit.VertexIndex2];
var uv3 = hit.MeshHit.TextureCoordinates[hit.VertexIndex3];
var uvMouse = new Vector(
uv1.X * hit.VertexWeight1 + uv2.X * hit.VertexWeight2 + uv3.X * hit.VertexWeight3)
uv1.Y * hit.VertexWeight1 + uv2.Y * hit.VertexWeight2 + uv3.Y * hit.VertexWeight3);
and the code to update the transform during a drag will look something like this:
...
var translate = translateAtDragStart + uvMouse - uvMouseAtDragStart;
... = new TranslateTransform(translate.X, translate.Y);
You'll have to adapt this to the exact situation.
Note that your HitTest callback may be called multiple times, starting at the closest mesh and moving back. It may even be called with 2D hits, for example if a 2D object is in front of your Viewport3D. So you'll want to check each hit to see if it is really what you want, for example during dragging you want to keep checking the position on the mesh being dragged even if it is no longer foremost. Return HitTestResultBehavior.Stop from you callback once you have acted on the mesh being dragged.