Game Development Community

In-game cursor

by Sean H. · 07/08/2005 (7:10 am) · 24 comments

Hey hey hey everybody! This is my first resource and although it's rather short, I'm glad to finally be able to give back to the community. I spent several hours last night researching and trying to figure this out for my game and I finally came up with a solution which takes a few seconds to implement. I am no posting it here so you guys don't have to waste time figuring it out and to give back to the community which has given me so many solutions. =)

first a little background:

youll notice that the only time a cursor appears is when a GuiControl is on-screen. without any extraneous resources, a GuiControl is the only way to get a mouse cursor. However, the in-game Gui is usually a GameTSCTRL(Game Three Space Control).

for reference: fps/client/scripts/serverconnection.cs

function GameConnection::initialControlSet(%this)
{
   echo ("*** Initial Control Object");

   // The first control object has been set by the server
   // and we are now ready to go.
   
   // first check if the editor is active
   if (!Editor::checkActiveLoadDone())
   {
      if (Canvas.getContent() != PlayGui.getId())
         Canvas.setContent(PlayGui);
   }
}

this sneaky little function is called automatically by the engine right before the game begins. This is where the PlayGui is bound to the screen.

additional reference: fps/client/ui/playGui

new GameTSCtrl(PlayGui) {

   profile = "GuiContentProfile";
   horizSizing = "right";
   vertSizing = "bottom";
   position = "0 0";
   extent = "640 480";
   minExtent = "8 8";
   visible = "1";
   helpTag = "0";
   noCursor = true;
   

   new GuiBitmapCtrl(CenterPrintDlg) {
      profile = "CenterPrintProfile";
      etc....

we need a GameTSCTRL for in-game menus, but this particular GUI gets rid of the cursor. If we were to make this a GuiControl instead, the cursor would work but then there would be no gameplay screen.

So how do we get both a gameplay screen and a mouse cursor? We can do this by simply embedding the GameTSCTRL into a larger GuiControl.

modify fps/client/ui/playGui as follows:

new GuiControl(PlayGui){
    profile="GuiContentProfile"
    
    new GameTSCTRL(PlayGui2){
    //everything else remains the same
    };
};

Dont forget to add another " }; " at the end. In effect you are surrounding the GameTSCTRL within a GuiControl. This gives the benefit of an in-game menu with the added bonus of a mouse cursor. Best of all, the current ActionMap will still be valid with the exception of the mouse which now controls the cursor. For further reference, the default mouse cursor is defined in common/ui/defaultprofiles.cs.

I know this is simple, but I've seen a few questions about in-game cursors so I thought I'd post my findings. Happy torquing!
Page «Previous 1 2
#1
07/08/2005 (7:38 am)
Umm... can't you just set "noCursor = false;" in the original datablock?
#2
07/08/2005 (8:14 am)
i originally typed this and it got eaten so i forgot to retype some things. but no, setting the nocursor attribute to false doesnt work. try it and see.
#3
07/08/2005 (12:16 pm)
Couldn't someone just use Canvas.setCursor(true); ? That's what I use to toggle my in-game clicker(tho I have an engine mod for 3D selection).
#4
07/08/2005 (1:28 pm)
-Josh

you would need the engine mod to use that function like that. this is for people who need an in-game cursor using script only.
#5
07/08/2005 (8:14 pm)
No, you would need to modify the engine to get 3D mouse selection. Kinda like I said:
Quote:(tho I have an engine mod for 3D selection)

Canvas.setCursor(true); Will activate the cursor no matter what GUI is currently on the Canvas.
#6
07/09/2005 (3:16 am)
Including a curser in the game is very good. Especially for kid and mom type of players.

Since this is a recent forum thread, I have a few pressing questions. I'm trying to find my way through Torque's code. I am a newbie to the engine.

One of my projects is to create a software game for younger kids. I prefer not to have server connections if that's possible.

One way that I thought of was to override with code like this from the starMissionGui from the StrongHold/RottenWheels


// if (playerAnswer !$= ""){

%id = SM_missionList.getSelectedId();
%mission = getField(SM_missionList.getRowTextById(%id), 1);

if ($pref::HostMultiPlayer)
%serverType = "MultiPlayer";
else
%serverType = "SinglePlayer";

createServer(%serverType, %mission);
%conn = new GameConnection(ServerConnection);
RootGroup.add(ServerConnection);
%conn.setConnectArgs($pref::Player::Name);
%conn.setJoinPassword($Client::Password);
%conn.connectLocal();

// }else{
// loadMainMenu();
// }


By adding a count flag during the second cycle to proceed to the next function

1) I'm seeing a lot of the dot notation that looks like instantiation. I looked everywhere for those classes and was unable to find them. If they're library functions, I need to know where I can find them.

2) This script that I took is found in the startMissionGui. The loadMainMenu() is found in the init.cs on line 120. I thought of creating a startTheMission.h, include it #include "startTheMission.h" into init.cs, and then instance this into startMissionGui to include the "else" part. I'm the type that would rather measure twice and cut once. Has anyone tried this? Or am I crazy?

3) My intentions are to find -> I want to be able to disable the sockets without effecting the code as a single player. I want to follow further into the code to see how the single player option works. I just can't find the class names that have these functions. I need some direction on this.

4) Just a general question. init.cs on line 34, $Server::Dedicated=false , does this statement allow a connection from any IP address? If so, if I were to put "true" there, would this make the connection allowable to one IP address? What would happen? Or am I way off base with this question?

Please forgive me for being new.

thanks,
Tatjana
#7
07/09/2005 (12:46 pm)
-Josh, I shouldve been more clear. i dont know what version of the engine you are using, but in the book version, that function takes a cursor object as its argument. when i try to call setcursor(true) i get an error:

1 is not a valid cursor

im pretty sure its because of the version of the engine that i have because one of my resources lists the this function is supposed to take a bool as its argument. but I cant use the function that way.

the main reason i posted this is because i was racking my brain trying to figure out how to get a cursor on the screen. it seemed like everything I did that shouldve worked wasnt working. once I found a way to do it I just decided to post it in a resource just in case someone else was having the same problem.

it turns out that last night i found another way of doing it. theres a canvas function: Canvas.cursorOn(); which enables the cursor. this function works fine with the book version but you need to be careful of when you call it. ive found you can call CursorOn() at the end of serverconnection.cs and the cursor will be there when the game starts. however, if you pull up the console and close it, the cursor disappears. so I added another call to CursorOn() for when the console closes and that worked fine. the main problem with using this particular function is that it may become invalidated as dialogs are pushed and popped. Ive found that calling Cursoron() in PlayGUI::onwake doesnt work, so you need to make sure to call Cursoron() for every circumstance where the cursor may become invalidated. figuring out when this function needs to be called(or any cursor-enabling function) is more tedious than the method I have here if you want a persistent mouse cursor.

to conclude, just like any good engine, in torue theres multiple ways of doing just about everything, including getting an on-screen cursor. what method you should use may depend on the version of the engine you have as well as your particular usage. all in all, in my opinion the fact that the GameTSCTRL can be embedded into a larger GuiControl is counter-intuitive and somewhat instructional. achieving a mouse cursor this way eliminates the need to make any function calls whatsoever.
#8
07/09/2005 (4:59 pm)
BTW: Just a quick note, the reason the nocursor attribute doesn't work when you set it to false is that the code only checks for the existence of the variable...

in common\client\cursor.cs(49)

if(%control.noCursor $= "")
{
%cursorShouldBeOn = true;
break;
}

A quick change to test to see if == true would also work... (and IMHO, should be that way regardless... why test for the existence of a variable without testing to see it's value?)
#9
07/10/2005 (12:40 pm)
Found the function breakdown in example\common\server\whatever files here. the search in windows XP is not always thorough.

Not so easy for those new to Torque,

But easy for those who are seasoned. Thanks anyway
#10
07/21/2005 (5:04 am)
Search in windows xp is utter trash. That's why I've got my code residing on a linux box. Grep Power To The People! ;)
It might be that I'm just lazy and that I need to add the cs files and such as a text file type in windows somewhere, but I already got a solution that works so I don't bother spending time on figuring it out.
#11
07/21/2005 (7:29 pm)
@Anders Jacobsen

It's about working smarter, not harder :- ) That I need to learn.

Take care :- )
#12
07/22/2005 (8:29 am)
hi all,

dunno if anyone is folowing this thread, but thanks, its a good resource.

quick question: how do you change the extents of the gameTSControl on the fly? I want the cursor to appear when running full screen, and also, i want to be able to frame the game scene and surround with controls, similar to mission editor.

i also would like the game scene to get it's extents from the prefs file at start up, so it loads full screen based on the prefs file.

any ideas?

j
#13
01/13/2006 (9:13 pm)
CursorOn() and CursorOff() work well for this.

function toggleCursor(%val) {
if (%val) {
if ($cursoron) {
CursorOff();
} else {
CursorOn();
}
$cursoron = !$cursoron;
}
}


moveMap.bind( keyboard, m, toggleCursor );
#14
02/03/2006 (5:12 am)
doesnt work with 1.4 i get a split screen!
#15
02/03/2006 (8:13 am)
got it to work with out this to get a cursor on screen just set noCursor = "0";
#16
02/14/2006 (2:36 pm)
ok, so let's summarize what everyone's said here.

from the looks of it, there's 3 ways to invoke an in-game mouse cursor in script:

1. set the gui noCursor = "0"
2. call CursorOn() and CursorOff()
3. Canvas.setCursor(true)
4. Canvas.cursorOn()

from my experience, methods 2 and 3 don't work with version 1.2(book version) of the engine, method 4 works with the book version, and method 1 could work if someone modifies common\client\cursor.cs like Tim says above. this may have been fixed in 1.4. it also looks like, from what Dylan has said, that the method outlined in this resource doesn't work with version 1.4 of the engine. if you have a version of the engine later than 1.2 then you'll probably want to get a cursor using one of these 4 methods rather than the method I have outlined here.

however, you may still want to try doing it this way because if it works, youll have a persistent in-game cursor without having to call any functions.
#17
05/28/2006 (5:16 am)
I tried the all the methods and cursonOn/Off and it gives me the mouse cursor back but breaks the binding of the mouse to pitch and yaw..

What I am looking for it to keep the binds to pitch/yaw because my game is a third person game that 'rotates' the character but still shows a mouse cursor which I can turn into a targetting reticle later...Anybody?
#18
07/29/2006 (11:12 am)
I realise that this thread is getting a little off the subject, but I' looking for a solution to a scripting problem involving the mouse as well. I use noCursor="" in my TScontrol to ensure the cursor is displayed (and bind pitch and yaw to was+d), but I have been scouring the editor code all day for a way to "select" items in the window. Essentially, my game is more of an RPG come fps, but I'd like to be able to click on objects from a distance, such as a chest to open it or a (non hostile!) character to go over and talk to them. If anyone could provide some script-only code to do this (or point it out if I've overlooked it) then it'd be much appreciated. Thanks!
#19
01/23/2007 (9:15 am)
Here's a glitch I can't seem to figure out. I have buttons on my playgui and my cursor is visible by calling canvas.CursorOn(). When I click on any of the buttons they work just how I want them to. However I have binded the right mouse button to call a function that will switch the view to a camera view. BUT when I click the right mouse button nothing happens, it's as if it's completely disabled? Has anyone experienced this or would know what's going on? Why does my left mouse button work the way I want and my right mouse button is disabled?
THX.
#20
02/08/2007 (10:48 pm)
Another way to do it (somewhat simply, I think) would be to creat a script function (or just stick this code in your normal Yaw/Pitch functions if you're not planning on using them) and bind the mouse to it...


function doubleCheckCursor(%value)
{
if(!Canvas.isCursorOn) Canvas.cursorOn();
}
Page «Previous 1 2