Linking 2D/3D GameObjects to GUI Windows?

I know the subject might immediately strike many of you as naive, but I’m not entirely certain how to ask the question without sounding like I don’t know what I’m talking about. :smile:

Simply put, I’m thinking of a floating inventory element like the paper-doll system in Ultima 7

…I’m not looking for completed scripts mind you (what fun is that?), just a “is it possible?” and perhaps some guidance on where to begin looking.

In a nutshell:

  • If possible, how can you drag and drop 2D elements onto a GUI window and have those elements become ‘children’ of said GUI window, such that if you drag the window, the contents go along with it?

  • How to make the individual elements within the window still able to be dragged, not only inside the GUI window, but back out and into the game world(thus unlinking it from the GUI window “parent”)?

  • Is this functionality possible with 3D elements? Can you drag a 3D gameObject from the game world onto a GUI window and have the 3D object then become a child of the window and behave just like I describe above?

Again general answers and direction should suffice, though I won’t turn away more explicit responses if indeed it’s the best way to describe the answers I seek. :smile:

Thanks yet again for your time guys!

-Steve

Using render to texture (unity pro only), you could render the 3D object to a texture once you start dragging it, render this texture with the GUI at the x/y location of the mouse and finally render the texture inside the window once the drag-drop is completed.

Thanks AngryAnt…that sounds like the most reasonable path to take.

Now, what about the first half of my question, regarding parenting of 2D elements ? That’s actually the meat of what I’d really like to know. :smile:

Yes, it’s definitely possible to achieve the same visual end-result, but you just won’t do that using parent-child relationships built into our UI system. You’ll be drawing some object and need to manage its location or have conditional code to include it in a group or ??? My point is that it’s definitely doable, and there are a few ways to go about it. But you’re not making “UI objects” that have a parent property or anything like that so it’s going to require you to sort out your own clever solution.

:slight_smile:

Yea as I suspected. I was already thinking about groups, and even GUI.BeginGroup mentions, albeit briefly, a child/parent relationship.

Description
Begin a group. Must be matched with a call to EndGroup.
When you begin a group, the coordinate system for GUI controls are set so (0,0) is the top-left corner of the group. All controls are clipped to the group. Groups can be nested - if they are, children are clipped to their parents.
This is very useful when moving a bunch of GUI elements around on screen. A common use case is designing your menus to fit on a specific screen size, then centering the GUI on larger displays.

Can this description be expanded upon a bit? Am I reading this incorrectly? Where are relationships defined for this to be useful?

But either way cool, much appreciated Higgy! :smile:

(P.S. I stopped receiving email alerts to new posts to threads I started/am watching. This is the second time now I happened upon a thread with a new reply without receiving an email.)

Groups are used for that sort of thing for sure. The complication here is the way you code in our GUI system. I think seeing it in “action” will be illustrative.

Here is a simple case, where there is a box being drawn, and an empty group (no background, no nothing, “invisible”):

function OnGUI () {

  // anything here is out of the group
  GUI.Box(Rect(1,1,10,10), "");

  GUI.BeginGroup(Rect(100,100,100,100));

  // anything here is in the group
  
  GUI.EndGroup();

}

Thus in order to “group” your UI objects, you need them inline within your code. Here is that some box, in the group:

function OnGUI () {

  // anything here is out of the group

  GUI.BeginGroup(Rect(100,100,100,100));

  // anything here is in the group
  GUI.Box(Rect(1,1,10,10), "");
  
  GUI.EndGroup();

}

Note: to be clear, in the second code example the box will of course be drawn in a different position.

So yes, you’ll use groups as part of all this, plus some additional code to decide when to draw what and where. :stuck_out_tongue:

So I could create pointers in the body of the group, and deal with what they’re referencing elsewhere, correct?

See, this could work after all, and not be too terrible! :smile:

Thanks Higgy! :smile:

Your use of “pointers” has me very nervous. Elements within your user interface are not objects, you don’t “reference a particular button/label/whatever”. Do you see how quite literally I needed to change the actual text of my source script to move the Box in/out of the group (admittedly it’s a simple case). I wasn’t moving around a “pointer” or reference to some object.

var BoxInGroup = false;

function OnGUI () {

  if (!BoxInGroup) { GUI.Box(...); }

  GUI.BeginGroup(...);

  if (BoxInGroup) { GUI.Box(...); }

  GUI.EndGroup();

}

So I’m not sure what you happen to mean by “pointer”, but the above is an example of the sort of juggling you’ll need to do.

If you haven’t done so I suggest getting familiar with the basics of using UnityGUI to draw user interface elements before going too deep into drag-and-drop operations:

GUI Scripting Guide

Chalk it up to semantics and my poor use of the terms. :smile: All I was suggesting is that we created variables we could change at run-time that would modify the GUI elements being drawn in the group. There wouldn’t be anything there until a item in the game-world for example was picked up.

So from what I’m gathering now, there isn’t a way to “add” GUI elements at run-time to a group?

Yea see, I can’t venture any more guesses then without making you even more nervous, hehe.

Oh and to be clear I’m not looking for the answers to be handed to me. In fact my question was a way to gather if it was worth going down that path. Yea I have everything I could find related to GUI scripting open(including the GUI Scripting Guide) and I’m doing my best to study, but I’m honestly not seeing it yet. :slight_smile:

What I’m understanding though so far is that GUI’s in Unity are meant to be created initially rather than edited at run-time. In other words you already know what you’re going to need, from windows to buttons to sliders, and the goal is to construct a rigid framework. Maybe an inventory system isn’t meant to be done with the GUI, and rather with sprites? shrugs

Bingo. You could use generic functions like DrawPickupOverlay() that draws template overlays with formatting and even via custom function arguments too.

Well yes, like the example I showed. But again, these aren’t “objects” so there is no “group” object, you need conditional code inside and outside the group block(s) to decide what gets drawn where (to “add/remove” objects from the group).

LOL

Sorry to double post as you were writing your response, so I’ll ask here again so as not to lose it, but is it entirely possible that this might be better handled with billboards?

To use what I’m most experienced with, in Virtools 2D entities are objects like any other BeObject (which is akin to Unity’s GameObject). What’s great is that being “2D” is just how it’s rendered, but is otherwise used like a 3D entity with regards to behavioral functionality. I could for example construct a large 2D entity, with a ‘open bag’ texture, and set it’s draw order so it’s rendered before all the 2D ‘item’ entities. At that point I can drag the items from the world, even leave them 3D but probably convert to a 2D entity and simply parent them to the ‘bag’. I can leave the 2D entity individually draggable along with the bag…move the bag everything goes…move the item entities and only they move. Detect when they’re not over the bag anymore, boom unparent and drop them back into the world.

Okay Steve that’s great and all but…?

Well maybe it’s easier to work with the 2D entity paradigm rather than GUI? Maybe? :smile:

“Better”? I dunno… It’s all possible either way. Get started with the UnityGUI system, it’s really quite nice in the end. You’ll just need to sort its ins and outs and you’ll see what you can in fact do (a lot!).

Hi HiggyB and SteveB…

sorry I’m using your post to put my own questions but I think they’re somewhat related…

from my flash and actionscript experience, I tend to try doing things the same way in unity, specially when it comes to adding GUI objects to the application…

is it possible to do something like adding gui objects like buttons and textfields so they can be dragged with the window. I got this code from the documentation

var windowRect = Rect (20, 20, 120, 50);

function OnGUI () {
// Register the window.
windowRect = GUI.Window (0, windowRect, DoMyWindow, "My Window");
}

// Make the contents of the window
function DoMyWindow (windowID : int) {
// Make a very long rect that is 20 pixels tall.
// This will make the window be resizable by the top
// title bar - no matter how wide it gets.
GUI.DragWindow (Rect (0,0, 10000, 20));
}

and the window drags perfectly… if I add a GUI.Button on the OnGUI function it won’t drag with the window…

my purpose is to build a “settings input” window so I can use the entered values throughout my app and at the same time, allowing users to drag the settings window as they please…

thanks for your help and patience :slight_smile:

The GUI.Button call should be inside DoMyWindow. If you put it straight into OnGUI, the button will be displayed as part of the main GUI, not the window.

tried that and when I drag the window, the button remains in it’s place… one other thing, the button’s drawn under the window although it remains clickable…

Strange… Can you post the whole script? It’s possible you’ve found a bug but it would be worth checking the script out before filing a report.

hi andeeee

tried it again and works fine now… must have been doing something wrong…

here’s the example code:

var windowRect = Rect (20, 20, 120, 50);

function OnGUI () {
// Register the window.
windowRect = GUI.Window (0, windowRect, DoMyWindow, "My Window");
}

// Make the contents of the window
function DoMyWindow (windowID : int) {
// Make a very long rect that is 20 pixels tall.
// This will make the window be resizable by the top
// title bar - no matter how wide it gets.
if(GUI.Button(Rect (20, 20, 60, 35), "click me")) {
	print("you clicked me");
}
GUI.DragWindow (Rect (0,0, 10000, 20));
}

hi again andeeee…

still the dragging of a window… here’s the code I’ve got and with it I can’t get any window to drag, less to say any buttons inside :frowning:

guess I found the reason why… it has to do with where I define the rectangles for both windows.

if I do it outside the OnGUI function, the window’s are draggable… however, if I do it inside the function, they’re not… at first I thought only the GUI.Window() function mattered…

here’s the code

// Variáveis que armazenam os parâmetros introduzidos nos respectivos campos de texto
var textoAltura = "";
var textoLargura = "";
var textoEspessura = "";
var textoComprimentoA = "";
var textoComprimentoB = "";

var doWindow0 = false;
var doWindow1 = false;

var janelaParedes: Rect = Rect (400, 400, 400, 300);
var janelaParedes1: Rect = Rect (400, 400, 400, 300); 

function OnGUI()
{
	// Menu Lateral - Paineis
	GUI.Box (Rect (10,40,150,Screen.height - 40), "Propriedades");
	
	// Menu Principal
	GUI.Box (Rect (10,10,Screen.width - 20, 30), "");
	
	/*##### if done here, the windows don't drag #####


 var janelaParedes: Rect = Rect (Screen.width / 2 - 200 ,Screen.height / 2 - 150, 400, 300);
	var janelaParedes1: Rect = Rect (Screen.width / 2 - 200 ,Screen.height / 2 - 150, 400, 300); 

############################### */

	if (doWindow0)
		janelaParedes = GUI.Window (0, janelaParedes, DoWindow0, "Criar Paredes - Escolher Opcao");
	
	if (doWindow1) {
		janelaParedes1 = GUI.Window (1, janelaParedes1, DoWindow1, "Wizzard para layout de paredes");
	} 
	
	if (GUI.Button(Rect (15, 15, 100,20), "Criar Paredes")){
		if (doWindow0 == true) {
			doWindow0 = false;
		} else {
			doWindow0 = true;
		}
	}
	
}

function DoWindow0 (windowID : int) {
	
	if (GUI.Button (Rect (20, 20, 75, 75), "4 Paredes")) {
		doWindow0 = false;
		doWindow1 = true;
	} 
	GUI.DragWindow (Rect (0,0, 10000, 20));
}

function DoWindow1 (windowID : int) {
	// Criação do icon do tipo de parede, com legenda
	GUI.Box (Rect ((Screen.width / 2 - 200 ) + 20, (Screen.height / 2 - 150) + 40, 100, 100), "4 paredes");
	
	// Criação das labels para identificação dos diferentes campos de parâmetros.
	GUI.Label(Rect ((Screen.width / 2 - 200 ) + 250, (Screen.height / 2 - 150) + 40, 90, 30), "a"); 
	GUI.Label(Rect ((Screen.width / 2 - 200 ) + 340, (Screen.height / 2 - 150) + 40, 90, 30), "b"); 
	
	GUI.Label(Rect ((Screen.width / 2 - 200 ) + 130, (Screen.height / 2 - 150) + 60, 90, 30), "Comprimento"); 
	
	
	// Criação dos campos de texto para introdução dos parâmetros de configuração do compartimento
	// Estes parâmetros definem as dimensões das paredes do compartimento (altura, comprimento e espessura)
	textoComprimentoA = GUI.TextArea(new Rect ((Screen.width / 2 - 200 ) + 220, (Screen.height / 2 - 150) + 60, 75, 20), textoComprimentoA);
	textoComprimentoB = GUI.TextArea(new Rect ((Screen.width / 2 - 200 ) + 305, (Screen.height / 2 - 150) + 60, 75, 20), textoComprimentoB); 
	
}