This page has been translated automatically.
Video Tutorials
Interface
Essentials
Advanced
How To
Professional (SIM)
UnigineEditor
Interface Overview
Assets Workflow
Settings and Preferences
Working With Projects
Adjusting Node Parameters
Setting Up Materials
Setting Up Properties
Lighting
Sandworm
Using Editor Tools for Specific Tasks
Extending Editor Functionality
Built-in Node Types
Nodes
Objects
Effects
Decals
Light Sources
Geodetics
World Nodes
Sound Objects
Pathfinding Objects
Players
Programming
Fundamentals
Setting Up Development Environment
C++
C#
UnigineScript
UUSL (Unified UNIGINE Shader Language)
Plugins
File Formats
Materials and Shaders
Rebuilding the Engine Tools
GUI
Double Precision Coordinates
API
Containers
Common Functionality
Controls-Related Classes
Engine-Related Classes
Filesystem Functionality
GUI-Related Classes
Math Functionality
Node-Related Classes
Objects-Related Classes
Networking Functionality
Pathfinding-Related Classes
Physics-Related Classes
Plugins-Related Classes
IG Plugin
CIGIConnector Plugin
Rendering-Related Classes
Content Creation
Content Optimization
Materials
Material Nodes Library
Miscellaneous
Input
Math
Matrix
Textures
Art Samples
Tutorials
Warning! This version of documentation is OUTDATED, as it describes an older SDK version! Please switch to the documentation for the latest SDK version.
Warning! This version of documentation describes an old SDK version which is no longer supported! Please upgrade to the latest SDK version.

Using Manipulators to Transform Objects

After adding an object to the scene in Unigine Editor, you can control object transformations with control devices. But sometimes transformations are supposed to be made at application runtime. For example, when you create your own game with a world editor, where you can place objects in the world and move them around.

This usage example will teach you how to:

  1. Select an object on the screen with the mouse using Intersections.
  2. Use manipulator widgets to modify the object transform matrix.
  3. Switch between different manipulator widgets using the keyboard.

See Also#

Creating Manipulators to Control Object Transformations#

There are 3 types of manipulator widgets used for object transforming:

All these manipulators work the same way, each of them visually represents a part of the transformation matrix that you can change by dragging the control elements of the widget. Use the CHANGED callback of the widget to make the selected object follow manipulators transformations.

Source code (C#)
public class Manipulator : Component
{
	// declare object and translator widget manipulator variables
    Unigine.Node obj;
	WidgetManipulator ObjManTranslator;
	
    private void Init()
    {
        // write here code to be called on component initialization
		
		// create a manipulator class instance and add it to the UI
        gui = Gui.GetCurrent();
        ObjManTranslator = new WidgetManipulatorTranslator(gui);
        gui.AddChild(ObjManTranslator);
		
		// setting the ApplyTransform method as a callback on changing the widget state
		ObjManTranslator.AddCallback(Gui.CALLBACK_INDEX.CHANGED, ApplyTransform);
    }
	
	// a callback method used to transform an object
	private void ApplyTransform()
	{
		if(obj != null)
			obj.WorldTransform = ObjManTranslator.Transform;
	}
}

Selecting Objects Using Mouse Cursor#

To select an object under the mouse cursor we should cast a ray from the cursor location in the view direction of the camera using the World.GetIntersection() method, that returns an intersected object (if any).

Source code (C#)
// find an object under the cursor
private Unigine.Node GetNodeUnderCursor()
{
	ivec2 mouse = Input.MousePosition;

	// find a point 100 units away in front of the camera
	Vec3 p0 = Game.Player.WorldPosition;
		
	EngineWindow main_window = WindowManager.MainWindow;
	if (main_window)
	{
		ivec2 main_pos = main_window.Position;
		mouse.x += main_pos.x;
		mouse.y += main_pos.y;
	}
	Vec3 p1 = p0 + new vec3(Game.Player.GetDirectionFromMainWindow(mouse.x, mouse.y)) * 100;
		
	// cast a ray, that will detect an object within 100 units in front of the camera
	return World.GetIntersection(p0, p1, 1, intersection);
}

Putting it All Together#

Now let's put it all together and add a keyboard handler to switch the current manipulator. For example, let's use Z, X, C keys to select Translator, Rotator, Scaler Manipulators accordingly. The selected widget will be displayed on the screen where the object is located (i.e. it will have the same transformation).

  1. Create a new C# componentManipulator. Double-click it in the Asset Browser to edit code in your IDE.
  2. Copy the code below and paste it to your component.
  3. Assign Manipulator to any enabled node in the world and click Play.
Source code (C#)
#region Math Variables
#if UNIGINE_DOUBLE
using Scalar = System.Double;
using Vec2 = Unigine.dvec2;
using Vec3 = Unigine.dvec3;
using Vec4 = Unigine.dvec4;
using Mat4 = Unigine.dmat4;
#else
using Scalar = System.Single;
using Vec2 = Unigine.vec2;
using Vec3 = Unigine.vec3;
using Vec4 = Unigine.vec4;
using Mat4 = Unigine.mat4;
using WorldBoundBox = Unigine.BoundBox;
using WorldBoundSphere = Unigine.BoundSphere;
using WorldBoundFrustum = Unigine.BoundFrustum;
#endif
#endregion

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 Manipulator : Component
{
	// WorldIntersection object to store the information about the intersection 
	WorldIntersection intersection = new WorldIntersection();
 
	// Unigine.Object object to gain access to a selected object's transform in Unigine 
	Unigine.Node obj;
 
	// create manipulators for each type of transform(Translating, Scaling, Rotating) 
	WidgetManipulator ObjManTranslator;
	WidgetManipulator ObjManScaler;
	WidgetManipulator ObjManRotator;
	
	// create widget manipulator used to store transformation matrix of an active widget
	WidgetManipulator CurrentObjectManipulator;
	Gui gui;

	[Method(Order=2)] private void Init()
	{
		// write here code to be called on component initialization 
		gui = Gui.GetCurrent();

		// create widget for each transformation type
		ObjManTranslator = new WidgetManipulatorTranslator(gui);
		ObjManScaler = new WidgetManipulatorScaler(gui);
		ObjManRotator = new WidgetManipulatorRotator(gui);
		
		// set projection for the widgets
		ObjManTranslator.Projection= Game.Player.Camera.Projection;
		ObjManScaler.Projection = Game.Player.Camera.Projection;
		ObjManRotator.Projection = Game.Player.Camera.Projection;

		// add widgets to UI
		gui.AddChild(ObjManTranslator);
		gui.AddChild(ObjManScaler);
		gui.AddChild(ObjManRotator);

		// add a callback for each widget   
		ObjManTranslator.AddCallback(Gui.CALLBACK_INDEX.CHANGED, ApplyTransform);
		ObjManRotator.AddCallback(Gui.CALLBACK_INDEX.CHANGED, ApplyTransform);
		ObjManScaler.AddCallback(Gui.CALLBACK_INDEX.CHANGED, ApplyTransform);

		// hide created widgets
		ObjManScaler.Hidden = true;
		ObjManRotator.Hidden = true;
		ObjManTranslator.Hidden = true;
	}
 
	private void Update()
	{
		// write here code to be called before updating each render frame
		 if (!Game.Player)
			return;
	
		// set modelview for each widget manipulator every frame
		ObjManTranslator.Modelview = Game.Player.Camera.Modelview;
		ObjManScaler.Modelview = Game.Player.Camera.Modelview;
		ObjManRotator.Modelview = Game.Player.Camera.Modelview;

		// select an object with right-click
		if (Input.IsMouseButtonDown(Input.MOUSE_BUTTON.RIGHT))
		{
			obj = GetNodeUnderCursor();
			CurrentObjectManipulator.Transform = obj.WorldTransform;
		}

		// choose manipulator with Z,X,C keys
		if(obj)
		{
			if(Input.IsKeyDown(Input.KEY.Z))
				SwitchManipulator(ObjManTranslator);
			if(Input.IsKeyDown(Input.KEY.X))
				SwitchManipulator(ObjManRotator);
			if(Input.IsKeyDown(Input.KEY.C))
				SwitchManipulator(ObjManScaler);
			if (!Input.IsMouseButtonPressed(Input.MOUSE_BUTTON.LEFT))
				CurrentObjectManipulator.Transform = obj.WorldTransform;
		}
	}
 
	// transform an object
	private void ApplyTransform()
	{
		if(obj != null && Input.IsMouseButtonPressed(Input.MOUSE_BUTTON.LEFT))
			obj.WorldTransform = CurrentObjectManipulator.Transform;
	}
 
	// find an object under the cursor
	private Unigine.Node GetNodeUnderCursor()
	{
		ivec2 mouse = Input.MousePosition;

		// find a point 100 units away in front of the camera
		Vec3 p0 = Game.Player.WorldPosition;
		
		EngineWindow main_window = WindowManager.MainWindow;
		if (main_window)
		{
			ivec2 main_pos = main_window.Position;
			mouse.x += main_pos.x;
			mouse.y += main_pos.y;
		}
		Vec3 p1 = p0 + new vec3(Game.Player.GetDirectionFromMainWindow(mouse.x, mouse.y)) * 100;
		
		// cast a ray, that will detect an object within 100 units in front of the camera
		return World.GetIntersection(p0, p1, 1, intersection);
	}

	// relocate chosen manipulator to the position of selected object and make it visible
	void SwitchManipulator(WidgetManipulator CurrentManipulator)
	{
		// relocate a widget and making it visible
		CurrentManipulator.Transform = obj.WorldTransform;
		CurrentManipulator.Hidden = false;
		
		// make other widgets hidden
		CurrentObjectManipulator = CurrentManipulator;
		if(ObjManTranslator != CurrentManipulator)
			ObjManTranslator.Hidden = true;
		if(ObjManRotator != CurrentManipulator)
			ObjManRotator.Hidden = true;
		if(ObjManScaler != CurrentManipulator)
			ObjManScaler.Hidden = true;
	}
}
Last update: 2022-12-14
Build: ()