Hiding Meshes.

From TrainzOnline
Jump to: navigation, search

I have kept the roof invisible until now so that you are able to see that the train is stopping as designed. We could restore it by changing a tag in config.txt but doing that wouldn't teach you about the Property Editor or about saving object data to the session.

Trainz doesn't provide any means within the user interface to hide and display meshes but it does provide a mechanism to extend the interface by providing a Property Editor for any scripted object which needs the facility. This needs quite a lot of code and quite a lot of effort to understand but it provides powerful and extensible facilities so it will be well worth the effort.

include "Buildable.gs"

class Tutorial isclass Buildable {

   bool doorsOpen = false;
   bool roofVisible;

   public void Init(void) {
      inherited();
      SetFXCoronaTexture("corona",null);
      AddHandler(me,"Object","","ObjectHandler");
   }

   Asset GetCorona(string mesh, string effect) {
      Soup meshtable = GetAsset().GetConfigSoup().GetNamedSoup("mesh-table");
      Soup effects = meshtable.GetNamedSoup(mesh).GetNamedSoup("effects");
      KUID kuid = effects.GetNamedSoup(effect).GetNamedTagAsKUID("texture-kuid");
      return World.FindAsset(kuid);
   }

   thread void RingTheBell(void) {
      while (doorsOpen) {
         Sleep(0.35 + World.Play2DSound(GetAsset(),"bell.wav"));
      }
   }

   void ObjectHandler(Message msg) {
      Vehicle vehicle = cast<Vehicle>msg.src;
      if (!vehicle) return;
      if (msg.minor == "InnerEnter") {
         doorsOpen = true;
         SetMeshAnimationState("default", true);
         SetFXCoronaTexture("corona",GetCorona("default","corona"));
         RingTheBell();
      }
      else if (msg.minor == "InnerLeave") {
         doorsOpen = false;
         SetMeshAnimationState("default", false);
         SetFXCoronaTexture("corona",null);
      }
   }

/* SetProperties() is another method which is called by the game engine. Its purpose is to
   read the session files and to provide you with the opportunity to retrieve any data which
   has been saved there in previous runs.  The method is also called when the Property Editor
   is closed, to save any changes which have been made.  The Undo system also uses this method. 
   We are using it here to restore any value for the roof visibility which has previously been 
   saved by the game. There will be nothing there of course, when the asset is first placed */ 

   public void SetProperties(Soup soup) {
      inherited(soup);
      roofVisible = soup.GetNamedTagAsBool ("roof",true);
      SetMeshVisible("roof",roofVisible,1.0);
   }

/* GetProperties() is again called by the game engine, this time it's used to take any changes
   made by the user and to save them to the session files. */

   public Soup GetProperties(void) {
      Soup soup = inherited();
      soup.SetNamedTag("roof",roofVisible);
      return soup;
   } 

/* GetDescriptionHTML() is where you define the HTML code that will be loaded into the Property
   Editor when you press [F3] in Surveyor, select the [?] icon, and click on the Engine Shed. The
   HTML code supported is very simple. You just need to provide the basics. The local variable 
   roofStatus is used to provide text to be used by the interface to show whether the roof 
   is to be hidden or displayed. 

   <a href=live://property/roof> is a special hyperlink format used by Trainz to identify a link 
   clicked within the Property Editor. The 'roof' part, known as a propertyID, is used by other 
   related functions to identify values that the user wants to modify. */

   public string GetDescriptionHTML(void) {
      string roofStatus = "Show";
      if (roofVisible) roofStatus = "Hide";
      string html = inherited()
          + "<font size=5><br>"
          + "Roof: <a href=live://property/roof>" + roofStatus + "</a><br>"
          + "</font>";
      return html;
   }

/* The remaining methods are all standard routines called by the game to establish what needs 
   to be done in response to a user click on any of the links in the Property Editor. 

   GetPropertyType() establishes whether the property, "roof" in our case, is to be treated as
   a number, as a string value or is to be selected from a list.  Roof represents the simplest
   property type, where merely clicking on the link is enough information for the game to do what 
   needs to be done. We indicate this to Trainz by returning the string "link". */

   public string GetPropertyType(string pID) {
      string result = inherited(pID);
      if (pID == "roof") result = "link";
      return result;
   }

/* LinkPropertyValue() is where we tell the game what is to be done when properties which have been
   defined as "link" are pressed. In our case we take the boolean value roofVisible and make it the 
   opposite of itself, toggling its value. (The symbol ! means not). Having done this we can use 
   the new value of roofVisible as a parameter to SetMesh() which hides or shows the submesh.  The 
   final parameter of SetMeshVisible() specifies the time to fade the mesh in or out. */ 

   public void LinkPropertyValue(string pID) {
      if (pID == "roof") {
         roofVisible = !roofVisible;
         SetMeshVisible("roof",roofVisible,1.0);
      }
      else inherited(pID);
   }

};

The main thing to notice about these standard methods is the use of the keyword inherited(). Each of the class definitions used in TrainzScript inherits properties from its parent. Buildable, which we are using here, descends from SceneryWithTrack, which descends from MapObject, which descends from MeshObject and so on. inherited(), in its various forms, ensures that anything which the ancestors of the current class have to say about the operation in progress is taken into account.

When the game calls GetDescriptionHTML() the call is first referred to our object's immediate parent. The referral is chained up throughout the hierarchy. At each stage the ancestor object is allowed to add HTML code to be presented in the Property Editor. None of the ancestors actually add anything at present, but they might do in the future. If you miss out the calls to inherited() you might well miss out on any future advice from your grandparents.

Save the script file and commit the asset. You should now have access to a link in the Property Editor enabling you to hide or show the roof mesh. If you show the mesh and save the session, the roof should still be visible when you reload. This is thanks to GetProperties() and SetProperties(). Be aware that properties are not saved to the map, only to the session files. If you load the map without a session you will only ever see the asset's initial defaults.

Next Tutorial: Handling Name Effects.

Back to Getting Started

Personal tools