This page has been translated automatically.
Unigine Basics
1. Introduction
2. Managing Virtual Worlds
3. Preparing 3D Models
4. Materials
5. Cameras and Lighting
7. Making Cutscenes and Recording Videos
8. Preparing Your Project for Release
9. Physics
10. Optimization Basics
11. PROJECT2: First-Person Shooter
12. PROJECT3: Third-Person Cross-Country Arcade Racing Game
13. PROJECT4: VR Application With Simple Interaction

User Interface

In UNIGINE a Graphical User Interface (GUI) is composed of different types of widgets added to it. Basically, there are two ways of creating GUI:

  • By adding widgets to the system GUI (UNIGINE user interface) that is rendered on top of application window. In this case we use the Gui class.
  • By adding widgets to a GUI object positioned in the world. In this case, any postprocessing filter can be applied. By creating a specific Gui object (or GuiMesh for arbitrary geometry) that can be placed anywhere in the scene, and adding widgets to it. This can be useful, for example, to implement interaction with the interface displayed on a computer screen in a room (i.e. UI bound to an object that can be viewed from different angles). In this case, a post-processing filter can be applied.

There are 2 ways to create the GUI layout:

  • Directly from code via GUI classes
  • Using UI files with the description of user interface. Such a description file in XML-like format can be created for a complex interface to write less code.

The following code demonstrates how to add Label and Slider widgets to the system GUI:

Source code (C#)
private void Init()
{
	// getting a reference to the system GUI
	Gui gui = Gui.GetCurrent();

	// creating a label widget and setting up its parameters
	WidgetLabel widget_label = new WidgetLabel(gui, "Label text:");
	widget_label.SetToolTip("This is my label!");
	widget_label.Arrange();
	widget_label.SetPosition(10, 10);

	// creating a Slider widget and setting up its parameters
	WidgetSlider widget_slider = new WidgetSlider(gui, 0, 360, 90);
	widget_slider.SetToolTip("This is my slider!");
	widget_slider.Arrange();
	widget_slider.SetPosition(100, 10);

	gui.AddChild(widget_label, Gui.ALIGN_OVERLAP | Gui.ALIGN_FIXED);
	gui.AddChild(widget_slider, Gui.ALIGN_OVERLAP | Gui.ALIGN_FIXED);
}

In order to use GUI elements (not just watch them rendered) we must specify handlers for various events (click, change, etc.). The following code demonstrates how to set event handlers:

Source code (C#)
void onSliderChanged(Widget sender)
{
	Log.Message("\n The value of the slider has been changed: {0}\n", (sender as WidgetSlider).Value);
}

private void Init()
{
	// getting the reference to the system GUI
	Gui gui = Gui.GetCurrent();

	// creating the Button widget and setting its parameters
	WidgetButton widget_button = new WidgetButton(gui, "Press me");
	widget_button.Arrange();
	widget_button.SetPosition(10,10);
	
	// creating the Slider widget and setting its parameters
	WidgetSlider widget_slider = new WidgetSlider(gui);
	widget_button.Arrange();
	widget_button.SetPosition(100,10);

	// setting a lambda function to handle CLICKED event (mouse click)
	widget_button.EventClicked.Connect(() => Log.Message("Button is pressed\n"));
	// setting a method to handle CHANGED event (changing)
	widget_slider.EventChanged.Connect(onSliderChanged);

	// adding the created widgets to the system GUI
	gui.AddChild(widget_button, Gui.ALIGN_OVERLAP | Gui.ALIGN_FIXED);
	gui.AddChild(widget_slider, Gui.ALIGN_OVERLAP | Gui.ALIGN_FIXED);
}

Practice
#

In architectural visualization projects, a widespread option is changing materials on various objects, for example, to preview different wallpapers on the walls and match them with the decor of the furniture. For our project, let's create a component (also inherit it from Interactable) that displays a list of available materials for a selected object in the UI based on ObjectGui with the ability to select and automatically apply them.

  1. Create a new component called MaterialCustomizer and add the following code to it:

    Source code (C#)
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using Unigine;
    
    [Component(PropertyGuid = "AUTOGENERATED_GUID")] // <-- this line is generated automatically for a new component
    public class MaterialCustomizer : Interactable
    {
    	[Parameter(Tooltip = "List of materials for object customization")]
    	public  List<Material> MaterialsList = null;
    
    	private ObjectGui gui = null;	// GUI object for displaying of the material selection interface
    
    	// the function that assigns the material selected in the menu to the selected customized object's surface
    	private void select_material_handler(Widget w)
    	{
    		(node as Unigine.Object).SetMaterial(MaterialsList[(w as WidgetComboBox).CurrentItem],ComponentSystem.FindComponentInWorld<InputProcessor>().intersection.Surface);
    	}
    
    	private void Init()
    	{
    		// setting the text of the tooltip that will be displayed when the cursor hovers over the object
    		tooltip = "Right-click displays a menu where you can select a material for the object.";
    
    		// creating the GUI object to display the material selection interface and setting its size and resolution
    		gui = new ObjectGui(0.5f, 0.5f);
    		gui.SetScreenSize(600, 600);
    
    		// enabling intersection detection to interact with UI using the mouse
    		gui.SetIntersection(true, 0);
    
    		// making the interface always rotate to the user and not blocked by other objects
    		gui.Billboard = true;
    		gui.GetMaterialInherit(0).DepthTest = false;
    		// disabling the black background and temporarily hiding the UI
    		gui.Background = false;
    		gui.Enabled = false;
    
    		// setting the distance from which interaction with the interface is possible
    		gui.ControlDistance = 10;
    		
    		if(MaterialsList != null && MaterialsList.Count > 0)
    		{
    			// adding the WidgetVBox widget container for vertical layout of elements, setting indents
    			WidgetVBox vbox = new WidgetVBox(gui.GetGui());
    			vbox.SetSpace(20,20);
    
    			// enabling the background and setting its color
    			vbox.Background = 1;
    			vbox.BackgroundColor = new vec4(0.1f,0.5f,0.1f,0.4f);
    
    			// creating a WidgetLabel widget to display the header, setting its position and font size
    			WidgetLabel label = new WidgetLabel(gui.GetGui(), "Select the material:");
    			label.FontSize = 50;
    			// adding the Label widget to the container
    			vbox.AddChild(label,Gui.ALIGN_TOP);
    
    			// creating a WidgetComboBox widget to display a drop-down list of materials,
    			WidgetComboBox mat_menu  = new WidgetComboBox(gui.GetGui());
    			mat_menu.FontSize = 40;
    
    			// setting the callback on selection of an item from the list
    			mat_menu.EventChanged.Connect(select_material_handler);
    
    			// adding items to the menu according to the list of materials
    			for(int i = 0; i < MaterialsList.Count; i++)
    			{
    				string str = FileSystem.GetVirtualPath(MaterialsList[i].Path); 
    				mat_menu.AddItem(str.Substring(str.LastIndexOf("/")+1));
    			}
    			// adding the ComboBox widget to the container
    			vbox.AddChild(mat_menu,Gui.ALIGN_TOP);
    
    			// adding container widget to GUI
    			gui.GetGui().AddChild(vbox,Gui.ALIGN_EXPAND|Gui.ALIGN_OVERLAP);
    		}
    	}
    	
    	public override void Action(int num)
    	{
    		// action indices different from zero are invalid for this component, so they are ignored
    		if (num != 0)
    			return;
    
    		// placing the GUI near the click point
    		gui.WorldPosition = ComponentSystem.FindComponentInWorld<InputProcessor>().intersection.Point;
    
    		// hide the GUI for all other customizable objects (if any)
    		foreach(MaterialCustomizer customizer in ComponentSystem.FindComponentsInWorld<MaterialCustomizer>() )
    			if (this != customizer)
    				customizer.gui.Enabled = false;
    
    		// show or hide the interface of material selection for the object
    		gui.Enabled = !gui.Enabled;
    	}
    
    }
  2. Assign the component to the bedside_table_1 object in our scene.
  3. Fill in the list of materials. To do this, change the number of items in the list from 0 to 3 and then drag three materials into the corresponding fields.

Upon right-clicking an object a list of available materials will be displayed, you can choose the desired one, and it will be applied automatically right as you click it:

Last update: 2024-04-16
Build: ()