VGUI HTML Screen

From Valve Developer Community
Jump to: navigation, search

This is a tutorial on adding a HTML screen that can be shown during gameplay, and have it's address changed by in-game commands. I use it for adding backstory to my maps, perhaps it will be useful for others too.

Mod Note: This modification is for the Episode 1 engine, and will not work on the Orange Box at this time.

HTML Note: This modification creates a HTML control that has JavaScript disabled for security reasons.

Acknowledgements

All credit for the inital creation of the panel goes to the wiki at VGUI2: Creating a panel!

Change Log

Tuesday, January 23, 2007

  • A critical update has been released!
  • This critical update fixes the scrollbars which stopped working when the Monday update went in

Monday, January 22, 2007

  • Daedalus has updated the code to allow you to trigger entities in your map
If the given url starts with 'entity://', it will trigger an entity action.
 Example: 'entity://relay_open_door->trigger'
 You may also add a url to go to after the entity action has been fired by placing a ; at the end, and then your url. Eg:
   'entity://relay_open_door->trigger;html/sample2.html'
   'entity://relay_close_door->trigger;:www.google.com'
  • The sample map has been updated to display an example of this entity interaction.

Updating your code

  • You will need the modified IHTMLView.h, HTMLView.cpp and to follow the tutorial on adding the EntHTML object (below.)

Requirements

  • Visual Studio .Net 2003/2005
  • Source SDK

Getting Started

For this example, we'll be creating our own mod (you can later make changes to your own mod if you desire.) Please note that this will not work for unedited HL2/HL2:MP, CS:Source, etc. It requires changes to some core files.

We hope to end up with something that can display this:

Vgui htmlview.jpeg

Create your mod

Before we begin, we need to ensure we have the latest Source SDK source files. On the Source SDK screen, double click Refresh SDK Content. This ensures we don't have out of date source code.

Now double click click Create A Mod.

For this example, we'll be using HL2 single player, so select Modify Half-Life 2 Single Player and click Next.

I always like to put my mods in the SourceMods folder, but choose yourself where you'd like to put your mod, then enter a name for it, eg HTMLTest and click Next.

Source will now copy all the files over and prepare your mod.

Double checking

Now we need to be sure that everything works before we start messing with the code. If you've done this all before, you may skip this step.

Now, go to your mod folder, then go into your src folder. There are a few different Visual Studio .Net solution files. We want the one named Game_HL2. However, there are two different versions. Try to open the 2005 version first, and if that isn't recognized, use the 2003 version.

Compiling

At the top of the screen inside Visual Studio.Net should be a 'Solution Configuration' option, which by default reads Debug HL2. We want to change that to Release HL2 before proceeding.

Next, click the Build menu and then click Build Solution and grab yourself a coffee.

Testing

If all goes well, you should be able to run the 'run_mod.bat' file in your mod directory and have it load up HL2. You can't do much at this point except look around the menus.

If something went wrong...Post in the discussion or email me and I'll see how I can help.

Adding the HTMLView

Now we get to the code changes.

In Visual Studio, there should be a file tree (it may just show client_hl2 and server_hl2 currently.)

Click the + next to client_hl2 to expand it.

Adding the header files

We need to add our header file now. Just create one in the header folder of the project and paste my code in. Right click Header Files and click Add->Add New Item.

IHTMLView.h

This should go into the src\cl_dlls folder.

View source code

That wasn't too hard now, was it?

EntHTML.h

Same as above. Add a file named EntHTML.h to the header folder and paste the code in.

This should go into the src\public\vgui_controls folder.

View source code

Adding the source file

Now we add the source code for our HTML View.

HTMLView.cpp

Place this file into the Source files folder of the project.

The file should be placed in the src\cl_dlls folder.

View source code

Update your vgui_controls.lib

Now we need to update our vgui_controls.lib file.

Open up your Everything_SDK-200x solution file.

We need to create a new HTML control.

Header file

Copy the EntHTML.h file to your src\public folder.

Source file

Copy the EntHTML.cpp file to your src\vgui2\controls folder, and add it to your vgui_controls project:

  • Open the vgui_controls project
  • Right click Source Files and click
  • Add -> Existing Item (if you have already placed the EntHTML.cpp file in your src\vgui2\controls folder)
  • Add -> New Item (if you have not yet placed EntHTML.cpp into your src\vgui2\controls folder)
  • Remember to save your file to your src\vgui2\controls folder!
  • Right click the vgui_controls project and select Build Solution
  • After it all compiles successfully, return to your Game_HL2-200x project for the rest of this tutorial.

Other required code modifications

There are changes that we need to make to one of the core game files. Don't worry, we don't change much.

vgui_int.cpp

Find this file in the Source Files tree somewhere near the bottom and open it up.

At the top of the file are a bunch of #include statements. Under the last one (but before the line using namespace vgui), add this:

#include "IHTMLView.h"

This lets the game access our HTMLView.

Next, find the line void VGui_CreateGlobalPanels( void ), somewhere around line 154. There should be two statements beginning with VPANEL. Directly underneath these, add:

VPANEL gameParent	  = enginevgui->GetPanel( PANEL_INGAMESCREENS );
htmlview->Create(gameParent);

Next, find the line void VGui_Shutdown() which should be the function directory below the one you just edited. Somewhere in this function, after the { and before the } you need to add:

htmlview->Destroy();

Good news! We're almost done!

The User Interface

Now we need to add the UI file that the game loads for our HTML view.

HTMLView.res

Save this file to yourmod\resource\ui\HTMLView.res.

View source file

Optional step: Add HTMLView to main menu

This step isn't required, but may be helpful in quickly checking if things worked. Open up your yourmod\resource\GameMenu.res file, and add the following before the final }.

       "5"
	{
		"label" "HTMLView"
		"command" "engine ToggleHTMLView"
		"notmulti" "1"
	}

Finishing up

Ok, so all the code has been added, the resource file created, and the other source edited. Hit Build Solution again and wait for it to compile. If there are any problems, please post in the Discussion section of this page and I'll try to help out.

In-Game operation

So now, load up your mod. If you edited your GameMenu.res file, there should be a new menu item at the end simply titled 'HTMLView'. A big screen showing a black box and an 'Exit' button should appear when you click this.

Alternatively, use the console command ToggleHTMLView.

So far, all you've seen is a black box and a button. In the console, type one of the following:

cl_htmltarget :www.google.com
cl_htmltarget somefile/inyourmod/directory/example.txt
cl_htmltarget scripts/credits.txt

Note that the : tells the HTMLView that it is an external URL (since you can't use speech marks in Hammer.)

As of January 22, 2007, the following may also be used inside of html files (not in the console.)

  <a href="entity://entity_name->entity_action;new/page/to_go_to.html">Activate entity and move to new page</a>
  <a href="entity://relay_open_door->trigger">Open door</a>

Note: The entity interaction can only be done inside a html file, due to the limitations / complexities of the console.

And then either press the menu item or type ToggleHTMLView again and you should see google :)


Note that you can load up text or HTML files located in your mod directory. In my mod, I have created a HTML folder, and then created subfolders which contain backstory relevant to each map. I have a Point_servercommand entity that I tell to run cl_htmltarget html/ship/intro.txt and another command that runs ToggleHTMLView to display the HTML View.

For a detailed example, check the example map.

Sample Level

Want an example of how to implement this into your levels?

Download the example Hammer file and compiled .bsp file.

How does it work?

The example level consists of the following main entities:

The relays send commands to the Point_servercommand entity (which I call cmd) to update the HTML target (cl_htmltarget wherever.com) and to display the HTML view (ToggleHTMLView).

I typically create a base scenario, and then copy and paste that around the level (with unique names on.)

Base Scenario

What follows is a step by step guide on my base scenario for using my screen.

  • Place a new Point_servercommand entity in the world and name it cmd. This should be away from the rest of the entities you will place in this tutorial.
  • Place a Prop_static entity in the world and select an interesting model (eg, the clipboard: models/props_lab/clipboard.mdl)
  • Place a box (using the Invisible texture) over the area you want the 'use' area to be (typically, cover the front of the object). Tie this to entity Func_button and add the following output:
My output named: OnTrigger
Target entities named: relay_showhtml
Via this input: Trigger
  • Place a Logic_relay next to this, and name it relay_showhtml. On the Outputs tab, add the following outputs:
My output named: OnTrigger
Target entities named: cmd
Via this input: Command
With parameter override of: cl_htmltarget :www.google.com
My output named: OnTrigger
Target entities named: relay_show_view
Via this input: Trigger
My output named: OnTrigger
Target entities named: cmd
Via this input: Command
With parameter override of: ToggleHTMLView

At this point in time, you can go up and 'use' the object. However, the user would probably not know this. My solution to this is to make the object 'glow' when you approach it. This requires a Trigger_proximity and a Light_spot entity.

  • Create a Light_spot entity, and face it towards your object. Name it spot_objectglow and set it to 'Initially dark'. I also set the Inner (bright) angle to 10, and the Outer (fading) angle to 15, for small items and 13 and 18 respectively for larger items. Experiment a little.
  • Create a box that spans the area that player walks into to make the object glow, and texture it with the Trigger texture. Tie this to entity Trigger_proximity and add the following outputs:
My output named: OnStartTouch
Target entities named: spot_objectglow
Via this input: TurnOn
My output named: OnEndTouch
Target entities named: spot_objectglow
Via this input: TurnOff

And there you go!

Once you have these, I typically select all the objects we just inserted (except the Point_servercommand and Logic_relay named relay_show_view) and hit Copy, then Paste Special and ensure Make pasted entity names unique is ticked. Then it's simply a matter of changing the Logic_relay's output of cl_htmltarget :www.google.com to something else.

Check the example map for 3 examples!

Copyright Information

This code was largely created by modifying the code from the VGUI2: Creating a panel tutorial, so first and foremost follow the copyright for that. However, they don't specify a copyright, so I will.

I hereby release this code as Public Domain. You are free to use my code for whatever you like; you may base your code off mine; you may make as many changes to the code as you wish, all without my permission. Heck, remove the Author and such other info from the source file. No credit needs to be given if you use my code.

I would like it if someone who uses this code expresses gratitude, or at least a 'nice one!' comment in the discussion page though :) I'd like to think I helped someone.