I've been playing around with UIToolkit, and it's awesome. Though my clicks pass through the buttons, so when clicking the UI my raycast also starts. Is there a way to check if a click/touch is on the GUI?
Edit: I'm using Prime31's UIToolkit
Solved:
foreach (var touchable in _gui.touchableSprites) {
if ( !touchable.hidden && touchable.hitTest(new Vector2(clickPos.x, Screen.height - clickPos.y)) ) return;
}
Thanks.
Assuming you're using prime31's UIToolkit, take a look at the UIToolkit.cs(lines 81-95)
) script The author works an example showing how to handle highlighting his TouchableSprites. The same functionality can be adapted to doing a MouseOver event. I'm not sure if the author has added this functionality since 2011, I've not used UIToolkit in awhile.
Alternatively you can modify all of your ray tracing to return if the first layer hit is "UILayer" (UIToolkit's layer).
A third method, one that I use, is to create a global GUI element manager that stores a list of all GUI rects. When I add a new ray tracing function I call my manager class to see if the mouse cursor is contained in any GUI rect (there is a bit more sophistication that merges overlapping rects), if so, the ray trace is skipped.
Related
I want to create a blur effect similar to the picture below:
the picture is taken from this site:
https://forum.unity.com/threads/how-to-blur-specific-layers-only.555520/
I tried the post-processing profile and played around with the depth of field in the post-processing volume but it blurs all the scene.
I came across a YouTube Video that explains how to implement similar results to what I am looking for but things have changed drastically in the settings. For example, at 1:57 (minute and 57 seconds) he clicks on Add Additional Camera Data which I am struggling to find in the latest versions of LWRP.
I am using Unity version 2019.2.9f1
How can I achieve the result in the picture above? (Blurring all the scene except for one object)
Your guidance will be appreciated.
NOTE: My project is in VR using SteamVR and VRTK
Though your question is a bit broad I took some time to show you how it can be done.
First of all you will need to import the Post Processing package via the PackageManager
Window → PackageManager
Make sure to be in the All Packages view, search for post, find the Post Processing package and hit Install
Now first of all go to the Layer settings (Layers → Edit Layers)
and add two additional Layers: e.g. PostProcessing and Focused
Now to the cameras. Afaik it makes no difference whether you are in VR or not, usually you have one MainCamera that is moved along with your headset. If there should be two of them in your project setup just repeat the same steps for the second camera.
Make sure the MainCamera doesn't render the two added Layers → remove them from the Culling Mask
Add a new Camera FocusCamera as child to the existing MainCamera. This way it is automatically moved along with the main Camera.
RightClick on MainCamera &rightarrow Camera
It should have all the settings equal to the MainCamera except:
Clear Flags : Don't Clear
If you set it to Depth Only the focused object will always be rendered on top of everything, even if it is actually behind other objects in 3D space. You decide which effect you want here ;)
CullingMask : only Focused
Depth : Anything higher than the MainCamera so this camera is rendered on top of it
Make sure to remove the AudioListener component.
Finally add a new PostProcessingVolume to the scene. I would add it as child to the FocusCamera! Why? - Because this way it is automatically disabled together with the FocusCamera!
RightClick on FocusCamera → 3D Object → Post Processing Volume
Set its Layer to the added PostProcessing
enable Is Global so the distance to the volume doesn't matter and add a new profile by hitting new → Unity → Depth of field
In your case you want to overwrite the Focus Distance so check the box on the left and set a value close to the camera like e.g. 0.5
Until now nothing has really changed in your scene.
Now go to the MainCamera and, a component PostProcessingLayer and set the Layer to our added layer PostProcessing
Now everything should be blurred in your scene!
Almost ready to go! Now Disable the FocusCamera and add this script to it
using UnityEngine;
public class FocusSwitcher : MonoBehaviour
{
public string FocusedLayer = "Focused";
private GameObject currentlyFocused;
private int previousLayer;
public void SetFocused(GameObject obj)
{
// enables this camera and the postProcessingVolume which is the child
gameObject.SetActive(true);
// if something else was focused before reset it
if (currentlyFocused) currentlyFocused.layer = previousLayer;
// store and focus the new object
currentlyFocused = obj;
if (currentlyFocused)
{
previousLayer = currentlyFocused.layer;
currentlyFocused.layer = LayerMask.NameToLayer(FocusedLayer);
}
else
{
// if no object is focused disable the FocusCamera
// and PostProcessingVolume for not wasting rendering resources
gameObject.SetActive(false);
}
}
// On disable make sure to reset the current object
private void OnDisable()
{
if (currentlyFocused) currentlyFocused.layer =previousLayer;
currentlyFocused = null;
}
}
This will allow you to focus a certain GameObject on runtime by changing its layer to the Focused layer we added, the only one that is rendered by the FocusCamera. So this object will be rendered on top of the image without any blur effect!
For demonstration I just added this simple script to every cube object in order to enable focus on mouse enter and disable it on mouse exit:
using UnityEngine;
public class FocusMe : MonoBehaviour
{
[SerializeField] private FocusSwitcher focus;
private void OnMouseEnter()
{
focus.SetFocused(gameObject);
}
private void OnMouseExit()
{
// reset the focus
// in the future you should maybe check first
// if this object is actually the focused one currently
focus.SetFocused(null);
}
}
And here is what it looks like
as said I don't know exactly what your VR setup looks like. If you have to MainCameras simply add two child cameras to them. You still will need only one PostProcessingVolume and only one FocusSwitcher so you would probably move them to another object and handle the camera disabling etc differently but I hope the idea gets clear enough.
Use a separate camera for objects you don't want to blur and set a higher depth value.
Set the ClearFlags to depth only and in the CullingMask select the layer of that one object(or more objects). Obviously you would require to have a different layer for unblurred objects.
I have two canvasses. One is nested in the other. They both express a behavior when looked at. While looking at the outer canvas it works fine, but when I look at the inner canvas, the behavior of the outer canvas stops.
I pinned it down to my raycast not coming through the inner canvas.
Can someone help me or link me to a know solution?
I've tried layers but I don't quite understand them. I hope for an easier solution.
To be specific. the outer canvas closes when focus is lost, so I try to keep the object focused. When I enter the inner canvas it doesn't register it as a hit on the outer one and it starts to close.
I work specifically with HololensToolkit. It handles most of the gaze events but there doesn't seem to be an option to get multiple raycasts.
use RaycastAll, and work with the array of returned objects instead.
for example:
RaycastHit[] hits;
hits = Physics.RaycastAll(transform.position, transform.forward, 100.0F);
foreach (RaycastHit hit in hits)
{
if (hit.gameObject.tag == "menuobj")
//do something
}
I'm building an origami simulator, I want to be able to 'fold' the paper using a dat.gui slider. I want to also include orbital controls.
However, when I click on the slider and subsequently move my mouse out of the dat.gui window, the orbital controls have been triggered causing the model to jump to a different orientation.
Is there a way to prevent orbital controls from being triggered when I click in the dat.gui window?
Quoting the docs:
Constructor
OrbitControls( object : Camera, domElement : HTMLDOMElement )
object: (required) The camera to be controlled.
domElement: (optional) The HTML element used for event listeners. By default this is the whole document, however if you only want to the controls to work over a specific element (e.g. the canvas) you can specify that here.
In other words, to restrict the OrbitControls so that they don't enable when you click on the GUI, you must supply a reference to the canvas (renderer.domElement) or container (a div that contains the canvas) as second argument to the constructor. Happy coding! (And folding!)
My solution to your question is to: have dat.GUI "listen" to the values controlled by OrbitControls (the camera), so that the values are in sync between the two different "controllers" (OrderbitControls and dat.GUI), like so:
let gui = new dat.GUI();
let folder1 = gui.addFolder("Camera Position");
folder1.add(camera.position, "x", -100, 100).listen();
folder1.add(camera.position, "y", -100, 100).listen();
folder1.add(camera.position, "z", -100, 100).listen();
The listen() function on a tracked variable in dat.GUI will keep the values in sync, and relieve the "jumpiness" you are experiencing.
Reference to dat.GUI Controller functions documentation:
dat.gui
OrbitControls has an "enabled" property (in fact, I believe all of the controls have an "enabled" property - might want to check though). So if you have
orbitControls = new THREE.OrbitControls(...);
...
// in your dat.GUI block of code (or wherever you want to disable orbitControls)
orbitControls.enabled = false;
// this should disable orbitControls, and when you want to use orbitControls again, just do
orbitControls.enabled = true;
I am using KineticJS for implementing a graphical editor. I would like to drag a KineticJS Group and drop it into another shape. So far so good, done binding the "dropend" event to a handler in the group.
But I would like to change color to the potential destination shape while hovering on it during dragging, so as to give evidence that it is a suitable shape for drop.
I can't see a way of doing it and I am not been able to find any help in Kinetic documentation. How could I do?
Thanks,
eca
After some mumbling, I think I have found a solution:
var aShape = new Kinetic.Shape(...);
:
aShape.on("dragmove", function(evt) {
// Detect shapes under mouse position
var pos = aShape.getStage().getUserPosition(evt);
var collidingShapes = aShape.getStage().getIntersections(pos);
:
// If needed, filter out colliding shapes not suitable for drop
:
// Highlight drop target candidates, e.g. simulating a "mouseover"
for (var iTarget = 0; iTarget < collidingShapes.length; ++iTarget)
collidingShapes[iTarget].simulate("mouseover");
// If you need to remove highlighting, keep track of previously
// highlighted shapes and call simulate("mouseout") on those
// not currently in the candidates set.
});
Though what you did is actually working, I find it very slow. What I did, was to replace the line 3142 of kineticjs (v4.0.1):
else if(this.targetShape && !go.drag.moving)
with
else if (this.targetShape)
and it works like a charm. The mouseout and mouseover events are now fired.
Anyway, I don't know why, but there had been a property of the stage object (shapedragging or so) which pointed to a potential target, but it had been removed.
I was studying the jQuery UI Sortable widget and it said that all callback functions receive a ui object. Two of its properties are ui.helper nad ui.item. ui.helper is mentioned to be mostly a clone of ui.item, but I can't get the significance of calling it 'helper'. Also, the offset and position properties are defined in terms of the helper and not the item. What's the difference between the two ?
One of the answers mention that the helper fills the void, but the I read in the docs that the helper element is "used for dragging display". What exactly is this helper element and why is it named so?
From what I understand ui.helper is a "clone" of the ui.item. It is cloned so you can edit it with css and make it look like whatever you want it to look like while you are dragging it and it won't effect the original ui.item. So if you had a box and while it was being dragged you wanted it to turn into a blue box with curved edges but only while it was dragging you can by modifying ui.helper.
The helper is the element that fills the void (with visibility: hidden) when the item is dragged.