Class PropertyObject

From TrainzOnline
(Difference between revisions)
Jump to: navigation, search
m (1 revision)
m (GetDescriptionHTML: Added link to MiniBrowser with the list of supported HTML elements)
 
(25 intermediate revisions by 4 users not shown)
Line 1: Line 1:
*[[TrainzScript Langage Reference|API Hierarchy]]
+
*[[TrainzScript Library Reference|API Hierarchy]]
 
**PropertyObject
 
**PropertyObject
 
<br>
 
<br>
Line 5: Line 5:
 
This class provides an interface that allows an object to implement properties that can be saved or loaded to a session and edited by the user through a browser window in Surveyor. To enable this for an asset, it must inherit from PropertyObject (or from a derived child class such as [[Class ScenarioBehavior|ScenarioBehavior]] or [[Class MeshObject|MeshObject]]).  
 
This class provides an interface that allows an object to implement properties that can be saved or loaded to a session and edited by the user through a browser window in Surveyor. To enable this for an asset, it must inherit from PropertyObject (or from a derived child class such as [[Class ScenarioBehavior|ScenarioBehavior]] or [[Class MeshObject|MeshObject]]).  
  
PropertyObject operates by way of a series of predefined callback methods which are designed to be overridden by the script writer to allow Trainz to access an object's properties.  
+
PropertyObject operates by way of a series of predefined callback methods which are designed to be overridden by the script writer to allow Trainz to access an object's properties. Properties are referred to in the class methods by their propertyID. Trainz determines this by reference to links in the object browser in the form ''live://property/propertyID''.
  
Properties are referred to in the class methods by their propertyID. Trainz determines this by reference to links in the object browser in the form ''live://property/propertyID''.
+
When Trainz is saving a session, it asks each object to save its respective state into a [[Class Soup|Soup]] database. Trainz doesn't know what your object needs to save, but it does know that it can request an object's state via callbacks. Trainz relies on the script programmer to give careful thought to what data is needed to save and restore an objects state.  
  
When Trainz is saving a session, it asks each object to save its respective state into a [[Class Soup|Soup]] database. Trainz doesn't know what your object needs to save, but it does know that it can request an object's state via callbacks.  Trainz relies on the script programmer to give careful thought to how the asset is constructed.
+
Depending on circumstances, not all callback methods have to be implemented. For example, you don't need to override [[#GetPropertyElementList|GetPropertyElementList()]] if there are no list-selection properties.  
 
+
Depending on circumstances, not all callback methods have to be implemented. For example, you don't need to override [[#GetPropertyElementList|GetPropertyElementList()]] if there are no list-selection properties.  
+
  
 
==Callback Sequences==
 
==Callback Sequences==
 
The precise sequence of callback method calls will vary with the content of the browser and the user's input but the following gives a general idea:
 
The precise sequence of callback method calls will vary with the content of the browser and the user's input but the following gives a general idea:
*When the Property Browser is opened TRS calls:
+
*When the Property Browser is opened Trainz calls:
 
** [[#GetProperties|GetProperties()]] to read the current session data.
 
** [[#GetProperties|GetProperties()]] to read the current session data.
** [[#GetDescriptionHTML|GetDescriptionHTML()]] to read the HTML code for the browser window.
+
** [[#GetDescriptionHTML|GetDescriptionHTML()]] to read the HTML code for the browser configuration window.
 
*When the user clicks on a URL, the propertyID is extracted from the link and these calls are made:
 
*When the user clicks on a URL, the propertyID is extracted from the link and these calls are made:
** [[#GetPropertyType|GetPropertyType()]] to establish what type of property is to be edited.
+
** [[#GetPropertyType|GetPropertyType()]] to establish the 'type' of the property is to be edited.
**for "link" properties:
+
**For "link" properties Trainz will call:
*** [[#LinkPropertyValue|LinkPropertyValue()]] which should contain all the instructions necessary to complete the task.
+
*** [[#LinkPropertyValue|LinkPropertyValue()]], which should respond and set the desired value
**for "string", "int" and "float" properties:
+
**For "string", "int" and "float" properties:
*** [[#GetPropertyValue|GetPropertyValue()]] to establish the property's current contents.
+
*** [[#GetPropertyValue|GetPropertyValue()]] to establish the property's current value.
*** [[#GetPropertyDescription|GetPropertyDescription()]] to obtain a caption.
+
*** [[#GetPropertyName|GetPropertyName()]] and/or [[#GetPropertyDescription|GetPropertyDescription()]] to obtain display info for the UI.
*** TRS then provides a pop-up edit box with the caption and current value filled in and waits for the user to edit the property.
+
*** Trainz then provides a pop-up edit box with a caption and current value filled in and waits for the user to edit the property, if desired.
**for "list" properties:
+
**For "list" properties:
*** [[#GetPropertyDescription|GetPropertyDescription()]] to obtain a caption.
+
*** [[#GetPropertyName|GetPropertyName()]] and/or [[#GetPropertyDescription|GetPropertyDescription()]] to obtain display info for the UI.
*** [[#GetPropertyElementList|GetPropertyElementList()]] to obtain the contents of the list
+
*** [[#GetPropertyElementList|GetPropertyElementList()]] to obtain the list options to display to the player.
*** TRS then provides a pop-up edit box with the caption and the list of options completed and waits for the user to edit the property.
+
*** Trainz then provides a pop-up edit box with a caption and the list of options and waits for the user to edit the property, if desired.
 +
**For "map-object" and "asset-list" properties:
 +
*** [[#GetPropertyName|GetPropertyName()]] and/or [[#GetPropertyDescription|GetPropertyDescription()]] to obtain display info for the UI.
 +
*** Trainz displays a filterable list dialog to the player, showing a spinner while the search runs.
 +
*** When a search completes, Trainz calls [[#FilterPropertyElementList|FilterPropertyElementList()]], to allow the script to add/remove any custom entries.
 
*Once the user has carried out any edits:
 
*Once the user has carried out any edits:
 
** The appropriate variant of [[#SetPropertyValue|SetPropertyValue()]] is called to update the value of the property.
 
** The appropriate variant of [[#SetPropertyValue|SetPropertyValue()]] is called to update the value of the property.
** [[#GetDescriptionHTML|GetDescriptionHTML()]] is called again to refresh the contents of the Browser window, updating any variables that the script writer might have set.
+
** [[#GetDescriptionHTML|GetDescriptionHTML()]] is called again to refresh the contents of the Browser window for any new configuration.
 
*When all edits are complete:
 
*When all edits are complete:
**If the user confirms the changes by using the green tick to close the dialogue:
+
**If the user confirms their changes and closes the dialog:
 
*** [[#SetProperties|SetProperties()]] is called with the modified Soup to update the session database.
 
*** [[#SetProperties|SetProperties()]] is called with the modified Soup to update the session database.
**If the user cancels the changes by using the red cross to close the dialogue:
+
**If the user cancels the changes:
*** [[#SetProperties|SetProperties()]] is called with the original unaltered Soup to restore the database to the state that was current before the last editor session.
+
*** [[#SetProperties|SetProperties()]] is called with the original unaltered Soup to restore the script to it's original pre-edit state.
 
<br>
 
<br>
  
Throughout the above sequences TRS is only concerned with the loading and saving of properties.
+
Throughout the above sequences Trainz is only concerned with the loading and saving of properties. Wherever a change in a property requires an update to the appearance of the object or to the contents of its variables it is the responsibility of the script writer to implement these changes at the appropriate time. In general changes should be implemented in [[#SetProperties|SetProperties()]] since this will help to ensure that changes can be reversed if they are cancelled or when the game's ''UNDO'' command is invoked.
* Wherever a change in a property requires an update to the appearance of the object or to the contents of its variables it is the responsibility of the script writer to implement these changes at the appropriate time.
+
 
* In general changes should be implemented in [[#SetProperties|SetProperties()]] since this will help to ensure that changes can be reversed if they are cancelled or when the game's ''UNDO'' command is invoked.
+
 
<br>
+
==Save/Load==
 +
Scripted objects do not have their state automatically saved and restored. It is the responsibility of the individual scripts to save and restored any necessary state across a Surveyor save session/load session, or across a Driver save game/load game. This is implemented using the PropertyObject [[#GetProperties|GetProperties()]] and [[#SetProperties|SetProperties()]] functions. When saving, Trainz will ensure that GetProperties() has been called for every PropertyObject that is being saved. The [[Soup]] returned by this function is stored along with any native state for the object in question. When reloading, Trainz will first create the object and load the native state, then will call the SetProperties() function with the saved Soup which instructs the script to restore its state.
 +
 
  
 
==GetDescriptionHTML==
 
==GetDescriptionHTML==
 
{{MethodHeader|public string GetDescriptionHTML(void)}}
 
{{MethodHeader|public string GetDescriptionHTML(void)}}
 
;Parameters
 
;Parameters
*None
+
''None''
;Returned Value;
+
 
*HTML formatted string to be loaded into the Property Browser.
+
;Return Value;
;Syntax
+
HTML formatted string to be loaded into the Property Browser.
*This is a callback method which should be overridden to suit the calling asset.
+
 
;Implementation
+
;Example Implementation
  public string GetDescriptionHTML(void) {
+
  public string GetDescriptionHTML(void)
    return inherited()
+
{
    + <nowiki>"<font size=5><br>"</nowiki>
+
  StringTable strTable = GetAsset().GetStringTable();
    + <nowiki>"Forename: <a href=live://property/forename>" + foreName + "</a><br>"</nowiki>
+
 
    + <nowiki>"Surname: <a href=live://property/surname>" + surName + "</a><br>"</nowiki>
+
  HTMLBuffer buffer = HTMLBufferStatic.Construct();
    + <nowiki>"</font>";</nowiki>
+
  buffer.Print("<html><body>");
    return html;
+
 
 +
  buffer.Escape(strTable.GetString("property_name_forename"));
 +
  buffer.Print(": <a href=live://property/forename>");
 +
  buffer.Escape(m_foreName);
 +
  <nowiki>buffer.Print("</a><br>");</nowiki>
 +
  buffer.Escape(strTable.GetString("property_name_surname"));
 +
  buffer.Print(": <a href=live://property/forename>");
 +
  buffer.Escape(m_surName);
 +
  <nowiki>buffer.Print("</a><br>");</nowiki>
 +
  buffer.Print("</body></html>");
 +
 
 +
  return buffer.AsString();
 
  }
 
  }
 +
 
;Description
 
;Description
*This method is called by Trainz from Surveyor to retrieve the properties of the object as HTML code for display in a Browser window.
+
This method is called by Trainz to retrieve HTML which a player can use to configure the objects properties. Any embedded properties should use the ''live://property/propertyID'' format, all player readable strings should be sourced from the asset string-table, and all player configurable values should be appropriately escaped to avoid HTML corruption.
*Refer to the [[MiniBrowser]] page for details of supported HTML tags.
+
*Link URLs should be included in the form ''live://property/propertyID'', where propertyID is the name of the property.
+
*When the user clicks on a link Trainz will use the appropriate callback methods to establish the action that needs to be taken to enable the property to be edited.
+
*To allow for translation, text should be extracted from the asset's [[Class StringTable|StringTable]] rather than being included in code as a literal string. This allows translated string table data to be substituted in foreign language installations if it is available.
+
 
<br>
 
<br>
 +
The Trainz uses its Mini Browser to display the HTML. See the [[MiniBrowser]] page to find supported HTML elements.
  
 
==GetProperties==
 
==GetProperties==
 
{{MethodHeader|public Soup GetProperties(void)}}
 
{{MethodHeader|public Soup GetProperties(void)}}
 
;Parameters
 
;Parameters
*None
+
''None''
;Returned Value
+
*Soup object containing session file data assigned to the current object.
+
;Syntax
+
*This is a callback method which should be overridden to suit the calling asset.
+
;Implementation
+
public Soup GetProperties(void) {
+
    Soup soup = inherited();
+
    soup.SetNamedTag("forename",foreName);
+
    soup.SetNamedTag("surname",surName);
+
}
+
;Description
+
*This method is used to save current properties into the session database.
+
*Care must be taken to ensure it writes data in the same tag format that [[#SetProperties|SetProperties()]] is expecting.
+
*When overriding this method to handle your own properties, always call through to the overridden parent by using inherited().
+
<br>
+
  
==GetPropertyDescription==
+
;Return Value
{{MethodHeader|string GetPropertyDescription(string propertyID)}}
+
Soup object containing data appropriate to represent the configured state of the object.
;Parameters
+
*'''propertyID''' = Name of property.
+
;Returned Value
+
*Description to be used as a caption for the edit box presented to the user, allowing the current property to be edited.
+
;Syntax
+
*This is a callback method which should be overridden to suit the calling asset.
+
;Implementation
+
string GetPropertyDescription(string propertyID) {
+
    string result = inherited(propertyID);
+
    if (propertyID == "forename") result = "Enter Forename";
+
    else if (propertyID == "surname") result = "Enter Surname";
+
    return result;
+
}
+
<br>
+
  
==GetPropertyElementList==
+
;Example Implementation
{{MethodHeader|public string[ ] GetPropertyElementList(string propertyID)}}
+
  public Soup GetProperties(void)
;Parameters
+
{
*'''propertyID''' = Name of property.
+
  Soup soup = inherited();
;Returned Value
+
  soup.SetNamedTag("forename", m_foreName);
*String array to be presented to the user for a new selection to be made.
+
  soup.SetNamedTag("surname", m_surName);
;Syntax
+
  return soup;
*This is a callback method which should be overridden to suit the calling asset.
+
;Implementation
+
  public string[] GetPropertyElementList(string propertyID) {
+
    string[] result = inherited(propertyID);
+
    if (propertyID == "junctions") {
+
      Junction[] junctions = World.GetJunctionList();
+
      int n;
+
      for (n = 1; n < junctions.size(); n++) {
+
          result[result.size()] = junctions[n].GetName();
+
      }
+
    }
+
    return result;
+
 
  }
 
  }
;Description
 
*Retrieves a list of elements the user can select from for the named property.
 
*If a property is of type "list", as returned by [[#GetPropertyType|GetPropertyType()]], Trainz will display these items in a pop-up window for user selection.
 
*The script programmer is free to fill the returned elements array from the current game environment and can create this dynamically if necessary (eg a list of industries in the current route).
 
<br>
 
  
==GetPropertyHandler==
 
{{MethodHeader|public HTMLPropertyHandler GetPropertyHandler(void)}}
 
;Parameters
 
*None
 
;Returned Value
 
*A reference to the current Property Handler for this object, or null if none has been set.
 
 
;Description
 
;Description
*A PropertyObject can be overridden by assigning an HTMLPropertyHandler which allows more sophisticated processing. 
+
This method is used to save current properties into the session database. Care must be taken to ensure it writes data in the same tag format that [[#SetProperties|SetProperties()]] is expecting. When overriding this method to handle your own properties, always call through to the overridden parent by using inherited().
*This method returns a reference to such an object if it has been assigned.
+
*If this method returns null then no HTMLPropertyHandler is assigned and the default PropertyObject methods described on this page will apply.
+
 
<br>
 
<br>
  
==GetPropertyName==
+
==SetProperties==
{{MethodHeader|string GetPropertyName(string propertyID)}}
+
{{MethodHeader|public void SetProperties(Soup soup)}}
 
;Parameters
 
;Parameters
*'''propertyID''' = Name of property.
+
*'''soup''' = reference to ''soup'' to be saved to session.
 +
 
 
;Returned Value
 
;Returned Value
*The name of the current property.
+
None
;Syntax
+
 
*This is a callback method which should be overridden to suit the calling asset.
+
;Example Implementation
;Implementation
+
  public void SetProperties(Soup soup)
  string GetPropertyName(string propertyID) {
+
{
    string result = inherited(propertyID);
+
  inherited(soup);
    if (propertyID == "forename") result = "Forename";
+
  m_foreName = soup.GetNamedTag("forename");
    else if (propertyID == "surname") result = "Surname";
+
  m_surName = soup.GetNamedTag("surname");
    return result;
+
 
  }
 
  }
<br>
+
 
 +
;Description
 +
Restores object state with a Soup object returned from a previous call to GetProperties(). When overriding this method to handle your own properties, always call through to the overridden parent by using inherited(soup). This ensures that any data required by the parent class is appropriately set.
 +
<br>  
  
 
==GetPropertyType==
 
==GetPropertyType==
Line 166: Line 128:
 
;Parameters
 
;Parameters
 
*'''propertyID''' = Name of property.
 
*'''propertyID''' = Name of property.
;Returned Value
+
 
*The type of the current property.
+
;Return Value
;Syntax
+
The type of the current property.
*This is a callback method which should be overridden to suit the calling asset.
+
 
;Implementation
+
;Example Implementation
  string GetPropertyType(string propertyID) {
+
  string GetPropertyType(string propertyID)
    string result = inherited(propertyID);
+
{
    if (propertyID == "forename" or propertyID == "surname") result = "string";
+
  if (propertyID == "forename" or propertyID == "surname")
    return result;
+
    return "string";
 +
 
 +
  return inherited(propertyID);
 
  }
 
  }
;Description
 
*This method is used by Trainz to determine the type of the named property.
 
*The type of a property is defined using a string describing what type of data the property holds as well as extra information about the range, size and incremental count.
 
*The minimum and maximum range of the value and incremental steps are optional parameters.
 
*Lists may be sorted or unsorted.
 
*Property types supported are as set out below:
 
  
 +
;Description
 +
This method is used by Trainz to determine the type of the named property. The supported types and their parameters are listed in the table below.
 
{{TableHeader|width=50%|margin=15px}}
 
{{TableHeader|width=50%|margin=15px}}
|"string"||a string value
+
|Value type||Parameters||Description
 
|-
 
|-
|"string,5,25"||a string value between 5 and 25 characters in length
+
|string||minimum-length,maximum-length||A string value, with optional minimum and maximum lengths. e.g. "string,0,200".
 
|-
 
|-
|"int"||an integer value
+
|int||minimum-value,maximum-value,step-value||An integer value with optional minimum, maximum and 'step' value. e.g. "int,0,100,5".
 
|-
 
|-
|"int,0,100,5"||an integer betwen 0 and 100 with incremental steps of 5
+
|float||minimum-value,maximum-value,step-value||An floating point value with optional minimum, maximum and 'step' value. e.g. "float,0,10,0.5".
 
|-
 
|-
|"float"||a floating point value
+
|list||sorted-bool||An list, with an optional sorting flag (default off). e.g. "list,1" to sort, "list,0" for unsorted.
 
|-
 
|-
|"float,0,10,0.5"||a float beween 0 and 10 in 0.5 steps
+
|map-object||category-list||A list of map objects in the route which match a specific non-optional category list. e.g. "map-object,IND" for an industry list.
 
|-
 
|-
|"list"||an unsorted list
+
|asset-list||category-list||A list of locally installed, compatible and available assets which match a specific non-optional category list. e.g. "asset-list,DR" for a list of installed Driver Character assets.
 
|-
 
|-
|"list,1"||a sorted list
+
|link||||A link type. This would usually respond and set some specific value, or perhaps toggle a bool.
|-
+
|"link"||no additional information required
+
 
|}
 
|}
<br>
+
 
 +
==GetPropertyName==
 +
{{MethodHeader|string GetPropertyName(string propertyID)}}
 +
;Parameters
 +
*'''propertyID''' = Name of property.
 +
 
 +
;Return Value
 +
The name of the current property.
 +
 
 +
;Example Implementation
 +
string GetPropertyName(string propertyID)
 +
{
 +
  if (propertyID == "forename")
 +
    return GetAsset().GetStringTable().GetString("property_name_forename");
 +
  if (propertyID == "surname")
 +
    return GetAsset().GetStringTable().GetString("property_name_surname");
 +
 
 +
  return inherited(propertyID);
 +
}
 +
 
 +
==GetPropertyDescription==
 +
{{MethodHeader|string GetPropertyDescription(string propertyID)}}
 +
;Parameters
 +
*'''propertyID''' = Name of property.
 +
 
 +
;Return Value
 +
Description to be used as a caption for the edit box presented to the user for a specific property.
 +
 
 +
;Example Implementation
 +
string GetPropertyDescription(string propertyID)
 +
{
 +
  if (propertyID == "forename")
 +
    return GetAsset().GetStringTable().GetString("property_description_forename");
 +
  if (propertyID == "surname")
 +
    return GetAsset().GetStringTable().GetString("property_description_surname");
 +
 
 +
  return inherited(propertyID);
 +
}
  
 
==GetPropertyValue==
 
==GetPropertyValue==
Line 208: Line 203:
 
;Parameters
 
;Parameters
 
*'''propertyID''' = Name of property.
 
*'''propertyID''' = Name of property.
 +
 
;Returned Value
 
;Returned Value
*A string representation of the value of the current property.
+
A string representation of the value of the current property.
;Syntax
+
 
*This is a callback method which should be overridden to suit the calling asset.
+
;Example Implementation
;Implementation
+
  public string GetPropertyValue(string propertyID)
  public string GetPropertyValue(string propertyID) {
+
{
    string result = inherited(propertyID);
+
  if (propertyID == "forename")
    if (propertyID == "forename") result = foreName;
+
    return m_foreName;
    else if (propertyID == "surname") result = surName;
+
  if (propertyID == "surname")
    return result;
+
    return m_foreName;
 +
 
 +
  return inherited(propertyID);
 
  }
 
  }
 +
 
;Description
 
;Description
*Returns a string representation of the current value of the selected property.
+
Returns a string representation of the current value of the selected property, if possible. Where it is not possible to format a value into a string (such as with map-object and asset-list types) then any cached localised name may be returned, and native will attempt to find that object in any displayed list, etc.
 
<br>
 
<br>
  
Line 227: Line 226:
 
;Parameters
 
;Parameters
 
*'''propertyID''' = Name of property.
 
*'''propertyID''' = Name of property.
 +
 
;Returned Value
 
;Returned Value
*None
+
''None''
;Syntax
+
 
*This is a callback method which should be overridden to suit the calling asset.
+
;Example Implementation
;Implementation
+
  void LinkPropertyValue(string propertyID)
  void LinkPropertyValue(string propertyID) {
+
{
    string result = inherited(propertyID);
+
  if (propertyID == "doors")
    if (propertyID == "doors") {
+
  {
      doorsOpen = !doorsOpen;
+
    m_doorsOpen = !m_doorsOpen;
      SetMeshAnimationState("doors",doorsOpen);
+
    SetMeshAnimationState("doors", m_doorsOpen);
    }
+
    return;
 +
  }
 +
 
 +
  inherited(propertyID);
 
  }
 
  }
 +
 
;Description
 
;Description
*Trainz calls this method when the user has clicked on a property URL which is defined as a "link"
+
Called when the player clicks on a "link" property type. Link properties are most frequently used to toggle boolean values and selecting "radio" buttons.
*No further information will be available to the game.
+
*Link properties are most frequently used to toggle boolean values.
+
 
<br>
 
<br>
  
==PropertyBrowserRefresh==
+
==GetPropertyElementList==
{{MethodHeader|public void PropertyBrowserRefresh(Browser browser)}}
+
{{MethodHeader|public string[ ] GetPropertyElementList(string propertyID)}}
 
;Parameters
 
;Parameters
*'''browser''' = Reference to ''browser'' object displaying properties.
+
*'''propertyID''' = Name of property.
 +
 
 
;Returned Value
 
;Returned Value
*None
+
A string array to for the player to select a value from.
;Syntax
+
 
* This is a callback method which should be overridden to suit the calling asset.  
+
;Example Implementation
;Implementation  
+
  public string[] GetPropertyElementList(string propertyID)
  public void PropertyBrowserRefresh(Browser browser) {
+
{
    inherited(browser);
+
  if (propertyID == "mode")
    refreshed++;
+
  {
    Interface.Print("Browser has been refreshed " + refreshed + " times");
+
    StringTable strTable = GetAsset().GetStringTable();
 +
   
 +
    string[] result = new string[10];
 +
    int i;
 +
    for (i = 1; i < 10; ++i)
 +
      result[i] = strTable.GetString("property_list_mode_" + i);
 +
   
 +
    return result;
 +
  }
 +
 
 +
  return inherited(propertyID);
 
  }
 
  }
 +
 
;Description
 
;Description
*A callback method which the script writer can override to specify tasks to be carried out whenever the Browser is refreshed.
+
Retrieves a list possible values for a named property. Used for the "list" type. The returned list should support localisation by using string-table entries where appropriate.
 
<br>
 
<br>
  
==SetProperties==
+
==FilterPropertyElementList==
{{MethodHeader|public void SetProperties(Soup soup)}}
+
{{MethodHeader|public bool FilterPropertyElementList(string propertyID, GSObject[] listObjects, string[] listNames)}}
 
;Parameters
 
;Parameters
*'''soup''' = reference to ''soup'' to be saved to session.
+
*'''propertyID''' = Name of property.
 +
*'''listObjects''' = The list of objects about to be displayed.
 +
*'''listNames''' = The names of the objects about to be displayed.
 +
 
 
;Returned Value
 
;Returned Value
*None
+
Whether the filter function has altered the list at all.
;Syntax
+
 
*This is a callback method which should be overridden to suit the calling asset.
+
;Example Implementation
;Implementation
+
  public bool FilterPropertyElementList(string propertyID, GSObject[] listObjects, string[] listNames)
  public void SetProperties(Soup soup) {
+
{
    inherited(soup);
+
  if (propertyID == "object-list")
    foreName = soup.GetNamedTag("forename");
+
  {
    surName = soup.GetNamedTag("surname");
+
    bool bDidChangeAnything = false;
 +
    // Remove any already added objects from the list
 +
    int i;
 +
    for (i = 0; i < listObjects.size(); )
 +
    {
 +
      if (IsAlreadyInList(cast<GameObject>(listObjects[i])))
 +
      {
 +
        listObjects[i,i+1] = null;
 +
        listNames[i,i+1] = null;
 +
        bDidChangeAnything  = true;
 +
      }
 +
      else
 +
      {
 +
        ++i;
 +
      }
 +
    }
 +
   
 +
    return bDidChangeAnything;
 +
  }
 +
 
 +
  return inherited(propertyID, listObjects, listNames);
 
  }
 
  }
;Description
 
*Instructs the current object to initialise its properties from data held in the session files.
 
*The data is passed to the method via the ''soup'' parameter.
 
*If the database is empty, as it will be when an object is first placed, then the object should initialise itself with sensible defaults.
 
*When overriding this method to handle your own properties, always call through to the overridden parent by using inherited(soup)
 
*This ensures that any data required by any parent class is made available.
 
<br>
 
  
==SetPropertyHandler==
 
{{MethodHeader|public void SetPropertyHandler(HTMLPropertyHandler handler)}}
 
;Parameters
 
*'''handler''' = Handler to assign to this property object.
 
;Returned Value
 
*None
 
 
;Description
 
;Description
*A PropertyObject can be overridden by assigning an HTMLPropertyHandler which allows more sophisticated processing.
+
Used for "map-object" and "asset-list" types to allow the list to be filtered before display. This gives the script an opportunity to cull any inappropriate values (such as those already added) and/or add any custom entries (such as a "none" selection).
*This method allows PropertyObject methods to be processed by such an object.
+
*Once SetPropertyHandler() has been used to assign a Property Handler the default methods in this class will be replaced by the corresponding methods defined in the handler.
+
<br>
+
  
 
==SetPropertyValue==
 
==SetPropertyValue==
 
{{MethodHeader|
 
{{MethodHeader|
void SetPropertyValue(string propertyID, string value, int index)<br>
 
 
void SetPropertyValue(string propertyID, string value)<br>
 
void SetPropertyValue(string propertyID, string value)<br>
 +
void SetPropertyValue(string propertyID, int value)<br>
 
void SetPropertyValue(string propertyID, float value)<br>
 
void SetPropertyValue(string propertyID, float value)<br>
void SetPropertyValue(string propertyID, int value)
+
void SetPropertyValue(string propertyID, string value, int index)<br>
 +
void SetPropertyValue(string propertyID, GSObject value, string readableName)
 
}}
 
}}
 
;Parameters
 
;Parameters
 
*'''propertyID''' = Name of property.
 
*'''propertyID''' = Name of property.
*'''value''' = int, float or string value to assign to the property.
+
*'''value''' = string, int, float or object value to assign to the property.
*'''index''' = list index value to assign to the property.
+
*'''index''' = list types only, specifies the index of the selected item in the list.
;Returned Value
+
*'''readableName''' = map-object and asset-list types only, specifies the localised name of the object/asset selected.
*None
+
 
;Syntax
+
;Return Value
*These are callback methods which should be overridden to suit the calling asset.
+
''None''
;Implementation
+
 
  void SetPropertyValue(string propertyID, string value) {
+
;Example Implementations
    if (propertyID == "forename") foreName = value;
+
  void SetPropertyValue(string propertyID, string value)
    else if (propertyID == "surname") surName = value;
+
{
    else inherited(propertyID);
+
  if (propertyID == "forename")
 +
  {
 +
    m_foreName = value;
 +
    return;
 +
  }
 +
  if (propertyID == "surname")
 +
  {
 +
    m_surName = value;
 +
    return;
 +
  }
 +
 
 +
  inherited(propertyID, value);
 
  }
 
  }
 +
 +
void SetPropertyValue(string propertyID, GSObject value, string readableName)
 +
{
 +
  if (propertyID == "junction")
 +
  {
 +
    m_junctionID = cast<GameObjectID>(value);
 +
    m_junctionName = readableName;
 +
    return;
 +
  }
 +
  if (propertyID == "sound-asset")
 +
  {
 +
    m_sound = cast<Asset>(value);
 +
    m_soundName = readableName;
 +
    return;
 +
  }
 +
 
 +
  inherited(propertyID, value, readableName);
 +
}
 +
 
;Description
 
;Description
*Sets a new value for the named property.
+
Sets a new value for the named property. The variant called depends on the property type, as returned by GetPropertyType().
 
<br>
 
<br>
  
==Related Methods==
+
==PropertyBrowserRefresh==
 +
{{MethodHeader|public void PropertyBrowserRefresh(Browser browser)}}
 +
;Parameters
 +
*'''browser''' = Reference to ''browser'' object displaying properties.
 +
 
 +
;Returned Value
 +
''None''
 +
 
 +
;Description
 +
A callback method which the script writer can override to specify tasks to be carried out whenever the Browser is refreshed.
 +
<br>
 +
 
 +
==SetPropertyHandler==
 +
{{MethodHeader|public void SetPropertyHandler(HTMLPropertyHandler handler)}}
 +
;Parameters
 +
*'''handler''' = Handler to assign to this property object.
 +
 
 +
;Returned Value
 +
''None''
 +
 
 +
;Description
 +
Called to add a sub-handler property object to this object. The added HTMLPropertyHandler can then implement property lists, etc. This is useful for organising property values into groups. Several pre-defined HTMLPropertyHandler classes also already exist in the core Trainz scripts, which script programmers can use to save time and avoid code duplication.
 +
<br>
 +
 
 +
==GetPropertyHandler==
 +
{{MethodHeader|public HTMLPropertyHandler GetPropertyHandler(void)}}
 +
;Parameters
 +
''None''
 +
 
 +
;Returned Value
 +
A reference to the current property handler for this object, or null if none has been set.
 +
<br>
  
  
 
==Categories==
 
==Categories==
 
[[Category:Script Class]]
 
[[Category:Script Class]]

Latest revision as of 19:22, 5 April 2021


This class provides an interface that allows an object to implement properties that can be saved or loaded to a session and edited by the user through a browser window in Surveyor. To enable this for an asset, it must inherit from PropertyObject (or from a derived child class such as ScenarioBehavior or MeshObject).

PropertyObject operates by way of a series of predefined callback methods which are designed to be overridden by the script writer to allow Trainz to access an object's properties. Properties are referred to in the class methods by their propertyID. Trainz determines this by reference to links in the object browser in the form live://property/propertyID.

When Trainz is saving a session, it asks each object to save its respective state into a Soup database. Trainz doesn't know what your object needs to save, but it does know that it can request an object's state via callbacks. Trainz relies on the script programmer to give careful thought to what data is needed to save and restore an objects state.

Depending on circumstances, not all callback methods have to be implemented. For example, you don't need to override GetPropertyElementList() if there are no list-selection properties.

Contents

[edit] Callback Sequences

The precise sequence of callback method calls will vary with the content of the browser and the user's input but the following gives a general idea:

  • When the Property Browser is opened Trainz calls:
  • When the user clicks on a URL, the propertyID is extracted from the link and these calls are made:
    • GetPropertyType() to establish the 'type' of the property is to be edited.
    • For "link" properties Trainz will call:
    • For "string", "int" and "float" properties:
    • For "list" properties:
    • For "map-object" and "asset-list" properties:
  • Once the user has carried out any edits:
    • The appropriate variant of SetPropertyValue() is called to update the value of the property.
    • GetDescriptionHTML() is called again to refresh the contents of the Browser window for any new configuration.
  • When all edits are complete:
    • If the user confirms their changes and closes the dialog:
      • SetProperties() is called with the modified Soup to update the session database.
    • If the user cancels the changes:
      • SetProperties() is called with the original unaltered Soup to restore the script to it's original pre-edit state.


Throughout the above sequences Trainz is only concerned with the loading and saving of properties. Wherever a change in a property requires an update to the appearance of the object or to the contents of its variables it is the responsibility of the script writer to implement these changes at the appropriate time. In general changes should be implemented in SetProperties() since this will help to ensure that changes can be reversed if they are cancelled or when the game's UNDO command is invoked.


[edit] Save/Load

Scripted objects do not have their state automatically saved and restored. It is the responsibility of the individual scripts to save and restored any necessary state across a Surveyor save session/load session, or across a Driver save game/load game. This is implemented using the PropertyObject GetProperties() and SetProperties() functions. When saving, Trainz will ensure that GetProperties() has been called for every PropertyObject that is being saved. The Soup returned by this function is stored along with any native state for the object in question. When reloading, Trainz will first create the object and load the native state, then will call the SetProperties() function with the saved Soup which instructs the script to restore its state.


[edit] GetDescriptionHTML

public string GetDescriptionHTML(void)
Parameters

None

Return Value;

HTML formatted string to be loaded into the Property Browser.

Example Implementation
public string GetDescriptionHTML(void)
{
  StringTable strTable = GetAsset().GetStringTable();
  
  HTMLBuffer buffer = HTMLBufferStatic.Construct();
  buffer.Print("<html><body>");
  
  buffer.Escape(strTable.GetString("property_name_forename"));
  buffer.Print(": <a href=live://property/forename>");
  buffer.Escape(m_foreName);
  buffer.Print("</a><br>");
  buffer.Escape(strTable.GetString("property_name_surname"));
  buffer.Print(": <a href=live://property/forename>");
  buffer.Escape(m_surName);
  buffer.Print("</a><br>");
  buffer.Print("</body></html>");
  
  return buffer.AsString();
}
Description

This method is called by Trainz to retrieve HTML which a player can use to configure the objects properties. Any embedded properties should use the live://property/propertyID format, all player readable strings should be sourced from the asset string-table, and all player configurable values should be appropriately escaped to avoid HTML corruption.
The Trainz uses its Mini Browser to display the HTML. See the MiniBrowser page to find supported HTML elements.

[edit] GetProperties

public Soup GetProperties(void)
Parameters

None

Return Value

Soup object containing data appropriate to represent the configured state of the object.

Example Implementation
public Soup GetProperties(void)
{
  Soup soup = inherited();
  soup.SetNamedTag("forename", m_foreName);
  soup.SetNamedTag("surname", m_surName);
  return soup;
}
Description

This method is used to save current properties into the session database. Care must be taken to ensure it writes data in the same tag format that SetProperties() is expecting. When overriding this method to handle your own properties, always call through to the overridden parent by using inherited().

[edit] SetProperties

public void SetProperties(Soup soup)
Parameters
  • soup = reference to soup to be saved to session.
Returned Value

None

Example Implementation
public void SetProperties(Soup soup)
{
  inherited(soup);
  m_foreName = soup.GetNamedTag("forename");
  m_surName = soup.GetNamedTag("surname");
}
Description

Restores object state with a Soup object returned from a previous call to GetProperties(). When overriding this method to handle your own properties, always call through to the overridden parent by using inherited(soup). This ensures that any data required by the parent class is appropriately set.

[edit] GetPropertyType

string GetPropertyType(string propertyID)
Parameters
  • propertyID = Name of property.
Return Value

The type of the current property.

Example Implementation
string GetPropertyType(string propertyID)
{
  if (propertyID == "forename" or propertyID == "surname")
    return "string";
  
  return inherited(propertyID);
}
Description

This method is used by Trainz to determine the type of the named property. The supported types and their parameters are listed in the table below.

Value type Parameters Description
string minimum-length,maximum-length A string value, with optional minimum and maximum lengths. e.g. "string,0,200".
int minimum-value,maximum-value,step-value An integer value with optional minimum, maximum and 'step' value. e.g. "int,0,100,5".
float minimum-value,maximum-value,step-value An floating point value with optional minimum, maximum and 'step' value. e.g. "float,0,10,0.5".
list sorted-bool An list, with an optional sorting flag (default off). e.g. "list,1" to sort, "list,0" for unsorted.
map-object category-list A list of map objects in the route which match a specific non-optional category list. e.g. "map-object,IND" for an industry list.
asset-list category-list A list of locally installed, compatible and available assets which match a specific non-optional category list. e.g. "asset-list,DR" for a list of installed Driver Character assets.
link A link type. This would usually respond and set some specific value, or perhaps toggle a bool.

[edit] GetPropertyName

string GetPropertyName(string propertyID)
Parameters
  • propertyID = Name of property.
Return Value

The name of the current property.

Example Implementation
string GetPropertyName(string propertyID)
{
  if (propertyID == "forename")
    return GetAsset().GetStringTable().GetString("property_name_forename");
  if (propertyID == "surname")
    return GetAsset().GetStringTable().GetString("property_name_surname");
  
  return inherited(propertyID);
}

[edit] GetPropertyDescription

string GetPropertyDescription(string propertyID)
Parameters
  • propertyID = Name of property.
Return Value

Description to be used as a caption for the edit box presented to the user for a specific property.

Example Implementation
string GetPropertyDescription(string propertyID)
{
  if (propertyID == "forename")
    return GetAsset().GetStringTable().GetString("property_description_forename");
  if (propertyID == "surname")
    return GetAsset().GetStringTable().GetString("property_description_surname");
  
  return inherited(propertyID);
}

[edit] GetPropertyValue

public string GetPropertyValue(string propertyID)
Parameters
  • propertyID = Name of property.
Returned Value

A string representation of the value of the current property.

Example Implementation
public string GetPropertyValue(string propertyID)
{
  if (propertyID == "forename")
    return m_foreName;
  if (propertyID == "surname")
    return m_foreName;
  
  return inherited(propertyID);
}
Description

Returns a string representation of the current value of the selected property, if possible. Where it is not possible to format a value into a string (such as with map-object and asset-list types) then any cached localised name may be returned, and native will attempt to find that object in any displayed list, etc.

[edit] LinkPropertyValue

void LinkPropertyValue(string propertyID)
Parameters
  • propertyID = Name of property.
Returned Value

None

Example Implementation
void LinkPropertyValue(string propertyID)
{
  if (propertyID == "doors")
  {
    m_doorsOpen = !m_doorsOpen;
    SetMeshAnimationState("doors", m_doorsOpen);
    return;
  }
  
  inherited(propertyID);
}
Description

Called when the player clicks on a "link" property type. Link properties are most frequently used to toggle boolean values and selecting "radio" buttons.

[edit] GetPropertyElementList

public string[ ] GetPropertyElementList(string propertyID)
Parameters
  • propertyID = Name of property.
Returned Value

A string array to for the player to select a value from.

Example Implementation
public string[] GetPropertyElementList(string propertyID)
{
  if (propertyID == "mode")
  {
    StringTable strTable = GetAsset().GetStringTable();
    
    string[] result = new string[10];
    int i;
    for (i = 1; i < 10; ++i)
      result[i] = strTable.GetString("property_list_mode_" + i);
    
    return result;
  }
  
  return inherited(propertyID);
}
Description

Retrieves a list possible values for a named property. Used for the "list" type. The returned list should support localisation by using string-table entries where appropriate.

[edit] FilterPropertyElementList

public bool FilterPropertyElementList(string propertyID, GSObject[] listObjects, string[] listNames)
Parameters
  • propertyID = Name of property.
  • listObjects = The list of objects about to be displayed.
  • listNames = The names of the objects about to be displayed.
Returned Value

Whether the filter function has altered the list at all.

Example Implementation
public bool FilterPropertyElementList(string propertyID, GSObject[] listObjects, string[] listNames)
{
  if (propertyID == "object-list")
  {
    bool bDidChangeAnything = false;
    // Remove any already added objects from the list
    int i;
    for (i = 0; i < listObjects.size(); )
    {
      if (IsAlreadyInList(cast<GameObject>(listObjects[i])))
      {
        listObjects[i,i+1] = null;
        listNames[i,i+1] = null;
        bDidChangeAnything  = true;
      }
      else
      {
        ++i;
      }
    }
    
    return bDidChangeAnything;
  }
  
  return inherited(propertyID, listObjects, listNames);
}
Description

Used for "map-object" and "asset-list" types to allow the list to be filtered before display. This gives the script an opportunity to cull any inappropriate values (such as those already added) and/or add any custom entries (such as a "none" selection).

[edit] SetPropertyValue

void SetPropertyValue(string propertyID, string value)
void SetPropertyValue(string propertyID, int value)
void SetPropertyValue(string propertyID, float value)
void SetPropertyValue(string propertyID, string value, int index)
void SetPropertyValue(string propertyID, GSObject value, string readableName)

Parameters
  • propertyID = Name of property.
  • value = string, int, float or object value to assign to the property.
  • index = list types only, specifies the index of the selected item in the list.
  • readableName = map-object and asset-list types only, specifies the localised name of the object/asset selected.
Return Value

None

Example Implementations
void SetPropertyValue(string propertyID, string value)
{
  if (propertyID == "forename")
  {
    m_foreName = value;
    return;
  }
  if (propertyID == "surname")
  {
    m_surName = value;
    return;
  }
  
  inherited(propertyID, value);
}

void SetPropertyValue(string propertyID, GSObject value, string readableName)
{
  if (propertyID == "junction")
  {
    m_junctionID = cast<GameObjectID>(value);
    m_junctionName = readableName;
    return;
  }
  if (propertyID == "sound-asset")
  {
    m_sound = cast<Asset>(value);
    m_soundName = readableName;
    return;
  }
  
  inherited(propertyID, value, readableName);
}
Description

Sets a new value for the named property. The variant called depends on the property type, as returned by GetPropertyType().

[edit] PropertyBrowserRefresh

public void PropertyBrowserRefresh(Browser browser)
Parameters
  • browser = Reference to browser object displaying properties.
Returned Value

None

Description

A callback method which the script writer can override to specify tasks to be carried out whenever the Browser is refreshed.

[edit] SetPropertyHandler

public void SetPropertyHandler(HTMLPropertyHandler handler)
Parameters
  • handler = Handler to assign to this property object.
Returned Value

None

Description

Called to add a sub-handler property object to this object. The added HTMLPropertyHandler can then implement property lists, etc. This is useful for organising property values into groups. Several pre-defined HTMLPropertyHandler classes also already exist in the core Trainz scripts, which script programmers can use to save time and avoid code duplication.

[edit] GetPropertyHandler

public HTMLPropertyHandler GetPropertyHandler(void)
Parameters

None

Returned Value

A reference to the current property handler for this object, or null if none has been set.


[edit] Categories

Personal tools