- Home /
drag and drop into other cells
Hi guys, Im creating a sort of inventory, where you can select a person and drag their image into another cell. So far I have drag and drop code created with buttons and attaching a texture to the mouse position, but I dont know where to go from here. How do I have another button know when I am dropping an image onto it? It doesnt necessarily have to be a button. It could be a collider I suppose. Thanks,
Looks like this when run: http://imgur.com/Ri9VASH The image floating in the middle is actually being dragged by the mouse, but the screen cap made the mouse invisible.
Edit added code:
void Update () {
if (Input.GetMouseButtonDown (0)) {
MouseButtonDown = true;
}
if (Input.GetMouseButtonUp (0)) {
MouseButtonDown = false;
squadMember=0; //this makes it so no picture is displayed when you havent clicked on a button
}
}
private void OnGUI(){
Vector3 scrPos = Camera.main.WorldToScreenPoint(this.transform.position);
GUI.color = new Color(1,1,1,1f);
GUILayout.BeginArea(new Rect(0,0,Screen.width,Screen.height));
GUILayout.BeginHorizontal ();
//GUILayout.Space(Screen.width/25);
if (GUILayout.RepeatButton (WarriorTextureIcon, GUILayout.Width (Screen.width/7), GUILayout.Height (Screen.height/7))) {
squadMember=1;
}
GUILayout.Space(Screen.width/25);
if (GUILayout.RepeatButton (ArcherTextureIcon, GUILayout.Width (Screen.width/7), GUILayout.Height (Screen.height/7))) {
squadMember=2;
}
GUILayout.Space(Screen.width/25);
if (GUILayout.RepeatButton (MageTextureIcon, GUILayout.Width (Screen.width/7), GUILayout.Height (Screen.height/7))) {
squadMember=3;
}
//GUILayout.Space(Screen.width/25);
GUILayout.EndHorizontal ();
//////
GUILayout.BeginVertical();
GUILayout.Space(Screen.width/25);
if (GUILayout.RepeatButton (WarriorTextureIcon, GUILayout.Width (Screen.width/7), GUILayout.Height (Screen.height/7))) {
squadMember=1;
}
//////
GUILayout.EndArea ();
switch (squadMember)
{
case 1:
if (MouseButtonDown == true) {
GUI.DrawTexture (new Rect (Input.mousePosition.x - 30, Screen.height - Input.mousePosition.y - 30, 60, 60), WarriorTextureIcon);
}
break;
case 2:
if (MouseButtonDown == true) {
GUI.DrawTexture (new Rect (Input.mousePosition.x - 30, Screen.height - Input.mousePosition.y - 30, 60, 60), ArcherTextureIcon);
}
break;
case 3:
if (MouseButtonDown == true) {
GUI.DrawTexture (new Rect (Input.mousePosition.x - 30, Screen.height - Input.mousePosition.y - 30, 60, 60), MageTextureIcon);
}
break;
We really don't have enough information to even make a suggestion. How did you implement your buttons...world objects, GUITextures, GUI.DrawTexture(), other? What underlying data structures do you use? What is the layout of the buttons? Etc. Your drag and drop code would be helpful as well.
@robertbu Added code and image of the output. Used horizontal and vertical GUIlayout for buttons. $$anonymous$$ade it so it "Grabs" an image when you click down on the button, until you release the mouse button. I want to be able to place the image into an empty cell, and have that cell take on the image of what is being dragged. Im hoping to translate it into a drag and drop mechanics for phones. Thanks for your help
I've done very little with GUI.Layout (I use EZGUI), but it seems to me that it would be hard to make what you are trying work with GUI.Layout. I would think that the standard GUI interface with an 2D array of rectangles mapping to buttons would function much better. You could then easily test which button you drop the image on, and then if you had a 2D array of textures for theses buttons, you could just remove the image from it's old position and assign it to the new one.
@robertbu: That doesn't really matter. GUILayout just uses the normal GUI methods since all GUILayout methods are build on top of the GUI methods, they just add the layouting. You can use GUILayoutUtility.GetLastRect to get the layouted rect for the last control. This method only returns a useful value when you're not in the layout event as during this event the rects are collected and calculated.
@camtronius: I'm not sure how i'm supposed to help you without writing the whole system. Also "drag and drop" is nice and dandy but what's the actual purpose. What should happen when you drop something at the target? Like robertbu said you need some kind of data structure that represents the dragable / dropable content. At the moment it looks like you use hardcoded integer values. You talked about some kind of inventory system. Is the only purpose of that dragging images from cell to cell?
GUI positions, and screen positions are different. It would be better to detect your mouse up in GUI. So given a 'rect' you can do this in OnGUI():
Event e = Event.current;
if (e.type == EventType.$$anonymous$$ouseUp & rect.contains(e.mousePosition) {
Debug.Log("The mouse button was lifted in the rect");
}
Answer by robertbu · Jul 15, 2014 at 07:47 PM
This kind of question is not what Unity Answers typically deals with. Design discussions are directed to Unity Forums. Unity Answers focuses on single specific issues to help you write your own code. This was an interesting enough question that I started to write out a description of an approach to the problem, but I decided in the same time it would take for a detailed enough description, I could blast out a quick and dirty piece of demonstration code. This is not intended to solve your problem, but to just demonstrate an approach. It uses GUI, but @Bunney83 is right. With GUILayoutUtility.GetLastRect() you can dynamically build the rectangles and use GUILayout.
To use, drop the script on an empty game object. Open the 'texs' variable by clicking on the triangle. Set the size (8) and hit enter. Drag and drop textures to fill a few of the slots. Hit play:
using UnityEngine;
using System.Collections;
public class GUIDragCell : MonoBehaviour {
public int cols = 6;
public int rows = 3;
public Texture[] texs;
public int texWidth = 100;
public int texHeight = 100;
public int spacing = 20;
struct Cells {
public Rect rect;
public Texture tex;
}
private Cells[,] layout;
private int prevRow;
private int prevCol;
private Vector2 dragOffset;
private Texture dragTexture;
private Rect dragRect;
void Start () {
layout = new Cells[cols, rows];
Rect baseRect = new Rect(0,0,texWidth,texHeight);
Vector2 offset = new Vector2(cols * texWidth + (cols - 1) * spacing, rows * texHeight + (rows - 1) * spacing);
offset /= 2.0f;
offset.x = Screen.width / 2.0f - offset.x;
offset.y = Screen.height / 2.0f - offset.y;
float m = 0;
float n = 0;
for (int i = 0; i < rows; i++ ) {
for (int j = 0; j < cols; j++) {
layout[j,i].rect = baseRect;
layout[j,i].rect.x = m + offset.x ;
layout[j,i].rect.y = n + offset.y ;
layout[j,i].tex = texs[Random.Range(0, texs.Length)];
m += texWidth + spacing;
}
n += texHeight + spacing;
m = 0.0f;
}
}
void OnGUI () {
Event e = Event.current;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (layout[j,i].tex != null) {
GUI.DrawTexture (layout[j,i].rect, layout[j,i].tex);
}
}
}
if (e.type == EventType.MouseDown) {
HandleMouseDown(e.mousePosition);
}
if (dragTexture && e.type == EventType.MouseUp) {
HandleMouseUp(e.mousePosition);
}
if (dragTexture) {
dragRect.center = e.mousePosition + dragOffset;
GUI.DrawTexture (dragRect, dragTexture);
}
}
void HandleMouseDown(Vector2 mousePosition) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (layout[j,i].rect.Contains (mousePosition)) {
prevCol = j;
prevRow = i;
dragOffset = layout[j,i].rect.center - mousePosition;
dragRect = layout[j,i].rect;
dragTexture = layout[j,i].tex;
layout[j,i].tex = null;
return;
}
}
}
}
void HandleMouseUp(Vector2 mousePosition) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (layout[j,i].rect.Contains (mousePosition)) {
if (layout[j,i].tex != null) {
layout[prevCol, prevRow].tex = layout[j,i].tex;
}
layout[j,i].tex = dragTexture;
dragTexture = null;
return;
}
}
}
layout[prevCol, prevRow].tex = dragTexture;
dragTexture = null;
}
}
@robertbu I ended up using a blend of our code together to get a working product. I created 2 arrays, one for textures and one for rectangles. I used my drag and drop code and kept the buttons. I also used the event e to detect if mouse was up on one of the rectangles and to change the current texture of that rectangle. Everything worked out great. Thanks for your help!