1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013-2014 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include <nel/misc/types_nl.h>
28 #include <nel/misc/event_listener.h>
29 #include <nel/misc/command.h>
30 #include <nel/misc/log.h>
31 #include <nel/misc/displayer.h>
33 #include <nel/3d/u_camera.h>
34 #include <nel/3d/u_driver.h>
35 #include <nel/3d/u_text_context.h>
36 #include <nel/3d/u_instance.h>
37 #include <nel/3d/u_scene.h>
38 #include <nel/3d/u_3d_mouse_listener.h>
39 #include <nel/3d/u_material.h>
40 #include <nel/3d/u_landscape.h>
41 #include <nel/3d/stereo_hmd.h>
44 #include "snowballs_client.h"
45 #include "interface.h"
47 #if SBCLIENT_DEV_PIXEL_PROGRAM
48 #include <nel/3d/driver_user.h>
49 #include <nel/3d/driver.h>
50 #include <nel/3d/pixel_program.h>
51 #include <nel/3d/material.h>
52 #include <nel/3d/u_texture.h>
60 using namespace NLMISC
;
71 static list
<string
> StoredLines
;
72 static uint32 NbStoredLines
= 100;
74 // These variables are automatically set with the config file
76 static float CommandsBoxX
, CommandsBoxY
, CommandsBoxWidth
;
77 static float CommandsBoxBorder
;
78 static int CommandsNbLines
;
79 static float CommandsLineHeight
;
80 static int CommandsFontSize
;
81 static CRGBA CommandsBackColor
, CommandsFrontColor
;
82 static UMaterial CommandsMaterial
= NULL
;
88 // Display a string to the commands interface
89 void addLine (const string
&line
)
92 StoredLines
.push_back (line
);
94 // Clear old lines if too much lines are stored
95 while (StoredLines
.size () > NbStoredLines
)
97 StoredLines
.pop_front ();
101 // Display used to display on the commands interface
102 class CCommandsDisplayer
: public IDisplayer
104 virtual void doDisplay (const CLog::TDisplayInfo
&args
, const char *message
)
106 bool needSpace
= false;
109 if (args
.LogType
!= CLog::LOG_NO
)
111 str
+= logTypeToString(args
.LogType
);
115 if (needSpace
) { str
+= ": "; needSpace
= false; }
121 // Instance of the displayer
122 static CCommandsDisplayer CommandsDisplayer
;
124 // Check if the user line is a command or not (a commands precede by a '/')
125 bool commandLine (const string
&str
)
131 // If it's a command call it
132 command
= str
.substr(1);
133 // add the string in to the chat
134 addLine (string ("command> ") + str
);
135 ICommand::execute (command
, CommandsLog
);
144 // Manage the user keyboard input
145 class CCommandsListener
: public IEventListener
147 virtual void operator() ( const CEvent
& event
)
149 // If the interface is open, ignore keys for the command interface
150 if (interfaceOpen ()) return;
153 CEventChar
&ec
= (CEventChar
&)event
;
157 case 13 : // RETURN : Send the chat message
159 // If the line is empty, do nothing
160 if ( _Line
.size() == 0 ) break;
162 // If it's a command, execute it and don't send the command to the network
163 if ( ! commandLine( _Line
) )
165 // If online, send the chat line, otherwise, locally displays it
167 sendChatLine (_Line
);
169 addLine (string ("you said> ") + _Line
);
171 // Reset the command line
172 _LastCommand
= _Line
;
174 _MaxWidthReached
= false;
177 case 8 : // BACKSPACE : remove the last character
179 if ( _Line
.size() != 0 )
181 _Line
.erase( _Line
.end()-1 );
185 case 9 : // TAB : If it's a command, try to auto complete it
189 _Line
= _LastCommand
;
191 else if (!_Line
.empty() && _Line
[0] == '/')
193 string command
= _Line
.substr(1);
194 ICommand::expand(command
);
195 _Line
= '/' + command
;
199 case 27 : // ESCAPE : clear the command
202 _MaxWidthReached
= false;
205 default: // OTHERWISE : add the character to the line
207 if (! _MaxWidthReached
)
209 _Line
+= (char)ec
.Char
;
215 CCommandsListener() : _MaxWidthReached( false )
218 const string
& line() const
223 void setMaxWidthReached( bool b
)
225 _MaxWidthReached
= b
;
230 bool _MaxWidthReached
;
234 // Instance of the listener
235 static CCommandsListener CommandsListener
;
237 // This functions is automatically called when the config file changed (dynamically)
238 void cbUpdateCommands (CConfigFile::CVar
&var
)
240 if (var
.Name
== "CommandsBoxX") CommandsBoxX
= var
.asFloat ();
241 else if (var
.Name
== "CommandsBoxY") CommandsBoxY
= var
.asFloat ();
242 else if (var
.Name
== "CommandsBoxWidth") CommandsBoxWidth
= var
.asFloat ();
243 else if (var
.Name
== "CommandsBoxBorder") CommandsBoxBorder
= var
.asFloat ();
244 else if (var
.Name
== "CommandsNbLines") CommandsNbLines
= var
.asInt ();
245 else if (var
.Name
== "CommandsLineHeight") CommandsLineHeight
= var
.asFloat ();
246 else if (var
.Name
== "CommandsBackColor") CommandsBackColor
.set (var
.asInt(0), var
.asInt(1), var
.asInt(2), var
.asInt(3));
247 else if (var
.Name
== "CommandsFrontColor") CommandsFrontColor
.set (var
.asInt(0), var
.asInt(1), var
.asInt(2), var
.asInt(3));
248 else if (var
.Name
== "CommandsFontSize") CommandsFontSize
= var
.asInt ();
249 else nlwarning ("Unknown variable update %s", var
.Name
.c_str());
252 #if SBCLIENT_DEV_PIXEL_PROGRAM
254 CPixelProgram
*a_DevPixelProgram
= NULL
;
255 UTextureFile
*a_NelLogo
;
261 // Add the keyboard listener in the event server
262 Driver
->EventServer
.addListener (EventCharId
, &CommandsListener
);
264 // Add the command displayer to the standard log (to display NeL info)
265 CommandsLog
.addDisplayer (&CommandsDisplayer
);
267 DebugLog
->addDisplayer (&CommandsDisplayer
);
268 InfoLog
->addDisplayer (&CommandsDisplayer
);
269 WarningLog
->addDisplayer (&CommandsDisplayer
);
270 AssertLog
->addDisplayer (&CommandsDisplayer
);
271 ErrorLog
->addDisplayer (&CommandsDisplayer
);
274 // Add callback for the config file
275 ConfigFile
->setCallback ("CommandsBoxX", cbUpdateCommands
);
276 ConfigFile
->setCallback ("CommandsBoxY", cbUpdateCommands
);
277 ConfigFile
->setCallback ("CommandsBoxWidth", cbUpdateCommands
);
278 ConfigFile
->setCallback ("CommandsBoxBorder", cbUpdateCommands
);
279 ConfigFile
->setCallback ("CommandsNbLines", cbUpdateCommands
);
280 ConfigFile
->setCallback ("CommandsLineHeight", cbUpdateCommands
);
281 ConfigFile
->setCallback ("CommandsBackColor", cbUpdateCommands
);
282 ConfigFile
->setCallback ("CommandsFrontColor", cbUpdateCommands
);
283 ConfigFile
->setCallback ("CommandsFontSize", cbUpdateCommands
);
285 // Init the config file variable
286 cbUpdateCommands (ConfigFile
->getVar ("CommandsBoxX"));
287 cbUpdateCommands (ConfigFile
->getVar ("CommandsBoxY"));
288 cbUpdateCommands (ConfigFile
->getVar ("CommandsBoxWidth"));
289 cbUpdateCommands (ConfigFile
->getVar ("CommandsBoxBorder"));
290 cbUpdateCommands (ConfigFile
->getVar ("CommandsNbLines"));
291 cbUpdateCommands (ConfigFile
->getVar ("CommandsLineHeight"));
292 cbUpdateCommands (ConfigFile
->getVar ("CommandsBackColor"));
293 cbUpdateCommands (ConfigFile
->getVar ("CommandsFrontColor"));
294 cbUpdateCommands (ConfigFile
->getVar ("CommandsFontSize"));
296 CommandsMaterial
= Driver
->createMaterial();
297 CommandsMaterial
.initUnlit();
298 CommandsMaterial
.setBlendFunc(UMaterial::srcalpha
, UMaterial::invsrcalpha
);
299 CommandsMaterial
.setBlend(true);
301 #if SBCLIENT_DEV_PIXEL_PROGRAM
302 CommandsMaterial
.getObjectPtr()->setShader(NL3D::CMaterial::Program
);
303 a_NelLogo
= Driver
->createTextureFile("nel128.tga");
304 CommandsMaterial
.setTexture(dynamic_cast<NL3D::UTexture
*>(a_NelLogo
));
305 static const char *program_arbfp1
=
307 "PARAM c[1] = { { 1, 0 } };\n"
308 "MOV result.color.xzw, c[0].xyyx;\n"
309 "TEX result.color.y, fragment.texcoord[0], texture[0], 2D;\n"
311 static const char *program_fp40
=
313 "OPTION NV_fragment_program2;\n"
314 "PARAM c[1] = { { 1, 0 } };\n"
317 "OUTPUT oCol = result.color;\n"
318 "MOVR oCol.xzw, c[0].xyyx;\n"
319 "TEX oCol.y, fragment.texcoord[0], texture[0], 2D;\n"
321 static const char *program_ps_1_1
=
323 "def c0, 0.000000, 0.000000, 1.000000, 0.000000\n"
324 "def c1, 1.000000, 0.000000, 0.000000, 0.000000\n"
325 "def c2, 0.000000, 1.000000, 0.000000, 0.000000\n"
327 "mad r0.rgb, c2, t0, c1\n"
329 static const char *program_ps_2_0
=
332 "def c0, 1.00000000, 0.00000000, 0, 0\n"
338 static const char *program_ps_3_0
=
341 "def c0, 1.00000000, 0.00000000, 0, 0\n"
342 "dcl_texcoord0 v0.xy\n"
343 "mov oC0.xzw, c0.xyyx\n"
344 "texld oC0.y, v0, s0\n";
345 NL3D::IDriver
*d
= dynamic_cast<NL3D::CDriverUser
*>(Driver
)->getDriver();
346 a_DevPixelProgram
= new CPixelProgram();
349 IProgram::CSource
*source
= new IProgram::CSource();
350 source
->Features
.MaterialFlags
= CProgramFeatures::TextureStages
;
351 source
->Profile
= IProgram::arbfp1
;
352 source
->setSourcePtr(program_arbfp1
);
353 a_DevPixelProgram
->addSource(source
);
357 IProgram::CSource
*source
= new IProgram::CSource();
358 source
->Features
.MaterialFlags
= CProgramFeatures::TextureStages
;
359 source
->Profile
= IProgram::ps_2_0
;
360 source
->setSourcePtr(program_ps_2_0
);
361 a_DevPixelProgram
->addSource(source
);
363 /*if (d->supportPixelProgram(CPixelProgram::fp40))
366 a_DevPixelProgram = new CPixelProgram(program_fp40);
368 else if (d->supportPixelProgram(CPixelProgram::arbfp1))
371 a_DevPixelProgram = new CPixelProgram(program_arbfp1);
373 /*else if (d->supportPixelProgram(CPixelProgram::ps_3_0))
376 a_DevPixelProgram = new CPixelProgram(program_ps_3_0);
377 // Textures do not seem to work with ps_3_0...
379 /*else if (d->supportPixelProgram(CPixelProgram::ps_2_0))
382 a_DevPixelProgram = new CPixelProgram(program_ps_2_0);
384 else if (d->supportPixelProgram(CPixelProgram::ps_1_1))
387 a_DevPixelProgram = new CPixelProgram(program_ps_1_1);
392 void updateCommands()
394 // Snap to pixels (kind of ugly code, but looks better ingame)
395 uint32 _width
, _height
;
396 Driver
->getWindowSize(_width
, _height
);
397 float width
= (float)_width
, height
= (float)_height
;
398 NL3D::CViewport vp
= Driver
->getViewport();
399 width
*= vp
.getWidth();
400 height
*= vp
.getHeight();
401 float CommandsLineHeight
= CommandsFontSize
/ height
;
402 float CommandsBoxX
= ((float)(sint32
)(SBCLIENT::CommandsBoxX
* width
)) / width
;
403 float CommandsBoxWidth
= ((float)(sint32
)(SBCLIENT::CommandsBoxWidth
* width
)) / width
;
404 float CommandsBoxY
= ((float)(sint32
)(SBCLIENT::CommandsBoxY
* height
)) / height
;
405 float CommandsBoxHeight
= ((float)(sint32
)((CommandsNbLines
+ 1) * CommandsLineHeight
* width
)) / width
;
406 float CommandsBoxBorderX
= ((float)(sint32
)(SBCLIENT::CommandsBoxBorder
* width
)) / width
;
407 float CommandsBoxBorderY
= ((float)(sint32
)(SBCLIENT::CommandsBoxBorder
* height
)) / height
;
409 // Display the background
410 Driver
->setMatrixMode2D11 ();
411 #if SBCLIENT_DEV_PIXEL_PROGRAM
412 CommandsMaterial
.setColor(CRGBA::Blue
); // Test to check which shader is displaying.
414 CommandsMaterial
.setColor(CommandsBackColor
);
416 float x0
= CommandsBoxX
- CommandsBoxBorderX
;
417 float y0
= CommandsBoxY
- CommandsBoxBorderY
;
418 float x1
= CommandsBoxX
+ CommandsBoxWidth
+ CommandsBoxBorderX
;
419 float y1
= CommandsBoxY
+ CommandsBoxHeight
+ CommandsBoxBorderY
;
421 #if SBCLIENT_DEV_PIXEL_PROGRAM
422 NL3D::IDriver
*d
= dynamic_cast<NL3D::CDriverUser
*>(Driver
)->getDriver();
423 d
->activePixelProgram(a_DevPixelProgram
);
424 bool fogEnabled
= d
->fogEnabled();
427 // Driver->drawQuad(CQuad(CVector(x0, y0, 0), CVector(x1, y0, 0), CVector(x1, y1, 0), CVector(x0, y1, 0)), CommandsMaterial);
429 quadUV
.V0
= CVector(x0
, y0
, 0);
430 quadUV
.V1
= CVector(x1
, y0
, 0);
431 quadUV
.V2
= CVector(x1
, y1
, 0);
432 quadUV
.V3
= CVector(x0
, y1
, 0);
433 quadUV
.Uv0
= CUV(0, 1);
434 quadUV
.Uv1
= CUV(1, 1);
435 quadUV
.Uv2
= CUV(1, 0);
436 quadUV
.Uv3
= CUV(0, 0);
437 Driver
->drawQuad(quadUV
, CommandsMaterial
);
438 //Driver->drawBitmap(x0, y0, x1 - x0, y1 - y0, *a_NelLogo);
440 d
->enableFog(fogEnabled
);
441 d
->activePixelProgram(NULL
);
444 Driver
->drawQuad(CQuad(CVector(x0
, y0
, 0), CVector(x1
, y0
, 0), CVector(x1
, y1
, 0), CVector(x0
, y1
, 0)), CommandsMaterial
);
448 // Set the text context
449 TextContext
->setHotSpot (UTextContext::BottomLeft
);
450 TextContext
->setColor (CommandsFrontColor
);
451 TextContext
->setFontSize (CommandsFontSize
);
453 // Display the user input line
454 ucstring line
= ucstring("> ") + ucstring(CommandsListener
.line()) + ucstring("_");
455 uint32 csi
= TextContext
->textPush(line
);
456 float sw
= TextContext
->getStringInfo(csi
).StringWidth
/ width
; // make sure newly typed text is visible
457 TextContext
->printAt(sw
> CommandsBoxWidth
? CommandsBoxX
- sw
+ CommandsBoxWidth
: CommandsBoxX
, CommandsBoxY
, csi
);
458 TextContext
->erase(csi
);
460 // Display stored lines
461 float yPos
= CommandsBoxY
;
462 list
<string
>::reverse_iterator rit
= StoredLines
.rbegin();
463 for (sint32 i
= 0; i
< CommandsNbLines
; ++i
)
465 yPos
+= CommandsLineHeight
;
466 if (rit
== StoredLines
.rend()) break;
467 TextContext
->printfAt(CommandsBoxX
, yPos
, (*rit
).c_str());
472 void clearCommands ()
474 StoredLines
.clear ();
477 void releaseCommands()
479 #if SBCLIENT_DEV_PIXEL_PROGRAM
480 delete a_DevPixelProgram
;
481 a_DevPixelProgram
= NULL
;
483 // Remove the displayers
484 CommandsLog
.removeDisplayer(&CommandsDisplayer
);
486 DebugLog
->removeDisplayer(&CommandsDisplayer
);
487 InfoLog
->removeDisplayer(&CommandsDisplayer
);
488 WarningLog
->removeDisplayer(&CommandsDisplayer
);
489 AssertLog
->removeDisplayer(&CommandsDisplayer
);
490 ErrorLog
->removeDisplayer(&CommandsDisplayer
);
493 // Remove callbacks for the config file
494 ConfigFile
->setCallback("CommandsBoxX", NULL
);
495 ConfigFile
->setCallback("CommandsBoxY", NULL
);
496 ConfigFile
->setCallback("CommandsBoxWidth", NULL
);
497 ConfigFile
->setCallback("CommandsBoxBorder", NULL
);
498 ConfigFile
->setCallback("CommandsNbLines", NULL
);
499 ConfigFile
->setCallback("CommandsLineHeight", NULL
);
500 ConfigFile
->setCallback("CommandsBackColor", NULL
);
501 ConfigFile
->setCallback("CommandsFrontColor", NULL
);
502 ConfigFile
->setCallback("CommandsFontSize", NULL
);
504 // Remove the keyboard listener from the server
505 Driver
->EventServer
.removeListener(EventCharId
, &CommandsListener
);
507 // Remove the material
508 Driver
->deleteMaterial(CommandsMaterial
);
511 NLMISC_COMMAND(clear
,"clear the chat history","")
513 // check args, if there s not the right number of parameter, return bad
514 if(args
.size() != 0) return false;
519 } /* namespace SBCLIENT */