I am trying to detect multiple taps on the screen basically to create piano like app using the B4A SoundPool control and panel.touch event to trigger sounds.
My problem is that once the screen (or one panel of many representing keyboard) is touched and held others don't register.
I guess I would need to use a multitouch library but I can't figure out how I would use it to just detect multiple panels being touched. I don't need motion detection.
Here is my current code. One sub for all panels using Sender.Tag as unique identifier.
Is one Sub my problem?
Sub pnl_Touch (Action As Int, X As Float, Y As Float)
If Action = Activity.ACTION_DOWN Then
Dim key As Panel
key = Sender
Dim note As Int
note = key.Tag
Dim PlayID As Int
PlayID = SP.Play(note,1,1,1,0,1)
End If
End Sub
Yes, Multi-Touch is the way forward. See Andrew Graham's multi-touch library. Here is a working example - Multi-Touch tutorial
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?
I have a UIpanel in my application and i instantiate gameobject in it programmatically during runtime, the problem i have is i have to create more than 1000 gameobjects (sometimes up to 6000) in that panel and that takes a long time freezing the UI and trying it with Coroutines cause some lags as well.
is there any way to have a list of gameobjects and create them in UI panel during user scrolling that panel?
or can somebody suggest a better way of adding gameobjects to a panel without any lag or UI freeze?
UPDATE :
I added this to clear my goal.
i have a long list of items that i trying to put them in a list each item have a picture a some button and some texts, below there is a sample from a single item:
now i need to instantiate this complex sample in a panel and each item change itself based on a ID i pass after instantiation.
but i have a panel capacity problem and even if i cut some item when i put that many object in a panel at once scrolling in panel make it very slow and painful
also i need a scroll bar for my panel so i have to have all of my object available in the panel
hope this information helped.
When you describe it that way, its much clearer & much simpler.
Look at any mobile application: they do not put 6000 people records on a single page. Its normally paged or grouped, with a search option. So do that instead.
If you look at the facebook mobile app (a good standard) if you start scrolling to look at older posts, every few seconds it pauses for a second or two to load the next few posts. Its the same with the youtube app.
Because of this 65535 unity limit, just put in a paging limit (say 100-200 items).
Ok, I just wrote a test program which generated 1000 Text UI elements.
public class MakeLoadsOfUI : MonoBehaviour {
public GameObject prefab;
// Use this for initialization
void Start ()
{
MakeUI();
}
void MakeUI()
{
float startTime = Time.realtimeSinceStartup;
for (int i = 0; i < 1000; i++)
{
int x=i/40, y=i%40;
GameObject obj = (GameObject)Instantiate(prefab);
obj.transform.SetParent(transform); // attack to the canvas
RectTransform rt = obj.GetComponent<RectTransform>();
rt.anchoredPosition = new Vector2((x-10)*25, (y-10)*20);
obj.GetComponent<Text>().text = "UI:" + i;
}
float endTime = Time.realtimeSinceStartup;
Debug.Log("time taken:" + (endTime - startTime));
}
}
It took 0.15 seconds for 1000 elements which was quite reasonable. If you had a different result please elaborate, explaining how you did it.
I hope I am posting in the correct section. I know that it is possible to write a custom code in Unity so I have the following questions:
Imagine a house model in Unity. Would it be possible to have a code which helps to hide/unhide certain objects? For example, letter "W" would hide/unhide all windows, letter "C" would hide/unhide all columns etc.
If it would be possible to develop a code for that, what would be the workflow? How would Unity know what is window and what is door?
Taking one step further.. Would it be possible to have a code that unhides the next step of the project. For example, the first step would be building foundations. Would it be possible to have a code that would unhide the next step, say, 1st floor floor element, with a klick of a keyboard key? And then with the same key unhide the next step which might be 1st floor walls. And would it be possible with another key go backwards?
If such code would be possible, what do you think would be the workflow? How would Unity know which element is in which step?
Yes just have a class with an array of objects to show/hide and another property for what button will do it. Then just have a method that will hide/unhide each object in that class. In the update method of a behavior just check the input and call the method of the class based on what button was pressed.
Would it be possible to have a code which helps to hide/unhide?
Yes, you can do that by calling GameObject.SetActive() function
door.SetActive(true); // door is a game object;
How would Unity know what is window and what is door?
You can give the window/door a name, then access the game object by name
var door = GameObject.Find("MyDoor") as GameObject;
Would it be possible to have a code that would show the next step, say, 1st floor floor element, with a klick of a keyboard key?
Yes, you can do that with code snippet below:
int step = 1;
void Update() {
if (Input.GetKeyDown("space")){
print("space key was pressed");
step++;
}
if(step == 1) {
// do sth
}
else if(step == 2) {
// do sth
}
}
Given the above snippet, your last answer can be easily deduced.
I see 2 ways of doing what you asked.
1st way
GameObject[] walls;
walls = GameObject.FindGameObjectsWithTag("Wall");
foreach (GameObject wall in walls)
{
wall.setActive(true);
}
What you will have to do, besides the code, is to assign to those object a correct tag (like "Wall" "Window" "WatheverYouWillNeed"). So you can easily find all objects by giving them some kind of order (with tags).
Best practice tip
You may want to create a static class "Tags", and set public constants string inside the class, with all tag names.
public static class Tags
{
public static const WINDOW_TAG = "Window";
// ... more tags
}
2nd way
If what you want to set is only "visibility", you may want to modify only camera tag rendering. It doesn't even require any cycle at all. When you want to view windows, you just tell your camera to render the tag "Window".
// Turns on Windows Layer on mask using an OR operation
private void Show()
{
camera.cullingMask |= 1 << LayerMask.NameToLayer("Window");
}
// Turn off the bit using an AND operation with the complement of the shifted int:
private void Hide()
{
camera.cullingMask &= ~(1 << LayerMask.NameToLayer("Window"));
}
It may look odd the second option, but keep in mind that the cullingMask is composed of bits, and every bit is a Layer defined by your tags. The "Everything" culling mask is 111111. If you want to see only Window, for example, and window is the last element, your culling mask would look something like 0000001
Hope it helped! :)
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.
I have a FlowPanelLayout that can contain several UserControls called DataGridViewFilterSortElement. These controls look kind of like buttons, but different. I want the user to be able to click one of the DataGridViewFilterSortElement controls and drag it to another position (index) in the FlowLayoutPanel.
Is there a way to see the control physically moving as the user drags it to another position? In other words, is there a way to take a "snap shot" of the control that is being dragged (instead of a shadowed box) which would show the actual control moving as the cursor moves? Also, as the control is being dragged I'd like to have the other controls position to shift automatically instead of waiting for the user to drop the drag to see the shifts.
For example, let's say the FlowPanelLayout contains 3 controls and the user wants to drag the first control to the third controls position. So the user clicks and holds the first DataGridViewFilterSortElement, then drags over the second control, which causes the second control to shift to position 1 of 3, then the user drags over the third control, which causes the third control to shift to position 2 of 3, then the user drops the control in position 3. Is this possible? The little code I do have is below.
Here is a short little video that shows what I want to do: http://www.youtube.com/watch?v=YhyTni6KH0Q
Private Sub lblDescription_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown, lblDescription.MouseDown
' if the user left clicks and holds the element begin a DragDrop action
If e.Button = Windows.Forms.MouseButtons.Left Then
Me.DoDragDrop(Me, DragDropEffects.Move)
End If
End Sub
Private Sub SortFlowLayoutPanel_DragOver(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles Me.DragOver
e.Effect = DragDropEffects.Move
End Sub
Private Sub SortFlowLayoutPanel_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles SortFlowLayoutPanel.DragDrop
If e.Data.GetData(GetType(DataGridViewFilterSortElement)) IsNot Nothing Then
'Current Position
Dim myIndex As Integer = Me.SortFlowLayoutPanel.Controls.GetChildIndex(CType(e.Data.GetData(GetType(DataGridViewFilterSortElement)), DataGridViewFilterSortElement))
'Dragged to control to location of next picturebox
Dim element As DataGridViewFilterSortElement = CType(e.Data.GetData(GetType(DataGridViewFilterSortElement)), DataGridViewFilterSortElement)
Me.SortFlowLayoutPanel.Controls.SetChildIndex(element, myIndex)
End If
End Sub
Private Sub SortFlowLayoutPanel_DragOver(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles SortFlowLayoutPanel.DragOver
e.Effect = DragDropEffects.Move
End Sub
This page explains how to do what you want. I tried it, looks pretty good.
http://www.vbdotnetforums.com/gui/45818-flowlayoutpanel-repositioning-object.html