ContainerBridgeCrane

From TrainzOnline
(Difference between revisions)
Jump to: navigation, search
(Animation frames)
(Moving Containers)
Line 43: Line 43:
 
The crane's frame zero location is defined by the reacharea inset and will be calculated by containerStackTopWC minus craneOriginWC. The containerStackTopWC will be calculated by stackOriginWC plus stackPositionHeight. The stackPositionHeight is the sum of all stacked container's heights.
 
The crane's frame zero location is defined by the reacharea inset and will be calculated by containerStackTopWC minus craneOriginWC. The containerStackTopWC will be calculated by stackOriginWC plus stackPositionHeight. The stackPositionHeight is the sum of all stacked container's heights.
  
As moving speed in x, y, z direction of the crane parts we will use 5.4 km/h (~3.35 mi/s). This leads to frameCount/1500 to calculate the duration in seconds.
+
As moving speed in x, y, z direction of the crane parts we will use 5.4 km/h (~3.35 mi/s). Thus deltaFrameCount/1500 calculates the duration of the movement in seconds.
  
 
Now we are able to get the current frames list, the fromStack's frame list and the destStack's frame list to move the crane.
 
Now we are able to get the current frames list, the fromStack's frame list and the destStack's frame list to move the crane.

Revision as of 04:09, 28 April 2024

Contents

Container Bridge Crane

A bridge crane consists of several running parts. This parts are some kind of parented. The locical hirarchy of this parts look like this:

cranebase-->cranebridge(py)-->trolley(px)-->lift(sz,pz)-->rotor(rz)-->gear(sx)
  px, py, pz   animation move in x, y, z direction (moving in 1 mm steps)
  rx, ry, rz   animation rotation around x, y, z direction (rotation in 0.1° steps from -90.0° to +90.0° and zeroframe as -90.0°)
  sx, sy, sz   animation scale in x, y, z direction (zeroframe as 1.0 iss mandatory)

Reachable area

The special reacharea parameters for the bridge crane prototype looking like follows:

 acts.reacharea-251489 {
   reacharea.dimension.x       30000
   reacharea.dimension.y      100000
   reacharea.dimension.z       26000
   reacharea.origin_inset.x    15000
   reacharea.origin_inset.y    50000
   reacharea.origin_inset.z     5000
   max_container_count             7
 }

This data are for this prototype bridge crane.

Animation frames

The list of animation steps and values looks lik follows:

 Bridge (py)  100,001 Frames over     140m with BlenderFrames [1 .. 100001] for [  0,000 (  1  ) 100,000] in mm
 Trolley (px)  30,001 Frames over      30m with BlenderFrames [1 ..  30001] for [-15,000 (  1  ) +15,000] in mm
 Lift (sz)     25,001 Frames over     1-26 with BlenderFrames [1 ..  25001] for [  1.000 (0.001)  26.000]
 Lift (pz)     25,001 Frames over      25m with BlenderFrames [1 ..  25001] for [+21,000 (  1  )  -5,000] in mm
 Rotor (rz)     1,801 Frames over     180° with BlenderFrames [1 ..   1801] for [  -90.0 ( 0.1 )   +90.0] in ° (decimal grade)
 Gear (sy)     15,155 Frames over  16.154m with BlenderFrames [1 ..  15155] for [  1.000 (0.001)  16.154]
 ----------------------------------------------------------------------
 Containertype                  10ft    20ft     40ft     45ft     53ft
 Gear scale/length    1.000m  2.991m  6.058m  12.192m  13.716m  16.154m

Moving Containers

The task to move a container from one stack to another is written as following:

 # move crane (gear) to the "fromStack": stackWC,containerPosition and hook container
 # move crane (gear) to the "destStack": stackWC,containerPosition and dehook container

To calculate the destination frames we need the distance vector from the crane's frame zero location to the top of the container position at the stack. Since the location is used as WorldCoordinate and the stack and crane may reside in different baseboards, the first step is to "normalize" the baseboards. In the following this is agreed.

The crane's frame zero location is defined by the reacharea inset and will be calculated by containerStackTopWC minus craneOriginWC. The containerStackTopWC will be calculated by stackOriginWC plus stackPositionHeight. The stackPositionHeight is the sum of all stacked container's heights.

As moving speed in x, y, z direction of the crane parts we will use 5.4 km/h (~3.35 mi/s). Thus deltaFrameCount/1500 calculates the duration of the movement in seconds.

Now we are able to get the current frames list, the fromStack's frame list and the destStack's frame list to move the crane.

Asset files pre version 0.1

The files compile errorless and the messaging runs well. No more functionality implemented and tested in this pre version.

config.txt

 kuid               <kuid2:215489:110041:1>
 username           "aCTS CONTCRANE Animated Bridge Crane Scenery Utility V0.1"
 kind               "Scenery"
 category-class     "BU"
 
 description        "aCTS CONTCRANE Animated Bridge Crane Scenery Utility V0.1"
 
 trainz-build       4.6
 
 script             "acts_bridgecrane.gs"
 class              "acts_bridgecrane"
 
 surveyor-only      0
 
 mesh-table-lod-transition-distances    1000
 mesh-detail-level-count                1
 
 kuid-table {
   scriptinclude    <kuid2:215489:110000:1>
   skinskuid        <kuid2:215489:1100200:1>
   cont10ftsc       <kuid2:215489:1100211:1>
   cont10fthc       <kuid2:215489:1100212:1>
   cont20ftsc       <kuid2:215489:1100221:1>
   cont20fthc       <kuid2:215489:1100222:1>
   cont40ftsc       <kuid2:215489:1100231:1>
   cont40fthc       <kuid2:215489:1100232:1>
   cont45ftsc       <kuid2:215489:1100241:1>
   cont45fthc       <kuid2:215489:1100242:1>
   cont53ftsc       <kuid2:215489:1100251:1>
   cont53fthc       <kuid2:215489:1100252:1>
 }
 
 script-include-table {
   scriptinclude    <kuid2:215489:110000:1>
   skincolor        <kuid2:215489:1100200:1>
 }
 
 extensions
 {
   reacharea-215489
   {
     cranebase_dimension_x       30000
     cranebase_dimension_y      100000
     cranebase_dimension_z       26000
     cranebase_origin_inset_x    15000
     cranebase_origin_inset_y    50000
     cranebase_origin_inset_z     5000
     max_container_count             7
   }
 }
 
 mesh-table
 {
   cranebase-lod0
   {
     mesh                   "acts_cranebase.trainzmesh"
     auto-create            1
     lod-level              0
   }
   bridge-lod0
   {
     mesh                   "acts_bridge.trainzmesh"
     auto-create            1
     lod-level              0
     att-parent             "cranebase-lod0"
     anim                   "acts_bridge_scene.kin"
     animation-loop-speed   0.0
     critical-animation     0
   }
   trolley-lod0
   {
     mesh                   "acts_trolley.trainzmesh"
     auto-create            1
     lod-level              0
     att                    "a.bridge"
     att-parent             "bridge-lod0"
     anim                   "acts_trolley_scene.kin"
     animation-loop-speed   0.0
     critical-animation     0
   }
   lift-lod0
   {
     mesh                   "acts_lift.trainzmesh"
     auto-create            1
     lod-level              0
     att                    "a.trolley"
     att-parent             "trolley-lod0"
     anim                   "acts_lift_scene.kin"
     animation-loop-speed   0.0
     critical-animation     0
   }
   rotor-lod0
   {
     mesh                   "acts_rotor.trainzmesh"
     auto-create            1
     lod-level              0
     att                    "a.lift"
     att-parent             "lift-lod0"
     anim                   "acts_rotor_scene.kin"
     animation-loop-speed   0.0
     critical-animation     0
   }
   gear-lod0
   {
     mesh                   "acts_gear.trainzmesh"
     auto-create            1
     lod-level              0
     att                    "a.rotor"
     att-parent             "rotor-lod0"
     anim                   "acts_gear_scene.kin"
     animation-loop-speed   1.0
     critical-animation     0
   }
   cont10ftsc-lod0
   {
     mesh                   "acts_cont_10ftsc.trainzmesh"
     mesh-asset             <kuid2:215489:1100211:1>
     auto-create            0
     lod-level              0
     att                    "a.queue.sccontainer"
     att-parent             "gear-lod0"
     effects 
     {
       skincolor10ftsc 
       {
         kind       "texture-replacement"
         texture    "acts_container_allinone.texture"
       }
     }
   }
   cont10fthc-lod0
   {
     mesh                   "acts_cont_10fthc.trainzmesh"
     mesh-asset             <kuid2:215489:1100212:1>
     auto-create            0
     lod-level              0
     att                    "a.queue.hccontainer"
     att-parent             "gear-lod0"
     effects 
     {
       skincolor10fthc 
       {
         kind       "texture-replacement"
         texture    "acts_container_allinone.texture"
       }
     }
   }
   cont20ftsc-lod0
   {
     mesh                   "acts_cont_20ftsc.trainzmesh"
     mesh-asset             <kuid2:215489:1100221:1>
     auto-create            0
     lod-level              0
     att                    "a.queue.sccontainer"
     att-parent             "gear-lod0"
     effects 
     {
       skincolor20ftsc
       {
         kind       "texture-replacement"
         texture    "acts_container_allinone.texture"
       }
     }
   }
   cont20fthc-lod0
   {
     mesh                   "acts_cont_20fthc.trainzmesh"
     mesh-asset             <kuid2:215489:1100222:1>
     auto-create            0
     lod-level              0
     att                    "a.queue.hccontainer"
     att-parent             "gear-lod0"
     effects 
     {
       skincolor20fthc 
       {
         kind       "texture-replacement"
         texture    "acts_container_allinone.texture"
       }
     }
   }
   cont40ftsc-lod0
   {
     mesh                   "acts_cont_40ftsc.trainzmesh"
     mesh-asset             <kuid2:215489:1100231:1>
     auto-create            0
     lod-level              0
     att                    "a.queue.sccontainer"
     att-parent             "gear-lod0"
     effects 
     {
       skincolor40ftsc 
       {
         kind       "texture-replacement"
         texture    "acts_container_allinone.texture"
       }
     }
   }
   cont40fthc-lod0
   {
     mesh                   "acts_cont_40fthc.trainzmesh"
     mesh-asset             <kuid2:215489:1100232:1>
     auto-create            0
     lod-level              0
     att                    "a.queue.hccontainer"
     att-parent             "gear-lod0"
     effects 
     {
       skincolor40fthc 
       {
         kind       "texture-replacement"
         texture    "acts_container_allinone.texture"
       }
     }
   }
   cont45ftsc-lod0
   {
     mesh                   "acts_cont_45ftsc.trainzmesh"
     mesh-asset             <kuid2:215489:1100241:1>
     auto-create            0
     lod-level              0
     att                    "a.queue.sccontainer"
     att-parent             "gear-lod0"
     effects 
     {
       skincolor45ftsc 
       {
         kind       "texture-replacement"
         texture    "acts_container_allinone.texture"
       }
     }
   }
   cont45fthc-lod0
   {
     mesh                   "acts_cont_45fthc.trainzmesh"
     mesh-asset             <kuid2:215489:1100242:1>
     auto-create            0
     lod-level              0
     att                    "a.queue.hccontainer"
     att-parent             "gear-lod0"
     effects 
     {
       skincolor45fthc 
       {
         kind       "texture-replacement"
         texture    "acts_container_allinone.texture"
       }
     }
   }
   cont53ftsc-lod0
   {
     mesh                   "acts_cont_53ftsc.trainzmesh"
     mesh-asset             <kuid2:215489:1100251:1>
     auto-create            0
     lod-level              0
     att                    "a.queue.sccontainer"
     att-parent             "gear-lod0"
     effects 
     {
       skincolor53ftsc 
       {
         kind       "texture-replacement"
         texture    "acts_container_allinone.texture"
       }
     }
   }
   cont53fthc-lod0
   {
     mesh                   "acts_cont_53fthc.trainzmesh"
     mesh-asset             <kuid2:215489:1100252:1>
     auto-create            0
     lod-level              0
     att                    "a.queue.hccontainer"
     att-parent             "gear-lod0"
     effects 
     {
       skincolor53fthc
       {
         kind       "texture-replacement"
         texture    "acts_container_allinone.texture"
       }
     }
   }
 }
 
 thumbnails
 {
   0
   {
     image                  "acts_bridgecrane_thumb.jpg"
     width                  240
     height                 180
   }
 }
 

acts_bridgecrane.gs

 include "acts_bridgecrane_script.gs"
   
 //-----------------------------------------------------------------------------
 // aCTS Bridgecrane V0.1 Central Script - acts_bridgecrane.gs
 //-----------------------------------------------------------------------------
 // X acts_bridgecrane           <-- acts_bridgecrane_script
 //   acts_bridgecrane_script    <-- acts_bridgecrane_register
 //   acts_bridgecrane_register  <-- acts_bridgecrane_reachable
 //   acts_bridgecrane_reachable <-- acts_bridgecrane_moving
 //   acts_bridgecrane_moving    <-- acts_bridgecrane_globals
 //   acts_bridgecrane_globals   <-- acts_global_values
 //   acts_global_values         <-- MapObject
 //-----------------------------------------------------------------------------
 
 class acts_bridgecrane isclass acts_bridgecrane_script
 {
   // --------------------------------------------------------------------------
   // Mandatory INIT method
   // --------------------------------------------------------------------------
   public void Init(Asset asset)
   {
     inherited(asset);
     //-------------------------------------------------------------------------
     // Make shure that the right module is set for World.GetCurrentModle()
     // (see world.gs lines 939ff.) to start driver related initiations and
     // tell me, if my Init and SetProperties methods are finished.
     // Add handler for my tasks as dispatcher.
     //-------------------------------------------------------------------------
     AddHandler(me, "World", "ModuleInit", "WorldInitHandler");
     AddHandler(me, "OBJECTINIT", "", "ObjectInitHandler");
     AddHandler(me, "DISPATCHER", "", "DispatcherHandler");
     //-------------------------------------------------------------------------
     // It's nessecary to initalise the lib to force subscript preparing
     //-------------------------------------------------------------------------
     //World.GetLibrary(GetAsset().LookupKUIDTable("dummylibrary"));
     dispobj = World.GetLibrary(GetAsset().LookupKUIDTable("scriptinclude"));
     dispgoid = (cast<GameObject>dispobj).GetGameObjectID();
     //-------------------------------------------------------------------------
     // Load reacharea and other values from extension soup in my config.txt
     //-------------------------------------------------------------------------
     Soup csp = me.GetAsset().GetConfigSoupCached();
     csp = csp.GetNamedSoup("extensions");
     csp = csp.GetNamedSoup("reacharea-215489");
     cranebase_reacharea_x    = csp.GetNamedTagAsInt("cranebase_dimension_x"   );
     cranebase_reacharea_y    = csp.GetNamedTagAsInt("cranebase_dimension_y"   );
     cranebase_reacharea_z    = csp.GetNamedTagAsInt("cranebase_dimension_z"   );
     cranebase_origin_inset_x = csp.GetNamedTagAsInt("cranebase_origin_inset_x");
     cranebase_origin_inset_y = csp.GetNamedTagAsInt("cranebase_origin_inset_y");
     cranebase_origin_inset_z = csp.GetNamedTagAsInt("cranebase_origin_inset_z");
     max_container_count      = csp.GetNamedTagAsInt("max_container_count"     );
     //-------------------------------------------------------------------------
     moveCranePartsToZeroframe();
     //-------------------------------------------------------------------------
     isInitMethodFinnished = true;
     PostMessage(me,"OBJECTINIT","INIT_FINNISHED",0);   // Init method finnished
     //-------------------------------------------------------------------------
     return;
   }    
   // --------------------------------------------------------------------------
 };

acts_bridgecrane_script.gs

 include "acts_bridgecrane_reachable.gs"
 include "acts_tools_script.gs"
   
 //-----------------------------------------------------------------------------
 // aCTS Bridgecrane V0.1 Central Script - acts_bridgecrane_script.gs
 //-----------------------------------------------------------------------------
 //   acts_bridgecrane           <-- acts_bridgecrane_script
 // X acts_bridgecrane_script    <-- acts_bridgecrane_register
 // X acts_bridgecrane_register  <-- acts_bridgecrane_reachable
 //   acts_bridgecrane_reachable <-- acts_bridgecrane_moving
 //   acts_bridgecrane_moving    <-- acts_bridgecrane_globals
 //   acts_bridgecrane_globals   <-- acts_global_values
 //   acts_global_values         <-- MapObject
 //-----------------------------------------------------------------------------
 
 class acts_bridgecrane_register isclass acts_bridgecrane_reachable
 {
   //-------------------------------------------------------------------------
   // TBD: Outsource from acts_bridgecrane_script
   //-------------------------------------------------------------------------
 };
 
 class acts_bridgecrane_script isclass acts_bridgecrane_register
 {
   //---------------------------------------------------------------------------
   // public void SetProperties(Soup soup) ....................... ca. line  23
   // public Soup GetProperties(void) ............................ ca. line  85
   // public void ObjectInitHandler(Message msg) ................. ca. line 100
   // public void WorldInitHandler(Message msg) .................. ca. line 132
   // public void DispatcherHandler(Message msg) ................. ca. line 183
   //---------------------------------------------------------------------------
   public void SetProperties(Soup soup)   // Callback method after Init method
   {
     inherited(soup);
     //-------------------------------------------------------------------------
     ObjectDataSoup.Copy(soup.GetNamedSoup("ObjectData"));
     LocationSoup.Copy(soup.GetNamedSoup("Location"));
     OrientationSoup.Copy(soup.GetNamedSoup("Orientation")) ;
     /*/-------------------------------------------------------------------------
     if (acts_debug) Interface.Log(Interface.GetTimeStamp()
                     + "CONTCRANE SETPROPERTIES SOUPS");
     if (acts_debug) actsTools.ShowSoup(ObjectDataSoup,"ObjDS=>");
     if (acts_debug) actsTools.ShowSoup(LocationSoup,"LocDS=>");
     if (acts_debug) actsTools.ShowSoup(OrientationSoup,"OriDS=>");
     //-------------------------------------------------------------------------*/
     isSetPropertiesMethodFinnished = true;
     PostMessage(me,"OBJECTINIT","SETPROPS_FINNISHED",0.0);
     return;
   }
   //---------------------------------------------------------------------------
   public Soup GetProperties(void)   // Callback method before closing session
   {
     Soup soup = inherited();
     //-------------------------------------------------------------------------
     soup.SetNamedSoup("ObjectData",ObjectDataSoup);
     soup.SetNamedSoup("Location",LocationSoup    );
     soup.SetNamedSoup("Orientation",OrientationSoup );
     //-------------------------------------------------------------------------
     if (acts_debug) Interface.Log(Interface.GetTimeStamp()
                     + "CONTCRANE GETPROPERTIES SOUPS");
     if (acts_debug) actsTools.ShowSoup(ObjectDataSoup,"ObjDS=>");
     if (acts_debug) actsTools.ShowSoup(LocationSoup,"LocDS=>");
     if (acts_debug) actsTools.ShowSoup(OrientationSoup,"OriDS=>");
     //-------------------------------------------------------------------------*/
     return soup;
   } 
   //---------------------------------------------------------------------------
   public void WorldInitHandler(Message msg)
   {
     //-------------------------------------------------------------------------
     if (acts_debug) Interface.Log(Interface.GetTimeStamp()
             + " [" + objectgoid.SerialiseToString() + "]"
             + " CONTCRANE GOT WORLDINIT MESSAGE ["
             + msg.major+"] ["+msg.minor+"]");
     //-------------------------------------------------------------------------*/
     // If one of the two methods (Init or SetProperties) isn't finished yet, 
     // post "World","ModuleInit" message a little bit later again.
     // So it is guaranteed that the Init and SetProperties methods are finished
     // as well as the "World","ModuleInit" message tells to be save using the 
     // World.GetCurrentModule method.
     //-------------------------------------------------------------------------
     if (!(isSetPropertiesMethodFinnished and isInitMethodFinnished))
     {
       PostMessage(me, "World", "ModuleInit", 0.2);
     }
     //-------------------------------------------------------------------------
     isWorldInitFinnished = true;
     PostMessage(me, "OBJECTINIT", "WORLD_INIT_FINNISHED", 0.0);
     //-------------------------------------------------------------------------
     return;
   }
   //---------------------------------------------------------------------------
   public void ObjectInitHandler(Message msg)
   {
     //-------------------------------------------------------------------------
     // Until the Trainz core send the "World","ModuleInit" was send it is not
     // guarented to decide with the World.GetCurrentModule method to be in the 
     // returned module! 
     //-------------------------------------------------------------------------
     if (acts_debug) Interface.Log(Interface.GetTimeStamp()
             + " [" + objectgoid.SerialiseToString() + "]"
             + " CONTCRANE GOT MESSAGE ["+msg.major+"] ["+msg.minor+"]");
     //-------------------------------------------------------------------------*/
     if (msg.dst==me and msg.major=="OBJECTINIT")
     {
       if (msg.minor=="INIT_FINNISHED")
       {
           //-------------------------------------------------------------------
           // Not used yet
           //-------------------------------------------------------------------
       }
       //-----------------------------------------------------------------------
       if (msg.minor=="SETPROPS_FINNISHED")
       {
         if (ObjectDataSoup.CountTags()==0)
         {
           //-------------------------------------------------------------------
           // LoadObjectDataInfos(ObjectDataSoup);
           //-------------------------------------------------------------------
           ObjectDataSoup.SetNamedTag("goid",objectgoid);
           ObjectDataSoup.SetNamedTag("type",objecttype);
           ObjectDataSoup.SetNamedTag("regID",-1);
           ObjectDataSoup.SetNamedTag("active",false);
           //ObjectDataSoup.SetNamedTag("requested",false);
           //ObjectDataSoup.SetNamedTag("hooked",false);
           ObjectDataSoup.SetNamedTag("cranebase_reacharea_x",cranebase_reacharea_x);
           ObjectDataSoup.SetNamedTag("cranebase_reacharea_y",cranebase_reacharea_y);
           ObjectDataSoup.SetNamedTag("cranebase_reacharea_z",cranebase_reacharea_z);
           ObjectDataSoup.SetNamedTag("cranebase_origin_inset_x",cranebase_origin_inset_x);
           ObjectDataSoup.SetNamedTag("cranebase_origin_inset_y",cranebase_origin_inset_y);
           ObjectDataSoup.SetNamedTag("cranebase_origin_inset_z",cranebase_origin_inset_z);
           ObjectDataSoup.SetNamedTag("max_container_count",max_container_count);
         }
         //---------------------------------------------------------------------
         if (acts_debug) Interface.Log(Interface.GetTimeStamp()
                     + " => SOUP 'ObjectDataSoup'");
         if (acts_debug) actsTools.ShowSoup(ObjectDataSoup,"=>");
         //---------------------------------------------------------------------*/
         if (LocationSoup.CountTags()==0)
         {
           //-------------------------------------------------------------------
           // LoadLocationDataInfos(LocationDataSoup);
           //-------------------------------------------------------------------
           WorldCoordinate WC = me.GetMapObjectPosition();
           LocationSoup.SetNamedTag("bbx",WC.baseboardX);
           LocationSoup.SetNamedTag("bby",WC.baseboardY);
           LocationSoup.SetNamedTag("px",WC.x);
           LocationSoup.SetNamedTag("py",WC.y);
           LocationSoup.SetNamedTag("pz",WC.z);
         }
         //---------------------------------------------------------------------
         if (OrientationSoup.CountTags()==0)
         {
           //-------------------------------------------------------------------
           // LoadOrientationDataInfos(OrientationDataSoup);
           //-------------------------------------------------------------------
           Orientation OR = me.GetMapObjectOrientation();
           LocationSoup.SetNamedTag("rx",OR.rx);
           LocationSoup.SetNamedTag("ry",OR.ry);
           LocationSoup.SetNamedTag("rz",OR.rz);
           LocationSoup.SetNamedTag("gx",OR.rx*180.0/Math.PI);
           LocationSoup.SetNamedTag("gy",OR.ry*180.0/Math.PI);
           LocationSoup.SetNamedTag("gz",OR.rz*180.0/Math.PI);
         }
         //---------------------------------------------------------------------
         // TBD: Adjust position and rotation to rounded values and handle
         //      the different pssibilities.
         //      (some methods see acts_tools_script.gs)
         //---------------------------------------------------------------------
         // Soup sp = actsTools.AutoAdjustMapObject(cast<MapObject>(me));
         // LocationSoup    = sp.GetNamedSoup("AdjustedLocationSoup");
         // OrientationSoup = sp.GetNamedSoup("AdjustedOrientationSoup");
         //---------------------------------------------------------------------
       }
       //-----------------------------------------------------------------------
       if (msg.minor=="WORLD_INIT_FINNISHED")
       {
         //---------------------------------------------------------------------
         // Do no module only, driver module only or surveyor module only
         // related initiations
         //---------------------------------------------------------------------
         if (World.GetCurrentModule() == World.DRIVER_MODULE)
         {
           //-------------------------------------------------------------------
           PostMessage(cast<GameObject>dispobj,
                                "REGISTER", "REGISTER_ME", ObjectDataSoup, 0.0);
           //-------------------------------------------------------------------
         }
         //---------------------------------------------------------------------
         if (World.GetCurrentModule() == World.SURVEYOR_MODULE)
         {
           //-------------------------------------------------------------------
           // Not used yet
           //-------------------------------------------------------------------
         }
         //---------------------------------------------------------------------
         if (World.GetCurrentModule() == World.NO_MODULE)
         {
           //-------------------------------------------------------------------
           // Not used yet
           //-------------------------------------------------------------------
         }
       }
     }
   }
   //---------------------------------------------------------------------------
   public void DispatcherHandler(Message msg)
   {
     if (msg.dst==me and msg.major=="DISPATCHER")
     {
       //-----------------------------------------------------------------------
       if (acts_debug) Interface.Log(Interface.GetTimeStamp()
               + " [" + objectgoid.SerialiseToString() + "] ["
               + " CONTCRANE GOT MESSAGE FROM DISPATCHER"
               + (cast<GameObject>msg.src).GetGameObjectID().SerialiseToString()
               + "] ["+msg.major+"] ["+msg.minor+"]");
       //-----------------------------------------------------------------------*/
       if (msg.minor=="OBJECTSOUP_UPDATED")
       {
         //---------------------------------------------------------------------
         // Update the own ObjectDataSoup
         //---------------------------------------------------------------------
         ObjectDataSoup.Copy(cast<Soup>msg.paramSoup);
         //---------------------------------------------------------------------*/
       }
       if (msg.minor=="OBJECTSOUP_INSERTED")
       {
         //---------------------------------------------------------------------
         // Update the own ObjectDataSoup
         //---------------------------------------------------------------------
         ObjectDataSoup.Copy(cast<Soup>msg.paramSoup);
         //---------------------------------------------------------------------*/
       }
       if (msg.minor=="OBJECTSOUP_APPENDED")
       {
         //---------------------------------------------------------------------
         // Update the own ObjectDataSoup
         //---------------------------------------------------------------------
         ObjectDataSoup.Copy(cast<Soup>msg.paramSoup);
         //---------------------------------------------------------------------*/
       }
     }
     //-------------------------------------------------------------------------
     return;
   }
 };

File is located in dispatcher library.

acts_bridgecrane_reachable.gs

 include "acts_bridgecrane_globals.gs"
 include "acts_tools_script.gs"
   
 //-----------------------------------------------------------------------------
 // aCTS Bridgecrane V0.1 Central Script - acts_bridgecrane_reachable.gs
 //-----------------------------------------------------------------------------
 //   acts_bridgecrane           <-- acts_bridgecrane_script
 //   acts_bridgecrane_script    <-- acts_bridgecrane_register
 //   acts_bridgecrane_register  <-- acts_bridgecrane_reachable
 // X acts_bridgecrane_reachable <-- acts_bridgecrane_moving
 // X acts_bridgecrane_moving    <-- acts_bridgecrane_globals
 //   acts_bridgecrane_globals   <-- acts_global_values
 //   acts_global_values         <-- MapObject
 //-----------------------------------------------------------------------------
 
 class acts_bridgecrane_moving isclass acts_bridgecrane_globals
 {
   //---------------------------------------------------------------------------
   // Set zeroframe translations for the asset parts
   //---------------------------------------------------------------------------
   int bridge_zeroframe  = cranebase_origin_inset_y;
   int trolley_zeroframe = cranebase_origin_inset_x;
   int lift_zeroframe  = 0;     // Scale 1.000..25.000 (cranebase_reacharea_z)
   int rotor_zeroframe = 900;   // Decimal degree -90.0..+90.0 (precision 0.1°)
   int gear_zeroframe  = 2991;  // Scale 1.000-2.991-6.058-12.192-13.716-16.154
   //---------------------------------------------------------------------------
   void moveCranePartsToZeroframe(void)
   {
     me.SetMeshAnimationFrame("bridge-lod0",  bridge_zeroframe);
     me.SetMeshAnimationFrame("trolley-lod0", trolley_zeroframe);
     me.SetMeshAnimationFrame("lift-lod0",    lift_zeroframe);
     me.SetMeshAnimationFrame("rotor-lod0",   rotor_zeroframe);
     me.SetMeshAnimationFrame("gear-lod0",    gear_zeroframe);
   }
   //---------------------------------------------------------------------------
   // TBD: Where and when setting the fitting containers skin?
   //      Asset skins = GetAsset().FindAsset("skinskuid");
   //      SetFXTextureReplacement("skincolor40ftsc",skins,8);
   //      SetMeshVisible("cont40ftsc-lod0", true);
   //      me.SetMeshAnimationFrame("gear-lod0", 12191.0, 3.0);
   //---------------------------------------------------------------------------
 };
 
 /******************************************************************************
   -----------------------------------------------------------------------------
   In conjunction with the rotation of the cranearea there ar four cases to
   know about if a point lies within the reacharea, bounding edges are assumed
   to be outside.
   
    A B    B    
    D C   A C     0° ≤ w < 90°   CD < py < AB and AD < px < BC
           D
   
    B C    C
    A D   B D   90° ≤ w < 180°   AD < py < BC and AB < px < CD
           A
   
    C D    D 
    B A   C A  180° ≤ w < 270°   AB < py < CD and BC < px < AD   
           B
 
    D A    A    
    C B   D B  270° ≤ w < 360°   BC < py < AD and CD < px < AB
           C
   -----------------------------------------------------------------------------
 *******************************************************************************/
 class acts_bridgecrane_reachable isclass acts_bridgecrane_moving
 {
   // --------------------------------------------------------------------------
   // Loading values from config.txt extensions-219486 cranedata soup
   // --------------------------------------------------------------------------
   void LoadCraneDataInfos(Soup sp)
   {
     cranebase_reacharea_x          
       = sp.GetNamedTagAsInt("cranebase_reacharea_x",0);
     cranebase_reacharea_y          
       = sp.GetNamedTagAsInt("cranebase_reacharea_y",0);
     cranebase_reacharea_z          
       = sp.GetNamedTagAsInt("cranebase_reacharea_z",0);
     cranebase_origin_inset_x              
       = sp.GetNamedTagAsInt("cranebase_inset_x",0);
     cranebase_origin_inset_y              
       = sp.GetNamedTagAsInt("cranebase_inset_y",0);
     cranebase_origin_inset_z              
       = sp.GetNamedTagAsInt("cranebase_inset_z",0);
     trolley_bottom_height   
       = sp.GetNamedTagAsInt("trolley_bottom_height",0);
     lift_bottom_height 
       = sp.GetNamedTagAsInt("lift_bottom_height",0);
     gear_bottom_height 
       = sp.GetNamedTagAsInt("gear_bottom_height",0);
     max_container_count
       = sp.GetNamedTagAsInt("max_container_count",0);
   }
   // --------------------------------------------------------------------------
   // Returns the vertices of the reacharea rectangle. The insets and dimensions
   // where deliverd over a objects config extension subsoup. Rotations x and y 
   // are zero.
   //  A---+-----B
   //  |   ix    |   ix insetx, iy insety
   //  |iy-O-----+   dx=AD=BC dimensionx, dy=AB=CD dimensiony
   //  |   |     |   RC[0..3]<=>ABCD 
   //  D---+-----C
   //---------------------------------------------------------------------------
   public WorldCoordinate[] GetReachareaCorners()
   {
     WorldCoordinate[] RC = new WorldCoordinate[4];    // Reacharea corners ABCD
     WorldCoordinate OR = me.GetMapObjectPosition();   // Origin of crane OR
     //-------------------------------------------------------------------------
     RC[0].baseboardX = OR.baseboardX;
     RC[0].baseboardY = OR.baseboardY;
     RC[0].x = OR.x - cranebase_origin_inset_x;
     RC[0].y = OR.y - cranebase_origin_inset_y;
     RC[0].z = OR.z;
     //-------------------------------------------------------------------------
     RC[1].baseboardX = OR.baseboardX;
     RC[1].baseboardY = OR.baseboardY;
     RC[1].x = OR.x - cranebase_origin_inset_x;
     RC[1].y = OR.y + cranebase_reacharea_y - cranebase_origin_inset_y;
     RC[1].z = OR.z;
     //-------------------------------------------------------------------------
     RC[2].baseboardX = OR.baseboardX;
     RC[2].baseboardY = OR.baseboardY;
     RC[2].x = OR.x + cranebase_reacharea_x - cranebase_origin_inset_x;
     RC[2].y = OR.y + cranebase_reacharea_y - cranebase_origin_inset_y;
     RC[2].z = OR.z;
     //-------------------------------------------------------------------------
     RC[3].baseboardX = OR.baseboardX;
     RC[3].baseboardY = OR.baseboardY;
     RC[3].x = OR.x + cranebase_reacharea_x - cranebase_origin_inset_x;
     RC[3].y = OR.y - cranebase_origin_inset_y;
     RC[3].z = OR.z;
     //-------------------------------------------------------------------------
     return RC;
   }
   // --------------------------------------------------------------------------
   // The two point straight line formulas for x and y for the points A and B:
   //       (by-ay)                        (bx-ax)
   //   y = ------- * (x-ax) + by      x = ------- * (y-ay) + bx
   //       (bx-ax)                        (by-ay)
   //---------------------------------------------------------------------------
   public float ValueXStraightline(
                  WorldCoordinate P, WorldCoordinate A, WorldCoordinate B)
   { if (A.y==B.y) return A.y;
     else return cast<float>((B.x-A.x)*(P.y-A.y)/(B.y-A.y)); 
     return 0.0;
   }
   public float ValueYStraightline(
                  WorldCoordinate P, WorldCoordinate A, WorldCoordinate B)
   { if (A.x==B.x) return A.x;
     else return cast<float>((B.y-A.y)*(P.x-A.x)/(B.x-A.x));
     return 0.0;
   }
   // --------------------------------------------------------------------------
   // InsideReacharea returns true if the point is reachable, otherwise false.
   // Edges of the reacharea rectangle are assumed outside.
   //---------------------------------------------------------------------------
   public bool InsideReacharea(WorldCoordinate P, WorldCoordinate[] W)
   {
     //-------------------------------------------------------------------------
     // Adjust the point to the same baseboard as the container crane
     //-------------------------------------------------------------------------
     WorldCoordinate SP = actsTools.WCoordAdjustBaseboard(P,me.GetMapObjectPosition());
     //-------------------------------------------------------------------------
     // Calculate the case to proof
     //-------------------------------------------------------------------------
     float rz = me.GetMapObjectOrientation().rz;
     int wi = cast<int>(rz*180*100/Math.PI);     // int rounded to 1/100
     int ri = wi/(90*100);
     while (ri<0) ri=ri+4;
     while (ri>3) ri=ri-4;
     //-------------------------------------------------------------------------
     // Values of the edges (straight ölines) for the point coordinates
     //-------------------------------------------------------------------------
     float xAB = ValueXStraightline(P, W[0], W[1]);
     float yAB = ValueYStraightline(P, W[0], W[1]);
     float xBC = ValueXStraightline(P, W[1], W[2]);
     float yBC = ValueYStraightline(P, W[1], W[2]);
     float xCD = ValueXStraightline(P, W[2], W[3]);
     float yCD = ValueYStraightline(P, W[2], W[3]);
     float xAD = ValueXStraightline(P, W[0], W[3]);
     float yAD = ValueYStraightline(P, W[0], W[3]);
     //-------------------------------------------------------------------------
     // Calculating the resulting bool value
     //-------------------------------------------------------------------------
     switch(ri)
     {
       case 0:  //  0° <= rz° <  90°
         if(yCD < P.y and P.y < yAB and xAD < P.x and P.x < xBC) return true;
         return false;
       case 1:  //  90° <= rz° < 180°
         if(yAD < P.y and P.y < yBC and xAB < P.x and P.x < xCD) return true;
         return false;
       case 2:  // 180° <= rz° < 270°
         if(yAB < P.y and P.y < yCD and xBC < P.x and P.x < xAD) return true;
         return false;
       case 3:  // 270° <= rz° < 360°
         if(yBC < P.y and P.y < yAD and xCD < P.x and P.x < xAB) return true;
         return false;
       default:
         return false;
     }
     return false;
   }
   //---------------------------------------------------------------------------
   
 };

File is located in dispatcher library.

acts_bridgecrain_globals.gs

 include "acts_global_values.gs"
 include "acts_tools_script.gs"
 
 //---------------------------------------------------------------------------
 // aCTS Bridgecrane V0.1 Central Script - acts_bridgecrane_globals.gs
 //-----------------------------------------------------------------------------
 //   acts_bridgecrane           <-- acts_bridgecrane_script
 //   acts_bridgecrane_script    <-- acts_bridgecrane_register
 //   acts_bridgecrane_register  <-- acts_bridgecrane_reachable
 //   acts_bridgecrane_reachable <-- acts_bridgecrane_moving
 //   acts_bridgecrane_moving    <-- acts_bridgecrane_globals
 // X acts_bridgecrane_globals   <-- acts_global_values
 //   acts_global_values         <-- MapObject
 //-----------------------------------------------------------------------------
 
 class acts_bridgecrane_globals isclass acts_global_values
 {
   //---------------------------------------------------------------------------
   // AssetInstanceSoup {
   // X ObjectDataSoup { ... },    Only container, contstack, contcrane
   // X LocationSoup { ... },      Only container, contstack, contcrane
   // X OrientationSoup { ... },   Only container, contstack, contcrane
   //   SkinDataSoup { ... },      Only container
   //   ContentDataSoup { ... },   Only container
   //   DispatcherDataSoup { ... } Only dispatcher
   //   ContainerSoups  { ... }    Only dispatcher
   //   ContstackSoups  { ... }    Only dispatcher
   //   ContcraneSoups  { ... }    Only dispatcher
   // }
   //---------------------------------------------------------------------------
   // ObjectDataSoup { goid GameObjectID, type string,
   //                  length string, height string,  
   //                  stack goid, place int,           Only container
   //                  active bool, action string },
   // activ: true means the object sended a register message while session run
   //        All objects were set false while initialising dispatcher and if
   //        they stay false their entries will be deleted next initialising.
   // actions: ["APPENDED", "INSERTED", "UPDATED"];
   //---------------------------------------------------------------------------
   Soup ObjectDataSoup = Constructors.NewSoup();
   //---------------------------------------------------------------------------
   // LocationSoup { bbx int, bby int,               // WorlCoordinate parameter
   //                px float, py float, pz float }
   //-------------------------------------------------------------------------
   Soup LocationSoup = Constructors.NewSoup();
   //-------------------------------------------------------------------------
   // OrientationSoup { rx float, ry float, rz float,    // in rad 
   //                   gx float, gy float, gz float }   // in 1/10°
   //-------------------------------------------------------------------------
   Soup OrientationSoup = Constructors.NewSoup();
   //-------------------------------------------------------------------------
   GameObjectID objectgoid = me.GetGameObjectID();
   string       objecttype = "CONTCRANE";
   Library      dispobj;
   GameObjectID dispgoid;
   //---------------------------------------------------------------------------
   // Reach area values of the bridge crane will be loaded from this assets
   // config.txt file 
   //---------------------------------------------------------------------------
   int cranebase_reacharea_x;      //  30000 in [mm]
   int cranebase_reacharea_y;      // 100000 in [mm]
   int cranebase_reacharea_z;      //  26000 in [mm]
   int cranebase_origin_inset_x;   //  15000 in [mm]
   int cranebase_origin_inset_y;   //  50000 in [mm]
   int cranebase_origin_inset_z;   //   5000 in [mm]
   //---------------------------------------------------------------------------
   int lift_zero_length = 1000;   // 1000 in [mm] mandatory length for animation
   //---------------------------------------------------------------------------
   int trolley_bottom_height;   // in [mm]
   int lift_bottom_height;      // in [mm] with lift z width as 1,000 [mm]
   int rotor_bottom_height;     // in [mm] with rotor z width as 500 [mm]
   int gear_bottom_height;      // in [mm] with gear z width as 500 [mm]
   //---------------------------------------------------------------------------
   // TBD: And not proofed yet. Differntiate between maximum container count
   //      for high cube and standard cube containers.
   //---------------------------------------------------------------------------
   // For now the maximum count is calculated from reacharea z dimension minus
   // one hc height to ensure the movement of containers by the crane. Because
   // of possibly different base heights of the stacks inside the crane's
   // reacharea, there are some more different (possibly smaller) maximum
   // stackheights.
   // --------------------------------------------------------------------------
   int max_container_count;     // Construction based max stackable containers
   // --------------------------------------------------------------------------
 };
 
 //-----------------------------------------------------------------------------
 /* ****************************************************************************
    This is the scripted bridge crane object for an active container terminal
    system (aCTS). It is a kind of prototype of a bridge crane to let
    constructors know how the things are fitting and working for aCTS.
    ----------------------------------------------------------------------------
    Some hints here too (see config description too):
    * The script logs dependin on the acts_debug variable (See
      acts.global_values.gs). So the script contains some overhead for testing
      informations. 
    * Animations from Blender fbx runs from frame 1 ... n in Blender and fbx
      file. The import to Trainz will change this to frame 0 ... n-1, what is
      essential to know for precise transformations (moving and rotating) per
      animation frame.
    * The logical mesh hierarchy is as follows: cranebase-->
      -->cranebridge(py)-->trolley(px)-->lift(sz,pz)-->rotor(rz)-->gear(sx)
    * The cranes parts are imported to Trainz as own (animated) mesh objects
      with its respective origins at zero and its parented attachment points.
      All script calculations are based on this origin and the gaps to the
      attachment points for attaching the child meshes. The assets orientation
      is zero for x and y orientation.
    * The parent child hierarchy is realised within the mesh-table container.
    * The extensions values are in mm and define the reachable area of the
      cranes container gear. The dimensions x, y, z describe the cuboid
      length's, the gear may move and the insets x, y, z describes the location
      of the cranes origin within there.
    * The animations minimum frame 0 (resp. 1 in Blender) represents the locale
      relative minimal position (p = -inset) and the maximum frame (n = 
      dimension) the maximal position p=dimension-inset. Example: 
        dimension 80
        inset     30
        Trainz frames    0  10  20 30  40  50  60  70  80
        Blender frames   1  11  21 31  41  51  61  71  81
        Position       -30 -20 -10  0  10  20  30  40  50
    * The crane object (as well as the other object types) adjusts location to
      even mm and the orientation to 0.1 decimal degrees.
    * The movements of the cranes sub meshes will be realised with animation
      frame methods *MeshAnimation* from the MeshObject class in mashobject.gs
    ----------------------------------------------------------------------------
    Technical parameters for calculating script values 1 [mm] and 0.1 [°]
    ----------------------------------------------------------------------------
    Bridge  [BPY: 100,001F:    140m] BF[1 .. 100001] [0mm(1)100,000mm]
    Trolley [TPX:  30,001F:     30m] BF[1 ..  30001] [-15,000mm(1)+15,000mm]
    Lift    [LSZ:  25,001F:    1-26] BF[1 ..  25001] [1.000(0.001)26.000]
            [LPZ:  25,001F:     25m] BF[1 ..  25001] [+21,000mm(1)-5,000mm]
    Rotor   [ROZ:   1,801F:    180°] BF[1 ..   1801] [-90.0°(0.1)+90.0°]
    Gear    [GSY:  15,155F: 16.192m] BF[1 ..  16155] [1.000(0.001)16.154]
    ----------------------------------------------------------------------------
    Containertype                      10ft    20ft     40ft     45ft     53ft
    Gear scale scale/length  1.000m  2.991m  6.058m  12.192m  13.716m  16.154m
    ----------------------------------------------------------------------------
    More informations are documented within the config.txt and script comments.
    ----------------------------------------------------------------------------
    **************************************************************************** */

File is located in dispatcher library.

Personal tools