Openlayers 3 style a secondary geometry - geometry

I've got a feature object with three geometries on it, main and two others. Is there a way of styling each one of the geometries on a styleFunction pass? If one is a point geometry and the other two are linestring geometries, how would I style all three in one styleFunction?
I've got as far as having the sub-geometries available and the styleFunction can switch them with a call to this.setGeometryName() but after that I'm a bit stumped - as the point geometry at this point has already been styled (there is an array of styles waiting to be sent back from the styleFunction).
Am I correct in thinking I can style the other two geometries as well, or should I have a separate layer with separate geometries and style them individually (this would add an overhead).

Add sub-geometries as named 'sets' of the feature (feature.set()), then call them via this.get('name of geometry') and place that into an ol.style.Style call as the geometry parameter, then you can style it individually for that style.
Assuming your subgeometry is set on the feature as subgeom, your styleFunction could look like this:
function(feature, resolution) {
return [
new ol.style.Style({
// main geometry style
}),
new ol.style.Style({
geometry: feature.get('subgeom'),
// subgeom style
})
]
}

Related

How to change the texture of AnimatedSprite programatically

I have created a base scene that I intend to use for all human characters of my game. I am using an AnimatedSprite where I defined different animations for the different positions of the character, all using a texture that contains all the frames.
This works for a specific character, but now I would like to create other characters. Since I am using a character generator, all the sprite sheets are basically the same, but with different clothes, accessories, etc. I would like to avoid replicating the animation definitions for the other characters. I could achieve that by setting a different texture on each instance of the scene, but I can't find a way to do it.
If I edit the tscn file and set a different image, it does what I want.
I tried updating the atlas property of the animation frames, but doing that affects all instances of the scene:
func update_texture(value: Texture):
for animation in $AnimatedSprite.frames.animations:
for frame in animation.frames:
frame.atlas = value
I also tried cloning a SpriteFrames instance, by calling duplicate(0), updating it with the above code, then setting $AnimatedSprite.frames, but this also updates all instances of the scene.
What is the proper way to change the texture of a specific instance of AnimatedSprite?
I found a solution. The problem was that the duplicate method does not perform a deep clone, so I was having references to the same frame instances.
Here's my updated version:
func update_texture(texture: Texture):
var reference_frames: SpriteFrames = $AnimatedSprite.frames
var updated_frames = SpriteFrames.new()
for animation in reference_frames.get_animation_names():
if animation != "default":
updated_frames.add_animation(animation)
updated_frames.set_animation_speed(animation, reference_frames.get_animation_speed(animation))
updated_frames.set_animation_loop(animation, reference_frames.get_animation_loop(animation))
for i in reference_frames.get_frame_count(animation):
var updated_texture: AtlasTexture = reference_frames.get_frame(animation, i).duplicate()
updated_texture.atlas = texture
updated_frames.add_frame(animation, updated_texture)
updated_frames.remove_animation("default")
$AnimatedSprite.frames = updated_frames

Godot: Call external method

Lots of googling and I'm still not grasping what is probably a simple solution.
Scene: "Main". Contains a TileMap "Grid" with a script attached to it "Grid.gd".
Scene: "Player". Contains a KinematicBody2D "Player" with a script attached to it "Player.gd"
In Player.gd, I need to call a method in Grid.gd "_Calculate", pass it two variables, and have it return one variable.
var vNewPosition = Grid._Calculate(vPlayer, vInputDirection)
Error: The identifier "Grid" isn't declared in the current scope.
Obiously I need to reference the Grid.gd script somewhere to access it, but none of the many examples I have tried work.
Thanks in advance,
Josh
Given that
The Main scene has an instance of the Player scene
And
In Player.gd, I need to call a method in Grid.gd "_Calculate", pass it two variables, and have it return one variable.
I'll give you a few options.
The bad way
If Player knows the node path to Grid, it could use get_node to get it.
onready var _grid = get_node("../../grid")
Or something like that.
And then use it:
var vNewPosition = _grid._Calculate(vPlayer, vInputDirection)
This approach is, of course, not recommended. It will break if the node path is wrong.
The common way
Assuming Player does not know the node path (which is more likely), you can export a NodePath variable in Player.gd and use it to get the Grid:
exprort var grid_path:NodePath
onready var _grid = get_node(grid_path)
Then you need to set the Grid Path property in the Main scene to Grid.
This approach is better than the prior one, in that it does not depend on the path to Grid. However it still depends on a Grid being there. If Player makes no sense when there is no Grid, this approach is OK.
The good way
If Grid may or may not be there, and we want Player to work regardless, we can tweak the above approach:
exprort var grid_path:NodePath
onready var _grid = get_node_or_null(grid_path)
And remember to check if grid is null before using it:
if grid == null:
return # or whatever
var vNewPosition = grid._Calculate(vPlayer, vInputDirection)
Or like this:
var vNewPosition = grid._Calculate(vPlayer, vInputDirection) if grid != null else null
Which also allows us to specify a default value that vNewPosition will take when there is no grid (the null at the end of the line). And thus you can have the Player work when there is no Grid, and when there is it will use, and regardless of where (because Main tells it where it is).
This solution is not completely decoupled, because Player still knows grid is a thing that has _Calculate. Also we presume there is zero or one, not multiple. I can think of a way to approach that, but decoupling for the sake of decoupling is unnecessary. I'm calling this good enough for your use case. Yet, let me know if you want the over-engineered way.

How can I simulate hand rays on HoloLens 1?

I'm setting a new project which is intended to deploy to both HoloLens 1 and 2, and I'd like to use hand rays in both, or at least be able to simulate them on HoloLens 1 in preparation for HoloLens 2.
As far as I have got is:
Customizing the InputSimulationService to be gesture only (so I can test in editor)
Adding the GGVHand Controller Type to DefaultControllerPointer Options in the MRTK/Pointers section.
This gets it to show up and respond to clicks both in editor and device, but it does not use the hand coordinates and instead raycasts forward from 0,0,0, which suggests that the GGV Hand Controller is providing a GripPosition (of course with no rotation due to HL1) but not providing a Pointer Pose.
I imagine the cleanest way to do this would be to add a pointer pose to the GGV Hand controller, or add (estimated) rotation to the GripPosition and use this as the Pose Action in the ShellHandRayPointer. I can't immediately see where to customize/insert this in the MRTK.
Alternatively, I could customize the DefaultControllerPointer prefab but I am hesitant to do so as the MRTK seems to still be undergoing frequent changes and this would likely lead to upgrade headaches.
You could create a custom pointer that would set the pointer's rotation to be inferred based on the hand position, and then like you suggested use Grip Pose instead of Pointer Pose for the Pose Action.
The code of your custom pointer would look something like this:
// Note you could extend ShellHandRayPointer if you wanted the beam bending,
// however configuring that pointer requires careful setup of asset.
public class HL1HandRay : LinePointer
{
public override Quaternion Rotation
{
get
{
// Set rotation to be line from head to head, rotated a bit
float sign = Controller.ControllerHandedness == Handedness.Right ? -1f : 1f;
return Quaternion.Euler(0, sign * 35, 0) * Quaternion.LookRotation(Position - CameraCache.Main.transform.position, Vector3.up);
}
}
// We cannot use the base IsInteractionEnabled
// Because HL1 hands are always set to have their "IsInPointing pose" field as false
// You may want to do more thorough checks here, following BaseControllerPointer implementation
public override bool IsInteractionEnabled => IsFocusLocked || IsTracked;
}
Then create a new pointer prefab and configure your pointer profile to use the new pointer prefab. Creating your own prefab instead of modifying MRTK prefabs has advantage of ensuring that MRTK updates will not overwrite your prefabs.
Here's some captures of the simple pointer prefab I made to test this with relevant changes highlighted:
And then the components I used:

Dimensions of ImageMarker

I am new to Vuforia SDK. I have an image which acts as a target. I want to place this image on to the Imagemarker. In real time the size of the Imagemarker varies. Is there any method where I can get the width and height of the Imagemarker so that the target image fits exactly on the Imagemarker?
Since you did not specify if you are using the Unity or native APIs I will assume you are using Unity.
This is how you would go about it using the Vuforia API, placing this in a script attached to your ImageTarget GameObject.
IEnumerator Start()
{
Vuforia.ImageTarget img = GetComponent<Vuforia.ImageTargetBehaviour>().ImageTarget;
// This is rounded of in the console display,
// so individual components are printed afterwards
Debug.Log(img.GetSize());
Debug.Log(img.GetSize().x);
Debug.Log(img.GetSize().y);
Debug.Log(img.GetSize().z);
}
Alternatively you can directly use the Bounds of the renderer.
void Start()
{
Renderer r = GetComponent<Renderer>();
Debug.Log(r.bounds.size.x);
Debug.Log(r.bounds.size.y);
Debug.Log(r.bounds.size.z);
}
Needless to say this is just a quick solution, depending on the situation you might want to use this at runtime dynamically create content.
Yes, you can.
While placing the Image on the Image Marker to the relative size you want it to be, and when you run it you'll see that the size of the image will be relative to the Marker you've placed it on.

Trying to Use Transform to Rotate a UIView in MonoTouch

I have a UIControl defined in which I have used the MonoTouch.CoreGraphics classes to draw some items in and have put the UIControl into a UIView through AddSubview. I'm trying to take the view and turn the whole thing to simulate something sort of like movement of the minute or second hand on a clock or a dial. I'm under the impression that I can do that with the Transform on the UIView.
The name of my UIView is container. I've tried:
container.Transform.Rotate(-0.78f);
I have also tried:
CGAffineTransform t = CGAffineTransform.MakeIdentity();
t.Rotate(-0.78f);
container.Transform = t;
I have also tried:
CGAffineTransform t = CGAffineTransform.MakeRotation(-0.78f);
container.Transform = t;
I have also tried this and other combinations of it:
UIView.BeginAnimations("rotate");
UIView.SetAnimationDuration(0.5);
container.Transform.Rotate((float)Math.PI);
UIView.CommitAnimations();
None of the above have had any impact on my display. It does not rotate or move in the slightest. All of the iOS related posts refer to CGAffineTransformRotate, but I can't find a Mono exact match for that and am assuming that is the equivalent of what I am doing above. Is there some other way I should be trying to make my view rotate?
You are on the right track. I have a large game under development and do this all over the place in my code. Here is the simplest example I can give you:
using MonoTouch.CoreGraphics;
float degrees = 15;
UIView aView = new UIView(new RectangleF(10,10,10,10));
aView.Transform = CGAffineTransform.MakeRotation(3.14159f * degrees / 180f);
That's it.
The examples are sparse, especially the fact that the MakeRotation function is in radians (hence the use of pi to convert to degrees).

Resources