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;
Related
I have several shapes in LO Calc and I need those shapes to change their sizes when they are mouse clicked: the first click enlarges the shape, the second click restores the original size.
I'm trying to do this with a macro assigned to those shapes. My problem and my question: how to determine within a macro which shape has been clicked?
I know how to get the current selected shape:
dim doc as object
doc = ThisComponent
someVar = doc.CurrentSelection...
But a shape when clicked is not getting selected and this method is not working.
I tried to add a parameter for the event object to the macro:
sub ChangeSize( oEvent )
But this produces a message about wrong number of parameters.
Is there a way to detect the caller of a macro in LO Basic? Or maybe another way to implement size changing with a mouse click?
P.S. One can use a separate button for calling the macro and click this button after selecting the needed shape, but this way is less convenient.
EDIT: As I guessed below in the comments, the described task can be solved via the mouse and shape coordinates. The key points for the solution I found here:
How to get Document-Coordinates from a Mouse Click in an OpenOffice BASIC Macro
Instead of detecting the caller, assign a different one-line macro for each shape clicked event.
Sub ShapeClickedA
ChangeSize("ShapeA")
End Sub
Sub ShapeClickedB
ChangeSize("ShapeB")
End Sub
Related: LibreOffice macro showing simple TextBox shape
P.S. After answering, I realized you asked the linked question as well. How is this different, and is the other answer not satisfactory?
This post shows how to use the overobj function to set the pointer to change over the axes part of a gui. The problem is that this will override the pointer shape set by the zoom or pan toolbar buttons. I can test for various toolbar buttons being on like this:
if (strcmp(handles.zoom.State, 'off'))
obj_han=overobj('axes');
if ~isempty(obj_han)
set(handles.figure1,'Pointer','cross');
else
set(handles.figure1,'Pointer','arrow');
end
end
But that requires adding a new test for every tool button in the toolbar, which seems like a formula for error. How does zoom, for example, set the pointer? Is there a better way to integrate changing the pointer with the way the toolbar buttons make the change?
You could use the undocumented uimode and uimodemanager to get the current uimode and if the current uimode is empty, then none of the tools are active.
manager = uigetmodemanager(gcf);
% Only alter the pointer if the CurrentMode is empty
if isempty(manager.CurrentMode)
if ~isempty(obj_han)
set(handles.figure1, 'Pointer', 'cross')
else
set(handles.figure1, 'Pointer', 'arrow')
end
end
I would retrieve the uimodemanager outside of your callback and pass it explicitly to the callback so you don't have to retrieve it every time.
I'm building a UI system to edit selected 3D objects. I have spheres on the screen and I want to be able to edit their proprieties (radius for example). In order to do that I want the user to be able to click on a sphere and then it show a panel next to the object. When the user changes slider value the radius of the sphere which as been clicked on change. Using the new unity event system, I think it's easy to achieve, but I'm a new to unity and even if I know the basic I don't know how to organize this properly.
At the end my goal would be to select multiple sphere, right click and edit the radius to all selected spheres.!
Any tips on how to do that ? Sorry for my poor english. Thanks
Here's how you can do it:
Keep a bool for tracking if the object is selected, say, bool _isSelected
Toggle this boolean in the OnMouseUpAsButton() function. This function is called when you click on an object and release that click on the same object. Unity's OnMouseXXX() interfaces are very good for handling mouse events. You just need to define this function in the sphere objects' script.
Put together a Slider and arrange its value interval from editor. Define a function that will edit the scale value of the spheres and tie that function to that slider.
Below you can see an example of how I did that in a game of mine.
Unity simply catches the slider's value if you provide it with a public void _f(float val). It will appear on the top of the list as "Dynamic float". So, in your case, your slider update function should look like this:
public void SphereScaleSliderUpdate(float val)
{
foreach (GameObject sphere in GameObject.FindGameObjectsWithTag("your tag here"))
{
if (sphere.IsSelected) // don't forget to provide a public getter for _isSphere variable
{
sphere.transform.localScale = new Vector3(val, val, val);
}
}
}
Also, you need to create another script for toggling the menu(Canvas/Panel(optional)) that contains the slider, and you may add it to another object, like a UIManager. Assign the Canvas in the game hierarchy to a variable in that script, and then scan for RClick in the Update() function of the UIManager.
.
void Update()
{
if (Input.GetMouseButtonDown(1) // RClick event
{
// makes the slider appear through enabling canvas
_canvasHandle.enabled = true;
}
}
I implemented various uimenus in my uitable but there appears a very annoying behaviour.
function createUItable
h = figure
...
uimenu(h,'Label','MenuButton','Callback',#someAction)
end
%---------
function someAction(~,~)
%some action
end
But after executing the callback function, the menu button remains pressed and highlighted and not even that, when I slide over the next menu button, this one is triggered also!
This behaviour was also described at Matlab Central, but without solution.
I tried the suggested:
function someAction(~,~)
%some action
set(gcbo,'Enable','off')
drawnow
set(gcbo,'Enable','on')
end
which does not change anything. set(gcbo,'Enable','off') alone would solve the sliding problem, but also disables the whole button, what I don't want.
I also tried to use the 'Checked','Visible' and 'Interuptible' property without success.
This problem must be known, any hints?
I also thought about using uicontrol instead of uimenu and use a pushbutton, but I don't get it work.
Edit: when I put my menubutton into a submenu it works perfect:
button = uimenu(h,'Label','MenuButton');
uimenu(button,'Label','MenuButton','Callback',#someAction)
Edit2:
A pushbutton works also, but how could I place it into the menubar?
I guess MATLAB implementation is this way, because setting a callback at the top-level menu is very odd.
Naturally in GUI's (not only MATLAB), when you click the top-level menu (like "File", "Edit", etc.) the standard behaviour is, that a submenu pops open rather than an immediate action being executed.
So you should only use the top-level callback to e.g. dynamically create/modify the associated submenus.
I think there are two alternatives to go:
1) If you'd like to stick to that manner (one, always-visible button-like element), then you should rather use the toolbar via a uipushtool:
hToolbar = uitoolbar(parentFigure);
uipushtool(hToolbar, 'ClickedCallback', #someAction);
This does not have the 'Label' property though, so you'll have to work with 'CData' and may be a 'TooltipString'.
2) Create a top-level menu that contains your actual action-menu:
topMenu = uimenu(parent, 'Label', 'Actions');
uimenu(topMenu, 'Label', 'MenuButton', 'callback', #someAction)
From the general point of view on GUI design, both alternatives have the benefit of being the more commonly used style, thus being more intuitive to any user.
I found an interesting work-around for this problem while keeping the callback in the TOP menu. Turns out that using the uistack function released focus from the menu item so in the top-level menu callback, I placed
uistack(hObj,'down');
uistack(hObj,'up');
drawnow;
Which does nothing to the actual ordering but releases the menu items' focus.
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.