public ControllerContext(HttpContextBase context, 
     RouteData routeData, ControllerBase controller)
     : base(context, routeData)
 {
     Precondition.Require(controller, () => Error.ArgumentNull("controller"));
     _controller = controller;
 }
Exemplo n.º 2
0
 public StreamingConnection()
     : base()
 {
     HttpContextBase httpContextBase = new HttpContextWrapper(HttpContext.Current);
       RouteData routeData = new RouteData();
       routeData.Values.Add("controller", "Home");
       HomeContext = new ControllerContext(new RequestContext(httpContextBase, routeData), new HomeController());
 }
Exemplo n.º 3
0
        /// <summary>
        /// Initializes a new instance of the 
        /// <see cref="RequestContext"/> class
        /// </summary>
        /// <param name="context">An <see cref="HttpContextBase"/> of the current request</param>
        /// <param name="routeData">The route parameter dictionary</param>
        public RequestContext(HttpContextBase context, RouteData routeData)
        {
            Precondition.Require(context, () => Error.ArgumentNull("context"));
            Precondition.Require(routeData, () => Error.ArgumentNull("routeData"));

            _context = context;
            _routeData = routeData;
        }
Exemplo n.º 4
0
 public ViewContext(HttpContextBase context, RouteData routeData, 
     ControllerBase controller, IView view, ViewDataDictionary viewData, 
     TempDataDictionary tempData)
     : base(context, routeData, controller)
 {
     _view = view;
     _viewData = viewData;
     _tempData = tempData;
 }
Exemplo n.º 5
0
 public RouteData GetRouteData()
 {
     if (null != routeData)
     {
         return routeData;
     }
     HttpRequest request = new HttpRequest("default.aspx","http://localhost/weather/0512/3", null);
     HttpResponse response = new HttpResponse(new StringWriter());
     HttpContext context = new HttpContext(request, response);
     HttpContextBase contextWrapper = new HttpContextWrapper(context);
     return routeData = RouteTable.Routes.GetRouteData(contextWrapper);
 }
Exemplo n.º 6
0
        public IActionResult Handle(IHttpContext context, RouteData routeData)
        {
            var resource = routeData.Data as Resource;
            if (resource == null) return null;

            var resourceManager = resource.ResourceManager;
            if (resourceManager == null) return null;

            var body = Microsoft.SPOT.ResourceUtility.GetObject(resourceManager, resource.StringResource) as string;
            if (body == null) return null;

            return new ContentResult { Content = body, ContentType = resource.ContentType, LastModified = resource.LastModified };
        }
Exemplo n.º 7
0
		/// <summary>Sets the brightness value for the specified track position</summary>
		/// <param name="Data">The route data (Accessed via 'ref') which we wish to query the brightnes value from</param>
		/// <param name="TrackPosition">The track position to get the brightness value for</param>
		/// <returns>The brightness value</returns>
		private static double GetBrightness(ref RouteData Data, double TrackPosition)
		{
			double tmin = double.PositiveInfinity;
			double tmax = double.NegativeInfinity;
			double bmin = 1.0, bmax = 1.0;
			for (int i = 0; i < Data.Blocks.Length; i++)
			{
				for (int j = 0; j < Data.Blocks[i].Brightness.Length; j++)
				{
					if (Data.Blocks[i].Brightness[j].TrackPosition <= TrackPosition)
					{
						tmin = Data.Blocks[i].Brightness[j].TrackPosition;
						bmin = (double)Data.Blocks[i].Brightness[j].Value;
					}
				}
			}
			for (int i = Data.Blocks.Length - 1; i >= 0; i--)
			{
				for (int j = Data.Blocks[i].Brightness.Length - 1; j >= 0; j--)
				{
					if (Data.Blocks[i].Brightness[j].TrackPosition >= TrackPosition)
					{
						tmax = Data.Blocks[i].Brightness[j].TrackPosition;
						bmax = (double)Data.Blocks[i].Brightness[j].Value;
					}
				}
			}
			if (tmin == double.PositiveInfinity & tmax == double.NegativeInfinity)
			{
				return 1.0;
			}
			else if (tmin == double.PositiveInfinity)
			{
				return (bmax - 1.0) * TrackPosition / tmax + 1.0;
			}
			else if (tmax == double.NegativeInfinity)
			{
				return bmin;
			}
			else if (tmin == tmax)
			{
				return 0.5 * (bmin + bmax);
			}
			else
			{
				double n = (TrackPosition - tmin) / (tmax - tmin);
				return (1.0 - n) * bmin + n * bmax;
			}
		}
Exemplo n.º 8
0
 public ICommand GetOrCreateCommand(RouteData routeData,HttpMethods method,Context context)
 {
     SortedDictionary<string, Dictionary<HttpMethods,ICommand>> actions = null;
     if (!_Datas.TryGetValue(routeData.ControllerName, out actions))
     {
         return null;
     }
     Dictionary<HttpMethods, ICommand> methods = null;
     if (!actions.TryGetValue(routeData.ActionName, out methods))
     {
         return null;
     }
     foreach (var pair in methods) {
         if (((int)pair.Key & (int)method) > 0) return pair.Value;
     }
     return null;
 }
Exemplo n.º 9
0
 // Use this for initialization
 void Start()
 {
     for (int i=0;i<routePoints.Length;i++)
     {
         MapController mapController = GameObject.FindObjectOfType<MapController>();
         mapController.routePoints.Add(routePoints[i]);
         if(i>0)
         {
             for (int j=0;j<i;j++)
             {
                 RouteData route = new RouteData();
                 route.SetParams(routePoints[i],routePoints[j], "internal");
                 mapController.routes.Add(route);
             }
         }
     }
 }
Exemplo n.º 10
0
        protected void Page_Load(object sender, EventArgs e)
        {
            RouteData routeData = new RouteData();
            routeData.Values.Add("areaCode", "0512");
            routeData.Values.Add("days", "1");
            RequestContext requestContext = new RequestContext();
            requestContext.HttpContext = new HttpContextWrapper(HttpContext.Current);
            requestContext.RouteData = routeData;

            RouteValueDictionary values = new RouteValueDictionary();
            values.Add("areaCode", "028");
            values.Add("days", "3");

            Response.Write(RouteTable.Routes.GetVirtualPath(null, null).VirtualPath + "<br/>");
            Response.Write(RouteTable.Routes.GetVirtualPath(requestContext,null).VirtualPath + "<br/>");
            Response.Write(RouteTable.Routes.GetVirtualPath(requestContext,values).VirtualPath + "<br/>");
        }
Exemplo n.º 11
0
 public override RouteData GetRouteData(HttpContextBase httpContext)
 {
     Uri uri = httpContext.Request.Url;
     Uri baseAddress = new Uri(string.Format("{0}://{1}", uri.Scheme, uri.Authority));
     UriTemplateMatch match = this.UriTemplate.Match(baseAddress, uri);
     if (null == match)
     {
         return null;
     }
     RouteData routeData = new RouteData();
     routeData.RouteHandler = this.RouteHandler;
     routeData.Route = this;
     foreach (string name in match.BoundVariables.Keys)
     {
         routeData.Values.Add(name, match.BoundVariables[name]);
     }
     foreach (var token in this.DataTokens)
     {
         routeData.DataTokens.Add(token.Key, token.Value);
     }
     return routeData;
 }
Exemplo n.º 12
0
        private static async Task GetFile(HttpRequest request, HttpResponse response, RouteData routeData, IFiles files)
        {
            var file   = routeData.GetString("file");
            var source = await files.TryGetFileSource(file);

            if (source == null)
            {
                response.StatusCode = 404;
                return;
            }

            response.StatusCode = 200;
            if (source.Type == FileType.Text)
            {
                response.ContentType = "text/text";
                await response.SendFileAsync(source.FullPath);
            }
            else
            {
                response.ContentType = "application/binary";
                using (var stream = File.OpenRead(source.FullPath))
                {
                    await stream.CopyToAsync(response.Body);
                }
            }
        }
 public abstract Task Invoke(string requestId, dynamic viewModel, object @event, RouteData routeData, HttpRequest request);
Exemplo n.º 14
0
        public void Discover(ShapeTableBuilder builder)
        {
            builder.Describe("Menu")
            .OnDisplaying(displaying =>
            {
                var menu        = displaying.Shape;
                string menuName = menu.MenuName;

                menu.Classes.Add("menu-" + menuName.HtmlClassify());
                menu.Classes.Add("menu");
                menu.Metadata.Alternates.Add("Menu__" + EncodeAlternateElement(menuName));
            })
            .OnProcessing(processing =>
            {
                dynamic menu    = processing.Shape;
                string menuName = menu.MenuName;

                // Menu population is executed when processing the shape so that its value
                // can be cached. IShapeDisplayEvents is called before the ShapeDescriptor
                // events and thus this code can be cached.

                if ((bool)menu.HasItems)
                {
                    return;
                }

                var httpContext       = _httpContextAccessor.HttpContext;
                var navigationManager = httpContext.RequestServices.GetService <INavigationManager>();
                var shapeFactory      = httpContext.RequestServices.GetService <IShapeFactory>();

                IEnumerable <MenuItem> menuItems = navigationManager.BuildMenu(menuName);

                // adding query string parameters
                RouteData route = menu.RouteData;
                var routeData   = new RouteValueDictionary(route.Values);
                var query       = httpContext.Request.Query;

                if (query != null)
                {
                    foreach (var pair in query)
                    {
                        if (pair.Key != null && !routeData.ContainsKey(pair.Key))
                        {
                            routeData[pair.Key] = pair.Value;
                        }
                    }
                }

                // TODO: Flag Selected menu item

                NavigationHelper.PopulateMenu(shapeFactory, menu, menu, menuItems);
            });

            builder.Describe("MenuItem")
            .OnDisplaying(displaying =>
            {
                var menuItem = displaying.Shape;
                var menu     = menuItem.Menu;
                var menuName = menu.MenuName;
                int level    = menuItem.Level;

                menuItem.Metadata.Alternates.Add("MenuItem__level__" + level);
                menuItem.Metadata.Alternates.Add("MenuItem__" + EncodeAlternateElement(menuName));
                menuItem.Metadata.Alternates.Add("MenuItem__" + EncodeAlternateElement(menuName) + "__level__" + level);
            });

            builder.Describe("MenuItemLink")
            .OnDisplaying(displaying =>
            {
                var menuItem       = displaying.Shape;
                string menuName    = menuItem.Menu.MenuName;
                string contentType = null;
                int level          = menuItem.Level;

                menuItem.Metadata.Alternates.Add("MenuItemLink__level__" + level);

                // MenuItemLink__[ContentType] e.g. MenuItemLink-HtmlMenuItem
                // MenuItemLink__[ContentType]__level__[level] e.g. MenuItemLink-HtmlMenuItem-level-2
                if (contentType != null)
                {
                    menuItem.Metadata.Alternates.Add("MenuItemLink__" + EncodeAlternateElement(contentType));
                    menuItem.Metadata.Alternates.Add("MenuItemLink__" + EncodeAlternateElement(contentType) + "__level__" + level);
                }

                // MenuItemLink__[MenuName] e.g. MenuItemLink-Main-Menu
                // MenuItemLink__[MenuName]__level__[level] e.g. MenuItemLink-Main-Menu-level-2
                menuItem.Metadata.Alternates.Add("MenuItemLink__" + EncodeAlternateElement(menuName));
                menuItem.Metadata.Alternates.Add("MenuItemLink__" + EncodeAlternateElement(menuName) + "__level__" + level);

                // MenuItemLink__[MenuName]__[ContentType] e.g. MenuItemLink-Main-Menu-HtmlMenuItem
                // MenuItemLink__[MenuName]__[ContentType] e.g. MenuItemLink-Main-Menu-HtmlMenuItem-level-2
                if (contentType != null)
                {
                    menuItem.Metadata.Alternates.Add("MenuItemLink__" + EncodeAlternateElement(menuName) + "__" + EncodeAlternateElement(contentType));
                    menuItem.Metadata.Alternates.Add("MenuItemLink__" + EncodeAlternateElement(menuName) + "__" + EncodeAlternateElement(contentType) + "__level__" + level);
                }
            });
        }
Exemplo n.º 15
0
 public DynamicViewModel(RouteData routeData, IQueryCollection query, ILoggerFactory loggerFactory)
 {
     this.routeData     = routeData;
     this.query         = query;
     this.loggerFactory = loggerFactory;
 }
Exemplo n.º 16
0
 protected virtual IAction GetOrCreateCommand(RouteData routeData,HttpMethods method,Context context) {
     return this.ActionFactory.GetOrCreateCommand(routeData,method,context);
 }
Exemplo n.º 17
0
        /// <summary>
        /// Gets the <see cref="RouteData"/> for 
        /// the current <see cref="HttpContextBase"/>.
        /// </summary>
        /// <param name="context">The <see cref="HttpContext"/> 
        /// containing the incoming request.</param>
		/// <param name="variables">The <see cref="ValueDictionary"/> 
		/// containing the route variable values.</param>
        public override RouteData GetRouteData(HttpContextBase context, 
			ValueDictionary variables)
        {
            Precondition.Require(context, () => Error.ArgumentNull("context"));

            string applicationPath = GetApplicationPath(context);
            string appRelativePath = String.Concat(GetExecutionPath(context), context.Request.PathInfo);

            string virtualPath = (_parsedRoute.IsAppRelative) ? appRelativePath :
                String.Concat(applicationPath, appRelativePath);
            string path = (_parsedRoute.IsRelative) ? virtualPath :
                String.Concat(context.Request.Url.Authority, virtualPath);

			if (!MatchUriScheme(context))
				return null;

			ValueDictionary values = _parsedRoute.Match(path, variables, Defaults);
            if (values == null)
                return null;
            
            RouteData data = new RouteData(this, _handler);
            if (!MatchConstraints(context, values, RouteDirection.IncomingRequest))
                return null;

            foreach (KeyValuePair<string, object> kvp in values)
                data.Values.Add(kvp.Key, kvp.Value);
            
            if (_tokens != null)          
                foreach (KeyValuePair<string, object> kvp in _tokens)
                    data.Tokens[kvp.Key] = kvp.Value;
            
            return data;
        }
Exemplo n.º 18
0
        public async Task <ActionResult> Index(UserIndexOptions options, PagerParameters pagerParameters)
        {
            if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageUsers))
            {
                return(Unauthorized());
            }

            var siteSettings = await _siteService.GetSiteSettingsAsync();

            var pager = new Pager(pagerParameters, siteSettings.PageSize);

            // default options
            if (options == null)
            {
                options = new UserIndexOptions();
            }

            var users = _session.Query <User, UserIndex>();

            switch (options.Filter)
            {
            case UsersFilter.Approved:
                //users = users.Where(u => u.RegistrationStatus == UserStatus.Approved);
                break;

            case UsersFilter.Pending:
                //users = users.Where(u => u.RegistrationStatus == UserStatus.Pending);
                break;

            case UsersFilter.EmailPending:
                //users = users.Where(u => u.EmailStatus == UserStatus.Pending);
                break;
            }

            if (!string.IsNullOrWhiteSpace(options.Search))
            {
                users = users.Where(u => u.NormalizedUserName.Contains(options.Search) || u.NormalizedEmail.Contains(options.Search));
            }

            switch (options.Order)
            {
            case UsersOrder.Name:
                users = users.OrderBy(u => u.NormalizedUserName);
                break;

            case UsersOrder.Email:
                users = users.OrderBy(u => u.NormalizedEmail);
                break;

            case UsersOrder.CreatedUtc:
                //users = users.OrderBy(u => u.CreatedUtc);
                break;

            case UsersOrder.LastLoginUtc:
                //users = users.OrderBy(u => u.LastLoginUtc);
                break;
            }

            var count = await users.CountAsync();

            var results = await users
                          .Skip(pager.GetStartIndex())
                          .Take(pager.PageSize)
                          .ListAsync();

            // Maintain previous route data when generating page links
            var routeData = new RouteData();

            routeData.Values.Add("Options.Filter", options.Filter);
            routeData.Values.Add("Options.Search", options.Search);
            routeData.Values.Add("Options.Order", options.Order);

            var pagerShape = New.Pager(pager).TotalItemCount(count).RouteData(routeData);

            var model = new UsersIndexViewModel
            {
                Users = await Task.WhenAll(
                    results.Select(async x =>
                                   new UserEntry {
                    Shape = await _userDisplayManager.BuildDisplayAsync(x, this, "SummaryAdmin")
                })),
                Options = options,
                Pager   = pagerShape
            };

            return(View(model));
        }
        /// <summary>
        /// Asserts that the route matches the expression specified.  Checks controller, action, and any method arguments
        /// into the action as route values.
        /// </summary>
        /// <typeparam name="TController">The controller.</typeparam>
        /// <param name="routeData">The routeData to check</param>
        /// <param name="action">The action to call on TController.</param>
        public static RouteData ShouldMapTo <TController>(this RouteData routeData, Expression <Func <TController, ActionResult> > action)
            where TController : Controller
        {
            routeData.ShouldNotBeNull("The URL did not match any route");

            //check controller
            routeData.ShouldMapTo <TController>();

            //check action
            var    methodCall   = (MethodCallExpression)action.Body;
            string actualAction = routeData.Values.GetValue("action").ToString();

            string expectedAction = methodCall.Method.ActionName();

            actualAction.AssertSameStringAs(expectedAction);

            //check parameters
            for (int i = 0; i < methodCall.Arguments.Count; i++)
            {
                ParameterInfo param           = methodCall.Method.GetParameters()[i];
                bool          isReferenceType = !param.ParameterType.IsValueType;
                bool          isNullable      = isReferenceType ||
                                                (param.ParameterType.UnderlyingSystemType.IsGenericType && param.ParameterType.UnderlyingSystemType.GetGenericTypeDefinition() == typeof(Nullable <>));

                string     controllerParameterName = param.Name;
                bool       routeDataContainsValueForParameterName = routeData.Values.ContainsKey(controllerParameterName);
                object     actualValue          = routeData.Values.GetValue(controllerParameterName);
                object     expectedValue        = null;
                Expression expressionToEvaluate = methodCall.Arguments[i];

                // If the parameter is nullable and the expression is a Convert UnaryExpression,
                // we actually want to test against the value of the expression's operand.
                if (expressionToEvaluate.NodeType == ExpressionType.Convert &&
                    expressionToEvaluate is UnaryExpression)
                {
                    expressionToEvaluate = ((UnaryExpression)expressionToEvaluate).Operand;
                }

                switch (expressionToEvaluate.NodeType)
                {
                case ExpressionType.Constant:
                    expectedValue = ((ConstantExpression)expressionToEvaluate).Value;
                    break;

                case ExpressionType.New:
                case ExpressionType.MemberAccess:
                    expectedValue = Expression.Lambda(expressionToEvaluate).Compile().DynamicInvoke();
                    break;
                }

                if (isNullable && (string)actualValue == String.Empty && expectedValue == null)
                {
                    // The parameter is nullable so an expected value of '' is equivalent to null;
                    continue;
                }

                // HACK: this is only sufficient while System.Web.Mvc.UrlParameter has only a single value.
                if (actualValue == UrlParameter.Optional ||
                    (actualValue != null && actualValue.ToString().Equals("System.Web.Mvc.UrlParameter")))
                {
                    actualValue = null;
                }

                if (expectedValue is DateTime)
                {
                    actualValue = Convert.ToDateTime(actualValue);
                }
                else
                {
                    expectedValue = (expectedValue == null ? expectedValue : expectedValue.ToString());
                }

                string errorMsgFmt = "Value for parameter '{0}' did not match: expected '{1}' but was '{2}'";
                if (routeDataContainsValueForParameterName)
                {
                    errorMsgFmt += ".";
                }
                else
                {
                    errorMsgFmt += "; no value found in the route context action parameter named '{0}' - does your matching route contain a token called '{0}'?";
                }
                actualValue.ShouldEqual(expectedValue, String.Format(errorMsgFmt, controllerParameterName, expectedValue, actualValue));
            }

            return(routeData);
        }
            internal MatchingActionSequence(IReadOnlyList <ActionDescriptor> matches, RouteData routeData)
            {
                Contract.Requires(matches != null);
                Contract.Requires(matches.Count > 0);
                Contract.Requires(routeData != null);

                this.matches   = matches;
                this.routeData = routeData;
            }
Exemplo n.º 21
0
        /// <summary>
        /// Action加上[SupportFilter]在执行actin之前执行以下代码,通过[SupportFilter(ActionName="Index")]指定参数
        /// </summary>
        /// <param name="filterContext">页面传过来的上下文</param>
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //读取请求上下文中的Controller,Action,Id
            var routes = new RouteCollection();
            //RouteConfig.RegisterRoutes(routes);

            RouteData routeData = routes.GetRouteData(filterContext.HttpContext);

            //取出区域的控制器Action,id
            string ctlName = filterContext.Controller.ToString();

            string[] routeInfo  = ctlName.Split('.');
            string   controller = null;
            string   action     = null;
            string   id         = null;

            int iAreas = Array.IndexOf(routeInfo, "Areas");

            if (iAreas > 0)
            {
                //取区域及控制器
                Area = routeInfo[iAreas + 1];
            }
            int ctlIndex = Array.IndexOf(routeInfo, "Controllers");

            ctlIndex++;
            controller = routeInfo[ctlIndex].Replace("Controller", "").ToLower();

            string url = HttpContext.Current.Request.Url.ToString().ToLower();

            string[] urlArray    = url.Split('/');
            int      urlCtlIndex = Array.IndexOf(urlArray, controller);

            urlCtlIndex++;
            if (urlArray.Count() > urlCtlIndex)
            {
                action = urlArray[urlCtlIndex];
            }
            urlCtlIndex++;
            if (urlArray.Count() > urlCtlIndex)
            {
                id = urlArray[urlCtlIndex];
            }
            //url
            action = string.IsNullOrEmpty(action) ? "Index" : action;
            int actionIndex = action.IndexOf("?", 0);

            if (actionIndex > 1)
            {
                action = action.Substring(0, actionIndex);
            }
            id = string.IsNullOrEmpty(id) ? "" : id;

            //URL路径
            string  filePath = HttpContext.Current.Request.FilePath;
            Account account  = filterContext.HttpContext.Session["Account"] as Account;

            if (ValiddatePermission(account, controller, action, filePath))
            {
                return;
            }
            else
            {
                filterContext.Result = new EmptyResult();
                return;
            }
        }
        protected ActionResult ListExtensions(PackagingExtensionsOptions options, string packageType, Pager pager)
        {
            var selectedSource = _packagingSourceManager.GetSources().Where(s => s.Id == options.SourceId).FirstOrDefault();

            var sources = selectedSource != null
                ? new[] { selectedSource }
                : _packagingSourceManager.GetSources()
            ;

            IEnumerable <PackagingEntry> extensions = null;
            int totalCount = 0;

            foreach (var source in sources)
            {
                try {
                    Expression <Func <PublishedPackage, bool> > packagesCriteria = p => p.PackageType == packageType &&
                                                                                   p.IsLatestVersion &&
                                                                                   (string.IsNullOrEmpty(options.SearchText) ||
                                                                                    p.Title.Contains(options.SearchText) ||
                                                                                    p.Description.Contains(options.SearchText) ||
                                                                                    p.Tags.Contains(options.SearchText));

                    var sourceExtensions = _packagingSourceManager.GetExtensionList(true,
                                                                                    source,
                                                                                    packages => {
                        packages = packages.Where(packagesCriteria);

                        switch (options.Order)
                        {
                        case PackagingExtensionsOrder.Downloads:
                            packages = packages.OrderByDescending(p => p.DownloadCount).ThenBy(p => p.Title);
                            break;

                        case PackagingExtensionsOrder.Ratings:
                            packages = packages.OrderByDescending(p => p.Rating).ThenBy(p => p.Title);
                            break;

                        case PackagingExtensionsOrder.Alphanumeric:
                            packages = packages.OrderBy(p => p.Title);
                            break;
                        }

                        if (pager.PageSize != 0)
                        {
                            packages = packages.Skip((pager.Page - 1) * pager.PageSize).Take(pager.PageSize);
                        }

                        return(packages);
                    }).ToArray();

                    // count packages separately to prevent loading everything just to count
                    totalCount += _packagingSourceManager.GetExtensionCount(
                        source,
                        packages => packages.Where(packagesCriteria));

                    extensions = extensions == null ? sourceExtensions : extensions.Concat(sourceExtensions);

                    // apply another paging rule in case there were multiple sources
                    if (sources.Count() > 1)
                    {
                        switch (options.Order)
                        {
                        case PackagingExtensionsOrder.Downloads:
                            extensions = extensions.OrderByDescending(p => p.DownloadCount).ThenBy(p => p.Title);
                            break;

                        case PackagingExtensionsOrder.Ratings:
                            extensions = extensions.OrderByDescending(p => p.Rating).ThenBy(p => p.Title);
                            break;

                        case PackagingExtensionsOrder.Alphanumeric:
                            extensions = extensions.OrderBy(p => p.Title);
                            break;
                        }

                        if (pager.PageSize != 0)
                        {
                            extensions = extensions.Take(pager.PageSize);
                        }
                    }
                }
                catch (Exception exception) {
                    Services.Notifier.Error(T("Error loading extensions from gallery source '{0}'. {1}.", source.FeedTitle, exception.Message));
                }
            }

            extensions = extensions ?? new PackagingEntry[0];
            var pagerShape = Services.New.Pager(pager).TotalItemCount(totalCount);

            // maintain previous route data when generating page links
            var routeData = new RouteData();

            routeData.Values.Add("Options.Order", options.Order);
            routeData.Values.Add("Options.SearchText", options.SearchText);
            routeData.Values.Add("Options.SourceId", options.SourceId);
            pagerShape.RouteData(routeData);

            extensions = extensions.ToList();

            // Populate the notifications
            IEnumerable <Tuple <ExtensionDescriptor, PackagingEntry> > extensionDescriptors = _extensionManager.AvailableExtensions()
                                                                                              .Join(extensions, extensionDescriptor => extensionDescriptor.Id, packaginEntry => packaginEntry.ExtensionId(),
                                                                                                    (extensionDescriptor, packagingEntry) => new Tuple <ExtensionDescriptor, PackagingEntry>(extensionDescriptor, packagingEntry));

            foreach (Tuple <ExtensionDescriptor, PackagingEntry> packagings in extensionDescriptors)
            {
                packagings.Item2.Installed = true;

                if (_extensionDisplayEventHandler != null)
                {
                    foreach (string notification in _extensionDisplayEventHandler.Displaying(packagings.Item1, ControllerContext.RequestContext))
                    {
                        packagings.Item2.Notifications.Add(notification);
                    }
                }
            }

            return(View(packageType == DefaultExtensionTypes.Theme ? "Themes" : "Modules", new PackagingExtensionsViewModel {
                Extensions = extensions,
                Sources = _packagingSourceManager.GetSources().OrderBy(s => s.FeedTitle),
                Pager = pagerShape,
                Options = options
            }));
        }
Exemplo n.º 23
0
 public static ControllerContext CreateMockControllerContext(HttpContextBase httpContext, RouteData routeData)
 {
     return(new ControllerContext(httpContext ?? CreateMockHttpContext(), routeData, new Mock <ControllerBase>().Object));
 }
        /// <summary>
        /// Adds server variables for use by the JavaScript.
        /// </summary>
        private void AddServerVariables(object sender,
                                        Dictionary <string, object> e)
        {
            // Variables.
            var httpContext    = new HttpContextWrapper(HttpContext.Current);
            var routeData      = new RouteData();
            var requestContext = new RequestContext(httpContext, routeData);
            var helper         = new UrlHelper(requestContext);
            var key            = Constants.PackageNameCamelCase;


            // Add server variables.
            e.Add(key, new Dictionary <string, string>()
            {
                { "DeleteForm",
                  helper.GetUmbracoApiService <FormsController>(x =>
                                                                x.DeleteForm(null)) },
                { "PersistForm",
                  helper.GetUmbracoApiService <FormsController>(x =>
                                                                x.PersistForm(null)) },
                { "GetFormInfo",
                  helper.GetUmbracoApiService <FormsController>(x =>
                                                                x.GetFormInfo(null)) },
                { "MoveForm",
                  helper.GetUmbracoApiService <FormsController>(x =>
                                                                x.MoveForm(null)) },
                { "DeleteConfiguredForm",
                  helper.GetUmbracoApiService <ConfiguredFormsController>(x =>
                                                                          x.DeleteConfiguredForm(null)) },
                { "PersistConfiguredForm",
                  helper.GetUmbracoApiService <ConfiguredFormsController>(x =>
                                                                          x.PersistConfiguredForm(null)) },
                { "GetConfiguredFormInfo",
                  helper.GetUmbracoApiService <ConfiguredFormsController>(x =>
                                                                          x.GetConfiguredFormInfo(null)) },
                { "DeleteLayout",
                  helper.GetUmbracoApiService <LayoutsController>(x =>
                                                                  x.DeleteLayout(null)) },
                { "PersistLayout",
                  helper.GetUmbracoApiService <LayoutsController>(x =>
                                                                  x.PersistLayout(null)) },
                { "GetLayoutInfo",
                  helper.GetUmbracoApiService <LayoutsController>(x =>
                                                                  x.GetLayoutInfo(null)) },
                { "GetLayoutKinds",
                  helper.GetUmbracoApiService <LayoutsController>(x =>
                                                                  x.GetLayoutKinds()) },
                { "MoveLayout",
                  helper.GetUmbracoApiService <LayoutsController>(x =>
                                                                  x.MoveLayout(null)) },
                { "DeleteValidation",
                  helper.GetUmbracoApiService <ValidationsController>(x =>
                                                                      x.DeleteValidation(null)) },
                { "PersistValidation",
                  helper.GetUmbracoApiService <ValidationsController>(x =>
                                                                      x.PersistValidation(null)) },
                { "GetValidationInfo",
                  helper.GetUmbracoApiService <ValidationsController>(x =>
                                                                      x.GetValidationInfo(null)) },
                { "GetValidationsInfo",
                  helper.GetUmbracoApiService <ValidationsController>(x =>
                                                                      x.GetValidationsInfo(null)) },
                { "GetValidationKinds",
                  helper.GetUmbracoApiService <ValidationsController>(x =>
                                                                      x.GetValidationKinds()) },
                { "MoveValidation",
                  helper.GetUmbracoApiService <ValidationsController>(x =>
                                                                      x.MoveValidation(null)) },
                { "DeleteDataValue",
                  helper.GetUmbracoApiService <DataValuesController>(x =>
                                                                     x.DeleteDataValue(null)) },
                { "PersistDataValue",
                  helper.GetUmbracoApiService <DataValuesController>(x =>
                                                                     x.PersistDataValue(null)) },
                { "GetDataValueInfo",
                  helper.GetUmbracoApiService <DataValuesController>(x =>
                                                                     x.GetDataValueInfo(null)) },
                { "GetDataValuesInfo",
                  helper.GetUmbracoApiService <DataValuesController>(x =>
                                                                     x.GetDataValuesInfo(null)) },
                { "GetDataValueKinds",
                  helper.GetUmbracoApiService <DataValuesController>(x =>
                                                                     x.GetDataValueKinds()) },
                { "MoveDataValue",
                  helper.GetUmbracoApiService <DataValuesController>(x =>
                                                                     x.MoveDataValue(null)) },
                { "PersistFolder",
                  helper.GetUmbracoApiService <FoldersController>(x =>
                                                                  x.PersistFolder(null)) },
                { "GetFolderInfo",
                  helper.GetUmbracoApiService <FoldersController>(x =>
                                                                  x.GetFolderInfo(null)) },
                { "MoveFolder",
                  helper.GetUmbracoApiService <FoldersController>(x =>
                                                                  x.MoveFolder(null)) },
                { "DeleteFolder",
                  helper.GetUmbracoApiService <FoldersController>(x =>
                                                                  x.DeleteFolder(null)) },
                { "GetFieldTypes",
                  helper.GetUmbracoApiService <FieldsController>(x =>
                                                                 x.GetFieldTypes()) },
                { "GetHandlerTypes",
                  helper.GetUmbracoApiService <HandlersController>(x =>
                                                                   x.GetHandlerTypes()) },
                { "GetTemplates",
                  helper.GetUmbracoApiService <TemplatesController>(x =>
                                                                    x.GetTemplates()) },
                { "PermitAccess",
                  helper.GetUmbracoApiService <SetupController>(x =>
                                                                x.PermitAccessToFormulate()) },
                { "GetEntityChildren",
                  helper.GetUmbracoApiService <EntitiesController>(x =>
                                                                   x.GetEntityChildren(null)) },
                { "GetEntity",
                  helper.GetUmbracoApiService <EntitiesController>(x =>
                                                                   x.GetEntity(null)) },
                { "EditLayoutBase", "/formulate/formulate/editLayout/" },
                { "EditValidationBase",
                  "/formulate/formulate/editValidation/" },
                { "EditDataValueBase",
                  "/formulate/formulate/editDataValue/" },
                { "Layout.RootId", LayoutConstants.Id },
                { "Validation.RootId", ValidationConstants.Id },
                { "DataValue.RootId", DataValueConstants.Id },
                { "Form.RootId", FormConstants.Id }
            });
        }
Exemplo n.º 25
0
        public async void RouteEdit_EndDrawPolygonEvent(object sender, DrawPolygonEventArgs args)
        {
            dtGridRoute.Focus();


            if (args.isCancel)
            {
                int i = dtGridRoute.SelectedIndex;
                if (i > 0)
                {

                    RouteData currRouteData = (RouteData)dtGridRoute.Items[i];
                    if (!RouteShowList.ContainsKey(currRouteData.RouteName))
                    {
                        RouteShowList.Add(currRouteData.RouteName, currRouteData.route);
                    }
                }
            }
            else
            {
                Route route = null;// 
                if (!args.isNew)
                {
                      

                    if (dtGridRoute.ItemsSource == null) return;

                    List<RouteData> listData = (List<RouteData>)(dtGridRoute.ItemsSource);

                    RouteData currRouteData = null;
                    for (int j = 0; j < listData.Count; j++)
                    {
                        if (listData[j].RouteName == args.PolygonName)
                        {
                            currRouteData = listData[j];
                            break;
                        }
                    }

                    if (currRouteData == null) return;

                 //Victor   currRouteData.route.arr_legs = LegSector;
                    route = currRouteData.route;
                    if (!RouteShowList.ContainsKey(currRouteData.RouteName))
                    {
                        RouteShowList.Add(currRouteData.RouteName, currRouteData.route);
                    }


                }
                else
                {
                    route = new Route();                   

                   // LegSector = CreateLegSector(args.PolygonPnts);
                    route.Points =new List<DPoint>(args.PolygonPnts);
                    route.RouteName = args.PolygonName;

                    RouteData Rdata = new RouteData();
                    Rdata.route = route;




                    ((List<RouteData>)(dtGridRoute.ItemsSource)).Add(Rdata);
                    dtGridRoute.Items.Refresh();
                    dtGridRoute.SelectedItem = Rdata;
                    dtGridRoute.CurrentItem = Rdata;
                    DataGridWPFUtility.DataGridGotoLast(dtGridRoute);
                }

                await SAGSignalR.SaveRoute(VMMainViewModel.Instance.SimulationHubProxy, route);
            }
        }
Exemplo n.º 26
0
        public async void RouteEdit_EndDrawPolygonEvent(object sender, DrawPolygonEventArgs args)
        {
            dtGridRoute.Focus();


            if (args.isCancel)
            {
                int i = dtGridRoute.SelectedIndex;
                if (i > 0)
                {
                    RouteData currRouteData = (RouteData)dtGridRoute.Items[i];
                    if (!RouteShowList.ContainsKey(currRouteData.RouteName))
                    {
                        RouteShowList.Add(currRouteData.RouteName, currRouteData.route);
                    }
                }
            }
            else
            {
                Route route = null;//
                if (!args.isNew)
                {
                    if (dtGridRoute.ItemsSource == null)
                    {
                        return;
                    }

                    List <RouteData> listData = (List <RouteData>)(dtGridRoute.ItemsSource);

                    RouteData currRouteData = null;
                    for (int j = 0; j < listData.Count; j++)
                    {
                        if (listData[j].RouteName == args.PolygonName)
                        {
                            currRouteData = listData[j];
                            break;
                        }
                    }

                    if (currRouteData == null)
                    {
                        return;
                    }

                    //Victor   currRouteData.route.arr_legs = LegSector;
                    route = currRouteData.route;
                    if (!RouteShowList.ContainsKey(currRouteData.RouteName))
                    {
                        RouteShowList.Add(currRouteData.RouteName, currRouteData.route);
                    }
                }
                else
                {
                    route = new Route();

                    // LegSector = CreateLegSector(args.PolygonPnts);
                    route.Points    = new List <DPoint>(args.PolygonPnts);
                    route.RouteName = args.PolygonName;

                    RouteData Rdata = new RouteData();
                    Rdata.route = route;



                    ((List <RouteData>)(dtGridRoute.ItemsSource)).Add(Rdata);
                    dtGridRoute.Items.Refresh();
                    dtGridRoute.SelectedItem = Rdata;
                    dtGridRoute.CurrentItem  = Rdata;
                    DataGridWPFUtility.DataGridGotoLast(dtGridRoute);
                }

                await SAGSignalR.SaveRoute(VMMainViewModel.Instance.SimulationHubProxy, route);
            }
        }
Exemplo n.º 27
0
    void Update()
    {
        if(isDrawingMode)
        {
            if ( Input.GetMouseButtonDown (0)) {
                CheckStartPoint(Camera.main.ScreenToWorldPoint (Input.mousePosition));
            } else if(isDrawing && Input.GetMouseButton(0))
            {
                ContinueRoad (Camera.main.ScreenToWorldPoint (Input.mousePosition));
            } else if(Input.GetMouseButtonUp(0))
            {
                if(isDrawing)
                {
                    if(!isFinishFound)
                    {
                        GameObject removeThis = roads[roads.Count-1];
                        roads.RemoveAt(roads.Count-1);
                        Destroy(removeThis);
                    } else
                    {
                        RouteData route = new RouteData();
                        route.SetParams(mapController.RoutePointOnPosition(currentPositions[0]),mapController.RoutePointOnPosition(currentPositions[1]), "external");
                        mapController.routes.Add(route);
                    }
                    isDrawing = false;
                    isFinishFound = false;
                }

            }
        }
    }
Exemplo n.º 28
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RouteDataAssertions" /> class.
 /// </summary>
 public RouteDataAssertions(RouteData subject)
     : base(subject)
 {
     Subject = subject;
 }
Exemplo n.º 29
0
		private static void ParseRouteForData(string FileName, bool IsRW, System.Text.Encoding Encoding, string TrainPath, string ObjectPath, string SoundPath, ref RouteData Data, bool PreviewOnly) {
			//Read the entire routefile into memory
			string[] Lines = System.IO.File.ReadAllLines(FileName, Encoding);
			Expression[] Expressions;
			PreprocessSplitIntoExpressions(FileName, IsRW, Lines, out Expressions, true, 0.0);
			PreprocessChrRndSub(FileName, IsRW, ref Expressions);
			double[] UnitOfLength = new double[] { 1.0 };
			//Set units of speed initially to km/h
			//This represents 1km/h in m/s
			Data.UnitOfSpeed = 0.277777777777778;
			PreprocessOptions(IsRW, Expressions, ref Data, ref UnitOfLength);
			PreprocessSortByTrackPosition(IsRW, UnitOfLength, ref Expressions);
			ParseRouteForData(FileName, IsRW, Encoding, Expressions, TrainPath, ObjectPath, SoundPath, UnitOfLength, ref Data, PreviewOnly);
			Game.RouteUnitOfLength = UnitOfLength;
		}
Exemplo n.º 30
0
        protected void Application_Error(Object sender, EventArgs e)
        {
            Exception objExp = HttpContext.Current.Server.GetLastError();

            //LogHelper.WriteLog("\r\nIP:" + Request.UserHostAddress + "\r\nError Page:" + Request.Url + "\r\nInner Message:" + Server.GetLastError().InnerException.Message + "\r\nMessage:" + Server.GetLastError().Message, objExp);
            if (objExp != null)
            {
                string errString = string.Join("\r\n",
                                               new string[] {
                    "IP:" + Request.UserHostAddress,
                    "Error Page:" + Request.Url,
                    "Inner Message:" + (objExp.InnerException == null ? string.Empty : objExp.InnerException.Message),
                    "Message:" + (objExp == null ? string.Empty : objExp.Message)
                }
                                               );
                LogHelper.WriteLog(errString, objExp);
            }

            Exception exception = Server.GetLastError();

            // Log the exception.

            Response.Clear();

            RouteData routeData = new RouteData();

            routeData.Values.Add("action", "Index");
            routeData.Values.Add("controller", "Error");

            //HttpException httpException = exception as HttpException;


            //if (httpException == null)
            //{
            //    routeData.Values.Add("action", "Index");
            //}
            //else //It's an Http Exception, Let's handle it.
            //{
            //    switch (httpException.GetHttpCode())
            //    {
            //        case 404:
            //            // Page not found.
            //            routeData.Values.Add("action", "HttpError404");
            //            break;
            //        case 500:
            //            // Server error.
            //            routeData.Values.Add("action", "HttpError500");
            //            break;

            //        // Here you can handle Views to other error codes.
            //        // I choose a General error template
            //        default:
            //            routeData.Values.Add("action", "General");
            //            break;
            //    }
            //}

            // Pass exception details to the target error View.
            routeData.Values.Add("error", exception);

            // Clear the error on server.
            Server.ClearError();

            // Avoid IIS7 getting in the middle
            Response.TrySkipIisCustomErrors = true;

            // Call target Controller and pass the routeData.
            IController errorController = new ErrorController();

            errorController.Execute(new RequestContext(
                                        new HttpContextWrapper(Context), routeData));
        }
 public EmbeddedResourceHttpHandler(string rootPath, RouteData routeData)
 {
     _rootPath  = rootPath;
     _routeData = routeData;
 }
Exemplo n.º 32
0
 public void AfterAction(ActionDescriptor actionDescriptor, HttpContext httpContext, RouteData routeData)
 {
     Event(httpContext, "AspNetCore.Mvc AfterAction");
 }
Exemplo n.º 33
0
        public ActionResult Index(RulesIndexOptions options, PagerParameters pagerParameters)
        {
            if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to list rules")))
            {
                return(new HttpUnauthorizedResult());
            }

            var pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);

            // default options
            if (options == null)
            {
                options = new RulesIndexOptions();
            }

            var rules = _rulesServices.GetRules();

            switch (options.Filter)
            {
            case RulesFilter.Disabled:
                rules = rules.Where(r => r.Enabled == false);
                break;

            case RulesFilter.Enabled:
                rules = rules.Where(u => u.Enabled);
                break;
            }

            if (!String.IsNullOrWhiteSpace(options.Search))
            {
                rules = rules.Where(r => r.Name.Contains(options.Search));
            }

            var pagerShape = Shape.Pager(pager).TotalItemCount(rules.Count());

            switch (options.Order)
            {
            case RulesOrder.Name:
                rules = rules.OrderBy(u => u.Name);
                break;
            }

            var results = rules
                          .Skip(pager.GetStartIndex())
                          .Take(pager.PageSize)
                          .ToList();

            var model = new RulesIndexViewModel {
                Rules = results.Select(x => new RulesEntry {
                    Rule      = x,
                    IsChecked = false,
                    RuleId    = x.Id
                }).ToList(),
                Options = options,
                Pager   = pagerShape
            };

            // maintain previous route data when generating page links
            var routeData = new RouteData();

            routeData.Values.Add("Options.Filter", options.Filter);
            routeData.Values.Add("Options.Search", options.Search);
            routeData.Values.Add("Options.Order", options.Order);

            pagerShape.RouteData(routeData);

            return(View(model));
        }
Exemplo n.º 34
0
        public static MvcHtmlString FormController(this HtmlHelper htmlHelper, Guid id, FormViewMode viewMode, object routeValues, FormCollection collection = null)
        {
            var manager     = FormsManager.GetManager();
            var controlData = manager.GetControl <FormControl>(id);
            var control     = manager.LoadControl(controlData);

            control.Page = HttpContext.Current.Handler as Page;

            var mvcProxy = control as MvcProxyBase;

            if (mvcProxy == null)
            {
                throw new InvalidOperationException("Cannot render form controller with the given ID becaouse the control with this ID is not an MVC proxy.");
            }

            var actionInvoker = ObjectFactory.Resolve <IControllerActionInvoker>() as Telerik.Sitefinity.Mvc.ControllerActionInvoker;

            if (actionInvoker != null)
            {
                actionInvoker.DeserializeControllerProperties(mvcProxy);
            }

            var routeData = new RouteData();

            if (routeValues != null)
            {
                var routeDictionary = new RouteValueDictionary(routeValues);
                foreach (var kv in routeDictionary)
                {
                    routeData.Values.Add(kv.Key, kv.Value);
                }
            }

            var controller = mvcProxy.GetController();

            if (collection != null)
            {
                var formField = controller as IFormFieldController <IFormFieldModel>;

                if (formField != null && collection.Keys.Contains(formField.MetaField.FieldName))
                {
                    var fieldValue = collection[formField.MetaField.FieldName];
                    if (fieldValue != null)
                    {
                        routeData.Values.Add("Value", fieldValue);
                    }
                }
            }

            if (mvcProxy.IsIndexingMode() && controller.GetIndexRenderMode() == IndexRenderModes.NoOutput)
            {
                return(MvcHtmlString.Empty);
            }

            var controllerFactory = (ISitefinityControllerFactory)ControllerBuilder.Current.GetControllerFactory();
            var controllerType    = controller.GetType();
            var explicitMode      = ControllerHelpers.ExplicitMode(controllerType);

            if ((explicitMode == FormControlDisplayMode.Read && viewMode != FormViewMode.Read) || (explicitMode == FormControlDisplayMode.Write && viewMode != FormViewMode.Write))
            {
                return(MvcHtmlString.Empty);
            }

            routeData.Values["controller"] = controllerFactory.GetControllerName(controllerType);

            string action = typeof(IFormElementController <IFormElementModel>).IsAssignableFrom(controllerType) ? action = viewMode.ToString() : action = "Index";

            routeData.Values["action"] = action;

            using (var writer = new StringWriter())
            {
                var context = new HttpContextWrapper(new HttpContext(HttpContext.Current.Request, new HttpResponse(writer)));
                ControllerHelpers.PopulateHttpContext(context);

                controller.ControllerContext = new ControllerContext(context, routeData, controller);
                controller.ActionInvoker.InvokeAction(controller.ControllerContext, action);

                ControllerHelpers.RestoreHttpContext(controller);

                var result = writer.ToString();
                return(MvcHtmlString.Create(result));
            }
        }
Exemplo n.º 35
0
 // Very simple matching for the purpose of the exercise.
 public bool Matches(RouteData routeData, string httpMethod) =>
 HttpMethods.IsGet(httpMethod) &&
 string.Equals((string)routeData.Values["controller"], "orders", StringComparison.OrdinalIgnoreCase) &&
 !routeData.Values.ContainsKey("id");
Exemplo n.º 36
0
 public SessionControllerHandler(RouteData routeData)
     : base(routeData)
 {
 }
 public MyHttpControllerHandler(RouteData routeData)
     : base(routeData)
 {
 }
Exemplo n.º 38
0
        /// <summary>
        /// Mocks the http context to test against
        /// </summary>
        /// <param name="fullUrl"></param>
        /// <param name="routeData"></param>
        /// <returns></returns>
        private void CreateContext(Uri fullUrl, RouteData routeData = null)
        {
            //Request context

            var requestContextMock = new Mock <RequestContext>();

            RequestContext = requestContextMock.Object;

            //Cookie collection
            var cookieCollection = new HttpCookieCollection();

            cookieCollection.Add(new HttpCookie("UMB_UCONTEXT", "FBA996E7-D6BE-489B-B199-2B0F3D2DD826"));

            //Request
            var requestMock = new Mock <HttpRequestBase>();

            requestMock.Setup(x => x.AppRelativeCurrentExecutionFilePath).Returns("~" + fullUrl.AbsolutePath);
            requestMock.Setup(x => x.PathInfo).Returns(string.Empty);
            requestMock.Setup(x => x.RawUrl).Returns(VirtualPathUtility.ToAbsolute("~" + fullUrl.AbsolutePath, "/"));
            requestMock.Setup(x => x.RequestContext).Returns(RequestContext);
            requestMock.Setup(x => x.Url).Returns(fullUrl);
            requestMock.Setup(x => x.ApplicationPath).Returns("/");
            requestMock.Setup(x => x.Cookies).Returns(cookieCollection);
            requestMock.Setup(x => x.ServerVariables).Returns(new NameValueCollection());
            var queryStrings = HttpUtility.ParseQueryString(fullUrl.Query);

            requestMock.Setup(x => x.QueryString).Returns(queryStrings);
            requestMock.Setup(x => x.Form).Returns(new NameValueCollection());

            //Cache
            var cacheMock = new Mock <HttpCachePolicyBase>();

            //Response
            //var response = new FakeHttpResponse();
            var responseMock = new Mock <HttpResponseBase>();

            responseMock.Setup(x => x.ApplyAppPathModifier(It.IsAny <string>())).Returns((string s) => s);
            responseMock.Setup(x => x.Cache).Returns(cacheMock.Object);

            //Server

            var serverMock = new Mock <HttpServerUtilityBase>();

            serverMock.Setup(x => x.MapPath(It.IsAny <string>())).Returns(Environment.CurrentDirectory);

            //User
            var user = new Mock <IPrincipal>().Object;

            //HTTP Context

            var httpContextMock = new Mock <HttpContextBase>();

            httpContextMock.Setup(x => x.Cache).Returns(HttpRuntime.Cache);
            //note: foreach on Items should return DictionaryEntries!
            //httpContextMock.Setup(x => x.Items).Returns(new Dictionary<object, object>());
            httpContextMock.Setup(x => x.Items).Returns(new Hashtable());
            httpContextMock.Setup(x => x.Request).Returns(requestMock.Object);
            httpContextMock.Setup(x => x.Server).Returns(serverMock.Object);
            httpContextMock.Setup(x => x.Response).Returns(responseMock.Object);
            httpContextMock.Setup(x => x.User).Returns(user);

            HttpContext = httpContextMock.Object;

            requestContextMock.Setup(x => x.HttpContext).Returns(httpContextMock.Object);

            if (routeData != null)
            {
                requestContextMock.Setup(x => x.RouteData).Returns(routeData);
            }
        }
Exemplo n.º 39
0
        private static async Task PutFile(HttpRequest request, HttpResponse response, RouteData routeData, IFiles files)
        {
            var file = routeData.GetString("file");
            var type = request.Query.GetEnumOrDefault("type", FileType.Binary);

            await files.WriteAsync(file, request.Body, type);

            response.StatusCode = 201;
        }
Exemplo n.º 40
0
        /// <summary>
        /// Creates a scope used to instrument an MVC action and populates some common details.
        /// </summary>
        /// <param name="controllerContext">The System.Web.Mvc.ControllerContext that was passed as an argument to the instrumented method.</param>
        /// <returns>A new scope used to instrument an MVC action.</returns>
        public static Scope CreateScope(object controllerContext)
        {
            Scope scope = null;

            try
            {
                if (!Tracer.Instance.Settings.IsIntegrationEnabled(IntegrationName))
                {
                    // integration disabled, don't create a scope, skip this trace
                    return null;
                }

                if (controllerContext == null || controllerContext.GetType().FullName != ControllerContextTypeName)
                {
                    return null;
                }

                var httpContext = controllerContext.GetProperty<HttpContextBase>("HttpContext").GetValueOrDefault();

                if (httpContext == null)
                {
                    return null;
                }

                string host = httpContext.Request.Headers.Get("Host");
                string httpMethod = httpContext.Request.HttpMethod.ToUpperInvariant();
                string url = httpContext.Request.RawUrl.ToLowerInvariant();
                string resourceName = null;

                RouteData routeData = controllerContext.GetProperty<RouteData>("RouteData").GetValueOrDefault();
                Route route = routeData?.Route as Route;
                RouteValueDictionary routeValues = routeData?.Values;

                if (route == null && routeData?.Route.GetType().FullName == RouteCollectionRouteTypeName)
                {
                    var routeMatches = routeValues?.GetValueOrDefault("MS_DirectRouteMatches") as List<RouteData>;

                    if (routeMatches?.Count > 0)
                    {
                        // route was defined using attribute routing i.e. [Route("/path/{id}")]
                        // get route and routeValues from the RouteData in routeMatches
                        route = routeMatches[0].Route as Route;
                        routeValues = routeMatches[0].Values;

                        if (route != null)
                        {
                            var resourceUrl = route.Url?.ToLowerInvariant() ?? string.Empty;
                            if (resourceUrl.FirstOrDefault() != '/')
                            {
                                resourceUrl = string.Concat("/", resourceUrl);
                            }

                            resourceName = $"{httpMethod} {resourceUrl}";
                        }
                    }
                }

                if (string.IsNullOrEmpty(resourceName) && httpContext.Request.Url != null)
                {
                    var cleanUri = UriHelpers.GetRelativeUrl(httpContext.Request.Url, tryRemoveIds: true);
                    resourceName = $"{httpMethod} {cleanUri.ToLowerInvariant()}";
                }

                string controllerName = (routeValues?.GetValueOrDefault("controller") as string)?.ToLowerInvariant();
                string actionName = (routeValues?.GetValueOrDefault("action") as string)?.ToLowerInvariant();

                if (string.IsNullOrEmpty(resourceName))
                {
                    // Keep the legacy resource name, just to have something
                    resourceName = $"{httpMethod} {controllerName}.{actionName}";
                }

                SpanContext propagatedContext = null;
                var tracer = Tracer.Instance;

                if (tracer.ActiveScope == null)
                {
                    try
                    {
                        // extract propagated http headers
                        var headers = httpContext.Request.Headers.Wrap();
                        propagatedContext = B3SpanContextPropagator.Instance.Extract(headers);
                    }
                    catch (Exception ex)
                    {
                        Log.Error(ex, "Error extracting propagated HTTP headers.");
                    }
                }

                scope = Tracer.Instance.StartActive(OperationName, propagatedContext);
                Span span = scope.Span;

                // Fail safe to catch templates in routing values
                resourceName =
                    resourceName
                       .Replace("{controller}", controllerName)
                       .Replace("{action}", actionName);

                IPAddress remoteIp = null;
                if (Tracer.Instance.Settings.AddClientIpToServerSpans)
                {
                    IPAddress.TryParse(httpContext.Request.UserHostAddress, out remoteIp);
                }

                span.DecorateWebServerSpan(
                    resourceName: resourceName,
                    method: httpMethod,
                    host: host,
                    httpUrl: url,
                    remoteIp: remoteIp);
                span.SetTag(Tags.AspNetRoute, route?.Url);
                span.SetTag(Tags.AspNetController, controllerName);
                span.SetTag(Tags.AspNetAction, actionName);

                // set analytics sample rate if enabled
                var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: true);
                span.SetMetric(Tags.Analytics, analyticsSampleRate);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error creating or populating scope.");
            }

            return scope;
        }
Exemplo n.º 41
0
        public async virtual Task RouteAsync([NotNull] RouteContext context)
        {
            EnsureLoggers(context.HttpContext);

            var requestPath = context.HttpContext.Request.Path.Value;

            if (!string.IsNullOrEmpty(requestPath) && requestPath[0] == '/')
            {
                requestPath = requestPath.Substring(1);
            }

            var values = _matcher.Match(requestPath);

            if (values == null)
            {
                // If we got back a null value set, that means the URI did not match
                return;
            }

            var oldRouteData = context.RouteData;

            var newRouteData = new RouteData(oldRouteData);
            MergeValues(newRouteData.DataTokens, _dataTokens);
            newRouteData.Routers.Add(_target);
            MergeValues(newRouteData.Values, values);

            if (!RouteConstraintMatcher.Match(
                Constraints,
                newRouteData.Values,
                context.HttpContext,
                this,
                RouteDirection.IncomingRequest,
                _constraintLogger))
            {
                return;
            }

            _logger.LogVerbose(
                "Request successfully matched the route with name '{RouteName}' and template '{RouteTemplate}'.",
                Name,
                RouteTemplate);

            try
            {
                context.RouteData = newRouteData;

                await _target.RouteAsync(context);
            }
            finally
            {
                // Restore the original values to prevent polluting the route data.
                if (!context.IsHandled)
                {
                    context.RouteData = oldRouteData;
                }
            }
        }
Exemplo n.º 42
0
 // ================================
 // create missing blocks
 private static void CreateMissingBlocks(ref RouteData Data, ref int BlocksUsed, int ToIndex, bool PreviewOnly)
 {
     if (ToIndex >= BlocksUsed) {
         while (Data.Blocks.Length <= ToIndex) {
             Array.Resize<Block>(ref Data.Blocks, Data.Blocks.Length << 1);
         }
         for (int i = BlocksUsed; i <= ToIndex; i++) {
             Data.Blocks[i] = new Block();
             if (!PreviewOnly) {
                 Data.Blocks[i].Background = -1;
                 Data.Blocks[i].Brightness = new Brightness[] { };
                 Data.Blocks[i].Fog = Data.Blocks[i - 1].Fog;
                 Data.Blocks[i].FogDefined = false;
                 Data.Blocks[i].Cycle = Data.Blocks[i - 1].Cycle;
                 Data.Blocks[i].Height = double.NaN;
             }
             Data.Blocks[i].RailType = new int[Data.Blocks[i - 1].RailType.Length];
             for (int j = 0; j < Data.Blocks[i].RailType.Length; j++) {
                 Data.Blocks[i].RailType[j] = Data.Blocks[i - 1].RailType[j];
             }
             Data.Blocks[i].Rail = new Rail[Data.Blocks[i - 1].Rail.Length];
             for (int j = 0; j < Data.Blocks[i].Rail.Length; j++) {
                 Data.Blocks[i].Rail[j].RailStart = Data.Blocks[i - 1].Rail[j].RailStart;
                 Data.Blocks[i].Rail[j].RailStartX = Data.Blocks[i - 1].Rail[j].RailStartX;
                 Data.Blocks[i].Rail[j].RailStartY = Data.Blocks[i - 1].Rail[j].RailStartY;
                 Data.Blocks[i].Rail[j].RailStartRefreshed = false;
                 Data.Blocks[i].Rail[j].RailEnd = false;
                 Data.Blocks[i].Rail[j].RailEndX = Data.Blocks[i - 1].Rail[j].RailStartX;
                 Data.Blocks[i].Rail[j].RailEndY = Data.Blocks[i - 1].Rail[j].RailStartY;
             }
             if (!PreviewOnly) {
                 Data.Blocks[i].RailWall = new WallDike[Data.Blocks[i - 1].RailWall.Length];
                 for (int j = 0; j < Data.Blocks[i].RailWall.Length; j++) {
                     Data.Blocks[i].RailWall[j] = Data.Blocks[i - 1].RailWall[j];
                 }
                 Data.Blocks[i].RailDike = new WallDike[Data.Blocks[i - 1].RailDike.Length];
                 for (int j = 0; j < Data.Blocks[i].RailDike.Length; j++) {
                     Data.Blocks[i].RailDike[j] = Data.Blocks[i - 1].RailDike[j];
                 }
                 Data.Blocks[i].RailPole = new Pole[Data.Blocks[i - 1].RailPole.Length];
                 for (int j = 0; j < Data.Blocks[i].RailPole.Length; j++) {
                     Data.Blocks[i].RailPole[j] = Data.Blocks[i - 1].RailPole[j];
                 }
                 Data.Blocks[i].Form = new Form[] { };
                 Data.Blocks[i].Crack = new Crack[] { };
                 Data.Blocks[i].Signal = new Signal[] { };
                 Data.Blocks[i].Section = new Section[] { };
                 Data.Blocks[i].Sound = new Sound[] { };
                 Data.Blocks[i].Transponder = new Transponder[] { };
                 Data.Blocks[i].RailFreeObj = new FreeObj[][] { };
                 Data.Blocks[i].GroundFreeObj = new FreeObj[] { };
                 Data.Blocks[i].PointsOfInterest = new PointOfInterest[] { };
             }
             Data.Blocks[i].Pitch = Data.Blocks[i - 1].Pitch;
             Data.Blocks[i].Limit = new Limit[] { };
             Data.Blocks[i].Stop = new Stop[] { };
             Data.Blocks[i].Station = -1;
             Data.Blocks[i].StationPassAlarm = false;
             Data.Blocks[i].CurrentTrackState = Data.Blocks[i - 1].CurrentTrackState;
             Data.Blocks[i].Turn = 0.0;
             Data.Blocks[i].Accuracy = Data.Blocks[i - 1].Accuracy;
             Data.Blocks[i].AdhesionMultiplier = Data.Blocks[i - 1].AdhesionMultiplier;
         }
         BlocksUsed = ToIndex + 1;
     }
 }
Exemplo n.º 43
0
        private  async void LoadData()
        {
            List<RouteData> RouteDataList = new List<RouteData>();
            try
            {
                IEnumerable<GeneralActivityDTO> Activities = await SAGSignalR.GetAllActivites(VMMainViewModel.Instance.SimulationHubProxy);


                IEnumerable<Route> Routes = await SAGSignalR.getRoutes(VMMainViewModel.Instance.SimulationHubProxy);
                if (Routes!=null)
                {
                    foreach (Route route in Routes)
                    {
                        RouteData Rdata = new RouteData();
                        Rdata.route = route;

                        if (Activities != null)
                        {
                            foreach (GeneralActivityDTO activity in Activities)
                            {
                                if (activity.RouteActivity.RouteGuid == route.RouteGuid)
                                {
                                    Rdata.IsInUse = true;
                                    break;
                                }
                            }

                        }


                        RouteDataList.Add(Rdata);

                    }
                }




               
                dtGridRoute.ItemsSource = null;
                dtGridRoute.ItemsSource = RouteDataList;

                if(dtGridRoute.ItemsSource==null)
                {
                    dtGridRoute.ItemsSource = new List<RouteData>();
                }


            }
            catch(Exception ex)
            {

            }

        }
Exemplo n.º 44
0
 // parse route for data
 private static void ParseRouteForData(string FileName, bool IsRW, System.Text.Encoding Encoding, Expression[] Expressions, string TrainPath, string ObjectPath, string SoundPath, double[] UnitOfLength, ref RouteData Data, bool PreviewOnly)
 {
     System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
     string Section = ""; bool SectionAlwaysPrefix = false;
     int BlockIndex = 0;
     int BlocksUsed = Data.Blocks.Length;
     Game.Stations = new Game.Station[] { };
     int CurrentStation = -1;
     int CurrentStop = -1;
     bool DepartureSignalUsed = false;
     int CurrentSection = 0;
     bool ValueBasedSections = false;
     double progressFactor = Expressions.Length == 0 ? 0.3333 : 0.3333 / (double)Expressions.Length;
     // process non-track namespaces
     for (int j = 0; j < Expressions.Length; j++) {
         Loading.RouteProgress = (double)j * progressFactor;
         if ((j & 255) == 0) {
             System.Threading.Thread.Sleep(1);
             if (Loading.Cancel) return;
         }
         if (Expressions[j].Text.StartsWith("[") & Expressions[j].Text.EndsWith("]")) {
             Section = Expressions[j].Text.Substring(1, Expressions[j].Text.Length - 2).Trim();
             if (string.Compare(Section, "object", StringComparison.OrdinalIgnoreCase) == 0) {
                 Section = "Structure";
             } else if (string.Compare(Section, "railway", StringComparison.OrdinalIgnoreCase) == 0) {
                 Section = "Track";
             }
             SectionAlwaysPrefix = true;
         } else {
             // find equals
             int Equals = Expressions[j].Text.IndexOf('=');
             if (Equals >= 0) {
                 // handle RW cycle syntax
                 string t = Expressions[j].Text.Substring(0, Equals);
                 if (Section.ToLowerInvariant() == "cycle" & SectionAlwaysPrefix) {
                     double b; if (Interface.TryParseDoubleVb6(t, out b)) {
                         t = ".Ground(" + t + ")";
                     }
                 } else if (Section.ToLowerInvariant() == "signal" & SectionAlwaysPrefix) {
                     double b; if (Interface.TryParseDoubleVb6(t, out b)) {
                         t = ".Void(" + t + ")";
                     }
                 }
                 // convert RW style into CSV style
                 Expressions[j].Text = t + " " + Expressions[j].Text.Substring(Equals + 1);
             }
             // separate command and arguments
             string Command, ArgumentSequence;
             SeparateCommandsAndArguments(Expressions[j], out Command, out ArgumentSequence, Culture, Expressions[j].File, j, false);
             // process command
             double Number;
             bool NumberCheck = !IsRW || string.Compare(Section, "track", StringComparison.OrdinalIgnoreCase) == 0;
             if (NumberCheck && Interface.TryParseDouble(Command, UnitOfLength, out Number)) {
                 // track position (ignored)
             } else {
                 // split arguments
                 string[] Arguments;
                 {
                     int n = 0;
                     for (int k = 0; k < ArgumentSequence.Length; k++) {
                         if (IsRW & ArgumentSequence[k] == ',') {
                             n++;
                         } else if (ArgumentSequence[k] == ';') {
                             n++;
                         }
                     }
                     Arguments = new string[n + 1];
                     int a = 0, h = 0;
                     for (int k = 0; k < ArgumentSequence.Length; k++) {
                         if (IsRW & ArgumentSequence[k] == ',') {
                             Arguments[h] = ArgumentSequence.Substring(a, k - a).Trim();
                             a = k + 1; h++;
                         } else if (ArgumentSequence[k] == ';') {
                             Arguments[h] = ArgumentSequence.Substring(a, k - a).Trim();
                             a = k + 1; h++;
                         }
                     }
                     if (ArgumentSequence.Length - a > 0) {
                         Arguments[h] = ArgumentSequence.Substring(a).Trim();
                         h++;
                     }
                     Array.Resize<string>(ref Arguments, h);
                 }
                 // preprocess command
                 if (Command.ToLowerInvariant() == "with") {
                     if (Arguments.Length >= 1) {
                         Section = Arguments[0];
                         SectionAlwaysPrefix = false;
                     } else {
                         Section = "";
                         SectionAlwaysPrefix = false;
                     }
                     Command = null;
                 } else {
                     if (Command.StartsWith(".")) {
                         Command = Section + Command;
                     } else if (SectionAlwaysPrefix) {
                         Command = Section + "." + Command;
                     }
                     Command = Command.Replace(".Void", "");
                     if (Command.StartsWith("structure", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".load", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 5).TrimEnd();
                     } else if (Command.StartsWith("texture.background", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".load", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 5).TrimEnd();
                     } else if (Command.StartsWith("texture.background", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".x", StringComparison.OrdinalIgnoreCase)) {
                         Command = "texture.background.x" + Command.Substring(18, Command.Length - 20).TrimEnd();
                     } else if (Command.StartsWith("texture.background", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".aspect", StringComparison.OrdinalIgnoreCase)) {
                         Command = "texture.background.aspect" + Command.Substring(18, Command.Length - 25).TrimEnd();
                     } else if (Command.StartsWith("structure.back", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".x", StringComparison.OrdinalIgnoreCase)) {
                         Command = "texture.background.x" + Command.Substring(14, Command.Length - 16).TrimEnd();
                     } else if (Command.StartsWith("structure.back", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".aspect", StringComparison.OrdinalIgnoreCase)) {
                         Command = "texture.background.aspect" + Command.Substring(14, Command.Length - 21).TrimEnd();
                     } else if (Command.StartsWith("cycle", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".params", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 7).TrimEnd();
                     } else if (Command.StartsWith("signal", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".load", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 5).TrimEnd();
                     } else if (Command.StartsWith("train.run", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".set", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 4).TrimEnd();
                     } else if (Command.StartsWith("train.flange", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".set", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 4).TrimEnd();
                     } else if (Command.StartsWith("train.timetable", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".day.load", StringComparison.OrdinalIgnoreCase)) {
                         Command = "train.timetable.day" + Command.Substring(15, Command.Length - 24).Trim();
                     } else if (Command.StartsWith("train.timetable", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".night.load", StringComparison.OrdinalIgnoreCase)) {
                         Command = "train.timetable.night" + Command.Substring(15, Command.Length - 26).Trim();
                     } else if (Command.StartsWith("train.timetable", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".day", StringComparison.OrdinalIgnoreCase)) {
                         Command = "train.timetable.day" + Command.Substring(15, Command.Length - 19).Trim();
                     } else if (Command.StartsWith("train.timetable", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".night", StringComparison.OrdinalIgnoreCase)) {
                         Command = "train.timetable.night" + Command.Substring(15, Command.Length - 21).Trim();
                     } else if (Command.StartsWith("route.signal", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".set", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 4).TrimEnd();
                     }
                 }
                 // handle indices
                 int CommandIndex1 = 0, CommandIndex2 = 0;
                 if (Command != null && Command.EndsWith(")")) {
                     for (int k = Command.Length - 2; k >= 0; k--) {
                         if (Command[k] == '(') {
                             string Indices = Command.Substring(k + 1, Command.Length - k - 2).TrimStart();
                             Command = Command.Substring(0, k).TrimEnd();
                             int h = Indices.IndexOf(";");
                             if (h >= 0) {
                                 string a = Indices.Substring(0, h).TrimEnd();
                                 string b = Indices.Substring(h + 1).TrimStart();
                                 if (a.Length > 0 && !Interface.TryParseIntVb6(a, out CommandIndex1)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Invalid first index appeared at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File + ".");
                                     Command = null; break;
                                 } else if (b.Length > 0 && !Interface.TryParseIntVb6(b, out CommandIndex2)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Invalid second index appeared at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File + ".");
                                     Command = null; break;
                                 }
                             } else {
                                 if (Indices.Length > 0 && !Interface.TryParseIntVb6(Indices, out CommandIndex1)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Invalid index appeared at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File + ".");
                                     Command = null; break;
                                 }
                             }
                             break;
                         }
                     }
                 }
                 // process command
                 if (Command != null && Command.Length != 0) {
                     switch (Command.ToLowerInvariant()) {
                             // options
                         case "options.blocklength":
                             {
                                 double length = 25.0;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], UnitOfLength, out length)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Length is invalid in Options.BlockLength at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     length = 25.0;
                                 }
                                 Data.BlockInterval = length;
                             } break;
                         case "options.unitoflength":
                         case "options.unitofspeed":
                         case "options.objectvisibility":
                             break;
                         case "options.sectionbehavior":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 int a;
                                 if (!Interface.TryParseIntVb6(Arguments[0], out a)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Mode is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (a != 0 & a != 1) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Mode is expected to be either 0 or 1 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     ValueBasedSections = a == 1;
                                 }
                             } break;
                         case "options.cantbehavior":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 int a;
                                 if (!Interface.TryParseIntVb6(Arguments[0], out a)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Mode is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (a != 0 & a != 1) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Mode is expected to be either 0 or 1 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     Data.SignedCant = a == 1;
                                 }
                             } break;
                         case "options.fogbehavior":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 int a;
                                 if (!Interface.TryParseIntVb6(Arguments[0], out a)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Mode is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (a != 0 & a != 1) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Mode is expected to be either 0 or 1 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     Data.FogTransitionMode = a == 1;
                                 }
                             } break;
                             // route
                         case "route.comment":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 Game.RouteComment = Arguments[0];
                             } break;
                         case "route.image":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 string f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), Arguments[0]);
                                 if (!System.IO.File.Exists(f)) {
                                     Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     Game.RouteImage = f;
                                 }
                             } break;
                         case "route.timetable":
                             if (!PreviewOnly) {
                                 if (Arguments.Length < 1) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "" + Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     Timetable.DefaultTimetableDescription = Arguments[0];
                                 }
                             } break;
                         case "route.change":
                             if (!PreviewOnly) {
                                 int change = 0;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out change)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Mode is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     change = 0;
                                 } else if (change < -1 | change > 1) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Mode is expected to be -1, 0 or 1 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     change = 0;
                                 }
                                 Game.TrainStart = (Game.TrainStartMode)change;
                             } break;
                         case "route.gauge":
                         case "train.gauge":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 double a;
                                 if (!Interface.TryParseDoubleVb6(Arguments[0], out a)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ValueInMillimeters is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (a <= 0.0) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ValueInMillimeters is expected to be positive in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     Game.RouteRailGauge = 0.001 * a;
                                 }
                             } break;
                         case "route.signal":
                             if (!PreviewOnly) {
                                 if (Arguments.Length < 1) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     double a;
                                     if (!Interface.TryParseDoubleVb6(Arguments[0], out a)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Speed is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (CommandIndex1 < 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "AspectIndex is expected to be non-negative in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (a < 0.0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Speed is expected to be non-negative in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.SignalSpeeds.Length) {
                                                 int n = Data.SignalSpeeds.Length;
                                                 Array.Resize<double>(ref Data.SignalSpeeds, CommandIndex1 + 1);
                                                 for (int i = n; i < CommandIndex1; i++) {
                                                     Data.SignalSpeeds[i] = double.PositiveInfinity;
                                                 }
                                             }
                                             Data.SignalSpeeds[CommandIndex1] = a * Data.UnitOfSpeed;
                                         }
                                     }
                                 }
                             } break;
                         case "route.runinterval":
                         case "train.interval":
                             {
                                 if (!PreviewOnly) {
                                     double[] intervals = new double[Arguments.Length];
                                     for (int k = 0; k < Arguments.Length; k++) {
                                         if (!Interface.TryParseDoubleVb6(Arguments[k], out intervals[k])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Interval" + k.ToString(Culture) + " is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                     }
                                     Array.Sort<double>(intervals);
                                     Game.PrecedingTrainTimeDeltas = intervals;
                                 }
                             } break;
                         case "train.velocity":
                             {
                                 if (!PreviewOnly) {
                                     double limit = 0.0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], out limit)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Speed is invalid in Train.Velocity at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         limit = 0.0;
                                     }
                                     Game.PrecedingTrainSpeedLimit = limit <= 0.0 ? double.PositiveInfinity : Data.UnitOfSpeed * limit;
                                 }
                             } break;
                         case "route.accelerationduetogravity":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 double a;
                                 if (!Interface.TryParseDoubleVb6(Arguments[0], out a)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Value is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (a <= 0.0) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Value is expected to be positive in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     Game.RouteAccelerationDueToGravity = a;
                                 }
                             } break;
                         case "route.elevation":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 double a;
                                 if (!Interface.TryParseDoubleVb6(Arguments[0], UnitOfLength, out a)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Height is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     Game.RouteInitialElevation = a;
                                 }
                             } break;
                         case "route.temperature":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 double a;
                                 if (!Interface.TryParseDoubleVb6(Arguments[0], out a)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ValueInCelsius is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (a <= -273.15) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ValueInCelsius is expected to be greater than to -273.15 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     Game.RouteInitialAirTemperature = a + 273.15;
                                 }
                             } break;
                         case "route.pressure":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 double a;
                                 if (!Interface.TryParseDoubleVb6(Arguments[0], out a)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ValueInKPa is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (a <= 0.0) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ValueInKPa is expected to be positive in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     Game.RouteInitialAirPressure = 1000.0 * a;
                                 }
                             } break;
                         case "route.ambientlight":
                             {
                                 int r = 255, g = 255, b = 255;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out r)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "RedValue is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (r < 0 | r > 255) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "RedValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     r = r < 0 ? 0 : 255;
                                 }
                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out g)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "GreenValue is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (g < 0 | g > 255) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "GreenValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     g = g < 0 ? 0 : 255;
                                 }
                                 if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out b)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "BlueValue is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (b < 0 | b > 255) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "BlueValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     b = b < 0 ? 0 : 255;
                                 }
                                 Renderer.OptionAmbientColor = new Color24((byte)r, (byte)g, (byte)b);
                             } break;
                         case "route.directionallight":
                             {
                                 int r = 255, g = 255, b = 255;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out r)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "RedValue is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (r < 0 | r > 255) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "RedValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     r = r < 0 ? 0 : 255;
                                 }
                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out g)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "GreenValue is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (g < 0 | g > 255) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "GreenValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     g = g < 0 ? 0 : 255;
                                 }
                                 if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out b)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "BlueValue is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (b < 0 | b > 255) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "BlueValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     b = b < 0 ? 0 : 255;
                                 }
                                 Renderer.OptionDiffuseColor = new Color24((byte)r, (byte)g, (byte)b);
                             }
                             break;
                         case "route.lightdirection":
                             {
                                 double theta = 60.0, phi = -26.565051177078;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], out theta)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Theta is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 }
                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[1], out phi)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Phi is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 }
                                 theta *= 0.0174532925199433;
                                 phi *= 0.0174532925199433;
                                 double dx = Math.Cos(theta) * Math.Sin(phi);
                                 double dy = -Math.Sin(theta);
                                 double dz = Math.Cos(theta) * Math.Cos(phi);
                                 Renderer.OptionLightPosition = new World.Vector3Df((float)-dx, (float)-dy, (float)-dz);
                             } break;
                             // train
                         case "train.folder":
                         case "train.file":
                             {
                                 if (PreviewOnly) {
                                     if (Arguments.Length < 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FolderName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             Game.TrainName = Arguments[0];
                                         }
                                     }
                                 }
                             } break;
                         case "train.run":
                         case "train.rail":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailTypeIndex is out of range in "+Command+" at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         int val = 0;
                                         if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out val)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RunSoundIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             val = 0;
                                         }
                                         if (val < 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RunSoundIndex is expected to be non-negative in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             val = 0;
                                         }
                                         if (CommandIndex1 >= Data.Structure.Run.Length) {
                                             Array.Resize<int>(ref Data.Structure.Run, CommandIndex1 + 1);
                                         }
                                         Data.Structure.Run[CommandIndex1] = val;
                                     }
                                 }
                             } break;
                         case "train.flange":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailTypeIndex is out of range in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         int val = 0;
                                         if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out val)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FlangeSoundIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             val = 0;
                                         }
                                         if (val < 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FlangeSoundIndex expected to be non-negative in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             val = 0;
                                         }
                                         if (CommandIndex1 >= Data.Structure.Flange.Length) {
                                             Array.Resize<int>(ref Data.Structure.Flange, CommandIndex1 + 1);
                                         }
                                         Data.Structure.Flange[CommandIndex1] = val;
                                     }
                                 }
                             } break;
                         case "train.timetable.day":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "TimetableIndex is expected to be non-negative in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (Arguments.Length < 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             while (CommandIndex1 >= Data.TimetableDaytime.Length) {
                                                 int n = Data.TimetableDaytime.Length;
                                                 Array.Resize<Textures.Texture>(ref Data.TimetableDaytime, n << 1);
                                                 for (int i = n; i < Data.TimetableDaytime.Length; i++) {
                                                     Data.TimetableDaytime[i] = null;
                                                 }
                                             }
                                             string f = OpenBveApi.Path.CombineFile(TrainPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             }
                                             if (System.IO.File.Exists(f)) {
                                                 Textures.RegisterTexture(f, out Data.TimetableDaytime[CommandIndex1]);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "train.timetable.night":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "TimetableIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (Arguments.Length < 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             while (CommandIndex1 >= Data.TimetableNighttime.Length) {
                                                 int n = Data.TimetableNighttime.Length;
                                                 Array.Resize<Textures.Texture>(ref Data.TimetableNighttime, n << 1);
                                                 for (int i = n; i < Data.TimetableNighttime.Length; i++) {
                                                     Data.TimetableNighttime[i] = null;
                                                 }
                                             }
                                             string f = OpenBveApi.Path.CombineFile(TrainPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             }
                                             if (System.IO.File.Exists(f)) {
                                                 Textures.RegisterTexture(f, out Data.TimetableNighttime[CommandIndex1]);
                                             }
                                         }
                                     }
                                 }
                             } break;
                             // structure
                         case "structure.rail":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.Rail.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.Rail, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.Rail[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.beacon":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "BeaconStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.Beacon.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.Beacon, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.Beacon[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.pole":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "AdditionalRailsCovered is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (CommandIndex2 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "PoleStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.Poles.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject[]>(ref Data.Structure.Poles, CommandIndex1 + 1);
                                             }
                                             if (Data.Structure.Poles[CommandIndex1] == null) {
                                                 Data.Structure.Poles[CommandIndex1] = new ObjectManager.UnifiedObject[CommandIndex2 + 1];
                                             } else if (CommandIndex2 >= Data.Structure.Poles[CommandIndex1].Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.Poles[CommandIndex1], CommandIndex2 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.Poles[CommandIndex1][CommandIndex2] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.ground":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "GroundStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.Ground.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.Ground, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.Ground[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.walll":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "WallStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.WallL.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.WallL, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.WallL[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.wallr":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "WallStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.WallR.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.WallR, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.WallR[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.dikel":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "DikeStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.DikeL.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.DikeL, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.DikeL[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.diker":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "DikeStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.DikeR.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.DikeR, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.DikeR[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.forml":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.FormL.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.FormL, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.FormL[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.formr":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.FormR.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.FormR, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.FormR[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.formcl":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.FormCL.Length) {
                                                 Array.Resize<ObjectManager.StaticObject>(ref Data.Structure.FormCL, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.FormCL[CommandIndex1] = ObjectManager.LoadStaticObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, true, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.formcr":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.FormCR.Length) {
                                                 Array.Resize<ObjectManager.StaticObject>(ref Data.Structure.FormCR, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.FormCR[CommandIndex1] = ObjectManager.LoadStaticObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, true, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.roofl":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 == 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex was omitted or is 0 in " + Command + " argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 CommandIndex1 = 1;
                                             }
                                             if (CommandIndex1 < 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex is expected to be non-negativ in " + Command + " argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 if (CommandIndex1 >= Data.Structure.RoofL.Length) {
                                                     Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.RoofL, CommandIndex1 + 1);
                                                 }
                                                 string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                                 if (!System.IO.File.Exists(f)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 } else {
                                                     Data.Structure.RoofL[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                                 }
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.roofr":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 == 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex was omitted or is 0 in " + Command + " argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 CommandIndex1 = 1;
                                             }
                                             if (CommandIndex1 < 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex is expected to be non-negativ in " + Command + " argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 if (CommandIndex1 >= Data.Structure.RoofR.Length) {
                                                     Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.RoofR, CommandIndex1 + 1);
                                                 }
                                                 string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                                 if (!System.IO.File.Exists(f)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 } else {
                                                     Data.Structure.RoofR[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                                 }
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.roofcl":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 == 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex was omitted or is 0 in " + Command + " argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 CommandIndex1 = 1;
                                             }
                                             if (CommandIndex1 < 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex is expected to be non-negativ in " + Command + " argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 if (CommandIndex1 >= Data.Structure.RoofCL.Length) {
                                                     Array.Resize<ObjectManager.StaticObject>(ref Data.Structure.RoofCL, CommandIndex1 + 1);
                                                 }
                                                 string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                                 if (!System.IO.File.Exists(f)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 } else {
                                                     Data.Structure.RoofCL[CommandIndex1] = ObjectManager.LoadStaticObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, true, false, false);
                                                 }
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.roofcr":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 == 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex was omitted or is 0 in " + Command + " argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 CommandIndex1 = 1;
                                             }
                                             if (CommandIndex1 < 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex is expected to be non-negativ in " + Command + " argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 if (CommandIndex1 >= Data.Structure.RoofCR.Length) {
                                                     Array.Resize<ObjectManager.StaticObject>(ref Data.Structure.RoofCR, CommandIndex1 + 1);
                                                 }
                                                 string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                                 if (!System.IO.File.Exists(f)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 } else {
                                                     Data.Structure.RoofCR[CommandIndex1] = ObjectManager.LoadStaticObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, true, false, false);
                                                 }
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.crackl":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "CrackStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.CrackL.Length) {
                                                 Array.Resize<ObjectManager.StaticObject>(ref Data.Structure.CrackL, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.CrackL[CommandIndex1] = ObjectManager.LoadStaticObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, true, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.crackr":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "CrackStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.CrackR.Length) {
                                                 Array.Resize<ObjectManager.StaticObject>(ref Data.Structure.CrackR, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.CrackR[CommandIndex1] = ObjectManager.LoadStaticObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, true, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.freeobj":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FreeObjStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.FreeObj.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.FreeObj, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " could not be found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.FreeObj[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                             // signal
                         case "signal":
                             {
                                 if (!PreviewOnly) {
                                     if (Arguments.Length < 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have between 1 and 2 arguments at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (CommandIndex1 >= Data.SignalData.Length) {
                                             Array.Resize<SignalData>(ref Data.SignalData, CommandIndex1 + 1);
                                         }
                                         if (Arguments[0].EndsWith(".animated", StringComparison.OrdinalIgnoreCase)) {
                                             if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "AnimatedObjectFile contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 if (Arguments.Length > 1) {
                                                     Interface.AddMessage(Interface.MessageType.Warning, false, Command + " is expected to have exactly 1 argument when using animated objects at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 }
                                                 string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                                 if (!System.IO.File.Exists(f)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, true, "SignalFileWithoutExtension " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 } else {
                                                     ObjectManager.UnifiedObject Object = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                                     if (Object is ObjectManager.AnimatedObjectCollection) {
                                                         AnimatedObjectSignalData Signal = new AnimatedObjectSignalData();
                                                         Signal.Objects = (ObjectManager.AnimatedObjectCollection)Object;
                                                         Data.SignalData[CommandIndex1] = Signal;
                                                     } else {
                                                         Interface.AddMessage(Interface.MessageType.Error, true, "GlowFileWithoutExtension " + f + " is not a valid animated object in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                     }
                                                 }
                                             }
                                         } else {
                                             if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "SignalFileWithoutExtension contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 if (Arguments.Length > 2) {
                                                     Interface.AddMessage(Interface.MessageType.Warning, false, Command + " is expected to have between 1 and 2 arguments at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 }
                                                 string f = System.IO.Path.Combine(ObjectPath, Arguments[0]);
                                                 Bve4SignalData Signal = new Bve4SignalData();
                                                 Signal.BaseObject = ObjectManager.LoadStaticObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                                 Signal.GlowObject = null;
                                                 string Folder = System.IO.Path.GetDirectoryName(f);
                                                 if (!System.IO.Directory.Exists(Folder)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, true, "The folder " + Folder + " could not be found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 } else {
                                                     Signal.SignalTextures = LoadAllTextures(f, false);
                                                     Signal.GlowTextures = new Textures.Texture[] { };
                                                     if (Arguments.Length >= 2 && Arguments[1].Length != 0) {
                                                         if (Interface.ContainsInvalidPathChars(Arguments[1])) {
                                                             Interface.AddMessage(Interface.MessageType.Error, false, "GlowFileWithoutExtension contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                         } else {
                                                             f = System.IO.Path.Combine(ObjectPath, Arguments[1]);
                                                             Signal.GlowObject = ObjectManager.LoadStaticObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                                             if (Signal.GlowObject != null) {
                                                                 Signal.GlowTextures = LoadAllTextures(f, true);
                                                                 for (int p = 0; p < Signal.GlowObject.Mesh.Materials.Length; p++) {
                                                                     Signal.GlowObject.Mesh.Materials[p].BlendMode = World.MeshMaterialBlendMode.Additive;
                                                                     Signal.GlowObject.Mesh.Materials[p].GlowAttenuationData = World.GetGlowAttenuationData(200.0, World.GlowAttenuationMode.DivisionExponent4);
                                                                 }
                                                             }
                                                         }
                                                     }
                                                     Data.SignalData[CommandIndex1] = Signal;
                                                 }
                                             }
                                         }
                                     }
                                 }
                             } break;
                             // texture
                         case "texture.background":
                         case "structure.back":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "BackgroundTextureIndex is expected to be non-negative at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (Arguments.Length < 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Backgrounds.Length) {
                                                 int a = Data.Backgrounds.Length;
                                                 Array.Resize<World.Background>(ref Data.Backgrounds, CommandIndex1 + 1);
                                                 for (int k = a; k <= CommandIndex1; k++) {
                                                     Data.Backgrounds[k] = new World.Background(null, 6, false);
                                                 }
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Textures.RegisterTexture(f, out Data.Backgrounds[CommandIndex1].Texture);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "texture.background.x":
                         case "structure.back.x":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "BackgroundTextureIndex is expected to be non-negative at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (Arguments.Length < 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false,  Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (CommandIndex1 >= Data.Backgrounds.Length) {
                                             int a = Data.Backgrounds.Length;
                                             Array.Resize<World.Background>(ref Data.Backgrounds, CommandIndex1 + 1);
                                             for (int k = a; k <= CommandIndex1; k++) {
                                                 Data.Backgrounds[k] = new World.Background(null, 6, false);
                                             }
                                         }
                                         int x;
                                         if (!Interface.TryParseIntVb6(Arguments[0], out x)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "BackgroundTextureIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (x == 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RepetitionCount is expected to be non-zero in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             Data.Backgrounds[CommandIndex1].Repetition = x;
                                         }
                                     }
                                 }
                             } break;
                         case "texture.background.aspect":
                         case "structure.back.aspect":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "BackgroundTextureIndex is expected to be non-negative at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (Arguments.Length < 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false,  Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (CommandIndex1 >= Data.Backgrounds.Length) {
                                             int a = Data.Backgrounds.Length;
                                             Array.Resize<World.Background>(ref Data.Backgrounds, CommandIndex1 + 1);
                                             for (int k = a; k <= CommandIndex1; k++) {
                                                 Data.Backgrounds[k] = new World.Background(null, 6, false);
                                             }
                                         }
                                         int aspect;
                                         if (!Interface.TryParseIntVb6(Arguments[0], out aspect)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "BackgroundTextureIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (aspect != 0 & aspect != 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Value is expected to be either 0 or 1 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             Data.Backgrounds[CommandIndex1].KeepAspectRatio = aspect == 1;
                                         }
                                     }
                                 }
                             } break;
                             // cycle
                         case "cycle.ground":
                             if (!PreviewOnly) {
                                 if (CommandIndex1 >= Data.Structure.Cycle.Length) {
                                     Array.Resize<int[]>(ref Data.Structure.Cycle, CommandIndex1 + 1);
                                 }
                                 Data.Structure.Cycle[CommandIndex1] = new int[Arguments.Length];
                                 for (int k = 0; k < Arguments.Length; k++) {
                                     int ix = 0;
                                     if (Arguments[k].Length > 0 && !Interface.TryParseIntVb6(Arguments[k], out ix)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "GroundStructureIndex" + (k + 1).ToString(Culture) + " is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         ix = 0;
                                     }
                                     if (ix < 0 | ix >= Data.Structure.Ground.Length) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "GroundStructureIndex" + (k + 1).ToString(Culture) + " is out of range in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         ix = 0;
                                     }
                                     Data.Structure.Cycle[CommandIndex1][k] = ix;
                                 }
                             } break;
                     }
                 }
             }
         }
     }
     // process track namespace
     for (int j = 0; j < Expressions.Length; j++) {
         Loading.RouteProgress = 0.3333 + (double)j * progressFactor;
         if ((j & 255) == 0) {
             System.Threading.Thread.Sleep(1);
             if (Loading.Cancel) return;
         }
         if (Expressions[j].Text.StartsWith("[") & Expressions[j].Text.EndsWith("]")) {
             Section = Expressions[j].Text.Substring(1, Expressions[j].Text.Length - 2).Trim();
             if (string.Compare(Section, "object", StringComparison.OrdinalIgnoreCase) == 0) {
                 Section = "Structure";
             } else if (string.Compare(Section, "railway", StringComparison.OrdinalIgnoreCase) == 0) {
                 Section = "Track";
             }
             SectionAlwaysPrefix = true;
         } else {
             // find equals
             int Equals = Expressions[j].Text.IndexOf('=');
             if (Equals >= 0) {
                 // handle RW cycle syntax
                 string t = Expressions[j].Text.Substring(0, Equals);
                 if (Section.ToLowerInvariant() == "cycle" & SectionAlwaysPrefix) {
                     double b; if (Interface.TryParseDoubleVb6(t, out b)) {
                         t = ".Ground(" + t + ")";
                     }
                 } else if (Section.ToLowerInvariant() == "signal" & SectionAlwaysPrefix) {
                     double b; if (Interface.TryParseDoubleVb6(t, out b)) {
                         t = ".Void(" + t + ")";
                     }
                 }
                 // convert RW style into CSV style
                 Expressions[j].Text = t + " " + Expressions[j].Text.Substring(Equals + 1);
             }
             // separate command and arguments
             string Command, ArgumentSequence;
             SeparateCommandsAndArguments(Expressions[j], out Command, out ArgumentSequence, Culture, Expressions[j].File, j, false);
             // process command
             double Number;
             bool NumberCheck = !IsRW || string.Compare(Section, "track", StringComparison.OrdinalIgnoreCase) == 0;
             if (NumberCheck && Interface.TryParseDouble(Command, UnitOfLength, out Number)) {
                 // track position
                 if (ArgumentSequence.Length != 0) {
                     Interface.AddMessage(Interface.MessageType.Error, false, "A track position must not contain any arguments at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                 } else if (Number < 0.0) {
                     Interface.AddMessage(Interface.MessageType.Error, false, "Negative track position encountered at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                 } else {
                     Data.TrackPosition = Number;
                     BlockIndex = (int)Math.Floor(Number / Data.BlockInterval + 0.001);
                     if (Data.FirstUsedBlock == -1) Data.FirstUsedBlock = BlockIndex;
                     CreateMissingBlocks(ref Data, ref BlocksUsed, BlockIndex, PreviewOnly);
                 }
             } else {
                 // split arguments
                 string[] Arguments;
                 {
                     int n = 0;
                     for (int k = 0; k < ArgumentSequence.Length; k++) {
                         if (IsRW & ArgumentSequence[k] == ',') {
                             n++;
                         } else if (ArgumentSequence[k] == ';') {
                             n++;
                         }
                     }
                     Arguments = new string[n + 1];
                     int a = 0, h = 0;
                     for (int k = 0; k < ArgumentSequence.Length; k++) {
                         if (IsRW & ArgumentSequence[k] == ',') {
                             Arguments[h] = ArgumentSequence.Substring(a, k - a).Trim();
                             a = k + 1; h++;
                         } else if (ArgumentSequence[k] == ';') {
                             Arguments[h] = ArgumentSequence.Substring(a, k - a).Trim();
                             a = k + 1; h++;
                         }
                     }
                     if (ArgumentSequence.Length - a > 0) {
                         Arguments[h] = ArgumentSequence.Substring(a).Trim();
                         h++;
                     }
                     Array.Resize<string>(ref Arguments, h);
                 }
                 // preprocess command
                 if (Command.ToLowerInvariant() == "with") {
                     if (Arguments.Length >= 1) {
                         Section = Arguments[0];
                         SectionAlwaysPrefix = false;
                     } else {
                         Section = "";
                         SectionAlwaysPrefix = false;
                     }
                     Command = null;
                 } else {
                     if (Command.StartsWith(".")) {
                         Command = Section + Command;
                     } else if (SectionAlwaysPrefix) {
                         Command = Section + "." + Command;
                     }
                     Command = Command.Replace(".Void", "");
                     if (Command.StartsWith("structure", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".load", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 5).TrimEnd();
                     } else if (Command.StartsWith("texture.background", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".load", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 5).TrimEnd();
                     } else if (Command.StartsWith("texture.background", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".x", StringComparison.OrdinalIgnoreCase)) {
                         Command = "texture.background.x" + Command.Substring(18, Command.Length - 20).TrimEnd();
                     } else if (Command.StartsWith("texture.background", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".aspect", StringComparison.OrdinalIgnoreCase)) {
                         Command = "texture.background.aspect" + Command.Substring(18, Command.Length - 25).TrimEnd();
                     } else if (Command.StartsWith("structure.back", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".x", StringComparison.OrdinalIgnoreCase)) {
                         Command = "texture.background.x" + Command.Substring(14, Command.Length - 16).TrimEnd();
                     } else if (Command.StartsWith("structure.back", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".aspect", StringComparison.OrdinalIgnoreCase)) {
                         Command = "texture.background.aspect" + Command.Substring(14, Command.Length - 21).TrimEnd();
                     } else if (Command.StartsWith("cycle", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".params", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 7).TrimEnd();
                     } else if (Command.StartsWith("signal", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".load", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 5).TrimEnd();
                     } else if (Command.StartsWith("train.run", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".set", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 4).TrimEnd();
                     } else if (Command.StartsWith("train.flange", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".set", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 4).TrimEnd();
                     } else if (Command.StartsWith("train.timetable", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".day.load", StringComparison.OrdinalIgnoreCase)) {
                         Command = "train.timetable.day" + Command.Substring(15, Command.Length - 24).Trim();
                     } else if (Command.StartsWith("train.timetable", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".night.load", StringComparison.OrdinalIgnoreCase)) {
                         Command = "train.timetable.night" + Command.Substring(15, Command.Length - 26).Trim();
                     } else if (Command.StartsWith("train.timetable", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".day", StringComparison.OrdinalIgnoreCase)) {
                         Command = "train.timetable.day" + Command.Substring(15, Command.Length - 19).Trim();
                     } else if (Command.StartsWith("train.timetable", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".night", StringComparison.OrdinalIgnoreCase)) {
                         Command = "train.timetable.night" + Command.Substring(15, Command.Length - 21).Trim();
                     } else if (Command.StartsWith("route.signal", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".set", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 4).TrimEnd();
                     }
                 }
                 // handle indices
                 int CommandIndex1 = 0, CommandIndex2 = 0;
                 if (Command != null && Command.EndsWith(")")) {
                     for (int k = Command.Length - 2; k >= 0; k--) {
                         if (Command[k] == '(') {
                             string Indices = Command.Substring(k + 1, Command.Length - k - 2).TrimStart();
                             Command = Command.Substring(0, k).TrimEnd();
                             int h = Indices.IndexOf(";");
                             if (h >= 0) {
                                 string a = Indices.Substring(0, h).TrimEnd();
                                 string b = Indices.Substring(h + 1).TrimStart();
                                 if (a.Length > 0 && !Interface.TryParseIntVb6(a, out CommandIndex1)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Invalid first index appeared at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File + ".");
                                     Command = null; break;
                                 } else if (b.Length > 0 && !Interface.TryParseIntVb6(b, out CommandIndex2)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Invalid second index appeared at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File + ".");
                                     Command = null; break;
                                 }
                             } else {
                                 if (Indices.Length > 0 && !Interface.TryParseIntVb6(Indices, out CommandIndex1)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Invalid index appeared at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File + ".");
                                     Command = null; break;
                                 }
                             }
                             break;
                         }
                     }
                 }
                 // process command
                 if (Command != null && Command.Length != 0) {
                     switch (Command.ToLowerInvariant()) {
                             // non-track
                         case "options.blocklength":
                         case "options.unitoflength":
                         case "options.unitofspeed":
                         case "options.objectvisibility":
                         case "options.sectionbehavior":
                         case "options.fogbehavior":
                         case "options.cantbehavior":
                         case "route.comment":
                         case "route.image":
                         case "route.timetable":
                         case "route.change":
                         case "route.gauge":
                         case "train.gauge":
                         case "route.signal":
                         case "route.runinterval":
                         case "train.interval":
                         case "route.accelerationduetogravity":
                         case "route.elevation":
                         case "route.temperature":
                         case "route.pressure":
                         case "route.ambientlight":
                         case "route.directionallight":
                         case "route.lightdirection":
                         case "route.developerid":
                         case "train.folder":
                         case "train.file":
                         case "train.run":
                         case "train.rail":
                         case "train.flange":
                         case "train.timetable.day":
                         case "train.timetable.night":
                         case "train.velocity":
                         case "train.acceleration":
                         case "train.station":
                         case "structure.rail":
                         case "structure.beacon":
                         case "structure.pole":
                         case "structure.ground":
                         case "structure.walll":
                         case "structure.wallr":
                         case "structure.dikel":
                         case "structure.diker":
                         case "structure.forml":
                         case "structure.formr":
                         case "structure.formcl":
                         case "structure.formcr":
                         case "structure.roofl":
                         case "structure.roofr":
                         case "structure.roofcl":
                         case "structure.roofcr":
                         case "structure.crackl":
                         case "structure.crackr":
                         case "structure.freeobj":
                         case "signal":
                         case "texture.background":
                         case "structure.back":
                         case "structure.back.x":
                         case "structure.back.aspect":
                         case "texture.background.x":
                         case "texture.background.aspect":
                         case "cycle.ground":
                             break;
                             // track
                         case "track.railstart":
                         case "track.rail":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx < 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is expected to be positive in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (string.Compare(Command, "track.railstart", StringComparison.OrdinalIgnoreCase) == 0) {
                                             if (idx < Data.Blocks[BlockIndex].Rail.Length && Data.Blocks[BlockIndex].Rail[idx].RailStart) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is required to reference a non-existing rail in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             }
                                         }
                                         if (Data.Blocks[BlockIndex].Rail.Length <= idx) {
                                             Array.Resize<Rail>(ref Data.Blocks[BlockIndex].Rail, idx + 1);
                                         }
                                         if (Data.Blocks[BlockIndex].Rail[idx].RailStartRefreshed) {
                                             Data.Blocks[BlockIndex].Rail[idx].RailEnd = true;
                                         }
                                         {
                                             Data.Blocks[BlockIndex].Rail[idx].RailStart = true;
                                             Data.Blocks[BlockIndex].Rail[idx].RailStartRefreshed = true;
                                             if (Arguments.Length >= 2) {
                                                 if (Arguments[1].Length > 0) {
                                                     double x;
                                                     if (!Interface.TryParseDoubleVb6(Arguments[1], UnitOfLength, out x)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                         x = 0.0;
                                                     }
                                                     Data.Blocks[BlockIndex].Rail[idx].RailStartX = x;
                                                 }
                                                 if (!Data.Blocks[BlockIndex].Rail[idx].RailEnd) {
                                                     Data.Blocks[BlockIndex].Rail[idx].RailEndX = Data.Blocks[BlockIndex].Rail[idx].RailStartX;
                                                 }
                                             }
                                             if (Arguments.Length >= 3) {
                                                 if (Arguments[2].Length > 0) {
                                                     double y;
                                                     if (!Interface.TryParseDoubleVb6(Arguments[2], UnitOfLength, out y)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                         y = 0.0;
                                                     }
                                                     Data.Blocks[BlockIndex].Rail[idx].RailStartY = y;
                                                 }
                                                 if (!Data.Blocks[BlockIndex].Rail[idx].RailEnd) {
                                                     Data.Blocks[BlockIndex].Rail[idx].RailEndY = Data.Blocks[BlockIndex].Rail[idx].RailStartY;
                                                 }
                                             }
                                             if (Data.Blocks[BlockIndex].RailType.Length <= idx) {
                                                 Array.Resize<int>(ref Data.Blocks[BlockIndex].RailType, idx + 1);
                                             }
                                             if (Arguments.Length >= 4 && Arguments[3].Length != 0) {
                                                 int sttype;
                                                 if (!Interface.TryParseIntVb6(Arguments[3], out sttype)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "RailStructureIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                     sttype = 0;
                                                 }
                                                 if (sttype < 0) {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "RailStructureIndex is expected to be non-negative in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 } else if (sttype >= Data.Structure.Rail.Length || Data.Structure.Rail[sttype] == null) {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "RailStructureIndex references an object not loaded in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 } else {
                                                     Data.Blocks[BlockIndex].RailType[idx] = sttype;
                                                 }
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "track.railend":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx < 0 || idx >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx].RailStart) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex references a non-existing rail in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Data.Blocks[BlockIndex].RailType.Length <= idx) {
                                             Array.Resize<Rail>(ref Data.Blocks[BlockIndex].Rail, idx + 1);
                                         }
                                         Data.Blocks[BlockIndex].Rail[idx].RailStart = false;
                                         Data.Blocks[BlockIndex].Rail[idx].RailStartRefreshed = false;
                                         Data.Blocks[BlockIndex].Rail[idx].RailEnd = true;
                                         if (Arguments.Length >= 2 && Arguments[1].Length > 0) {
                                             double x;
                                             if (!Interface.TryParseDoubleVb6(Arguments[1], UnitOfLength, out x)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 x = 0.0;
                                             }
                                             Data.Blocks[BlockIndex].Rail[idx].RailEndX = x;
                                         }
                                         if (Arguments.Length >= 3 && Arguments[2].Length > 0) {
                                             double y;
                                             if (!Interface.TryParseDoubleVb6(Arguments[2], UnitOfLength, out y)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 y = 0.0;
                                             }
                                             Data.Blocks[BlockIndex].Rail[idx].RailEndY = y;
                                         }
                                     }
                                 }
                             } break;
                         case "track.railtype":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     int sttype = 0;
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out sttype)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailStructureIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         sttype = 0;
                                     }
                                     if (idx < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx].RailStart) {
                                             Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex could be out of range in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                         if (sttype < 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RailStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (sttype >= Data.Structure.Rail.Length || Data.Structure.Rail[sttype] == null) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RailStructureIndex references an object not loaded in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (Data.Blocks[BlockIndex].RailType.Length <= idx) {
                                                 Array.Resize<int>(ref Data.Blocks[BlockIndex].RailType, idx + 1);
                                             }
                                             Data.Blocks[BlockIndex].RailType[idx] = sttype;
                                         }
                                     }
                                 }
                             } break;
                         case "track.accuracy":
                             {
                                 double r = 2.0;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], out r)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Value is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     r = 2.0;
                                 }
                                 if (r < 0.0) {
                                     r = 0.0;
                                 } else if (r > 4.0) {
                                     r = 4.0;
                                 }
                                 Data.Blocks[BlockIndex].Accuracy = r;
                             } break;
                         case "track.pitch":
                             {
                                 double p = 0.0;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], out p)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ValueInPermille is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     p = 0.0;
                                 }
                                 Data.Blocks[BlockIndex].Pitch = 0.001 * p;
                             } break;
                         case "track.curve":
                             {
                                 double radius = 0.0;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], UnitOfLength, out radius)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Radius is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     radius = 0.0;
                                 }
                                 double cant = 0.0;
                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[1], out cant)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "CantInMillimeters is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     cant = 0.0;
                                 } else {
                                     cant *= 0.001;
                                 }
                                 if (Data.SignedCant) {
                                     if (radius != 0.0) {
                                         cant *= (double)Math.Sign(radius);
                                     }
                                 } else {
                                     cant = Math.Abs(cant) * (double)Math.Sign(radius);
                                 }
                                 Data.Blocks[BlockIndex].CurrentTrackState.CurveRadius = radius;
                                 Data.Blocks[BlockIndex].CurrentTrackState.CurveCant = cant;
                                 Data.Blocks[BlockIndex].CurrentTrackState.CurveCantTangent = 0.0;
                             } break;
                         case "track.turn":
                             {
                                 double s = 0.0;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], out s)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Ratio is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     s = 0.0;
                                 }
                                 Data.Blocks[BlockIndex].Turn = s;
                             } break;
                         case "track.adhesion":
                             {
                                 double a = 100.0;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], out a)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Value is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     a = 100.0;
                                 }
                                 if (a < 0.0) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Value is expected to be non-negative in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     a = 100.0;
                                 }
                                 Data.Blocks[BlockIndex].AdhesionMultiplier = 0.01 * a;
                             } break;
                         case "track.brightness":
                             {
                                 if (!PreviewOnly) {
                                     float value = 255.0f;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseFloatVb6(Arguments[0], out value)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Value is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         value = 255.0f;
                                     }
                                     value /= 255.0f;
                                     if (value < 0.0f) value = 0.0f;
                                     if (value > 1.0f) value = 1.0f;
                                     int n = Data.Blocks[BlockIndex].Brightness.Length;
                                     Array.Resize<Brightness>(ref Data.Blocks[BlockIndex].Brightness, n + 1);
                                     Data.Blocks[BlockIndex].Brightness[n].TrackPosition = Data.TrackPosition;
                                     Data.Blocks[BlockIndex].Brightness[n].Value = value;
                                 }
                             } break;
                         case "track.fog":
                             {
                                 if (!PreviewOnly) {
                                     double start = 0.0, end = 0.0;
                                     int r = 128, g = 128, b = 128;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], out start)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "StartingDistance is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         start = 0.0;
                                     }
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[1], out end)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "EndingDistance is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         end = 0.0;
                                     }
                                     if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out r)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RedValue is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         r = 128;
                                     } else if (r < 0 | r > 255) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RedValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         r = r < 0 ? 0 : 255;
                                     }
                                     if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseIntVb6(Arguments[3], out g)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "GreenValue is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         g = 128;
                                     } else if (g < 0 | g > 255) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "GreenValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         g = g < 0 ? 0 : 255;
                                     }
                                     if (Arguments.Length >= 5 && Arguments[4].Length > 0 && !Interface.TryParseIntVb6(Arguments[4], out b)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "BlueValue is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         b = 128;
                                     } else if (b < 0 | b > 255) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "BlueValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         b = b < 0 ? 0 : 255;
                                     }
                                     if (start < end) {
                                         Data.Blocks[BlockIndex].Fog.Start = (float)start;
                                         Data.Blocks[BlockIndex].Fog.End = (float)end;
                                     } else {
                                         Data.Blocks[BlockIndex].Fog.Start = Game.NoFogStart;
                                         Data.Blocks[BlockIndex].Fog.End = Game.NoFogEnd;
                                     }
                                     Data.Blocks[BlockIndex].Fog.Color = new Color24((byte)r, (byte)g, (byte)b);
                                     Data.Blocks[BlockIndex].FogDefined = true;
                                 }
                             } break;
                         case "track.section":
                         case "track.sections":
                             {
                                 if (!PreviewOnly) {
                                     if (Arguments.Length == 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "At least one argument is required in " + Command + "at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         int[] aspects = new int[Arguments.Length];
                                         for (int i = 0; i < Arguments.Length; i++) {
                                             if (!Interface.TryParseIntVb6(Arguments[i], out aspects[i])) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Aspect" + i.ToString(Culture) + " is invalid in " + Command + "at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 aspects[i] = -1;
                                             } else if (aspects[i] < 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Aspect" + i.ToString(Culture) + " is expected to be non-negative in " + Command + "at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 aspects[i] = -1;
                                             }
                                         }
                                         bool valueBased = ValueBasedSections | string.Equals(Command, "Track.SectionS", StringComparison.OrdinalIgnoreCase);
                                         if (valueBased) {
                                             Array.Sort<int>(aspects);
                                         }
                                         int n = Data.Blocks[BlockIndex].Section.Length;
                                         Array.Resize<Section>(ref Data.Blocks[BlockIndex].Section, n + 1);
                                         Data.Blocks[BlockIndex].Section[n].TrackPosition = Data.TrackPosition;
                                         Data.Blocks[BlockIndex].Section[n].Aspects = aspects;
                                         Data.Blocks[BlockIndex].Section[n].Type = valueBased ? Game.SectionType.ValueBased : Game.SectionType.IndexBased;
                                         Data.Blocks[BlockIndex].Section[n].DepartureStationIndex = -1;
                                         if (CurrentStation >= 0 && Game.Stations[CurrentStation].ForceStopSignal) {
                                             if (CurrentStation >= 0 & CurrentStop >= 0 & !DepartureSignalUsed) {
                                                 Data.Blocks[BlockIndex].Section[n].DepartureStationIndex = CurrentStation;
                                                 DepartureSignalUsed = true;
                                             }
                                         }
                                         CurrentSection++;
                                     }
                                 }
                             } break;
                         case "track.sigf":
                             {
                                 if (!PreviewOnly) {
                                     int objidx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out objidx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "SignalIndex is invalid in Track.SigF at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         objidx = 0;
                                     }
                                     if (objidx >= 0 & objidx < Data.SignalData.Length && Data.SignalData[objidx] != null) {
                                         int section = 0;
                                         if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out section)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Section is invalid in Track.SigF at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             section = 0;
                                         }
                                         double x = 0.0, y = 0.0;
                                         if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[2], UnitOfLength, out x)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in Track.SigF at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             x = 0.0;
                                         }
                                         if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[3], UnitOfLength, out y)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in Track.SigF at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             y = 0.0;
                                         }
                                         double yaw = 0.0, pitch = 0.0, roll = 0.0;
                                         if (Arguments.Length >= 5 && Arguments[4].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[4], out yaw)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Yaw is invalid in Track.SigF at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             yaw = 0.0;
                                         }
                                         if (Arguments.Length >= 6 && Arguments[5].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[5], out pitch)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Pitch is invalid in Track.SigF at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             pitch = 0.0;
                                         }
                                         if (Arguments.Length >= 7 && Arguments[6].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[6], out roll)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Roll is invalid in Track.SigF at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             roll = 0.0;
                                         }
                                         int n = Data.Blocks[BlockIndex].Signal.Length;
                                         Array.Resize<Signal>(ref Data.Blocks[BlockIndex].Signal, n + 1);
                                         Data.Blocks[BlockIndex].Signal[n].TrackPosition = Data.TrackPosition;
                                         Data.Blocks[BlockIndex].Signal[n].Section = CurrentSection + section;
                                         Data.Blocks[BlockIndex].Signal[n].SignalCompatibilityObjectIndex = -1;
                                         Data.Blocks[BlockIndex].Signal[n].SignalObjectIndex = objidx;
                                         Data.Blocks[BlockIndex].Signal[n].X = x;
                                         Data.Blocks[BlockIndex].Signal[n].Y = y < 0.0 ? 4.8 : y;
                                         Data.Blocks[BlockIndex].Signal[n].Yaw = 0.0174532925199433 * yaw;
                                         Data.Blocks[BlockIndex].Signal[n].Pitch = 0.0174532925199433 * pitch;
                                         Data.Blocks[BlockIndex].Signal[n].Roll = 0.0174532925199433 * roll;
                                         Data.Blocks[BlockIndex].Signal[n].ShowObject = true;
                                         Data.Blocks[BlockIndex].Signal[n].ShowPost = y < 0.0;
                                         Data.Blocks[BlockIndex].Signal[n].GameSignalIndex = -1;
                                     } else {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "SignalIndex references a signal object not loaded in Track.SigF at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     }
                                 }
                             } break;
                         case "track.signal":
                         case "track.sig":
                             {
                                 if (!PreviewOnly) {
                                     int num = -2;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out num)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Aspects is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         num = -2;
                                     }
                                     if (num != -2 & num != 2 & num != 3 & num != -4 & num != 4 & num != -5 & num != 5 & num != 6) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Aspects has an unsupported value in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         num = num == -3 | num == -6 ? -num : -4;
                                     }
                                     double x = 0.0, y = 0.0;
                                     if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[2], UnitOfLength, out x)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         x = 0.0;
                                     }
                                     if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[3], UnitOfLength, out y)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         y = 0.0;
                                     }
                                     double yaw = 0.0, pitch = 0.0, roll = 0.0;
                                     if (Arguments.Length >= 5 && Arguments[4].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[4], out yaw)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Yaw is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         yaw = 0.0;
                                     }
                                     if (Arguments.Length >= 6 && Arguments[5].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[5], out pitch)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Pitch is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         pitch = 0.0;
                                     }
                                     if (Arguments.Length >= 7 && Arguments[6].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[6], out roll)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Roll is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         roll = 0.0;
                                     }
                                     int[] aspects; int comp;
                                     switch (num) {
                                             case 2: aspects = new int[] { 0, 2 }; comp = 0; break;
                                             case -2: aspects = new int[] { 0, 4 }; comp = 1; break;
                                             case 3: aspects = new int[] { 0, 2, 4 }; comp = 2; break;
                                             case 4: aspects = new int[] { 0, 1, 2, 4 }; comp = 3; break;
                                             case -4: aspects = new int[] { 0, 2, 3, 4 }; comp = 4; break;
                                             case 5: aspects = new int[] { 0, 1, 2, 3, 4 }; comp = 5; break;
                                             case -5: aspects = new int[] { 0, 2, 3, 4, 5 }; comp = 6; break;
                                             case 6: aspects = new int[] { 0, 1, 2, 3, 4, 5 }; comp = 7; break;
                                             default: aspects = new int[] { 0, 2 }; comp = 0; break;
                                     }
                                     int n = Data.Blocks[BlockIndex].Section.Length;
                                     Array.Resize<Section>(ref Data.Blocks[BlockIndex].Section, n + 1);
                                     Data.Blocks[BlockIndex].Section[n].TrackPosition = Data.TrackPosition;
                                     Data.Blocks[BlockIndex].Section[n].Aspects = aspects;
                                     Data.Blocks[BlockIndex].Section[n].DepartureStationIndex = -1;
                                     Data.Blocks[BlockIndex].Section[n].Invisible = x == 0.0;
                                     Data.Blocks[BlockIndex].Section[n].Type = Game.SectionType.ValueBased;
                                     if (CurrentStation >= 0 && Game.Stations[CurrentStation].ForceStopSignal) {
                                         if (CurrentStation >= 0 & CurrentStop >= 0 & !DepartureSignalUsed) {
                                             Data.Blocks[BlockIndex].Section[n].DepartureStationIndex = CurrentStation;
                                             DepartureSignalUsed = true;
                                         }
                                     }
                                     CurrentSection++;
                                     n = Data.Blocks[BlockIndex].Signal.Length;
                                     Array.Resize<Signal>(ref Data.Blocks[BlockIndex].Signal, n + 1);
                                     Data.Blocks[BlockIndex].Signal[n].TrackPosition = Data.TrackPosition;
                                     Data.Blocks[BlockIndex].Signal[n].Section = CurrentSection;
                                     Data.Blocks[BlockIndex].Signal[n].SignalCompatibilityObjectIndex = comp;
                                     Data.Blocks[BlockIndex].Signal[n].SignalObjectIndex = -1;
                                     Data.Blocks[BlockIndex].Signal[n].X = x;
                                     Data.Blocks[BlockIndex].Signal[n].Y = y < 0.0 ? 4.8 : y;
                                     Data.Blocks[BlockIndex].Signal[n].Yaw = 0.0174532925199433 * yaw;
                                     Data.Blocks[BlockIndex].Signal[n].Pitch = 0.0174532925199433 * pitch;
                                     Data.Blocks[BlockIndex].Signal[n].Roll = 0.0174532925199433 * roll;
                                     Data.Blocks[BlockIndex].Signal[n].ShowObject = x != 0.0;
                                     Data.Blocks[BlockIndex].Signal[n].ShowPost = x != 0.0 & y < 0.0;
                                     Data.Blocks[BlockIndex].Signal[n].GameSignalIndex = -1;
                                 }
                             } break;
                         case "track.relay":
                             {
                                 if (!PreviewOnly) {
                                     double x = 0.0, y = 0.0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], UnitOfLength, out x)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in Track.Relay at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         x = 0.0;
                                     }
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[1], UnitOfLength, out y)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in Track.Relay at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         y = 0.0;
                                     }
                                     double yaw = 0.0, pitch = 0.0, roll = 0.0;
                                     if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[2], out yaw)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Yaw is invalid in Track.Relay at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         yaw = 0.0;
                                     }
                                     if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[3], out pitch)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Pitch is invalid in Track.Relay at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         pitch = 0.0;
                                     }
                                     if (Arguments.Length >= 5 && Arguments[4].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[4], out roll)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Roll is invalid in Track.Relay at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         roll = 0.0;
                                     }
                                     int n = Data.Blocks[BlockIndex].Signal.Length;
                                     Array.Resize<Signal>(ref Data.Blocks[BlockIndex].Signal, n + 1);
                                     Data.Blocks[BlockIndex].Signal[n].TrackPosition = Data.TrackPosition;
                                     Data.Blocks[BlockIndex].Signal[n].Section = CurrentSection + 1;
                                     Data.Blocks[BlockIndex].Signal[n].SignalCompatibilityObjectIndex = 8;
                                     Data.Blocks[BlockIndex].Signal[n].SignalObjectIndex = -1;
                                     Data.Blocks[BlockIndex].Signal[n].X = x;
                                     Data.Blocks[BlockIndex].Signal[n].Y = y < 0.0 ? 4.8 : y;
                                     Data.Blocks[BlockIndex].Signal[n].Yaw = yaw * 0.0174532925199433;
                                     Data.Blocks[BlockIndex].Signal[n].Pitch = pitch * 0.0174532925199433;
                                     Data.Blocks[BlockIndex].Signal[n].Roll = roll * 0.0174532925199433;
                                     Data.Blocks[BlockIndex].Signal[n].ShowObject = x != 0.0;
                                     Data.Blocks[BlockIndex].Signal[n].ShowPost = x != 0.0 & y < 0.0;
                                 }
                             } break;
                         case "track.beacon":
                             {
                                 if (!PreviewOnly) {
                                     int type = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out type)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Type is invalid in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         type = 0;
                                     }
                                     if (type < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Type is expected to be non-positive in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         int structure = 0, section = 0, optional = 0;
                                         if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out structure)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "BeaconStructureIndex is invalid in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             structure = 0;
                                         }
                                         if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out section)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Section is invalid in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             section = 0;
                                         }
                                         if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseIntVb6(Arguments[3], out optional)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Data is invalid in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             optional = 0;
                                         }
                                         if (structure < -1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "BeaconStructureIndex is expected to be non-negative or -1 in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             structure = -1;
                                         } else if (structure >= 0 && (structure >= Data.Structure.Beacon.Length || Data.Structure.Beacon[structure] == null)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "BeaconStructureIndex references an object not loaded in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             structure = -1;
                                         }
                                         if (section == -1) {
                                             //section = (int)TrackManager.TransponderSpecialSection.NextRedSection;
                                         } else if (section < 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Section is expected to be non-negative or -1 in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             section = CurrentSection + 1;
                                         } else {
                                             section += CurrentSection;
                                         }
                                         double x = 0.0, y = 0.0;
                                         double yaw = 0.0, pitch = 0.0, roll = 0.0;
                                         if (Arguments.Length >= 5 && Arguments[4].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[4], UnitOfLength, out x)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             x = 0.0;
                                         }
                                         if (Arguments.Length >= 6 && Arguments[5].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[5], UnitOfLength, out y)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             y = 0.0;
                                         }
                                         if (Arguments.Length >= 7 && Arguments[6].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[6], out yaw)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Yaw is invalid in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             yaw = 0.0;
                                         }
                                         if (Arguments.Length >= 8 && Arguments[7].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[7], out pitch)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Pitch is invalid in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             pitch = 0.0;
                                         }
                                         if (Arguments.Length >= 9 && Arguments[8].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[8], out roll)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Roll is invalid in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             roll = 0.0;
                                         }
                                         int n = Data.Blocks[BlockIndex].Transponder.Length;
                                         Array.Resize<Transponder>(ref Data.Blocks[BlockIndex].Transponder, n + 1);
                                         Data.Blocks[BlockIndex].Transponder[n].TrackPosition = Data.TrackPosition;
                                         Data.Blocks[BlockIndex].Transponder[n].Type = type;
                                         Data.Blocks[BlockIndex].Transponder[n].Data = optional;
                                         Data.Blocks[BlockIndex].Transponder[n].BeaconStructureIndex = structure;
                                         Data.Blocks[BlockIndex].Transponder[n].Section = section;
                                         Data.Blocks[BlockIndex].Transponder[n].ShowDefaultObject = false;
                                         Data.Blocks[BlockIndex].Transponder[n].X = x;
                                         Data.Blocks[BlockIndex].Transponder[n].Y = y;
                                         Data.Blocks[BlockIndex].Transponder[n].Yaw = yaw * 0.0174532925199433;
                                         Data.Blocks[BlockIndex].Transponder[n].Pitch = pitch * 0.0174532925199433;
                                         Data.Blocks[BlockIndex].Transponder[n].Roll = roll * 0.0174532925199433;
                                     }
                                 }
                             } break;
                         case "track.transponder":
                         case "track.tr":
                             {
                                 if (!PreviewOnly) {
                                     int type = 0, oversig = 0, work = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out type)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Type is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         type = 0;
                                     }
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out oversig)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Signals is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         oversig = 0;
                                     }
                                     if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out work)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "SwitchSystems is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         work = 0;
                                     }
                                     if (oversig < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Signals is expected to be non-negative in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         oversig = 0;
                                     }
                                     double x = 0.0, y = 0.0;
                                     if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[3], UnitOfLength, out x)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         x = 0.0;
                                     }
                                     if (Arguments.Length >= 5 && Arguments[4].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[4], UnitOfLength, out y)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         y = 0.0;
                                     }
                                     double yaw = 0.0, pitch = 0.0, roll = 0.0;
                                     if (Arguments.Length >= 6 && Arguments[5].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[5], out yaw)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Yaw is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         yaw = 0.0;
                                     }
                                     if (Arguments.Length >= 7 && Arguments[6].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[6], out pitch)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Pitch is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         pitch = 0.0;
                                     }
                                     if (Arguments.Length >= 8 && Arguments[7].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[7], out roll)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Roll is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         roll = 0.0;
                                     }
                                     int n = Data.Blocks[BlockIndex].Transponder.Length;
                                     Array.Resize<Transponder>(ref Data.Blocks[BlockIndex].Transponder, n + 1);
                                     Data.Blocks[BlockIndex].Transponder[n].TrackPosition = Data.TrackPosition;
                                     Data.Blocks[BlockIndex].Transponder[n].Type = type;
                                     Data.Blocks[BlockIndex].Transponder[n].Data = work;
                                     Data.Blocks[BlockIndex].Transponder[n].ShowDefaultObject = true;
                                     Data.Blocks[BlockIndex].Transponder[n].BeaconStructureIndex = -1;
                                     Data.Blocks[BlockIndex].Transponder[n].X = x;
                                     Data.Blocks[BlockIndex].Transponder[n].Y = y;
                                     Data.Blocks[BlockIndex].Transponder[n].Yaw = yaw * 0.0174532925199433;
                                     Data.Blocks[BlockIndex].Transponder[n].Pitch = pitch * 0.0174532925199433;
                                     Data.Blocks[BlockIndex].Transponder[n].Roll = roll * 0.0174532925199433;
                                     Data.Blocks[BlockIndex].Transponder[n].Section = CurrentSection + oversig + 1;
                                 }
                             } break;
                         case "track.atssn":
                             {
                                 if (!PreviewOnly) {
                                     int n = Data.Blocks[BlockIndex].Transponder.Length;
                                     Array.Resize<Transponder>(ref Data.Blocks[BlockIndex].Transponder, n + 1);
                                     Data.Blocks[BlockIndex].Transponder[n].TrackPosition = Data.TrackPosition;
                                     Data.Blocks[BlockIndex].Transponder[n].Type = 0;
                                     Data.Blocks[BlockIndex].Transponder[n].Data = 0;
                                     Data.Blocks[BlockIndex].Transponder[n].ShowDefaultObject = true;
                                     Data.Blocks[BlockIndex].Transponder[n].BeaconStructureIndex = -1;
                                     Data.Blocks[BlockIndex].Transponder[n].Section = CurrentSection + 1;
                                 }
                             } break;
                         case "track.atsp":
                             {
                                 if (!PreviewOnly) {
                                     int n = Data.Blocks[BlockIndex].Transponder.Length;
                                     Array.Resize<Transponder>(ref Data.Blocks[BlockIndex].Transponder, n + 1);
                                     Data.Blocks[BlockIndex].Transponder[n].TrackPosition = Data.TrackPosition;
                                     Data.Blocks[BlockIndex].Transponder[n].Type = 3;
                                     Data.Blocks[BlockIndex].Transponder[n].Data = 0;
                                     Data.Blocks[BlockIndex].Transponder[n].ShowDefaultObject = true;
                                     Data.Blocks[BlockIndex].Transponder[n].BeaconStructureIndex = -1;
                                     Data.Blocks[BlockIndex].Transponder[n].Section = CurrentSection + 1;
                                 }
                             } break;
                         case "track.pattern":
                             {
                                 if (!PreviewOnly) {
                                     int type = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out type)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Type is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         type = 0;
                                     }
                                     double speed = 0.0;
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[1], out speed)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Speed is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         speed = 0.0;
                                     }
                                     int n = Data.Blocks[BlockIndex].Transponder.Length;
                                     Array.Resize<Transponder>(ref Data.Blocks[BlockIndex].Transponder, n + 1);
                                     Data.Blocks[BlockIndex].Transponder[n].TrackPosition = Data.TrackPosition;
                                     if (type == 0) {
                                         Data.Blocks[BlockIndex].Transponder[n].Type = TrackManager.SpecialTransponderTypes.InternalAtsPTemporarySpeedLimit;
                                         Data.Blocks[BlockIndex].Transponder[n].Data = speed == 0.0 ? int.MaxValue : (int)Math.Round(speed * Data.UnitOfSpeed * 3.6);
                                     } else {
                                         Data.Blocks[BlockIndex].Transponder[n].Type = TrackManager.SpecialTransponderTypes.AtsPPermanentSpeedLimit;
                                         Data.Blocks[BlockIndex].Transponder[n].Data = speed == 0.0 ? int.MaxValue : (int)Math.Round(speed * Data.UnitOfSpeed * 3.6);
                                     }
                                     Data.Blocks[BlockIndex].Transponder[n].Section = -1;
                                     Data.Blocks[BlockIndex].Transponder[n].BeaconStructureIndex = -1;
                                 }
                             } break;
                         case "track.plimit":
                             {
                                 if (!PreviewOnly) {
                                     double speed = 0.0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], out speed)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Speed is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         speed = 0.0;
                                     }
                                     int n = Data.Blocks[BlockIndex].Transponder.Length;
                                     Array.Resize<Transponder>(ref Data.Blocks[BlockIndex].Transponder, n + 1);
                                     Data.Blocks[BlockIndex].Transponder[n].TrackPosition = Data.TrackPosition;
                                     Data.Blocks[BlockIndex].Transponder[n].Type = TrackManager.SpecialTransponderTypes.AtsPPermanentSpeedLimit;
                                     Data.Blocks[BlockIndex].Transponder[n].Data = speed == 0.0 ? int.MaxValue : (int)Math.Round(speed * Data.UnitOfSpeed * 3.6);
                                     Data.Blocks[BlockIndex].Transponder[n].Section = -1;
                                     Data.Blocks[BlockIndex].Transponder[n].BeaconStructureIndex = -1;
                                 }
                             } break;
                         case "track.limit":
                             {
                                 double limit = 0.0;
                                 int direction = 0, cource = 0;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], out limit)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Speed is invalid in Track.Limit at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     limit = 0.0;
                                 }
                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out direction)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Direction is invalid in Track.Limit at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     direction = 0;
                                 }
                                 if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out cource)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Cource is invalid in Track.Limit at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     cource = 0;
                                 }
                                 int n = Data.Blocks[BlockIndex].Limit.Length;
                                 Array.Resize<Limit>(ref Data.Blocks[BlockIndex].Limit, n + 1);
                                 Data.Blocks[BlockIndex].Limit[n].TrackPosition = Data.TrackPosition;
                                 Data.Blocks[BlockIndex].Limit[n].Speed = limit <= 0.0 ? double.PositiveInfinity : Data.UnitOfSpeed * limit;
                                 Data.Blocks[BlockIndex].Limit[n].Direction = direction;
                                 Data.Blocks[BlockIndex].Limit[n].Cource = cource;
                             } break;
                         case "track.stop":
                             if (CurrentStation == -1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, "A stop without a station is invalid in Track.Stop at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 int dir = 0;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out dir)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Direction is invalid in Track.Stop at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     dir = 0;
                                 }
                                 double backw = 5.0, forw = 5.0;
                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[1], UnitOfLength, out backw)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "BackwardTolerance is invalid in Track.Stop at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     backw = 5.0;
                                 } else if (backw <= 0.0) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "BackwardTolerance is expected to be positive in Track.Stop at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     backw = 5.0;
                                 }
                                 if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[2], UnitOfLength, out forw)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ForwardTolerance is invalid in Track.Stop at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     forw = 5.0;
                                 } else if (forw <= 0.0) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ForwardTolerance is expected to be positive in Track.Stop at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     forw = 5.0;
                                 }
                                 int cars = 0;
                                 if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseIntVb6(Arguments[3], out cars)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Cars is invalid in Track.Stop at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     cars = 0;
                                 }
                                 int n = Data.Blocks[BlockIndex].Stop.Length;
                                 Array.Resize<Stop>(ref Data.Blocks[BlockIndex].Stop, n + 1);
                                 Data.Blocks[BlockIndex].Stop[n].TrackPosition = Data.TrackPosition;
                                 Data.Blocks[BlockIndex].Stop[n].Station = CurrentStation;
                                 Data.Blocks[BlockIndex].Stop[n].Direction = dir;
                                 Data.Blocks[BlockIndex].Stop[n].ForwardTolerance = forw;
                                 Data.Blocks[BlockIndex].Stop[n].BackwardTolerance = backw;
                                 Data.Blocks[BlockIndex].Stop[n].Cars = cars;
                                 CurrentStop = cars;
                             } break;
                         case "track.sta":
                             {
                                 CurrentStation++;
                                 Array.Resize<Game.Station>(ref Game.Stations, CurrentStation + 1);
                                 Game.Stations[CurrentStation].Name = string.Empty;
                                 Game.Stations[CurrentStation].StopMode = Game.StationStopMode.AllStop;
                                 Game.Stations[CurrentStation].StationType = Game.StationType.Normal;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0) {
                                     Game.Stations[CurrentStation].Name = Arguments[0];
                                 }
                                 double arr = -1.0, dep = -1.0;
                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0) {
                                     if (string.Equals(Arguments[1], "P", StringComparison.OrdinalIgnoreCase) | string.Equals(Arguments[1], "L", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.AllPass;
                                     } else if (string.Equals(Arguments[1], "B", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.PlayerPass;
                                     } else if (Arguments[1].StartsWith("B:", StringComparison.InvariantCultureIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.PlayerPass;
                                         if (!Interface.TryParseTime(Arguments[1].Substring(2).TrimStart(), out arr)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "ArrivalTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             arr = -1.0;
                                         }
                                     } else if (string.Equals(Arguments[1], "S", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.PlayerStop;
                                     } else if (Arguments[1].StartsWith("S:", StringComparison.InvariantCultureIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.PlayerStop;
                                         if (!Interface.TryParseTime(Arguments[1].Substring(2).TrimStart(), out arr)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "ArrivalTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             arr = -1.0;
                                         }
                                     } else if (!Interface.TryParseTime(Arguments[1], out arr)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "ArrivalTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         arr = -1.0;
                                     }
                                 }
                                 if (Arguments.Length >= 3 && Arguments[2].Length > 0) {
                                     if (string.Equals(Arguments[2], "T", StringComparison.OrdinalIgnoreCase) | string.Equals(Arguments[2], "=", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StationType = Game.StationType.Terminal;
                                     } else if (Arguments[2].StartsWith("T:", StringComparison.InvariantCultureIgnoreCase)) {
                                         Game.Stations[CurrentStation].StationType = Game.StationType.Terminal;
                                         if (!Interface.TryParseTime(Arguments[2].Substring(2).TrimStart(), out dep)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "DepartureTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             dep = -1.0;
                                         }
                                     } else if (string.Equals(Arguments[2], "C", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StationType = Game.StationType.ChangeEnds;
                                     } else if (Arguments[2].StartsWith("C:", StringComparison.InvariantCultureIgnoreCase)) {
                                         Game.Stations[CurrentStation].StationType = Game.StationType.ChangeEnds;
                                         if (!Interface.TryParseTime(Arguments[2].Substring(2).TrimStart(), out dep)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "DepartureTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             dep = -1.0;
                                         }
                                     } else if (!Interface.TryParseTime(Arguments[2], out dep)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "DepartureTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         dep = -1.0;
                                     }
                                 }
                                 int passalarm = 0;
                                 if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseIntVb6(Arguments[3], out passalarm)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "PassAlarm is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     passalarm = 0;
                                 }
                                 int door = 0;
                                 bool doorboth = false;
                                 if (Arguments.Length >= 5 && Arguments[4].Length != 0) {
                                     switch (Arguments[4].ToUpperInvariant()) {
                                         case "L":
                                             door = -1;
                                             break;
                                         case "R":
                                             door = 1;
                                             break;
                                         case "N":
                                             door = 0;
                                             break;
                                         case "B":
                                             doorboth = true;
                                             break;
                                         default:
                                             if (!Interface.TryParseIntVb6(Arguments[4], out door)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Doors is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 door = 0;
                                             }
                                             break;
                                     }
                                 }
                                 int stop = 0;
                                 if (Arguments.Length >= 6 && Arguments[5].Length > 0 && !Interface.TryParseIntVb6(Arguments[5], out stop)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ForcedRedSignal is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     stop = 0;
                                 }
                                 int device = 0;
                                 if (Arguments.Length >= 7 && Arguments[6].Length > 0) {
                                     if (string.Compare(Arguments[6], "ats", StringComparison.OrdinalIgnoreCase) == 0) {
                                         device = 0;
                                     } else if (string.Compare(Arguments[6], "atc", StringComparison.OrdinalIgnoreCase) == 0) {
                                         device = 1;
                                     } else if (!Interface.TryParseIntVb6(Arguments[6], out device)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "System is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         device = 0;
                                     }
                                     if (device != 0 & device != 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "System is not supported in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         device = 0;
                                     }
                                 }
                                 Sounds.SoundBuffer arrsnd = null;
                                 Sounds.SoundBuffer depsnd = null;
                                 if (!PreviewOnly) {
                                     if (Arguments.Length >= 8 && Arguments[7].Length > 0) {
                                         if (Interface.ContainsInvalidPathChars(Arguments[7])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "ArrivalSound contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             string f = OpenBveApi.Path.CombineFile(SoundPath, Arguments[7]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "ArrivalSound " + f + " not found in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 const double radius = 30.0;
                                                 arrsnd = Sounds.RegisterBuffer(f, radius);
                                             }
                                         }
                                     }
                                 }
                                 double halt = 15.0;
                                 if (Arguments.Length >= 9 && Arguments[8].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[8], out halt)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "StopDuration is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     halt = 15.0;
                                 } else if (halt < 5.0) {
                                     halt = 5.0;
                                 }
                                 double jam = 100.0;
                                 if (!PreviewOnly) {
                                     if (Arguments.Length >= 10 && Arguments[9].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[9], out jam)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "PassengerRatio is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         jam = 100.0;
                                     } else if (jam < 0.0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "PassengerRatio is expected to be non-negative in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         jam = 100.0;
                                     }
                                 }
                                 if (!PreviewOnly) {
                                     if (Arguments.Length >= 11 && Arguments[10].Length > 0) {
                                         if (Interface.ContainsInvalidPathChars(Arguments[10])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "DepartureSound contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             string f = OpenBveApi.Path.CombineFile(SoundPath, Arguments[10]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "DepartureSound " + f + " not found in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 const double radius = 30.0;
                                                 depsnd = Sounds.RegisterBuffer(f, radius);
                                             }
                                         }
                                     }
                                 }
                                 int ttidx = -1;
                                 Textures.Texture tdt = null, tnt = null;
                                 if (!PreviewOnly) {
                                     if (Arguments.Length >= 12 && Arguments[11].Length > 0) {
                                         if (!Interface.TryParseIntVb6(Arguments[11], out ttidx)) {
                                             ttidx = -1;
                                         } else {
                                             if (ttidx < 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "TimetableIndex is expected to be non-negative in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 ttidx = -1;
                                             } else if (ttidx >= Data.TimetableDaytime.Length & ttidx >= Data.TimetableNighttime.Length) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "TimetableIndex references textures not loaded in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 ttidx = -1;
                                             }
                                             tdt = ttidx >= 0 & ttidx < Data.TimetableDaytime.Length ? Data.TimetableDaytime[ttidx] : null;
                                             tnt = ttidx >= 0 & ttidx < Data.TimetableNighttime.Length ? Data.TimetableNighttime[ttidx] : null;
                                             ttidx = 0;
                                         }
                                     } else {
                                         ttidx = -1;
                                     }
                                     if (ttidx == -1) {
                                         if (CurrentStation > 0) {
                                             tdt = Game.Stations[CurrentStation - 1].TimetableDaytimeTexture;
                                             tnt = Game.Stations[CurrentStation - 1].TimetableNighttimeTexture;
                                         } else if (Data.TimetableDaytime.Length > 0 & Data.TimetableNighttime.Length > 0) {
                                             tdt = Data.TimetableDaytime[0];
                                             tnt = Data.TimetableNighttime[0];
                                         } else {
                                             tdt = null;
                                             tnt = null;
                                         }
                                     }
                                 }
                                 if (Game.Stations[CurrentStation].Name.Length == 0 & (Game.Stations[CurrentStation].StopMode == Game.StationStopMode.PlayerStop | Game.Stations[CurrentStation].StopMode == Game.StationStopMode.AllStop)) {
                                     Game.Stations[CurrentStation].Name = "Station " + (CurrentStation + 1).ToString(Culture) + ")";
                                 }
                                 Game.Stations[CurrentStation].ArrivalTime = arr;
                                 Game.Stations[CurrentStation].ArrivalSoundBuffer = arrsnd;
                                 Game.Stations[CurrentStation].DepartureTime = dep;
                                 Game.Stations[CurrentStation].DepartureSoundBuffer = depsnd;
                                 Game.Stations[CurrentStation].StopTime = halt;
                                 Game.Stations[CurrentStation].ForceStopSignal = stop == 1;
                                 Game.Stations[CurrentStation].OpenLeftDoors = door < 0.0 | doorboth;
                                 Game.Stations[CurrentStation].OpenRightDoors = door > 0.0 | doorboth;
                                 Game.Stations[CurrentStation].SafetySystem = device == 1 ? Game.SafetySystem.Atc : Game.SafetySystem.Ats;
                                 Game.Stations[CurrentStation].Stops = new Game.StationStop[] { };
                                 Game.Stations[CurrentStation].PassengerRatio = 0.01 * jam;
                                 Game.Stations[CurrentStation].TimetableDaytimeTexture = tdt;
                                 Game.Stations[CurrentStation].TimetableNighttimeTexture = tnt;
                                 Game.Stations[CurrentStation].DefaultTrackPosition = Data.TrackPosition;
                                 Data.Blocks[BlockIndex].Station = CurrentStation;
                                 Data.Blocks[BlockIndex].StationPassAlarm = passalarm == 1;
                                 CurrentStop = -1;
                                 DepartureSignalUsed = false;
                             } break;
                         case "track.station":
                             {
                                 CurrentStation++;
                                 Array.Resize<Game.Station>(ref Game.Stations, CurrentStation + 1);
                                 Game.Stations[CurrentStation].Name = string.Empty;
                                 Game.Stations[CurrentStation].StopMode = Game.StationStopMode.AllStop;
                                 Game.Stations[CurrentStation].StationType = Game.StationType.Normal;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0) {
                                     Game.Stations[CurrentStation].Name = Arguments[0];
                                 }
                                 double arr = -1.0, dep = -1.0;
                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0) {
                                     if (string.Equals(Arguments[1], "P", StringComparison.OrdinalIgnoreCase) | string.Equals(Arguments[1], "L", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.AllPass;
                                     } else if (string.Equals(Arguments[1], "B", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.PlayerPass;
                                     } else if (Arguments[1].StartsWith("B:", StringComparison.InvariantCultureIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.PlayerPass;
                                         if (!Interface.TryParseTime(Arguments[1].Substring(2).TrimStart(), out arr)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "ArrivalTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             arr = -1.0;
                                         }
                                     } else if (string.Equals(Arguments[1], "S", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.PlayerStop;
                                     } else if (Arguments[1].StartsWith("S:", StringComparison.InvariantCultureIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.PlayerStop;
                                         if (!Interface.TryParseTime(Arguments[1].Substring(2).TrimStart(), out arr)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "ArrivalTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             arr = -1.0;
                                         }
                                     } else if (!Interface.TryParseTime(Arguments[1], out arr)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "ArrivalTime is invalid in Track.Station at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         arr = -1.0;
                                     }
                                 }
                                 if (Arguments.Length >= 3 && Arguments[2].Length > 0) {
                                     if (string.Equals(Arguments[2], "T", StringComparison.OrdinalIgnoreCase) | string.Equals(Arguments[2], "=", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StationType = Game.StationType.Terminal;
                                     } else if (Arguments[2].StartsWith("T:", StringComparison.InvariantCultureIgnoreCase)) {
                                         Game.Stations[CurrentStation].StationType = Game.StationType.Terminal;
                                         if (!Interface.TryParseTime(Arguments[2].Substring(2).TrimStart(), out dep)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "DepartureTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             dep = -1.0;
                                         }
                                     } else if (string.Equals(Arguments[2], "C", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StationType = Game.StationType.ChangeEnds;
                                     } else if (Arguments[2].StartsWith("C:", StringComparison.InvariantCultureIgnoreCase)) {
                                         Game.Stations[CurrentStation].StationType = Game.StationType.ChangeEnds;
                                         if (!Interface.TryParseTime(Arguments[2].Substring(2).TrimStart(), out dep)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "DepartureTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             dep = -1.0;
                                         }
                                     } else if (!Interface.TryParseTime(Arguments[2], out dep)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "DepartureTime is invalid in Track.Station at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         dep = -1.0;
                                     }
                                 }
                                 int stop = 0;
                                 if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseIntVb6(Arguments[3], out stop)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ForcedRedSignal is invalid in Track.Station at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     stop = 0;
                                 }
                                 int device = 0;
                                 if (Arguments.Length >= 5 && Arguments[4].Length > 0) {
                                     if (string.Compare(Arguments[4], "ats", StringComparison.OrdinalIgnoreCase) == 0) {
                                         device = 0;
                                     } else if (string.Compare(Arguments[4], "atc", StringComparison.OrdinalIgnoreCase) == 0) {
                                         device = 1;
                                     } else if (!Interface.TryParseIntVb6(Arguments[4], out device)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "System is invalid in Track.Station at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         device = 0;
                                     } else if (device != 0 & device != 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "System is not supported in Track.Station at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         device = 0;
                                     }
                                 }
                                 Sounds.SoundBuffer depsnd = null;
                                 if (!PreviewOnly) {
                                     if (Arguments.Length >= 6 && Arguments[5].Length != 0) {
                                         if (Interface.ContainsInvalidPathChars(Arguments[5])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "DepartureSound contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             string f = OpenBveApi.Path.CombineFile(SoundPath, Arguments[5]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "DepartureSound " + f + " not found in Track.Station at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 const double radius = 30.0;
                                                 depsnd = Sounds.RegisterBuffer(f, radius);
                                             }
                                         }
                                     }
                                 }
                                 if (Game.Stations[CurrentStation].Name.Length == 0 & (Game.Stations[CurrentStation].StopMode == Game.StationStopMode.PlayerStop | Game.Stations[CurrentStation].StopMode == Game.StationStopMode.AllStop)) {
                                     Game.Stations[CurrentStation].Name = "Station " + (CurrentStation + 1).ToString(Culture) + ")";
                                 }
                                 Game.Stations[CurrentStation].ArrivalTime = arr;
                                 Game.Stations[CurrentStation].ArrivalSoundBuffer = null;
                                 Game.Stations[CurrentStation].DepartureTime = dep;
                                 Game.Stations[CurrentStation].DepartureSoundBuffer = depsnd;
                                 Game.Stations[CurrentStation].StopTime = 15.0;
                                 Game.Stations[CurrentStation].ForceStopSignal = stop == 1;
                                 Game.Stations[CurrentStation].OpenLeftDoors = true;
                                 Game.Stations[CurrentStation].OpenRightDoors = true;
                                 Game.Stations[CurrentStation].SafetySystem = device == 1 ? Game.SafetySystem.Atc : Game.SafetySystem.Ats;
                                 Game.Stations[CurrentStation].Stops = new Game.StationStop[] { };
                                 Game.Stations[CurrentStation].PassengerRatio = 1.0;
                                 Game.Stations[CurrentStation].TimetableDaytimeTexture = null;
                                 Game.Stations[CurrentStation].TimetableNighttimeTexture = null;
                                 Game.Stations[CurrentStation].DefaultTrackPosition = Data.TrackPosition;
                                 Data.Blocks[BlockIndex].Station = CurrentStation;
                                 Data.Blocks[BlockIndex].StationPassAlarm = false;
                                 CurrentStop = -1;
                                 DepartureSignalUsed = false;
                             } break;
                         case "track.buffer":
                             {
                                 if (!PreviewOnly) {
                                     int n = Game.BufferTrackPositions.Length;
                                     Array.Resize<double>(ref Game.BufferTrackPositions, n + 1);
                                     Game.BufferTrackPositions[n] = Data.TrackPosition;
                                 }
                             } break;
                         case "track.form":
                             {
                                 if (!PreviewOnly) {
                                     int idx1 = 0, idx2 = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx1)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex1 is invalid in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx1 = 0;
                                     }
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0) {
                                         if (string.Compare(Arguments[1], "L", StringComparison.OrdinalIgnoreCase) == 0) {
                                             idx2 = Form.SecondaryRailL;
                                         } else if (string.Compare(Arguments[1], "R", StringComparison.OrdinalIgnoreCase) == 0) {
                                             idx2 = Form.SecondaryRailR;
                                         } else if (IsRW && string.Compare(Arguments[1], "9X", StringComparison.OrdinalIgnoreCase) == 0) {
                                             idx2 = int.MaxValue;
                                         } else if (!Interface.TryParseIntVb6(Arguments[1], out idx2)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex2 is invalid in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             idx2 = 0;
                                         }
                                     }
                                     if (IsRW) {
                                         if (idx2 == int.MaxValue) {
                                             idx2 = 9;
                                         } else if (idx2 == -9) {
                                             idx2 = Form.SecondaryRailL;
                                         } else if (idx2 == 9) {
                                             idx2 = Form.SecondaryRailR;
                                         }
                                     }
                                     if (idx1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex1 is expected to be non-negative in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (idx2 < 0 & idx2 != Form.SecondaryRailStub & idx2 != Form.SecondaryRailL & idx2 != Form.SecondaryRailR) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex2 is expected to be greater or equal to -2 in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx1 >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx1].RailStart) {
                                             Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex1 could be out of range in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                         if (idx2 != Form.SecondaryRailStub & idx2 != Form.SecondaryRailL & idx2 != Form.SecondaryRailR && (idx2 >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx2].RailStart)) {
                                             Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex2 could be out of range in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                         int roof = 0, pf = 0;
                                         if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out roof)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex is invalid in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             roof = 0;
                                         }
                                         if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseIntVb6(Arguments[3], out pf)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex is invalid in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             pf = 0;
                                         }
                                         if (roof != 0 & (roof < 0 || (roof >= Data.Structure.RoofL.Length || Data.Structure.RoofL[roof] == null) || (roof >= Data.Structure.RoofR.Length || Data.Structure.RoofR[roof] == null))) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references an object not loaded in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (pf < 0 | (pf >= Data.Structure.FormL.Length || Data.Structure.FormL[pf] == null) & (pf >= Data.Structure.FormR.Length || Data.Structure.FormR[pf] == null)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references an object not loaded in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             }
                                             int n = Data.Blocks[BlockIndex].Form.Length;
                                             Array.Resize<Form>(ref Data.Blocks[BlockIndex].Form, n + 1);
                                             Data.Blocks[BlockIndex].Form[n].PrimaryRail = idx1;
                                             Data.Blocks[BlockIndex].Form[n].SecondaryRail = idx2;
                                             Data.Blocks[BlockIndex].Form[n].FormType = pf;
                                             Data.Blocks[BlockIndex].Form[n].RoofType = roof;
                                         }
                                     }
                                 }
                             } break;
                         case "track.pole":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in Track.Pole at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is expected to be non-negative in Track.Pole at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx].RailStart) {
                                             Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex could be out of range in Track.Pole at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                         if (idx >= Data.Blocks[BlockIndex].RailPole.Length) {
                                             Array.Resize<Pole>(ref Data.Blocks[BlockIndex].RailPole, idx + 1);
                                             Data.Blocks[BlockIndex].RailPole[idx].Mode = 0;
                                             Data.Blocks[BlockIndex].RailPole[idx].Location = 0;
                                             Data.Blocks[BlockIndex].RailPole[idx].Interval = 2.0 * Data.BlockInterval;
                                             Data.Blocks[BlockIndex].RailPole[idx].Type = 0;
                                         }
                                         int typ = Data.Blocks[BlockIndex].RailPole[idx].Mode;
                                         int sttype = Data.Blocks[BlockIndex].RailPole[idx].Type;
                                         if (Arguments.Length >= 2 && Arguments[1].Length > 0) {
                                             if (!Interface.TryParseIntVb6(Arguments[1], out typ)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "AdditionalRailsCovered is invalid in Track.Pole at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 typ = 0;
                                             }
                                         }
                                         if (Arguments.Length >= 3 && Arguments[2].Length > 0) {
                                             double loc;
                                             if (!Interface.TryParseDoubleVb6(Arguments[2], out loc)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Location is invalid in Track.Pole at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 loc = 0.0;
                                             }
                                             Data.Blocks[BlockIndex].RailPole[idx].Location = loc;
                                         }
                                         if (Arguments.Length >= 4 && Arguments[3].Length > 0) {
                                             double dist;
                                             if (!Interface.TryParseDoubleVb6(Arguments[3], UnitOfLength, out dist)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Interval is invalid in Track.Pole at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 dist = Data.BlockInterval;
                                             }
                                             Data.Blocks[BlockIndex].RailPole[idx].Interval = dist;
                                         }
                                         if (Arguments.Length >= 5 && Arguments[4].Length > 0) {
                                             if (!Interface.TryParseIntVb6(Arguments[4], out sttype)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "PoleStructureIndex is invalid in Track.Pole at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 sttype = 0;
                                             }
                                         }
                                         if (typ < 0 || typ >= Data.Structure.Poles.Length || Data.Structure.Poles[typ] == null) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "PoleStructureIndex references an object not loaded in Track.Pole at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (sttype < 0 || sttype >= Data.Structure.Poles[typ].Length || Data.Structure.Poles[typ][sttype] == null) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "PoleStructureIndex references an object not loaded in Track.Pole at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             Data.Blocks[BlockIndex].RailPole[idx].Mode = typ;
                                             Data.Blocks[BlockIndex].RailPole[idx].Type = sttype;
                                             Data.Blocks[BlockIndex].RailPole[idx].Exists = true;
                                         }
                                     }
                                 }
                             } break;
                         case "track.poleend":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in Track.PoleEnd at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx < 0 | idx >= Data.Blocks[BlockIndex].RailPole.Length) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex does not reference an existing pole in Track.PoleEnd at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx >= Data.Blocks[BlockIndex].Rail.Length || (!Data.Blocks[BlockIndex].Rail[idx].RailStart & !Data.Blocks[BlockIndex].Rail[idx].RailEnd)) {
                                             Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex could be out of range in Track.PoleEnd at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                         Data.Blocks[BlockIndex].RailPole[idx].Exists = false;
                                     }
                                 }
                             } break;
                         case "track.wall":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in Track.Wall at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is expected to be a non-negative integer in Track.Wall at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     int dir = 0;
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out dir)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Direction is invalid in Track.Wall at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         dir = 0;
                                     }
                                     int sttype = 0;
                                     if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out sttype)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "WallStructureIndex is invalid in Track.Wall at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         sttype = 0;
                                     }
                                     if (sttype < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "WallStructureIndex is expected to be a non-negative integer in Track.Wall at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         sttype = 0;
                                     }
                                     if (dir <= 0 && (sttype >= Data.Structure.WallL.Length || Data.Structure.WallL[sttype] == null) ||
                                         dir >= 0 && (sttype >= Data.Structure.WallR.Length || Data.Structure.WallR[sttype] == null)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "WallStructureIndex references an object not loaded in Track.Wall at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx < 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is expected to be non-negative in Track.Wall at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (idx >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx].RailStart) {
                                                 Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex could be out of range in Track.Wall at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             }
                                             if (idx >= Data.Blocks[BlockIndex].RailWall.Length) {
                                                 Array.Resize<WallDike>(ref Data.Blocks[BlockIndex].RailWall, idx + 1);
                                             }
                                             Data.Blocks[BlockIndex].RailWall[idx].Exists = true;
                                             Data.Blocks[BlockIndex].RailWall[idx].Type = sttype;
                                             Data.Blocks[BlockIndex].RailWall[idx].Direction = dir;
                                         }
                                     }
                                 }
                             } break;
                         case "track.wallend":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in Track.WallEnd at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx < 0 | idx >= Data.Blocks[BlockIndex].RailWall.Length) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex does not reference an existing wall in Track.WallEnd at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx >= Data.Blocks[BlockIndex].Rail.Length || (!Data.Blocks[BlockIndex].Rail[idx].RailStart & !Data.Blocks[BlockIndex].Rail[idx].RailEnd)) {
                                             Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex could be out of range in Track.WallEnd at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                         Data.Blocks[BlockIndex].RailWall[idx].Exists = false;
                                     }
                                 }
                             } break;
                         case "track.dike":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in Track.Dike at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is expected to be a non-negative integer in Track.Dike at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     int dir = 0;
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out dir)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Direction is invalid in Track.Dike at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         dir = 0;
                                     }
                                     int sttype = 0;
                                     if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out sttype)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "DikeStructureIndex is invalid in Track.Dike at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         sttype = 0;
                                     }
                                     if (sttype < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "DikeStructureIndex is expected to be a non-negative integer in Track.Wall at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         sttype = 0;
                                     }
                                     if (dir <= 0 && (sttype >= Data.Structure.DikeL.Length || Data.Structure.DikeL[sttype] == null) ||
                                         dir >= 0 && (sttype >= Data.Structure.DikeR.Length || Data.Structure.DikeR[sttype] == null)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "DikeStructureIndex references an object not loaded in Track.Dike at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx < 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is expected to be non-negative in Track.Dike at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (idx >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx].RailStart) {
                                                 Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex could be out of range in Track.Dike at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             }
                                             if (idx >= Data.Blocks[BlockIndex].RailDike.Length) {
                                                 Array.Resize<WallDike>(ref Data.Blocks[BlockIndex].RailDike, idx + 1);
                                             }
                                             Data.Blocks[BlockIndex].RailDike[idx].Exists = true;
                                             Data.Blocks[BlockIndex].RailDike[idx].Type = sttype;
                                             Data.Blocks[BlockIndex].RailDike[idx].Direction = dir;
                                         }
                                     }
                                 }
                             } break;
                         case "track.dikeend":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in Track.DikeEnd at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx < 0 | idx >= Data.Blocks[BlockIndex].RailDike.Length) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex does not reference an existing dike in Track.DikeEnd at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx >= Data.Blocks[BlockIndex].Rail.Length || (!Data.Blocks[BlockIndex].Rail[idx].RailStart & !Data.Blocks[BlockIndex].Rail[idx].RailEnd)) {
                                             Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex could be out of range in Track.DikeEnd at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                         Data.Blocks[BlockIndex].RailDike[idx].Exists = false;
                                     }
                                 }
                             } break;
                         case "track.marker":
                             {
                                 if (!PreviewOnly) {
                                     if (Arguments.Length < 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Track.Marker is expected to have at least one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                         if (!System.IO.File.Exists(f)) {
                                             Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in Track.Marker at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             double dist = Data.BlockInterval;
                                             if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[1], UnitOfLength, out dist)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Distance is invalid in Track.Marker at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 dist = Data.BlockInterval;
                                             }
                                             double start, end;
                                             if (dist < 0.0) {
                                                 start = Data.TrackPosition;
                                                 end = Data.TrackPosition - dist;
                                             } else {
                                                 start = Data.TrackPosition - dist;
                                                 end = Data.TrackPosition;
                                             }
                                             if (start < 0.0) start = 0.0;
                                             if (end < 0.0) end = 0.0;
                                             if (end <= start) end = start + 0.01;
                                             int n = Data.Markers.Length;
                                             Array.Resize<Marker>(ref Data.Markers, n + 1);
                                             Data.Markers[n].StartingPosition = start;
                                             Data.Markers[n].EndingPosition = end;
                                             Textures.RegisterTexture(f, new OpenBveApi.Textures.TextureParameters(null, new Color24(64, 64, 64)), out Data.Markers[n].Texture);
                                         }
                                     }
                                 }
                             } break;
                         case "track.height":
                             {
                                 if (!PreviewOnly) {
                                     double h = 0.0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], UnitOfLength, out h)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Height is invalid in Track.Height at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         h = 0.0;
                                     }
                                     Data.Blocks[BlockIndex].Height = IsRW ? h + 0.3 : h;
                                 }
                             } break;
                         case "track.ground":
                             {
                                 if (!PreviewOnly) {
                                     int cytype = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out cytype)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "CycleIndex is invalid in Track.Ground at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         cytype = 0;
                                     }
                                     if (cytype < Data.Structure.Cycle.Length && Data.Structure.Cycle[cytype] != null) {
                                         Data.Blocks[BlockIndex].Cycle = Data.Structure.Cycle[cytype];
                                     } else {
                                         if (cytype >= Data.Structure.Ground.Length || Data.Structure.Ground[cytype] == null) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "CycleIndex references an object not loaded in Track.Ground at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             Data.Blocks[BlockIndex].Cycle = new int[] { cytype };
                                         }
                                     }
                                 }
                             } break;
                         case "track.crack":
                             {
                                 if (!PreviewOnly) {
                                     int idx1 = 0, idx2 = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx1)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex1 is invalid in Track.Crack at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx1 = 0;
                                     }
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out idx2)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex2 is invalid in Track.Crack at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx2 = 0;
                                     }
                                     int sttype = 0;
                                     if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out sttype)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "CrackStructureIndex is invalid in Track.Crack at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         sttype = 0;
                                     }
                                     if (sttype < 0 || (sttype >= Data.Structure.CrackL.Length || Data.Structure.CrackL[sttype] == null) || (sttype >= Data.Structure.CrackR.Length || Data.Structure.CrackR[sttype] == null)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "CrackStructureIndex references an object not loaded in Track.Crack at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx1 < 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex1 is expected to be non-negative in Track.Crack at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (idx2 < 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex2 is expected to be non-negative in Track.Crack at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (idx1 == idx2) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex1 is expected to be unequal to Index2 in Track.Crack at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (idx1 >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx1].RailStart) {
                                                 Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex1 could be out of range in Track.Crack at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             }
                                             if (idx2 >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx2].RailStart) {
                                                 Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex2 could be out of range in Track.Crack at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             }
                                             int n = Data.Blocks[BlockIndex].Crack.Length;
                                             Array.Resize<Crack>(ref Data.Blocks[BlockIndex].Crack, n + 1);
                                             Data.Blocks[BlockIndex].Crack[n].PrimaryRail = idx1;
                                             Data.Blocks[BlockIndex].Crack[n].SecondaryRail = idx2;
                                             Data.Blocks[BlockIndex].Crack[n].Type = sttype;
                                         }
                                     }
                                 }
                             } break;
                         case "track.freeobj":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0, sttype = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out sttype)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FreeObjStructureIndex is invalid in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         sttype = 0;
                                     }
                                     if (idx < -1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is expected to be non-negative or -1 in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (sttype < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FreeObjStructureIndex is expected to be non-negative in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx >= 0 && (idx >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx].RailStart)) {
                                             Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex could be out of range in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                         if (sttype >= Data.Structure.FreeObj.Length || Data.Structure.FreeObj[sttype] == null || Data.Structure.FreeObj[sttype] == null) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FreeObjStructureIndex references an object not loaded in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             double x = 0.0, y = 0.0;
                                             double yaw = 0.0, pitch = 0.0, roll = 0.0;
                                             if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[2], UnitOfLength, out x)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 x = 0.0;
                                             }
                                             if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[3], UnitOfLength, out y)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 y = 0.0;
                                             }
                                             if (Arguments.Length >= 5 && Arguments[4].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[4], out yaw)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Yaw is invalid in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 yaw = 0.0;
                                             }
                                             if (Arguments.Length >= 6 && Arguments[5].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[5], out pitch)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Pitch is invalid in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 pitch = 0.0;
                                             }
                                             if (Arguments.Length >= 7 && Arguments[6].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[6], out roll)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Roll is invalid in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 roll = 0.0;
                                             }
                                             if (idx == -1) {
                                                 int n;
                                                 n = Data.Blocks[BlockIndex].GroundFreeObj.Length;
                                                 Array.Resize<FreeObj>(ref Data.Blocks[BlockIndex].GroundFreeObj, n + 1);
                                                 Data.Blocks[BlockIndex].GroundFreeObj[n].TrackPosition = Data.TrackPosition;
                                                 Data.Blocks[BlockIndex].GroundFreeObj[n].Type = sttype;
                                                 Data.Blocks[BlockIndex].GroundFreeObj[n].X = x;
                                                 Data.Blocks[BlockIndex].GroundFreeObj[n].Y = y;
                                                 Data.Blocks[BlockIndex].GroundFreeObj[n].Yaw = yaw * 0.0174532925199433;
                                                 Data.Blocks[BlockIndex].GroundFreeObj[n].Pitch = pitch * 0.0174532925199433;
                                                 Data.Blocks[BlockIndex].GroundFreeObj[n].Roll = roll * 0.0174532925199433;
                                             } else {
                                                 if (idx >= Data.Blocks[BlockIndex].RailFreeObj.Length) {
                                                     Array.Resize<FreeObj[]>(ref Data.Blocks[BlockIndex].RailFreeObj, idx + 1);
                                                 }
                                                 int n;
                                                 if (Data.Blocks[BlockIndex].RailFreeObj[idx] == null) {
                                                     Data.Blocks[BlockIndex].RailFreeObj[idx] = new FreeObj[1];
                                                     n = 0;
                                                 } else {
                                                     n = Data.Blocks[BlockIndex].RailFreeObj[idx].Length;
                                                     Array.Resize<FreeObj>(ref Data.Blocks[BlockIndex].RailFreeObj[idx], n + 1);
                                                 }
                                                 Data.Blocks[BlockIndex].RailFreeObj[idx][n].TrackPosition = Data.TrackPosition;
                                                 Data.Blocks[BlockIndex].RailFreeObj[idx][n].Type = sttype;
                                                 Data.Blocks[BlockIndex].RailFreeObj[idx][n].X = x;
                                                 Data.Blocks[BlockIndex].RailFreeObj[idx][n].Y = y;
                                                 Data.Blocks[BlockIndex].RailFreeObj[idx][n].Yaw = yaw * 0.0174532925199433;
                                                 Data.Blocks[BlockIndex].RailFreeObj[idx][n].Pitch = pitch * 0.0174532925199433;
                                                 Data.Blocks[BlockIndex].RailFreeObj[idx][n].Roll = roll * 0.0174532925199433;
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "track.back":
                             {
                                 if (!PreviewOnly) {
                                     int typ = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out typ)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "BackgroundTextureIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         typ = 0;
                                     }
                                     if (typ < 0 | typ >= Data.Backgrounds.Length) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "BackgroundTextureIndex references a texture not loaded in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (Data.Backgrounds[typ].Texture == null) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "BackgroundTextureIndex has not been loaded via Texture.Background in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         Data.Blocks[BlockIndex].Background = typ;
                                     }
                                 }
                             } break;
                         case "track.announce":
                             {
                                 if (!PreviewOnly) {
                                     if (Arguments.Length == 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have between 1 and 2 arguments at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             string f = OpenBveApi.Path.CombineFile(SoundPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 double speed = 0.0;
                                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[1], out speed)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "Speed is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                     speed = 0.0;
                                                 }
                                                 int n = Data.Blocks[BlockIndex].Sound.Length;
                                                 Array.Resize<Sound>(ref Data.Blocks[BlockIndex].Sound, n + 1);
                                                 Data.Blocks[BlockIndex].Sound[n].TrackPosition = Data.TrackPosition;
                                                 const double radius = 15.0;
                                                 Data.Blocks[BlockIndex].Sound[n].SoundBuffer = Sounds.RegisterBuffer(f, radius);
                                                 Data.Blocks[BlockIndex].Sound[n].Type = speed == 0.0 ? SoundType.TrainStatic : SoundType.TrainDynamic;
                                                 Data.Blocks[BlockIndex].Sound[n].Speed = speed * Data.UnitOfSpeed;
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "track.doppler":
                             {
                                 if (!PreviewOnly) {
                                     if (Arguments.Length == 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have between 1 and 3 arguments at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             string f = OpenBveApi.Path.CombineFile(SoundPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 double x = 0.0, y = 0.0;
                                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0 & !Interface.TryParseDoubleVb6(Arguments[1], UnitOfLength, out x)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                     x = 0.0;
                                                 }
                                                 if (Arguments.Length >= 3 && Arguments[2].Length > 0 & !Interface.TryParseDoubleVb6(Arguments[2], UnitOfLength, out y)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                     y = 0.0;
                                                 }
                                                 int n = Data.Blocks[BlockIndex].Sound.Length;
                                                 Array.Resize<Sound>(ref Data.Blocks[BlockIndex].Sound, n + 1);
                                                 Data.Blocks[BlockIndex].Sound[n].TrackPosition = Data.TrackPosition;
                                                 const double radius = 15.0;
                                                 Data.Blocks[BlockIndex].Sound[n].SoundBuffer = Sounds.RegisterBuffer(f, radius);
                                                 Data.Blocks[BlockIndex].Sound[n].Type = SoundType.World;
                                                 Data.Blocks[BlockIndex].Sound[n].X = x;
                                                 Data.Blocks[BlockIndex].Sound[n].Y = y;
                                                 Data.Blocks[BlockIndex].Sound[n].Radius = radius;
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "track.pretrain":
                             {
                                 if (!PreviewOnly) {
                                     if (Arguments.Length == 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have exactly 1 argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         double time = 0.0;
                                         if (Arguments[0].Length > 0 & !Interface.TryParseTime(Arguments[0], out time)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Time is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             time = 0.0;
                                         }
                                         int n = Game.BogusPretrainInstructions.Length;
                                         if (n != 0 && Game.BogusPretrainInstructions[n - 1].Time >= time) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Time is expected to be in ascending order between successive " + Command + " commands at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                         Array.Resize<Game.BogusPretrainInstruction>(ref Game.BogusPretrainInstructions, n + 1);
                                         Game.BogusPretrainInstructions[n].TrackPosition = Data.TrackPosition;
                                         Game.BogusPretrainInstructions[n].Time = time;
                                     }
                                 }
                             } break;
                         case "track.pointofinterest":
                         case "track.poi":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is expected to be non-negative in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx >= 0 && (idx >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx].RailStart)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex references a non-existing rail in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     }
                                     double x = 0.0, y = 0.0;
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[1], UnitOfLength, out x)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         x = 0.0;
                                     }
                                     if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[2], UnitOfLength, out y)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         y = 0.0;
                                     }
                                     double yaw = 0.0, pitch = 0.0, roll = 0.0;
                                     if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[3], out yaw)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Yaw is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         yaw = 0.0;
                                     }
                                     if (Arguments.Length >= 5 && Arguments[4].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[4], out pitch)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Pitch is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         pitch = 0.0;
                                     }
                                     if (Arguments.Length >= 6 && Arguments[5].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[5], out roll)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Roll is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         roll = 0.0;
                                     }
                                     string text = null;
                                     if (Arguments.Length >= 7 && Arguments[6].Length != 0) {
                                         text = Arguments[6];
                                     }
                                     int n = Data.Blocks[BlockIndex].PointsOfInterest.Length;
                                     Array.Resize<PointOfInterest>(ref Data.Blocks[BlockIndex].PointsOfInterest, n + 1);
                                     Data.Blocks[BlockIndex].PointsOfInterest[n].TrackPosition = Data.TrackPosition;
                                     Data.Blocks[BlockIndex].PointsOfInterest[n].RailIndex = idx;
                                     Data.Blocks[BlockIndex].PointsOfInterest[n].X = x;
                                     Data.Blocks[BlockIndex].PointsOfInterest[n].Y = y;
                                     Data.Blocks[BlockIndex].PointsOfInterest[n].Yaw = 0.0174532925199433 * yaw;
                                     Data.Blocks[BlockIndex].PointsOfInterest[n].Pitch = 0.0174532925199433 * pitch;
                                     Data.Blocks[BlockIndex].PointsOfInterest[n].Roll = 0.0174532925199433 * roll;
                                     Data.Blocks[BlockIndex].PointsOfInterest[n].Text = text;
                                 }
                             } break;
                         default:
                             Interface.AddMessage(Interface.MessageType.Warning, false, "The command " + Command + " is not supported at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             break;
                     }
                 }
             }
         }
     }
     if (!PreviewOnly) {
         // timetable
         Timetable.CustomTextures = new Textures.Texture[Data.TimetableDaytime.Length + Data.TimetableNighttime.Length];
         int n = 0;
         for (int i = 0; i < Data.TimetableDaytime.Length; i++) {
             if (Data.TimetableDaytime[i] != null) {
                 Timetable.CustomTextures[n] = Data.TimetableDaytime[i];
                 n++;
             }
         }
         for (int i = 0; i < Data.TimetableNighttime.Length; i++) {
             if (Data.TimetableNighttime[i] != null) {
                 Timetable.CustomTextures[n] = Data.TimetableNighttime[i];
                 n++;
             }
         }
         Array.Resize<Textures.Texture>(ref Timetable.CustomTextures, n);
     }
     // blocks
     Array.Resize<Block>(ref Data.Blocks, BlocksUsed);
 }
Exemplo n.º 45
0
        public static void Initialize()
        {
            SecretBaseDatabase.locationMap = new Dictionary<byte, LocationData>();
            SecretBaseDatabase.locationList = new List<LocationData>();
            SecretBaseDatabase.roomMap = new Dictionary<SecretBaseRoomID, RoomData>();
            SecretBaseDatabase.roomList = new List<RoomData>();
            SecretBaseDatabase.routeMap = new Dictionary<byte, RouteData>();
            SecretBaseDatabase.routeList = new List<RouteData>();

            SQLiteCommand command;
            SQLiteDataReader reader;
            DataTable table;

            SQLiteConnection connection = new SQLiteConnection("Data Source=SecretBaseDatabase.db");
            connection.Open();

            // Load Locations
            command = new SQLiteCommand("SELECT * FROM Locations", connection);
            reader = command.ExecuteReader();
            table = new DataTable("Locations");
            table.Load(reader);
            foreach (DataRow row in table.Rows) {
                LocationData location = new LocationData(row);
                locationMap.Add(location.ID, location);
                locationList.Add(location);
            }

            // Load Rooms
            command = new SQLiteCommand("SELECT * FROM Rooms", connection);
            reader = command.ExecuteReader();
            table = new DataTable("Rooms");
            table.Load(reader);
            foreach (DataRow row in table.Rows) {
                RoomData room = new RoomData(row);
                roomMap.Add(new SecretBaseRoomID { Type = room.Type, Layout = room.Layout }, room);
                roomList.Add(room);
            }

            // Load Routes
            command = new SQLiteCommand("SELECT * FROM Routes", connection);
            reader = command.ExecuteReader();
            table = new DataTable("Routes");
            table.Load(reader);
            foreach (DataRow row in table.Rows) {
                RouteData route = new RouteData(row);
                routeMap.Add(route.ID, route);
                routeList.Add(route);
            }

            connection.Close();
        }
Exemplo n.º 46
0
 // parse route
 internal static void ParseRoute(string FileName, bool IsRW, System.Text.Encoding Encoding, string TrainPath, string ObjectPath, string SoundPath, bool PreviewOnly)
 {
     // initialize data
     string CompatibilityFolder = Program.FileSystem.GetDataFolder("Compatibility");
     RouteData Data = new RouteData();
     Data.BlockInterval = 25.0;
     Data.AccurateObjectDisposal = false;
     Data.FirstUsedBlock = -1;
     Data.Blocks = new Block[1];
     Data.Blocks[0] = new Block();
     Data.Blocks[0].Rail = new Rail[1];
     Data.Blocks[0].Rail[0].RailStart = true;
     Data.Blocks[0].RailType = new int[] { 0 };
     Data.Blocks[0].Limit = new Limit[] { };
     Data.Blocks[0].Stop = new Stop[] { };
     Data.Blocks[0].Station = -1;
     Data.Blocks[0].StationPassAlarm = false;
     Data.Blocks[0].Accuracy = 2.0;
     Data.Blocks[0].AdhesionMultiplier = 1.0;
     Data.Blocks[0].CurrentTrackState = new TrackManager.TrackElement(0.0);
     if (!PreviewOnly) {
         Data.Blocks[0].Background = 0;
         Data.Blocks[0].Brightness = new Brightness[] { };
         Data.Blocks[0].Fog.Start = Game.NoFogStart;
         Data.Blocks[0].Fog.End = Game.NoFogEnd;
         Data.Blocks[0].Fog.Color = new Color24(128, 128, 128);
         Data.Blocks[0].Cycle = new int[] { -1 };
         Data.Blocks[0].Height = IsRW ? 0.3 : 0.0;
         Data.Blocks[0].RailFreeObj = new FreeObj[][] { };
         Data.Blocks[0].GroundFreeObj = new FreeObj[] { };
         Data.Blocks[0].RailWall = new WallDike[] { };
         Data.Blocks[0].RailDike = new WallDike[] { };
         Data.Blocks[0].RailPole = new Pole[] { };
         Data.Blocks[0].Form = new Form[] { };
         Data.Blocks[0].Crack = new Crack[] { };
         Data.Blocks[0].Signal = new Signal[] { };
         Data.Blocks[0].Section = new Section[] { };
         Data.Blocks[0].Sound = new Sound[] { };
         Data.Blocks[0].Transponder = new Transponder[] { };
         Data.Blocks[0].PointsOfInterest = new PointOfInterest[] { };
         Data.Markers = new Marker[] { };
         string PoleFolder = OpenBveApi.Path.CombineDirectory(CompatibilityFolder, "Poles");
         Data.Structure.Poles = new ObjectManager.UnifiedObject[][] {
             new ObjectManager.UnifiedObject[] {
                 ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile (PoleFolder, "pole_1.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false)
             }, new ObjectManager.UnifiedObject[] {
                 ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile (PoleFolder, "pole_2.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false)
             }, new ObjectManager.UnifiedObject[] {
                 ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile (PoleFolder, "pole_3.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false)
             }, new ObjectManager.UnifiedObject[] {
                 ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile (PoleFolder, "pole_4.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false)
             }
         };
         Data.Structure.Rail = new ObjectManager.UnifiedObject[] { };
         Data.Structure.Ground = new ObjectManager.UnifiedObject[] { };
         Data.Structure.WallL = new ObjectManager.UnifiedObject[] { };
         Data.Structure.WallR = new ObjectManager.UnifiedObject[] { };
         Data.Structure.DikeL = new ObjectManager.UnifiedObject[] { };
         Data.Structure.DikeR = new ObjectManager.UnifiedObject[] { };
         Data.Structure.FormL = new ObjectManager.UnifiedObject[] { };
         Data.Structure.FormR = new ObjectManager.UnifiedObject[] { };
         Data.Structure.FormCL = new ObjectManager.StaticObject[] { };
         Data.Structure.FormCR = new ObjectManager.StaticObject[] { };
         Data.Structure.RoofL = new ObjectManager.UnifiedObject[] { };
         Data.Structure.RoofR = new ObjectManager.UnifiedObject[] { };
         Data.Structure.RoofCL = new ObjectManager.StaticObject[] { };
         Data.Structure.RoofCR = new ObjectManager.StaticObject[] { };
         Data.Structure.CrackL = new ObjectManager.StaticObject[] { };
         Data.Structure.CrackR = new ObjectManager.StaticObject[] { };
         Data.Structure.FreeObj = new ObjectManager.UnifiedObject[] { };
         Data.Structure.Beacon = new ObjectManager.UnifiedObject[] { };
         Data.Structure.Cycle = new int[][] { };
         Data.Structure.Run = new int[] { };
         Data.Structure.Flange = new int[] { };
         Data.Backgrounds = new World.Background[] { };
         Data.TimetableDaytime = new Textures.Texture[] { null, null, null, null };
         Data.TimetableNighttime = new Textures.Texture[] { null, null, null, null };
         // signals
         string SignalFolder = OpenBveApi.Path.CombineDirectory(CompatibilityFolder, "Signals");
         Data.SignalData = new SignalData[7];
         Data.SignalData[3] = new CompatibilitySignalData(new int[] { 0, 2, 4 }, new ObjectManager.StaticObject[] {
                                                          	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile (SignalFolder, "signal_3_0.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                          	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile (SignalFolder, "signal_3_2.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                          	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile (SignalFolder, "signal_3_4.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false)
                                                          });
         Data.SignalData[4] = new CompatibilitySignalData(new int[] { 0, 1, 2, 4 }, new ObjectManager.StaticObject[] {
                                                          	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile (SignalFolder, "signal_4_0.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                          	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile (SignalFolder, "signal_4a_1.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                          	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile (SignalFolder, "signal_4a_2.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                          	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile (SignalFolder, "signal_4a_4.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false)
                                                          });
         Data.SignalData[5] = new CompatibilitySignalData(new int[] { 0, 1, 2, 3, 4 }, new ObjectManager.StaticObject[] {
                                                          	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_5_0.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                          	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_5a_1.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                          	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_5_2.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                          	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_5_3.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                          	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_5_4.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false)
                                                          });
         Data.SignalData[6] = new CompatibilitySignalData(new int[] { 0, 3, 4 }, new ObjectManager.StaticObject[] {
                                                          	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "repeatingsignal_0.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                          	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "repeatingsignal_3.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                          	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "repeatingsignal_4.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false)
                                                          });
         // compatibility signals
         Data.CompatibilitySignalData = new CompatibilitySignalData[9];
         Data.CompatibilitySignalData[0] = new CompatibilitySignalData(new int[] { 0, 2 }, new ObjectManager.StaticObject[] {
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_2_0.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_2a_2.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false)
                                                                       });
         Data.CompatibilitySignalData[1] = new CompatibilitySignalData(new int[] { 0, 4 }, new ObjectManager.StaticObject[] {
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_2_0.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_2b_4.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false)
                                                                       });
         Data.CompatibilitySignalData[2] = new CompatibilitySignalData(new int[] { 0, 2, 4 }, new ObjectManager.StaticObject[] {
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_3_0.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_3_2.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_3_4.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false)
                                                                       });
         Data.CompatibilitySignalData[3] = new CompatibilitySignalData(new int[] { 0, 1, 2, 4 }, new ObjectManager.StaticObject[] {
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_4_0.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_4a_1.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_4a_2.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_4a_4.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false)
                                                                       });
         Data.CompatibilitySignalData[4] = new CompatibilitySignalData(new int[] { 0, 2, 3, 4 }, new ObjectManager.StaticObject[] {
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_4_0.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_4b_2.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_4b_3.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_4b_4.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false)
                                                                       });
         Data.CompatibilitySignalData[5] = new CompatibilitySignalData(new int[] { 0, 1, 2, 3, 4 }, new ObjectManager.StaticObject[] {
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_5_0.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_5a_1.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_5_2.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_5_3.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_5_4.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false)
                                                                       });
         Data.CompatibilitySignalData[6] = new CompatibilitySignalData(new int[] { 0, 2, 3, 4, 5 }, new ObjectManager.StaticObject[] {
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_5_0.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_5_2.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_5_3.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_5_4.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_5b_5.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false)
                                                                       });
         Data.CompatibilitySignalData[7] = new CompatibilitySignalData(new int[] { 0, 1, 2, 3, 4, 5 }, new ObjectManager.StaticObject[] {
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_6_0.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_6_1.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_6_2.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_6_3.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_6_4.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "signal_6_5.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false)
                                                                       });
         Data.CompatibilitySignalData[8] = new CompatibilitySignalData(new int[] { 0, 3, 4 }, new ObjectManager.StaticObject[] {
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "repeatingsignal_0.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "repeatingsignal_3.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false),
                                                                       	ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalFolder, "repeatingsignal_4.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false)
                                                                       });
         // game data
         Game.Sections = new Game.Section[1];
         Game.Sections[0].Aspects = new Game.SectionAspect[] { new Game.SectionAspect(0, 0.0), new Game.SectionAspect(4, double.PositiveInfinity) };
         Game.Sections[0].CurrentAspect = 0;
         Game.Sections[0].NextSection = -1;
         Game.Sections[0].PreviousSection = -1;
         Game.Sections[0].SignalIndices = new int[] { };
         Game.Sections[0].StationIndex = -1;
         Game.Sections[0].TrackPosition = 0;
         Game.Sections[0].Trains = new TrainManager.Train[] { };
         // continue
         Data.SignalSpeeds = new double[] { 0.0, 6.94444444444444, 15.2777777777778, 20.8333333333333, double.PositiveInfinity, double.PositiveInfinity };
     }
     ParseRouteForData(FileName, IsRW, Encoding, TrainPath, ObjectPath, SoundPath, ref Data, PreviewOnly);
     if (Loading.Cancel) return;
     ApplyRouteData(FileName, Encoding, ref Data, PreviewOnly);
 }
Exemplo n.º 47
0
 protected virtual object GetOrCreateController(IAction cmd,RouteData routeData,Context context) {
     return null;
     //return this.ControllerFactory(cmd, routeData, context);
 }
Exemplo n.º 48
0
        public async virtual Task RouteAsync(RouteContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            EnsureLoggers(context.HttpContext);

            var requestPath = context.HttpContext.Request.Path;
            var values = _matcher.Match(requestPath);

            if (values == null)
            {
                // If we got back a null value set, that means the URI did not match
                return;
            }

            var oldRouteData = context.RouteData;

            var newRouteData = new RouteData(oldRouteData);

            // Perf: Avoid accessing data tokens if you don't need to write to it, these dictionaries are all
            // created lazily.
            if (_dataTokens.Count > 0)
            {
                MergeValues(newRouteData.DataTokens, _dataTokens);
            }

            newRouteData.Routers.Add(_target);
            MergeValues(newRouteData.Values, values);

            if (!RouteConstraintMatcher.Match(
                Constraints,
                newRouteData.Values,
                context.HttpContext,
                this,
                RouteDirection.IncomingRequest,
                _constraintLogger))
            {
                return;
            }

            _logger.LogVerbose(
                "Request successfully matched the route with name '{RouteName}' and template '{RouteTemplate}'.",
                Name,
                RouteTemplate);

            try
            {
                context.RouteData = newRouteData;

                await _target.RouteAsync(context);
            }
            finally
            {
                // Restore the original values to prevent polluting the route data.
                if (!context.IsHandled)
                {
                    context.RouteData = oldRouteData;
                }
            }
        }
Exemplo n.º 49
0
        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            // 构造 regex
            domainRegex = CreateRegex(Domain);
            pathRegex   = CreateRegex(Url);

            // 请求信息
            string requestDomain = httpContext.Request.Headers["host"];

            if (!string.IsNullOrEmpty(requestDomain))
            {
                if (requestDomain.IndexOf(":") > 0)
                {
                    requestDomain = requestDomain.Substring(0, requestDomain.IndexOf(":"));
                }
            }
            else
            {
                requestDomain = httpContext.Request.Url.Host;
            }
            string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;

            // 匹配域名和路由
            Match domainMatch = domainRegex.Match(requestDomain);
            Match pathMatch   = pathRegex.Match(requestPath);

            // 路由数据
            RouteData data = null;

            if (domainMatch.Success && pathMatch.Success)
            {
                data = new RouteData(this, RouteHandler);

                // 添加默认选项
                if (Defaults != null)
                {
                    foreach (KeyValuePair <string, object> item in Defaults)
                    {
                        data.Values[item.Key] = item.Value;
                    }
                }

                // 匹配域名路由
                for (int i = 1; i < domainMatch.Groups.Count; i++)
                {
                    Group group = domainMatch.Groups[i];
                    if (group.Success)
                    {
                        string key = domainRegex.GroupNameFromNumber(i);

                        if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0))
                        {
                            if (!string.IsNullOrEmpty(group.Value))
                            {
                                data.Values[key] = group.Value;
                            }
                        }
                    }
                }

                // 匹配域名路径
                for (int i = 1; i < pathMatch.Groups.Count; i++)
                {
                    Group group = pathMatch.Groups[i];
                    if (group.Success)
                    {
                        string key = pathRegex.GroupNameFromNumber(i);

                        if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0))
                        {
                            if (!string.IsNullOrEmpty(group.Value))
                            {
                                data.Values[key] = group.Value;
                            }
                        }
                    }
                }
            }

            return(data);
        }
Exemplo n.º 50
0
        public async virtual Task RouteAsync([NotNull] RouteContext context)
        {
            EnsureLoggers(context.HttpContext);
            using (_logger.BeginScope("TemplateRoute.RouteAsync"))
            {
                var requestPath = context.HttpContext.Request.Path.Value;

                if (!string.IsNullOrEmpty(requestPath) && requestPath[0] == '/')
                {
                    requestPath = requestPath.Substring(1);
                }

                var values = _matcher.Match(requestPath);

                if (values == null)
                {
                    if (_logger.IsEnabled(LogLevel.Verbose))
                    {
                        _logger.WriteValues(CreateRouteAsyncValues(
                            requestPath,
                            context.RouteData.Values,
                            matchedValues: false,
                            matchedConstraints: false,
                            handled: context.IsHandled));
                    }

                    // If we got back a null value set, that means the URI did not match
                    return;
                }

                var oldRouteData = context.RouteData;

                var newRouteData = new RouteData(oldRouteData);
                MergeValues(newRouteData.DataTokens, _dataTokens);
                newRouteData.Routers.Add(_target);
                MergeValues(newRouteData.Values, values);

                if (!RouteConstraintMatcher.Match(
                    Constraints,
                    newRouteData.Values,
                    context.HttpContext,
                    this,
                    RouteDirection.IncomingRequest,
                    _constraintLogger))
                {
                    if (_logger.IsEnabled(LogLevel.Verbose))
                    {
                        _logger.WriteValues(CreateRouteAsyncValues(
                            requestPath,
                            newRouteData.Values,
                            matchedValues: true,
                            matchedConstraints: false,
                            handled: context.IsHandled));
                    }

                    return;
                }

                try
                {
                    context.RouteData = newRouteData;

                    await _target.RouteAsync(context);

                    if (_logger.IsEnabled(LogLevel.Verbose))
                    {
                        _logger.WriteValues(CreateRouteAsyncValues(
                            requestPath,
                            newRouteData.Values,
                            matchedValues: true,
                            matchedConstraints: true,
                            handled: context.IsHandled));
                    }
                }
                finally
                {
                    // Restore the original values to prevent polluting the route data.
                    if (!context.IsHandled)
                    {
                        context.RouteData = oldRouteData;
                    }
                }
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="T:RouteDataAssertions" /> class.
 /// </summary>
 public RouteDataAssertions(RouteData subject)
     : base(subject)
 {
     Subject = subject;
 }
Exemplo n.º 52
0
        public ActionResult Index(UserIndexOptions options, PagerParameters pagerParameters)
        {
            if (!service.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to list users")))
            {
                return(new HttpUnauthorizedResult());
            }

            var userType = contentDefinitionManager.GetTypeDefinition("User");
            var hasBasicUserProfilePart = userType.Parts.Any(p => p.PartDefinition.Name == nameof(BasicUserProfilePart));

            // Create criteria
            var session = transactionManager.GetSession();
            var query   = session.CreateCriteria <ContentItemVersionRecord>("version")
                          .CreateAlias("version.ContentItemRecord", "item", JoinType.InnerJoin)
                          // content item is aggregation of part records
                          .CreateAlias("item.ContentType", "type", JoinType.InnerJoin)
                          .CreateAlias("item.UserPartRecord", "user", JoinType.InnerJoin)
                          .Add(Restrictions.Eq("type.Name", "User"))
                          .Add(Restrictions.Eq("version.Published", true));

            if (hasBasicUserProfilePart)
            {
                query.CreateAlias(
                    "item.BasicUserProfilePartRecord",
                    "profile",
                    JoinType.LeftOuterJoin
                    ); // Not all user have profiles, e.g Admin
            }
            SetFilter(options, query, hasBasicUserProfilePart);

            var totalItemCount = query.SetProjection(Projections.RowCount()).UniqueResult <int>();
            var pager          = new Pager(siteService.GetSiteSettings(), pagerParameters);
            var pagerShape     = Shape.Pager(pager).TotalItemCount(totalItemCount);

            SetProjectionList(hasBasicUserProfilePart, query);
            // FirstResult is row index start from 0
            // pager.GetStartIndex() is calculated row index that we use
            // If we want page number, use pager.Page.
            query.SetFirstResult(pager.GetStartIndex()).SetMaxResults(pager.PageSize);
            SetSortOrder(options, query, hasBasicUserProfilePart);

            var results = query.List <BasicUserProfileDto>();
            var model   = new UserIndexViewModel {
                Users = results.Select(u => new ViewModels.UserEntry()
                {
                    User = u
                }).ToList(),
                Options = options,
                Pager   = pagerShape
            };

            // maintain previous route data when generating page links
            var routeData = new RouteData();

            routeData.Values.Add("Options.Filter", options.Filter);
            routeData.Values.Add("Options.Search", options.Search);
            routeData.Values.Add("Options.Order", options.Order);
            pagerShape.RouteData(routeData);

            // https://stackoverflow.com/questions/43565738/name-valuetuple-properties-when-creating-with-new/43566072#43566072
            // can't cast with "is (Url: string, Email: string>) activationEmail"
            if (TempData[activationEmailKey] is ValueTuple <string, string> activationEmail)
            {
                var(url, email)           = activationEmail;
                model.ActivationEmailSent = Shape.ActivationEmailSent(Url: url, Email: email);
            }
            ;

            return(View(model));
        }
Exemplo n.º 53
0
 private static void ParseRouteForData(string FileName, bool IsRW, System.Text.Encoding Encoding, string TrainPath, string ObjectPath, string SoundPath, ref RouteData Data, bool PreviewOnly)
 {
     // parse
     string[] Lines = System.IO.File.ReadAllLines(FileName, Encoding);
     Expression[] Expressions;
     PreprocessSplitIntoExpressions(FileName, IsRW, Lines, Encoding, out Expressions, true, 0.0);
     PreprocessChrRndSub(FileName, IsRW, ref Expressions);
     double[] UnitOfLength = new double[] { 1.0 };
     Data.UnitOfSpeed = 0.277777777777778;
     PreprocessOptions(FileName, IsRW, Encoding, Expressions, ref Data, ref UnitOfLength);
     PreprocessSortByTrackPosition(FileName, IsRW, UnitOfLength, ref Expressions);
     ParseRouteForData(FileName, IsRW, Encoding, Expressions, TrainPath, ObjectPath, SoundPath, UnitOfLength, ref Data, PreviewOnly);
     Game.RouteUnitOfLength = UnitOfLength;
 }
Exemplo n.º 54
0
        internal UrlActionInfo GetUrlActionInfo(RouteData routeData, HttpContext context)
        {
            if (routeData == null)
            {
                throw new ArgumentNullException("routeData");
            }
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            // 采用ASP.NET Routing后,这三个参数都应该可以直接获取到,
            // 如果URL没有指定,可以通过默认值,或者DataToken指定,
            // 所以不需要像RestServiceModule那样重新计算
            string nspace    = GetRouteString(routeData, "namespace");
            string className = GetRouteString(routeData, "controller");
            string action    = GetRouteString(routeData, "action");

            if (string.IsNullOrEmpty(className) || string.IsNullOrEmpty(action))
            {
                DiagnoseResult diagnoseResult = Http404DebugModule.TryGetDiagnoseResult(context);
                if (diagnoseResult != null)
                {
                    diagnoseResult.ErrorMessages.Add("不能从URL中提取到controller和action信息");
                }

                return(null);
            }

            if (action == "{HttpMethod}")                       // 允许定义这个特殊变量
            {
                action = context.Request.HttpMethod;
            }


            ControllerResolver controllerResolver = new ControllerResolver(context);

            UrlActionInfo info = new UrlActionInfo();

            info.RoutePattern = (routeData.Route as Route).Url;                         // 转换失败??
            info.Namesapce    = controllerResolver.GetNamespaceMap(nspace);
            info.ClassName    = className;
            info.MethodName   = action;

            info.Action     = action;
            info.Controller = s_recognizer.GetServiceFullName(info);


            // 将路由提取到的其它URL参数,保存到UrlActionInfo实例中。
            foreach (KeyValuePair <string, object> kvp in routeData.Values)
            {
                // 排除3个特定名字。
                if (kvp.Key.IsSame("namespace") || kvp.Key.IsSame("controller") || kvp.Key.IsSame("action"))
                {
                    continue;
                }

                string value = kvp.Value as string;
                if (string.IsNullOrEmpty(value) == false)
                {
                    info.AddParam(kvp.Key, value);
                }
            }

            return(info);
        }
Exemplo n.º 55
0
 // apply route data
 private static void ApplyRouteData(string FileName, System.Text.Encoding Encoding, ref RouteData Data, bool PreviewOnly)
 {
     string SignalPath, LimitPath, LimitGraphicsPath, TransponderPath;
     ObjectManager.StaticObject SignalPost, LimitPostStraight, LimitPostLeft, LimitPostRight, LimitPostInfinite;
     ObjectManager.StaticObject LimitOneDigit, LimitTwoDigits, LimitThreeDigits, StopPost;
     ObjectManager.StaticObject TransponderS, TransponderSN, TransponderFalseStart, TransponderPOrigin, TransponderPStop;
     if (!PreviewOnly) {
         string CompatibilityFolder = Program.FileSystem.GetDataFolder("Compatibility");
         // load compatibility objects
         SignalPath = OpenBveApi.Path.CombineDirectory(CompatibilityFolder, "Signals");
         SignalPost = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(SignalPath, "signal_post.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
         LimitPath = OpenBveApi.Path.CombineDirectory(CompatibilityFolder, "Limits");
         LimitGraphicsPath = OpenBveApi.Path.CombineDirectory(LimitPath, "Graphics");
         LimitPostStraight = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_straight.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
         LimitPostLeft = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_left.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
         LimitPostRight = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_right.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
         LimitPostInfinite = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_infinite.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
         LimitOneDigit = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_1_digit.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
         LimitTwoDigits = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_2_digits.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
         LimitThreeDigits = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(LimitPath, "limit_3_digits.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
         StopPost = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(CompatibilityFolder, "stop.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
         TransponderPath = OpenBveApi.Path.CombineDirectory(CompatibilityFolder, "Transponders");
         TransponderS = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(TransponderPath, "s.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
         TransponderSN = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(TransponderPath, "sn.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
         TransponderFalseStart = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(TransponderPath, "falsestart.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
         TransponderPOrigin = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(TransponderPath, "porigin.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
         TransponderPStop = ObjectManager.LoadStaticObject(OpenBveApi.Path.CombineFile(TransponderPath, "pstop.csv"), Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
     } else {
         SignalPath = null;
         LimitPath = null;
         LimitGraphicsPath = null;
         TransponderPath = null;
         SignalPost = null;
         LimitPostStraight = null;
         LimitPostLeft = null;
         LimitPostRight = null;
         LimitPostInfinite = null;
         LimitOneDigit = null;
         LimitTwoDigits = null;
         LimitThreeDigits = null;
         StopPost = null;
         TransponderS = null;
         TransponderSN = null;
         TransponderFalseStart = null;
         TransponderPOrigin = null;
         TransponderPStop = null;
     }
     // initialize
     System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
     int LastBlock = (int)Math.Floor((Data.TrackPosition + 600.0) / Data.BlockInterval + 0.001) + 1;
     int BlocksUsed = Data.Blocks.Length;
     CreateMissingBlocks(ref Data, ref BlocksUsed, LastBlock, PreviewOnly);
     Array.Resize<Block>(ref Data.Blocks, BlocksUsed);
     // interpolate height
     if (!PreviewOnly) {
         int z = 0;
         for (int i = 0; i < Data.Blocks.Length; i++) {
             if (!double.IsNaN(Data.Blocks[i].Height)) {
                 for (int j = i - 1; j >= 0; j--) {
                     if (!double.IsNaN(Data.Blocks[j].Height)) {
                         double a = Data.Blocks[j].Height;
                         double b = Data.Blocks[i].Height;
                         double d = (b - a) / (double)(i - j);
                         for (int k = j + 1; k < i; k++) {
                             a += d;
                             Data.Blocks[k].Height = a;
                         }
                         break;
                     }
                 }
                 z = i;
             }
         }
         for (int i = z + 1; i < Data.Blocks.Length; i++) {
             Data.Blocks[i].Height = Data.Blocks[z].Height;
         }
     }
     // background
     if (!PreviewOnly) {
         if (Data.Blocks[0].Background >= 0 & Data.Blocks[0].Background < Data.Backgrounds.Length) {
             World.CurrentBackground = Data.Backgrounds[Data.Blocks[0].Background];
         } else {
             World.CurrentBackground = new World.Background(null, 6, false);
         }
         World.TargetBackground = World.CurrentBackground;
     }
     // brightness
     int CurrentBrightnessElement = -1;
     int CurrentBrightnessEvent = -1;
     float CurrentBrightnessValue = 1.0f;
     double CurrentBrightnessTrackPosition = (double)Data.FirstUsedBlock * Data.BlockInterval;
     if (!PreviewOnly) {
         for (int i = Data.FirstUsedBlock; i < Data.Blocks.Length; i++) {
             if (Data.Blocks[i].Brightness != null && Data.Blocks[i].Brightness.Length != 0) {
                 CurrentBrightnessValue = Data.Blocks[i].Brightness[0].Value;
                 CurrentBrightnessTrackPosition = Data.Blocks[i].Brightness[0].Value;
                 break;
             }
         }
     }
     // create objects and track
     Vector3 Position = new Vector3(0.0, 0.0, 0.0);
     World.Vector2D Direction = new World.Vector2D(0.0, 1.0);
     TrackManager.CurrentTrack = new TrackManager.Track();
     TrackManager.CurrentTrack.Elements = new TrackManager.TrackElement[] { };
     double CurrentSpeedLimit = double.PositiveInfinity;
     int CurrentRunIndex = 0;
     int CurrentFlangeIndex = 0;
     if (Data.FirstUsedBlock < 0) Data.FirstUsedBlock = 0;
     TrackManager.CurrentTrack.Elements = new TrackManager.TrackElement[256];
     int CurrentTrackLength = 0;
     int PreviousFogElement = -1;
     int PreviousFogEvent = -1;
     Game.Fog PreviousFog = new Game.Fog(Game.NoFogStart, Game.NoFogEnd, new Color24(128, 128, 128), -Data.BlockInterval);
     Game.Fog CurrentFog = new Game.Fog(Game.NoFogStart, Game.NoFogEnd, new Color24(128, 128, 128), 0.0);
     // process blocks
     double progressFactor = Data.Blocks.Length - Data.FirstUsedBlock == 0 ? 0.5 : 0.5 / (double)(Data.Blocks.Length - Data.FirstUsedBlock);
     for (int i = Data.FirstUsedBlock; i < Data.Blocks.Length; i++) {
         Loading.RouteProgress = 0.6667 + (double)(i - Data.FirstUsedBlock) * progressFactor;
         if ((i & 15) == 0) {
             System.Threading.Thread.Sleep(1);
             if (Loading.Cancel) return;
         }
         double StartingDistance = (double)i * Data.BlockInterval;
         double EndingDistance = StartingDistance + Data.BlockInterval;
         // normalize
         World.Normalize(ref Direction.X, ref Direction.Y);
         // track
         if (!PreviewOnly) {
             if (Data.Blocks[i].Cycle.Length == 1 && Data.Blocks[i].Cycle[0] == -1) {
                 if (Data.Structure.Cycle.Length == 0 || Data.Structure.Cycle[0] == null) {
                     Data.Blocks[i].Cycle = new int[] { 0 };
                 } else {
                     Data.Blocks[i].Cycle = Data.Structure.Cycle[0];
                 }
             }
         }
         TrackManager.TrackElement WorldTrackElement = Data.Blocks[i].CurrentTrackState;
         int n = CurrentTrackLength;
         if (n >= TrackManager.CurrentTrack.Elements.Length) {
             Array.Resize<TrackManager.TrackElement>(ref TrackManager.CurrentTrack.Elements, TrackManager.CurrentTrack.Elements.Length << 1);
         }
         CurrentTrackLength++;
         TrackManager.CurrentTrack.Elements[n] = WorldTrackElement;
         TrackManager.CurrentTrack.Elements[n].WorldPosition = Position;
         TrackManager.CurrentTrack.Elements[n].WorldDirection = World.GetVector3(Direction, Data.Blocks[i].Pitch);
         TrackManager.CurrentTrack.Elements[n].WorldSide = new Vector3(Direction.Y, 0.0, -Direction.X);
         World.Cross(TrackManager.CurrentTrack.Elements[n].WorldDirection.X, TrackManager.CurrentTrack.Elements[n].WorldDirection.Y, TrackManager.CurrentTrack.Elements[n].WorldDirection.Z, TrackManager.CurrentTrack.Elements[n].WorldSide.X, TrackManager.CurrentTrack.Elements[n].WorldSide.Y, TrackManager.CurrentTrack.Elements[n].WorldSide.Z, out TrackManager.CurrentTrack.Elements[n].WorldUp.X, out TrackManager.CurrentTrack.Elements[n].WorldUp.Y, out TrackManager.CurrentTrack.Elements[n].WorldUp.Z);
         TrackManager.CurrentTrack.Elements[n].StartingTrackPosition = StartingDistance;
         TrackManager.CurrentTrack.Elements[n].Events = new TrackManager.GeneralEvent[] { };
         TrackManager.CurrentTrack.Elements[n].AdhesionMultiplier = Data.Blocks[i].AdhesionMultiplier;
         TrackManager.CurrentTrack.Elements[n].CsvRwAccuracyLevel = Data.Blocks[i].Accuracy;
         // background
         if (!PreviewOnly) {
             if (Data.Blocks[i].Background >= 0) {
                 int typ;
                 if (i == Data.FirstUsedBlock) {
                     typ = Data.Blocks[i].Background;
                 } else {
                     typ = Data.Backgrounds.Length > 0 ? 0 : -1;
                     for (int j = i - 1; j >= Data.FirstUsedBlock; j--) {
                         if (Data.Blocks[j].Background >= 0) {
                             typ = Data.Blocks[j].Background;
                             break;
                         }
                     }
                 }
                 if (typ >= 0 & typ < Data.Backgrounds.Length) {
                     int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
                     Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
                     TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.BackgroundChangeEvent(0.0, Data.Backgrounds[typ], Data.Backgrounds[Data.Blocks[i].Background]);
                 }
             }
         }
         // brightness
         if (!PreviewOnly) {
             for (int j = 0; j < Data.Blocks[i].Brightness.Length; j++) {
                 int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
                 Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
                 double d = Data.Blocks[i].Brightness[j].TrackPosition - StartingDistance;
                 TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.BrightnessChangeEvent(d, Data.Blocks[i].Brightness[j].Value, CurrentBrightnessValue, Data.Blocks[i].Brightness[j].TrackPosition - CurrentBrightnessTrackPosition, Data.Blocks[i].Brightness[j].Value, 0.0);
                 if (CurrentBrightnessElement >= 0 & CurrentBrightnessEvent >= 0) {
                     TrackManager.BrightnessChangeEvent bce = (TrackManager.BrightnessChangeEvent)TrackManager.CurrentTrack.Elements[CurrentBrightnessElement].Events[CurrentBrightnessEvent];
                     bce.NextBrightness = Data.Blocks[i].Brightness[j].Value;
                     bce.NextDistance = Data.Blocks[i].Brightness[j].TrackPosition - CurrentBrightnessTrackPosition;
                 }
                 CurrentBrightnessElement = n;
                 CurrentBrightnessEvent = m;
                 CurrentBrightnessValue = Data.Blocks[i].Brightness[j].Value;
                 CurrentBrightnessTrackPosition = Data.Blocks[i].Brightness[j].TrackPosition;
             }
         }
         // fog
         if (!PreviewOnly) {
             if (Data.FogTransitionMode) {
                 if (Data.Blocks[i].FogDefined) {
                     Data.Blocks[i].Fog.TrackPosition = StartingDistance;
                     int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
                     Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
                     TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.FogChangeEvent(0.0, PreviousFog, Data.Blocks[i].Fog, Data.Blocks[i].Fog);
                     if (PreviousFogElement >= 0 & PreviousFogEvent >= 0) {
                         TrackManager.FogChangeEvent e = (TrackManager.FogChangeEvent)TrackManager.CurrentTrack.Elements[PreviousFogElement].Events[PreviousFogEvent];
                         e.NextFog = Data.Blocks[i].Fog;
                     } else {
                         Game.PreviousFog = PreviousFog;
                         Game.CurrentFog = PreviousFog;
                         Game.NextFog = Data.Blocks[i].Fog;
                     }
                     PreviousFog = Data.Blocks[i].Fog;
                     PreviousFogElement = n;
                     PreviousFogEvent = m;
                 }
             } else {
                 Data.Blocks[i].Fog.TrackPosition = StartingDistance + Data.BlockInterval;
                 int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
                 Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
                 TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.FogChangeEvent(0.0, PreviousFog, CurrentFog, Data.Blocks[i].Fog);
                 PreviousFog = CurrentFog;
                 CurrentFog = Data.Blocks[i].Fog;
             }
         }
         // rail sounds
         if (!PreviewOnly) {
             int j = Data.Blocks[i].RailType[0];
             int r = j < Data.Structure.Run.Length ? Data.Structure.Run[j] : 0;
             int f = j < Data.Structure.Flange.Length ? Data.Structure.Flange[j] : 0;
             int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
             Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
             TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.RailSoundsChangeEvent(0.0, CurrentRunIndex, CurrentFlangeIndex, r, f);
             CurrentRunIndex = r;
             CurrentFlangeIndex = f;
         }
         // point sound
         if (!PreviewOnly) {
             if (i < Data.Blocks.Length - 1) {
                 bool q = false;
                 for (int j = 0; j < Data.Blocks[i].Rail.Length; j++) {
                     if (Data.Blocks[i].Rail[j].RailStart & Data.Blocks[i + 1].Rail.Length > j) {
                         bool qx = Math.Sign(Data.Blocks[i].Rail[j].RailStartX) != Math.Sign(Data.Blocks[i + 1].Rail[j].RailEndX);
                         bool qy = Data.Blocks[i].Rail[j].RailStartY * Data.Blocks[i + 1].Rail[j].RailEndY <= 0.0;
                         if (qx & qy) {
                             q = true;
                             break;
                         }
                     }
                 }
                 if (q) {
                     int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
                     Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
                     TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.SoundEvent(0.0, null, false, false, true, new Vector3(0.0, 0.0, 0.0), 12.5);
                 }
             }
         }
         // station
         if (Data.Blocks[i].Station >= 0) {
             // station
             int s = Data.Blocks[i].Station;
             int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
             Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
             TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.StationStartEvent(0.0, s);
             double dx, dy = 3.0;
             if (Game.Stations[s].OpenLeftDoors & !Game.Stations[s].OpenRightDoors) {
                 dx = -5.0;
             } else if (!Game.Stations[s].OpenLeftDoors & Game.Stations[s].OpenRightDoors) {
                 dx = 5.0;
             } else {
                 dx = 0.0;
             }
             Game.Stations[s].SoundOrigin.X = Position.X + dx * TrackManager.CurrentTrack.Elements[n].WorldSide.X + dy * TrackManager.CurrentTrack.Elements[n].WorldUp.X;
             Game.Stations[s].SoundOrigin.Y = Position.Y + dx * TrackManager.CurrentTrack.Elements[n].WorldSide.Y + dy * TrackManager.CurrentTrack.Elements[n].WorldUp.Y;
             Game.Stations[s].SoundOrigin.Z = Position.Z + dx * TrackManager.CurrentTrack.Elements[n].WorldSide.Z + dy * TrackManager.CurrentTrack.Elements[n].WorldUp.Z;
             // passalarm
             if (!PreviewOnly) {
                 if (Data.Blocks[i].StationPassAlarm) {
                     int b = i - 6;
                     if (b >= 0) {
                         int j = b - Data.FirstUsedBlock;
                         if (j >= 0) {
                             m = TrackManager.CurrentTrack.Elements[j].Events.Length;
                             Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[j].Events, m + 1);
                             TrackManager.CurrentTrack.Elements[j].Events[m] = new TrackManager.StationPassAlarmEvent(0.0);
                         }
                     }
                 }
             }
         }
         // stop
         for (int j = 0; j < Data.Blocks[i].Stop.Length; j++) {
             int s = Data.Blocks[i].Stop[j].Station;
             int t = Game.Stations[s].Stops.Length;
             Array.Resize<Game.StationStop>(ref Game.Stations[s].Stops, t + 1);
             Game.Stations[s].Stops[t].TrackPosition = Data.Blocks[i].Stop[j].TrackPosition;
             Game.Stations[s].Stops[t].ForwardTolerance = Data.Blocks[i].Stop[j].ForwardTolerance;
             Game.Stations[s].Stops[t].BackwardTolerance = Data.Blocks[i].Stop[j].BackwardTolerance;
             Game.Stations[s].Stops[t].Cars = Data.Blocks[i].Stop[j].Cars;
             double dx, dy = 2.0;
             if (Game.Stations[s].OpenLeftDoors & !Game.Stations[s].OpenRightDoors) {
                 dx = -5.0;
             } else if (!Game.Stations[s].OpenLeftDoors & Game.Stations[s].OpenRightDoors) {
                 dx = 5.0;
             } else {
                 dx = 0.0;
             }
             Game.Stations[s].SoundOrigin.X = Position.X + dx * TrackManager.CurrentTrack.Elements[n].WorldSide.X + dy * TrackManager.CurrentTrack.Elements[n].WorldUp.X;
             Game.Stations[s].SoundOrigin.Y = Position.Y + dx * TrackManager.CurrentTrack.Elements[n].WorldSide.Y + dy * TrackManager.CurrentTrack.Elements[n].WorldUp.Y;
             Game.Stations[s].SoundOrigin.Z = Position.Z + dx * TrackManager.CurrentTrack.Elements[n].WorldSide.Z + dy * TrackManager.CurrentTrack.Elements[n].WorldUp.Z;
         }
         // limit
         for (int j = 0; j < Data.Blocks[i].Limit.Length; j++) {
             int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
             Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
             double d = Data.Blocks[i].Limit[j].TrackPosition - StartingDistance;
             TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.LimitChangeEvent(d, CurrentSpeedLimit, Data.Blocks[i].Limit[j].Speed);
             CurrentSpeedLimit = Data.Blocks[i].Limit[j].Speed;
         }
         // marker
         if (!PreviewOnly) {
             for (int j = 0; j < Data.Markers.Length; j++) {
                 if (Data.Markers[j].StartingPosition >= StartingDistance & Data.Markers[j].StartingPosition < EndingDistance) {
                     int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
                     Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
                     double d = Data.Markers[j].StartingPosition - StartingDistance;
                     TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.MarkerStartEvent(d, Data.Markers[j].Texture);
                 }
                 if (Data.Markers[j].EndingPosition >= StartingDistance & Data.Markers[j].EndingPosition < EndingDistance) {
                     int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
                     Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
                     double d = Data.Markers[j].EndingPosition - StartingDistance;
                     TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.MarkerEndEvent(d, Data.Markers[j].Texture);
                 }
             }
         }
         // sound
         if (!PreviewOnly) {
             for (int j = 0; j < Data.Blocks[i].Sound.Length; j++) {
                 if (Data.Blocks[i].Sound[j].Type == SoundType.TrainStatic | Data.Blocks[i].Sound[j].Type == SoundType.TrainDynamic) {
                     int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
                     Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
                     double d = Data.Blocks[i].Sound[j].TrackPosition - StartingDistance;
                     switch (Data.Blocks[i].Sound[j].Type) {
                         case SoundType.TrainStatic:
                             TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.SoundEvent(d, Data.Blocks[i].Sound[j].SoundBuffer, true, true, false, new Vector3(0.0, 0.0, 0.0), 0.0);
                             break;
                         case SoundType.TrainDynamic:
                             TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.SoundEvent(d, Data.Blocks[i].Sound[j].SoundBuffer, false, false, true, new Vector3(0.0, 0.0, 0.0), Data.Blocks[i].Sound[j].Speed);
                             break;
                     }
                 }
             }
         }
         // turn
         if (Data.Blocks[i].Turn != 0.0) {
             double ag = -Math.Atan(Data.Blocks[i].Turn);
             double cosag = Math.Cos(ag);
             double sinag = Math.Sin(ag);
             World.Rotate(ref Direction, cosag, sinag);
             World.RotatePlane(ref TrackManager.CurrentTrack.Elements[n].WorldDirection, cosag, sinag);
             World.RotatePlane(ref TrackManager.CurrentTrack.Elements[n].WorldSide, cosag, sinag);
             World.Cross(TrackManager.CurrentTrack.Elements[n].WorldDirection.X, TrackManager.CurrentTrack.Elements[n].WorldDirection.Y, TrackManager.CurrentTrack.Elements[n].WorldDirection.Z, TrackManager.CurrentTrack.Elements[n].WorldSide.X, TrackManager.CurrentTrack.Elements[n].WorldSide.Y, TrackManager.CurrentTrack.Elements[n].WorldSide.Z, out TrackManager.CurrentTrack.Elements[n].WorldUp.X, out TrackManager.CurrentTrack.Elements[n].WorldUp.Y, out TrackManager.CurrentTrack.Elements[n].WorldUp.Z);
         }
         // curves
         double a = 0.0;
         double c = Data.BlockInterval;
         double h = 0.0;
         if (WorldTrackElement.CurveRadius != 0.0 & Data.Blocks[i].Pitch != 0.0) {
             double d = Data.BlockInterval;
             double p = Data.Blocks[i].Pitch;
             double r = WorldTrackElement.CurveRadius;
             double s = d / Math.Sqrt(1.0 + p * p);
             h = s * p;
             double b = s / Math.Abs(r);
             c = Math.Sqrt(2.0 * r * r * (1.0 - Math.Cos(b)));
             a = 0.5 * (double)Math.Sign(r) * b;
             World.Rotate(ref Direction, Math.Cos(-a), Math.Sin(-a));
         } else if (WorldTrackElement.CurveRadius != 0.0) {
             double d = Data.BlockInterval;
             double r = WorldTrackElement.CurveRadius;
             double b = d / Math.Abs(r);
             c = Math.Sqrt(2.0 * r * r * (1.0 - Math.Cos(b)));
             a = 0.5 * (double)Math.Sign(r) * b;
             World.Rotate(ref Direction, Math.Cos(-a), Math.Sin(-a));
         } else if (Data.Blocks[i].Pitch != 0.0) {
             double p = Data.Blocks[i].Pitch;
             double d = Data.BlockInterval;
             c = d / Math.Sqrt(1.0 + p * p);
             h = c * p;
         }
         double TrackYaw = Math.Atan2(Direction.X, Direction.Y);
         double TrackPitch = Math.Atan(Data.Blocks[i].Pitch);
         World.Transformation GroundTransformation = new World.Transformation(TrackYaw, 0.0, 0.0);
         World.Transformation TrackTransformation = new World.Transformation(TrackYaw, TrackPitch, 0.0);
         World.Transformation NullTransformation = new World.Transformation(0.0, 0.0, 0.0);
         // ground
         if (!PreviewOnly) {
             int cb = (int)Math.Floor((double)i + 0.001);
             int ci = (cb % Data.Blocks[i].Cycle.Length + Data.Blocks[i].Cycle.Length) % Data.Blocks[i].Cycle.Length;
             int gi = Data.Blocks[i].Cycle[ci];
             if (gi >= 0 & gi < Data.Structure.Ground.Length) {
                 if (Data.Structure.Ground[gi] != null) {
                     ObjectManager.CreateObject(Data.Structure.Ground[Data.Blocks[i].Cycle[ci]], Position + new Vector3(0.0, -Data.Blocks[i].Height, 0.0), GroundTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                 }
             }
         }
         // ground-aligned free objects
         if (!PreviewOnly) {
             for (int j = 0; j < Data.Blocks[i].GroundFreeObj.Length; j++) {
                 int sttype = Data.Blocks[i].GroundFreeObj[j].Type;
                 double d = Data.Blocks[i].GroundFreeObj[j].TrackPosition - StartingDistance;
                 double dx = Data.Blocks[i].GroundFreeObj[j].X;
                 double dy = Data.Blocks[i].GroundFreeObj[j].Y;
                 Vector3 wpos = Position + new Vector3(Direction.X * d + Direction.Y * dx, dy - Data.Blocks[i].Height, Direction.Y * d - Direction.X * dx);
                 double tpos = Data.Blocks[i].GroundFreeObj[j].TrackPosition;
                 ObjectManager.CreateObject(Data.Structure.FreeObj[sttype], wpos, GroundTransformation, new World.Transformation(Data.Blocks[i].GroundFreeObj[j].Yaw, Data.Blocks[i].GroundFreeObj[j].Pitch, Data.Blocks[i].GroundFreeObj[j].Roll), Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, tpos);
             }
         }
         // rail-aligned objects
         if (!PreviewOnly) {
             for (int j = 0; j < Data.Blocks[i].Rail.Length; j++) {
                 if (j > 0 && !Data.Blocks[i].Rail[j].RailStart) continue;
                 // rail
                 Vector3 pos;
                 World.Transformation RailTransformation;
                 double planar, updown;
                 if (j == 0) {
                     // rail 0
                     pos = Position;
                     planar = 0.0;
                     updown = 0.0;
                     RailTransformation = new World.Transformation(TrackTransformation, planar, updown, 0.0);
                     pos = Position;
                 } else {
                     // rails 1-infinity
                     double x = Data.Blocks[i].Rail[j].RailStartX;
                     double y = Data.Blocks[i].Rail[j].RailStartY;
                     Vector3 offset = new Vector3(Direction.Y * x, y, -Direction.X * x);
                     pos = Position + offset;
                     double dh;
                     if (i < Data.Blocks.Length - 1 && Data.Blocks[i + 1].Rail.Length > j) {
                         // take orientation of upcoming block into account
                         World.Vector2D Direction2 = Direction;
                         Vector3 Position2 = Position;
                         Position2.X += Direction.X * c;
                         Position2.Y += h;
                         Position2.Z += Direction.Y * c;
                         if (a != 0.0) {
                             World.Rotate(ref Direction2, Math.Cos(-a), Math.Sin(-a));
                         }
                         if (Data.Blocks[i + 1].Turn != 0.0) {
                             double ag = -Math.Atan(Data.Blocks[i + 1].Turn);
                             double cosag = Math.Cos(ag);
                             double sinag = Math.Sin(ag);
                             World.Rotate(ref Direction2, cosag, sinag);
                         }
                         double a2 = 0.0;
                         double c2 = Data.BlockInterval;
                         double h2 = 0.0;
                         if (Data.Blocks[i + 1].CurrentTrackState.CurveRadius != 0.0 & Data.Blocks[i + 1].Pitch != 0.0) {
                             double d2 = Data.BlockInterval;
                             double p2 = Data.Blocks[i + 1].Pitch;
                             double r2 = Data.Blocks[i + 1].CurrentTrackState.CurveRadius;
                             double s2 = d2 / Math.Sqrt(1.0 + p2 * p2);
                             h2 = s2 * p2;
                             double b2 = s2 / Math.Abs(r2);
                             c2 = Math.Sqrt(2.0 * r2 * r2 * (1.0 - Math.Cos(b2)));
                             a2 = 0.5 * (double)Math.Sign(r2) * b2;
                             World.Rotate(ref Direction2, Math.Cos(-a2), Math.Sin(-a2));
                         } else if (Data.Blocks[i + 1].CurrentTrackState.CurveRadius != 0.0) {
                             double d2 = Data.BlockInterval;
                             double r2 = Data.Blocks[i + 1].CurrentTrackState.CurveRadius;
                             double b2 = d2 / Math.Abs(r2);
                             c2 = Math.Sqrt(2.0 * r2 * r2 * (1.0 - Math.Cos(b2)));
                             a2 = 0.5 * (double)Math.Sign(r2) * b2;
                             World.Rotate(ref Direction2, Math.Cos(-a2), Math.Sin(-a2));
                         } else if (Data.Blocks[i + 1].Pitch != 0.0) {
                             double p2 = Data.Blocks[i + 1].Pitch;
                             double d2 = Data.BlockInterval;
                             c2 = d2 / Math.Sqrt(1.0 + p2 * p2);
                             h2 = c2 * p2;
                         }
                         double TrackYaw2 = Math.Atan2(Direction2.X, Direction2.Y);
                         double TrackPitch2 = Math.Atan(Data.Blocks[i + 1].Pitch);
                         World.Transformation GroundTransformation2 = new World.Transformation(TrackYaw2, 0.0, 0.0);
                         World.Transformation TrackTransformation2 = new World.Transformation(TrackYaw2, TrackPitch2, 0.0);
                         double x2 = Data.Blocks[i + 1].Rail[j].RailEndX;
                         double y2 = Data.Blocks[i + 1].Rail[j].RailEndY;
                         Vector3 offset2 = new Vector3(Direction2.Y * x2, y2, -Direction2.X * x2);
                         Vector3 pos2 = Position2 + offset2;
                         double rx = pos2.X - pos.X;
                         double ry = pos2.Y - pos.Y;
                         double rz = pos2.Z - pos.Z;
                         World.Normalize(ref rx, ref ry, ref rz);
                         RailTransformation.Z = new Vector3(rx, ry, rz);
                         RailTransformation.X = new Vector3(rz, 0.0, -rx);
                         World.Normalize(ref RailTransformation.X.X, ref RailTransformation.X.Z);
                         RailTransformation.Y = Vector3.Cross(RailTransformation.Z, RailTransformation.X);
                         double dx = Data.Blocks[i + 1].Rail[j].RailEndX - Data.Blocks[i].Rail[j].RailStartX;
                         double dy = Data.Blocks[i + 1].Rail[j].RailEndY - Data.Blocks[i].Rail[j].RailStartY;
                         planar = Math.Atan(dx / c);
                         dh = dy / c;
                         updown = Math.Atan(dh);
                     } else {
                         planar = 0.0;
                         dh = 0.0;
                         updown = 0.0;
                         RailTransformation = new World.Transformation(TrackTransformation, 0.0, 0.0, 0.0);
                     }
                 }
                 if (Data.Blocks[i].RailType[j] < Data.Structure.Rail.Length) {
                     if (Data.Structure.Rail[Data.Blocks[i].RailType[j]] != null) {
                         ObjectManager.CreateObject(Data.Structure.Rail[Data.Blocks[i].RailType[j]], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                     }
                 }
                 // points of interest
                 for (int k = 0; k < Data.Blocks[i].PointsOfInterest.Length; k++) {
                     if (Data.Blocks[i].PointsOfInterest[k].RailIndex == j) {
                         double d = Data.Blocks[i].PointsOfInterest[k].TrackPosition - StartingDistance;
                         double x = Data.Blocks[i].PointsOfInterest[k].X;
                         double y = Data.Blocks[i].PointsOfInterest[k].Y;
                         int m = Game.PointsOfInterest.Length;
                         Array.Resize<Game.PointOfInterest>(ref Game.PointsOfInterest, m + 1);
                         Game.PointsOfInterest[m].TrackPosition = Data.Blocks[i].PointsOfInterest[k].TrackPosition;
                         if (i < Data.Blocks.Length - 1 && Data.Blocks[i + 1].Rail.Length > j) {
                             double dx = Data.Blocks[i + 1].Rail[j].RailEndX - Data.Blocks[i].Rail[j].RailStartX;
                             double dy = Data.Blocks[i + 1].Rail[j].RailEndY - Data.Blocks[i].Rail[j].RailStartY;
                             dx = Data.Blocks[i].Rail[j].RailStartX + d / Data.BlockInterval * dx;
                             dy = Data.Blocks[i].Rail[j].RailStartY + d / Data.BlockInterval * dy;
                             Game.PointsOfInterest[m].TrackOffset = new Vector3(x + dx, y + dy, 0.0);
                         } else {
                             double dx = Data.Blocks[i].Rail[j].RailStartX;
                             double dy = Data.Blocks[i].Rail[j].RailStartY;
                             Game.PointsOfInterest[m].TrackOffset = new Vector3(x + dx, y + dy, 0.0);
                         }
                         Game.PointsOfInterest[m].TrackYaw = Data.Blocks[i].PointsOfInterest[k].Yaw + planar;
                         Game.PointsOfInterest[m].TrackPitch = Data.Blocks[i].PointsOfInterest[k].Pitch + updown;
                         Game.PointsOfInterest[m].TrackRoll = Data.Blocks[i].PointsOfInterest[k].Roll;
                         Game.PointsOfInterest[m].Text = Data.Blocks[i].PointsOfInterest[k].Text;
                     }
                 }
                 // poles
                 if (Data.Blocks[i].RailPole.Length > j && Data.Blocks[i].RailPole[j].Exists) {
                     double dz = StartingDistance / Data.Blocks[i].RailPole[j].Interval;
                     dz -= Math.Floor(dz + 0.5);
                     if (dz >= -0.01 & dz <= 0.01) {
                         if (Data.Blocks[i].RailPole[j].Mode == 0) {
                             if (Data.Blocks[i].RailPole[j].Location <= 0.0) {
                                 ObjectManager.CreateObject(Data.Structure.Poles[0][Data.Blocks[i].RailPole[j].Type], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                             } else {
                                 ObjectManager.UnifiedObject Pole = GetMirroredObject(Data.Structure.Poles[0][Data.Blocks[i].RailPole[j].Type]);
                                 ObjectManager.CreateObject(Pole, pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                             }
                         } else {
                             int m = Data.Blocks[i].RailPole[j].Mode;
                             double dx = -Data.Blocks[i].RailPole[j].Location * 3.8;
                             double wa = Math.Atan2(Direction.Y, Direction.X) - planar;
                             double wx = Math.Cos(wa);
                             double wy = Math.Tan(updown);
                             double wz = Math.Sin(wa);
                             World.Normalize(ref wx, ref wy, ref wz);
                             double sx = Direction.Y;
                             double sy = 0.0;
                             double sz = -Direction.X;
                             Vector3 wpos = pos + new Vector3(sx * dx + wx * dz, sy * dx + wy * dz, sz * dx + wz * dz);
                             int type = Data.Blocks[i].RailPole[j].Type;
                             ObjectManager.CreateObject(Data.Structure.Poles[m][type], wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                         }
                     }
                 }
                 // walls
                 if (Data.Blocks[i].RailWall.Length > j && Data.Blocks[i].RailWall[j].Exists) {
                     if (Data.Blocks[i].RailWall[j].Direction <= 0) {
                         ObjectManager.CreateObject(Data.Structure.WallL[Data.Blocks[i].RailWall[j].Type], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                     }
                     if (Data.Blocks[i].RailWall[j].Direction >= 0) {
                         ObjectManager.CreateObject(Data.Structure.WallR[Data.Blocks[i].RailWall[j].Type], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                     }
                 }
                 // dikes
                 if (Data.Blocks[i].RailDike.Length > j && Data.Blocks[i].RailDike[j].Exists) {
                     if (Data.Blocks[i].RailDike[j].Direction <= 0) {
                         ObjectManager.CreateObject(Data.Structure.DikeL[Data.Blocks[i].RailDike[j].Type], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                     }
                     if (Data.Blocks[i].RailDike[j].Direction >= 0) {
                         ObjectManager.CreateObject(Data.Structure.DikeR[Data.Blocks[i].RailDike[j].Type], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                     }
                 }
                 // sounds
                 if (j == 0) {
                     for (int k = 0; k < Data.Blocks[i].Sound.Length; k++) {
                         if (Data.Blocks[i].Sound[k].Type == SoundType.World) {
                             if (Data.Blocks[i].Sound[k].SoundBuffer != null) {
                                 double d = Data.Blocks[i].Sound[k].TrackPosition - StartingDistance;
                                 double dx = Data.Blocks[i].Sound[k].X;
                                 double dy = Data.Blocks[i].Sound[k].Y;
                                 double wa = Math.Atan2(Direction.Y, Direction.X) - planar;
                                 double wx = Math.Cos(wa);
                                 double wy = Math.Tan(updown);
                                 double wz = Math.Sin(wa);
                                 World.Normalize(ref wx, ref wy, ref wz);
                                 double sx = Direction.Y;
                                 double sy = 0.0;
                                 double sz = -Direction.X;
                                 double ux, uy, uz;
                                 World.Cross(wx, wy, wz, sx, sy, sz, out ux, out uy, out uz);
                                 Vector3 wpos = pos + new Vector3(sx * dx + ux * dy + wx * d, sy * dx + uy * dy + wy * d, sz * dx + uz * dy + wz * d);
                                 Sounds.PlaySound(Data.Blocks[i].Sound[k].SoundBuffer, 1.0, 1.0, wpos, true);
                             }
                         }
                     }
                 }
                 // forms
                 for (int k = 0; k < Data.Blocks[i].Form.Length; k++) {
                     // primary rail
                     if (Data.Blocks[i].Form[k].PrimaryRail == j) {
                         if (Data.Blocks[i].Form[k].SecondaryRail == Form.SecondaryRailStub) {
                             if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormL.Length || Data.Structure.FormL[Data.Blocks[i].Form[k].FormType] == null) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                             } else {
                                 ObjectManager.CreateObject(Data.Structure.FormL[Data.Blocks[i].Form[k].FormType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                                 if (Data.Blocks[i].Form[k].RoofType > 0) {
                                     if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofL.Length || Data.Structure.RoofL[Data.Blocks[i].Form[k].RoofType] == null) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                                     } else {
                                         ObjectManager.CreateObject(Data.Structure.RoofL[Data.Blocks[i].Form[k].RoofType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                                     }
                                 }
                             }
                         } else if (Data.Blocks[i].Form[k].SecondaryRail == Form.SecondaryRailL) {
                             if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormL.Length || Data.Structure.FormL[Data.Blocks[i].Form[k].FormType] == null) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                             } else {
                                 ObjectManager.CreateObject(Data.Structure.FormL[Data.Blocks[i].Form[k].FormType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                             }
                             if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormCL.Length || Data.Structure.FormCL[Data.Blocks[i].Form[k].FormType] == null) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormCL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                             } else {
                                 ObjectManager.CreateStaticObject(Data.Structure.FormCL[Data.Blocks[i].Form[k].FormType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                             }
                             if (Data.Blocks[i].Form[k].RoofType > 0) {
                                 if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofL.Length || Data.Structure.RoofL[Data.Blocks[i].Form[k].RoofType] == null) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                                 } else {
                                     ObjectManager.CreateObject(Data.Structure.RoofL[Data.Blocks[i].Form[k].RoofType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                                 }
                                 if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofCL.Length || Data.Structure.RoofCL[Data.Blocks[i].Form[k].RoofType] == null) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofCL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                                 } else {
                                     ObjectManager.CreateStaticObject(Data.Structure.RoofCL[Data.Blocks[i].Form[k].RoofType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                                 }
                             }
                         } else if (Data.Blocks[i].Form[k].SecondaryRail == Form.SecondaryRailR) {
                             if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormR.Length || Data.Structure.FormR[Data.Blocks[i].Form[k].FormType] == null) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                             } else {
                                 ObjectManager.CreateObject(Data.Structure.FormR[Data.Blocks[i].Form[k].FormType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                             }
                             if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormCR.Length || Data.Structure.FormCR[Data.Blocks[i].Form[k].FormType] == null) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormCR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                             } else {
                                 ObjectManager.CreateStaticObject(Data.Structure.FormCR[Data.Blocks[i].Form[k].FormType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                             }
                             if (Data.Blocks[i].Form[k].RoofType > 0) {
                                 if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofR.Length || Data.Structure.RoofR[Data.Blocks[i].Form[k].RoofType] == null) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                                 } else {
                                     ObjectManager.CreateObject(Data.Structure.RoofR[Data.Blocks[i].Form[k].RoofType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                                 }
                                 if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofCR.Length || Data.Structure.RoofCR[Data.Blocks[i].Form[k].RoofType] == null) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofCR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                                 } else {
                                     ObjectManager.CreateStaticObject(Data.Structure.RoofCR[Data.Blocks[i].Form[k].RoofType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                                 }
                             }
                         } else if (Data.Blocks[i].Form[k].SecondaryRail > 0) {
                             int p = Data.Blocks[i].Form[k].PrimaryRail;
                             double px0 = p > 0 ? Data.Blocks[i].Rail[p].RailStartX : 0.0;
                             double px1 = p > 0 ? Data.Blocks[i + 1].Rail[p].RailEndX : 0.0;
                             int s = Data.Blocks[i].Form[k].SecondaryRail;
                             if (s < 0 || s >= Data.Blocks[i].Rail.Length || !Data.Blocks[i].Rail[s].RailStart) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex2 is out of range in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName);
                             } else {
                                 double sx0 = Data.Blocks[i].Rail[s].RailStartX;
                                 double sx1 = Data.Blocks[i + 1].Rail[s].RailEndX;
                                 double d0 = sx0 - px0;
                                 double d1 = sx1 - px1;
                                 if (d0 < 0.0) {
                                     if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormL.Length || Data.Structure.FormL[Data.Blocks[i].Form[k].FormType] == null) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                                     } else {
                                         ObjectManager.CreateObject(Data.Structure.FormL[Data.Blocks[i].Form[k].FormType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                                     }
                                     if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormCL.Length || Data.Structure.FormCL[Data.Blocks[i].Form[k].FormType] == null) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormCL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                                     } else {
                                         ObjectManager.StaticObject FormC = GetTransformedStaticObject(Data.Structure.FormCL[Data.Blocks[i].Form[k].FormType], d0, d1);
                                         ObjectManager.CreateStaticObject(FormC, pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                                     }
                                     if (Data.Blocks[i].Form[k].RoofType > 0) {
                                         if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofL.Length || Data.Structure.RoofL[Data.Blocks[i].Form[k].RoofType] == null) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                                         } else {
                                             ObjectManager.CreateObject(Data.Structure.RoofL[Data.Blocks[i].Form[k].RoofType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                                         }
                                         if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofCL.Length || Data.Structure.RoofCL[Data.Blocks[i].Form[k].RoofType] == null) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofCL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                                         } else {
                                             ObjectManager.StaticObject RoofC = GetTransformedStaticObject(Data.Structure.RoofCL[Data.Blocks[i].Form[k].RoofType], d0, d1);
                                             ObjectManager.CreateStaticObject(RoofC, pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                                         }
                                     }
                                 } else if (d0 > 0.0) {
                                     if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormR.Length || Data.Structure.FormR[Data.Blocks[i].Form[k].FormType] == null) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                                     } else {
                                         ObjectManager.CreateObject(Data.Structure.FormR[Data.Blocks[i].Form[k].FormType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                                     }
                                     if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormCR.Length || Data.Structure.FormCR[Data.Blocks[i].Form[k].FormType] == null) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormCR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                                     } else {
                                         ObjectManager.StaticObject FormC = GetTransformedStaticObject(Data.Structure.FormCR[Data.Blocks[i].Form[k].FormType], d0, d1);
                                         ObjectManager.CreateStaticObject(FormC, pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                                     }
                                     if (Data.Blocks[i].Form[k].RoofType > 0) {
                                         if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofR.Length || Data.Structure.RoofR[Data.Blocks[i].Form[k].RoofType] == null) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                                         } else {
                                             ObjectManager.CreateObject(Data.Structure.RoofR[Data.Blocks[i].Form[k].RoofType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                                         }
                                         if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofCR.Length || Data.Structure.RoofCR[Data.Blocks[i].Form[k].RoofType] == null) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofCR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                                         } else {
                                             ObjectManager.StaticObject RoofC = GetTransformedStaticObject(Data.Structure.RoofCR[Data.Blocks[i].Form[k].RoofType], d0, d1);
                                             ObjectManager.CreateStaticObject(RoofC, pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                                         }
                                     }
                                 }
                             }
                         }
                     }
                     // secondary rail
                     if (Data.Blocks[i].Form[k].SecondaryRail == j) {
                         int p = Data.Blocks[i].Form[k].PrimaryRail;
                         double px = p > 0 ? Data.Blocks[i].Rail[p].RailStartX : 0.0;
                         int s = Data.Blocks[i].Form[k].SecondaryRail;
                         double sx = Data.Blocks[i].Rail[s].RailStartX;
                         double d = px - sx;
                         if (d < 0.0) {
                             if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormL.Length || Data.Structure.FormL[Data.Blocks[i].Form[k].FormType] == null) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                             } else {
                                 ObjectManager.CreateObject(Data.Structure.FormL[Data.Blocks[i].Form[k].FormType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                             }
                             if (Data.Blocks[i].Form[k].RoofType > 0) {
                                 if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofL.Length || Data.Structure.RoofL[Data.Blocks[i].Form[k].RoofType] == null) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofL not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                                 } else {
                                     ObjectManager.CreateObject(Data.Structure.RoofL[Data.Blocks[i].Form[k].RoofType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                                 }
                             }
                         } else {
                             if (Data.Blocks[i].Form[k].FormType >= Data.Structure.FormR.Length || Data.Structure.FormR[Data.Blocks[i].Form[k].FormType] == null) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references a FormR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                             } else {
                                 ObjectManager.CreateObject(Data.Structure.FormR[Data.Blocks[i].Form[k].FormType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                             }
                             if (Data.Blocks[i].Form[k].RoofType > 0) {
                                 if (Data.Blocks[i].Form[k].RoofType >= Data.Structure.RoofR.Length || Data.Structure.RoofR[Data.Blocks[i].Form[k].RoofType] == null) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references a RoofR not loaded in Track.Form at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                                 } else {
                                     ObjectManager.CreateObject(Data.Structure.RoofR[Data.Blocks[i].Form[k].RoofType], pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                                 }
                             }
                         }
                     }
                 }
                 // cracks
                 for (int k = 0; k < Data.Blocks[i].Crack.Length; k++) {
                     if (Data.Blocks[i].Crack[k].PrimaryRail == j) {
                         int p = Data.Blocks[i].Crack[k].PrimaryRail;
                         double px0 = p > 0 ? Data.Blocks[i].Rail[p].RailStartX : 0.0;
                         double px1 = p > 0 ? Data.Blocks[i + 1].Rail[p].RailEndX : 0.0;
                         int s = Data.Blocks[i].Crack[k].SecondaryRail;
                         if (s < 0 || s >= Data.Blocks[i].Rail.Length || !Data.Blocks[i].Rail[s].RailStart) {
                             Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex2 is out of range in Track.Crack at track position " + StartingDistance.ToString(Culture) + " in file " + FileName);
                         } else {
                             double sx0 = Data.Blocks[i].Rail[s].RailStartX;
                             double sx1 = Data.Blocks[i + 1].Rail[s].RailEndX;
                             double d0 = sx0 - px0;
                             double d1 = sx1 - px1;
                             if (d0 < 0.0) {
                                 if (Data.Blocks[i].Crack[k].Type >= Data.Structure.CrackL.Length || Data.Structure.CrackL[Data.Blocks[i].Crack[k].Type] == null) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "CrackStructureIndex references a CrackL not loaded in Track.Crack at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                                 } else {
                                     ObjectManager.StaticObject Crack = GetTransformedStaticObject(Data.Structure.CrackL[Data.Blocks[i].Crack[k].Type], d0, d1);
                                     ObjectManager.CreateStaticObject(Crack, pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                                 }
                             } else if (d0 > 0.0) {
                                 if (Data.Blocks[i].Crack[k].Type >= Data.Structure.CrackR.Length || Data.Structure.CrackR[Data.Blocks[i].Crack[k].Type] == null) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "CrackStructureIndex references a CrackR not loaded in Track.Crack at track position " + StartingDistance.ToString(Culture) + " in file " + FileName + ".");
                                 } else {
                                     ObjectManager.StaticObject Crack = GetTransformedStaticObject(Data.Structure.CrackR[Data.Blocks[i].Crack[k].Type], d0, d1);
                                     ObjectManager.CreateStaticObject(Crack, pos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, StartingDistance);
                                 }
                             }
                         }
                     }
                 }
                 // free objects
                 if (Data.Blocks[i].RailFreeObj.Length > j && Data.Blocks[i].RailFreeObj[j] != null) {
                     for (int k = 0; k < Data.Blocks[i].RailFreeObj[j].Length; k++) {
                         int sttype = Data.Blocks[i].RailFreeObj[j][k].Type;
                         double dx = Data.Blocks[i].RailFreeObj[j][k].X;
                         double dy = Data.Blocks[i].RailFreeObj[j][k].Y;
                         double dz = Data.Blocks[i].RailFreeObj[j][k].TrackPosition - StartingDistance;
                         Vector3 wpos = pos;
                         wpos.X += dx * RailTransformation.X.X + dy * RailTransformation.Y.X + dz * RailTransformation.Z.X;
                         wpos.Y += dx * RailTransformation.X.Y + dy * RailTransformation.Y.Y + dz * RailTransformation.Z.Y;
                         wpos.Z += dx * RailTransformation.X.Z + dy * RailTransformation.Y.Z + dz * RailTransformation.Z.Z;
                         double tpos = Data.Blocks[i].RailFreeObj[j][k].TrackPosition;
                         ObjectManager.CreateObject(Data.Structure.FreeObj[sttype], wpos, RailTransformation, new World.Transformation(Data.Blocks[i].RailFreeObj[j][k].Yaw, Data.Blocks[i].RailFreeObj[j][k].Pitch, Data.Blocks[i].RailFreeObj[j][k].Roll), -1, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, tpos, 1.0, false);
                     }
                 }
                 // transponder objects
                 if (j == 0) {
                     for (int k = 0; k < Data.Blocks[i].Transponder.Length; k++) {
                         ObjectManager.UnifiedObject obj = null;
                         if (Data.Blocks[i].Transponder[k].ShowDefaultObject) {
                             switch (Data.Blocks[i].Transponder[k].Type) {
                                     case 0: obj = TransponderS; break;
                                     case 1: obj = TransponderSN; break;
                                     case 2: obj = TransponderFalseStart; break;
                                     case 3: obj = TransponderPOrigin; break;
                                     case 4: obj = TransponderPStop; break;
                             }
                         } else {
                             int b = Data.Blocks[i].Transponder[k].BeaconStructureIndex;
                             if (b >= 0 & b < Data.Structure.Beacon.Length) {
                                 obj = Data.Structure.Beacon[b];
                             }
                         }
                         if (obj != null) {
                             double dx = Data.Blocks[i].Transponder[k].X;
                             double dy = Data.Blocks[i].Transponder[k].Y;
                             double dz = Data.Blocks[i].Transponder[k].TrackPosition - StartingDistance;
                             Vector3 wpos = pos;
                             wpos.X += dx * RailTransformation.X.X + dy * RailTransformation.Y.X + dz * RailTransformation.Z.X;
                             wpos.Y += dx * RailTransformation.X.Y + dy * RailTransformation.Y.Y + dz * RailTransformation.Z.Y;
                             wpos.Z += dx * RailTransformation.X.Z + dy * RailTransformation.Y.Z + dz * RailTransformation.Z.Z;
                             double tpos = Data.Blocks[i].Transponder[k].TrackPosition;
                             if (Data.Blocks[i].Transponder[k].ShowDefaultObject) {
                                 double b = 0.25 + 0.75 * GetBrightness(ref Data, tpos);
                                 ObjectManager.CreateObject(obj, wpos, RailTransformation, new World.Transformation(Data.Blocks[i].Transponder[k].Yaw, Data.Blocks[i].Transponder[k].Pitch, Data.Blocks[i].Transponder[k].Roll), -1, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, false);
                             } else {
                                 ObjectManager.CreateObject(obj, wpos, RailTransformation, new World.Transformation(Data.Blocks[i].Transponder[k].Yaw, Data.Blocks[i].Transponder[k].Pitch, Data.Blocks[i].Transponder[k].Roll), Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, tpos);
                             }
                         }
                     }
                 }
                 // sections/signals/transponders
                 if (j == 0) {
                     // signals
                     for (int k = 0; k < Data.Blocks[i].Signal.Length; k++) {
                         SignalData sd;
                         if (Data.Blocks[i].Signal[k].SignalCompatibilityObjectIndex >= 0) {
                             sd = Data.CompatibilitySignalData[Data.Blocks[i].Signal[k].SignalCompatibilityObjectIndex];
                         } else {
                             sd = Data.SignalData[Data.Blocks[i].Signal[k].SignalObjectIndex];
                         }
                         // objects
                         double dz = Data.Blocks[i].Signal[k].TrackPosition - StartingDistance;
                         if (Data.Blocks[i].Signal[k].ShowPost) {
                             // post
                             double dx = Data.Blocks[i].Signal[k].X;
                             Vector3 wpos = pos;
                             wpos.X += dx * RailTransformation.X.X + dz * RailTransformation.Z.X;
                             wpos.Y += dx * RailTransformation.X.Y + dz * RailTransformation.Z.Y;
                             wpos.Z += dx * RailTransformation.X.Z + dz * RailTransformation.Z.Z;
                             double tpos = Data.Blocks[i].Signal[k].TrackPosition;
                             double b = 0.25 + 0.75 * GetBrightness(ref Data, tpos);
                             ObjectManager.CreateStaticObject(SignalPost, wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, false);
                         }
                         if (Data.Blocks[i].Signal[k].ShowObject) {
                             // signal object
                             double dx = Data.Blocks[i].Signal[k].X;
                             double dy = Data.Blocks[i].Signal[k].Y;
                             Vector3 wpos = pos;
                             wpos.X += dx * RailTransformation.X.X + dy * RailTransformation.Y.X + dz * RailTransformation.Z.X;
                             wpos.Y += dx * RailTransformation.X.Y + dy * RailTransformation.Y.Y + dz * RailTransformation.Z.Y;
                             wpos.Z += dx * RailTransformation.X.Z + dy * RailTransformation.Y.Z + dz * RailTransformation.Z.Z;
                             double tpos = Data.Blocks[i].Signal[k].TrackPosition;
                             if (sd is AnimatedObjectSignalData) {
                                 AnimatedObjectSignalData aosd = (AnimatedObjectSignalData)sd;
                                 ObjectManager.CreateObject(aosd.Objects, wpos, RailTransformation, new World.Transformation(Data.Blocks[i].Signal[k].Yaw, Data.Blocks[i].Signal[k].Pitch, Data.Blocks[i].Signal[k].Roll), Data.Blocks[i].Signal[k].Section, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, tpos, 1.0, false);
                             } else if (sd is CompatibilitySignalData) {
                                 CompatibilitySignalData csd = (CompatibilitySignalData)sd;
                                 if (csd.Numbers.Length != 0) {
                                     double brightness = 0.25 + 0.75 * GetBrightness(ref Data, tpos);
                                     ObjectManager.AnimatedObjectCollection aoc = new ObjectManager.AnimatedObjectCollection();
                                     aoc.Objects = new ObjectManager.AnimatedObject[1];
                                     aoc.Objects[0] = new ObjectManager.AnimatedObject();
                                     aoc.Objects[0].States = new ObjectManager.AnimatedObjectState[csd.Numbers.Length];
                                     for (int l = 0; l < csd.Numbers.Length; l++) {
                                         aoc.Objects[0].States[l].Object = ObjectManager.CloneObject(csd.Objects[l]);
                                     }
                                     string expr = "";
                                     for (int l = 0; l < csd.Numbers.Length - 1; l++) {
                                         expr += "section " + csd.Numbers[l].ToString(Culture) + " <= " + l.ToString(Culture) + " ";
                                     }
                                     expr += (csd.Numbers.Length - 1).ToString(Culture);
                                     for (int l = 0; l < csd.Numbers.Length - 1; l++) {
                                         expr += " ?";
                                     }
                                     aoc.Objects[0].StateFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(expr);
                                     aoc.Objects[0].RefreshRate = 1.0 + 0.01 * Program.RandomNumberGenerator.NextDouble();
                                     ObjectManager.CreateObject(aoc, wpos, RailTransformation, new World.Transformation(Data.Blocks[i].Signal[k].Yaw, Data.Blocks[i].Signal[k].Pitch, Data.Blocks[i].Signal[k].Roll), Data.Blocks[i].Signal[k].Section, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, tpos, brightness, false);
                                 }
                             } else if (sd is Bve4SignalData) {
                                 Bve4SignalData b4sd = (Bve4SignalData)sd;
                                 if (b4sd.SignalTextures.Length != 0) {
                                     int m = Math.Max(b4sd.SignalTextures.Length, b4sd.GlowTextures.Length);
                                     int zn = 0;
                                     for (int l = 0; l < m; l++) {
                                         if (l < b4sd.SignalTextures.Length && b4sd.SignalTextures[l] != null || l < b4sd.GlowTextures.Length && b4sd.GlowTextures[l] != null) {
                                             zn++;
                                         }
                                     }
                                     ObjectManager.AnimatedObjectCollection aoc = new ObjectManager.AnimatedObjectCollection();
                                     aoc.Objects = new ObjectManager.AnimatedObject[1];
                                     aoc.Objects[0] = new ObjectManager.AnimatedObject();
                                     aoc.Objects[0].States = new ObjectManager.AnimatedObjectState[zn];
                                     int zi = 0;
                                     string expr = "";
                                     for (int l = 0; l < m; l++) {
                                         bool qs = l < b4sd.SignalTextures.Length && b4sd.SignalTextures[l] != null;
                                         bool qg = l < b4sd.GlowTextures.Length && b4sd.GlowTextures[l] != null;
                                         if (qs & qg) {
                                             ObjectManager.StaticObject so = ObjectManager.CloneObject(b4sd.BaseObject, b4sd.SignalTextures[l], null);
                                             ObjectManager.StaticObject go = ObjectManager.CloneObject(b4sd.GlowObject, b4sd.GlowTextures[l], null);
                                             ObjectManager.JoinObjects(ref so, go);
                                             aoc.Objects[0].States[zi].Object = so;
                                         } else if (qs) {
                                             ObjectManager.StaticObject so = ObjectManager.CloneObject(b4sd.BaseObject, b4sd.SignalTextures[l], null);
                                             aoc.Objects[0].States[zi].Object = so;
                                         } else if (qg) {
                                             ObjectManager.StaticObject go = ObjectManager.CloneObject(b4sd.GlowObject, b4sd.GlowTextures[l], null);
                                             aoc.Objects[0].States[zi].Object = go;
                                         }
                                         if (qs | qg) {
                                             if (zi < zn - 1) {
                                                 expr += "section " + l.ToString(Culture) + " <= " + zi.ToString(Culture) + " ";
                                             } else {
                                                 expr += zi.ToString(Culture);
                                             }
                                             zi++;
                                         }
                                     }
                                     for (int l = 0; l < zn - 1; l++) {
                                         expr += " ?";
                                     }
                                     aoc.Objects[0].StateFunction = FunctionScripts.GetFunctionScriptFromPostfixNotation(expr);
                                     aoc.Objects[0].RefreshRate = 1.0 + 0.01 * Program.RandomNumberGenerator.NextDouble();
                                     ObjectManager.CreateObject(aoc, wpos, RailTransformation, new World.Transformation(Data.Blocks[i].Signal[k].Yaw, Data.Blocks[i].Signal[k].Pitch, Data.Blocks[i].Signal[k].Roll), Data.Blocks[i].Signal[k].Section, Data.AccurateObjectDisposal, StartingDistance, EndingDistance, Data.BlockInterval, tpos, 1.0, false);
                                 }
                             }
                         }
                     }
                     // sections
                     for (int k = 0; k < Data.Blocks[i].Section.Length; k++) {
                         int m = Game.Sections.Length;
                         Array.Resize<Game.Section>(ref Game.Sections, m + 1);
                         Game.Sections[m].SignalIndices = new int[] { };
                         // create associated transponders
                         for (int g = 0; g <= i; g++) {
                             for (int l = 0; l < Data.Blocks[g].Transponder.Length; l++) {
                                 if (Data.Blocks[g].Transponder[l].Type != -1 & Data.Blocks[g].Transponder[l].Section == m) {
                                     int o = TrackManager.CurrentTrack.Elements[n - i + g].Events.Length;
                                     Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n - i + g].Events, o + 1);
                                     double dt = Data.Blocks[g].Transponder[l].TrackPosition - StartingDistance + (double)(i - g) * Data.BlockInterval;
                                     TrackManager.CurrentTrack.Elements[n - i + g].Events[o] = new TrackManager.TransponderEvent(dt, Data.Blocks[g].Transponder[l].Type, Data.Blocks[g].Transponder[l].Data, m);
                                     Data.Blocks[g].Transponder[l].Type = -1;
                                 }
                             }
                         }
                         // create section
                         Game.Sections[m].TrackPosition = Data.Blocks[i].Section[k].TrackPosition;
                         Game.Sections[m].Aspects = new Game.SectionAspect[Data.Blocks[i].Section[k].Aspects.Length];
                         for (int l = 0; l < Data.Blocks[i].Section[k].Aspects.Length; l++) {
                             Game.Sections[m].Aspects[l].Number = Data.Blocks[i].Section[k].Aspects[l];
                             if (Data.Blocks[i].Section[k].Aspects[l] >= 0 & Data.Blocks[i].Section[k].Aspects[l] < Data.SignalSpeeds.Length) {
                                 Game.Sections[m].Aspects[l].Speed = Data.SignalSpeeds[Data.Blocks[i].Section[k].Aspects[l]];
                             } else {
                                 Game.Sections[m].Aspects[l].Speed = double.PositiveInfinity;
                             }
                         }
                         Game.Sections[m].Type = Data.Blocks[i].Section[k].Type;
                         Game.Sections[m].CurrentAspect = -1;
                         if (m > 0) {
                             Game.Sections[m].PreviousSection = m - 1;
                             Game.Sections[m - 1].NextSection = m;
                         } else {
                             Game.Sections[m].PreviousSection = -1;
                         }
                         Game.Sections[m].NextSection = -1;
                         Game.Sections[m].StationIndex = Data.Blocks[i].Section[k].DepartureStationIndex;
                         Game.Sections[m].Invisible = Data.Blocks[i].Section[k].Invisible;
                         Game.Sections[m].Trains = new TrainManager.Train[] { };
                         // create section change event
                         double d = Data.Blocks[i].Section[k].TrackPosition - StartingDistance;
                         int p = TrackManager.CurrentTrack.Elements[n].Events.Length;
                         Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, p + 1);
                         TrackManager.CurrentTrack.Elements[n].Events[p] = new TrackManager.SectionChangeEvent(d, m - 1, m);
                     }
                     // transponders introduced after corresponding sections
                     for (int l = 0; l < Data.Blocks[i].Transponder.Length; l++) {
                         if (Data.Blocks[i].Transponder[l].Type != -1) {
                             int t = Data.Blocks[i].Transponder[l].Section;
                             if (t >= 0 & t < Game.Sections.Length) {
                                 int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
                                 Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
                                 double dt = Data.Blocks[i].Transponder[l].TrackPosition - StartingDistance;
                                 TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.TransponderEvent(dt, Data.Blocks[i].Transponder[l].Type, Data.Blocks[i].Transponder[l].Data, t);
                                 Data.Blocks[i].Transponder[l].Type = -1;
                             }
                         }
                     }
                 }
                 // limit
                 if (j == 0) {
                     for (int k = 0; k < Data.Blocks[i].Limit.Length; k++) {
                         if (Data.Blocks[i].Limit[k].Direction != 0) {
                             double dx = 2.2 * (double)Data.Blocks[i].Limit[k].Direction;
                             double dz = Data.Blocks[i].Limit[k].TrackPosition - StartingDistance;
                             Vector3 wpos = pos;
                             wpos.X += dx * RailTransformation.X.X + dz * RailTransformation.Z.X;
                             wpos.Y += dx * RailTransformation.X.Y + dz * RailTransformation.Z.Y;
                             wpos.Z += dx * RailTransformation.X.Z + dz * RailTransformation.Z.Z;
                             double tpos = Data.Blocks[i].Limit[k].TrackPosition;
                             double b = 0.25 + 0.75 * GetBrightness(ref Data, tpos);
                             if (Data.Blocks[i].Limit[k].Speed <= 0.0 | Data.Blocks[i].Limit[k].Speed >= 1000.0) {
                                 ObjectManager.CreateStaticObject(LimitPostInfinite, wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, false);
                             } else {
                                 if (Data.Blocks[i].Limit[k].Cource < 0) {
                                     ObjectManager.CreateStaticObject(LimitPostLeft, wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, false);
                                 } else if (Data.Blocks[i].Limit[k].Cource > 0) {
                                     ObjectManager.CreateStaticObject(LimitPostRight, wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, false);
                                 } else {
                                     ObjectManager.CreateStaticObject(LimitPostStraight, wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, false);
                                 }
                                 double lim = Data.Blocks[i].Limit[k].Speed / Data.UnitOfSpeed;
                                 if (lim < 10.0) {
                                     int d0 = (int)Math.Round(lim);
                                     int o = ObjectManager.CreateStaticObject(LimitOneDigit, wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, true);
                                     if (ObjectManager.Objects[o].Mesh.Materials.Length >= 1) {
                                         Textures.RegisterTexture(OpenBveApi.Path.CombineFile(LimitGraphicsPath, "limit_" + d0 + ".png"), out ObjectManager.Objects[o].Mesh.Materials[0].DaytimeTexture);
                                     }
                                 } else if (lim < 100.0) {
                                     int d1 = (int)Math.Round(lim);
                                     int d0 = d1 % 10;
                                     d1 /= 10;
                                     int o = ObjectManager.CreateStaticObject(LimitTwoDigits, wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, true);
                                     if (ObjectManager.Objects[o].Mesh.Materials.Length >= 1) {
                                         Textures.RegisterTexture(OpenBveApi.Path.CombineFile(LimitGraphicsPath, "limit_" + d1 + ".png"), out ObjectManager.Objects[o].Mesh.Materials[0].DaytimeTexture);
                                     }
                                     if (ObjectManager.Objects[o].Mesh.Materials.Length >= 2) {
                                         Textures.RegisterTexture(OpenBveApi.Path.CombineFile(LimitGraphicsPath, "limit_" + d0 + ".png"), out ObjectManager.Objects[o].Mesh.Materials[1].DaytimeTexture);
                                     }
                                 } else {
                                     int d2 = (int)Math.Round(lim);
                                     int d0 = d2 % 10;
                                     int d1 = (d2 / 10) % 10;
                                     d2 /= 100;
                                     int o = ObjectManager.CreateStaticObject(LimitThreeDigits, wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, true);
                                     if (ObjectManager.Objects[o].Mesh.Materials.Length >= 1) {
                                         Textures.RegisterTexture(OpenBveApi.Path.CombineFile(LimitGraphicsPath, "limit_" + d2 + ".png"), out ObjectManager.Objects[o].Mesh.Materials[0].DaytimeTexture);
                                     }
                                     if (ObjectManager.Objects[o].Mesh.Materials.Length >= 2) {
                                         Textures.RegisterTexture(OpenBveApi.Path.CombineFile(LimitGraphicsPath, "limit_" + d1 + ".png"), out ObjectManager.Objects[o].Mesh.Materials[1].DaytimeTexture);
                                     }
                                     if (ObjectManager.Objects[o].Mesh.Materials.Length >= 3) {
                                         Textures.RegisterTexture(OpenBveApi.Path.CombineFile(LimitGraphicsPath, "limit_" + d0 + ".png"), out ObjectManager.Objects[o].Mesh.Materials[2].DaytimeTexture);
                                     }
                                 }
                             }
                         }
                     }
                 }
                 // stop
                 if (j == 0) {
                     for (int k = 0; k < Data.Blocks[i].Stop.Length; k++) {
                         if (Data.Blocks[i].Stop[k].Direction != 0) {
                             double dx = 1.8 * (double)Data.Blocks[i].Stop[k].Direction;
                             double dz = Data.Blocks[i].Stop[k].TrackPosition - StartingDistance;
                             Vector3 wpos = pos;
                             wpos.X += dx * RailTransformation.X.X + dz * RailTransformation.Z.X;
                             wpos.Y += dx * RailTransformation.X.Y + dz * RailTransformation.Z.Y;
                             wpos.Z += dx * RailTransformation.X.Z + dz * RailTransformation.Z.Z;
                             double tpos = Data.Blocks[i].Stop[k].TrackPosition;
                             double b = 0.25 + 0.75 * GetBrightness(ref Data, tpos);
                             ObjectManager.CreateStaticObject(StopPost, wpos, RailTransformation, NullTransformation, Data.AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, Data.BlockInterval, tpos, b, false);
                         }
                     }
                 }
             }
         }
         // finalize block
         Position.X += Direction.X * c;
         Position.Y += h;
         Position.Z += Direction.Y * c;
         if (a != 0.0) {
             World.Rotate(ref Direction, Math.Cos(-a), Math.Sin(-a));
         }
     }
     // orphaned transponders
     if (!PreviewOnly) {
         for (int i = Data.FirstUsedBlock; i < Data.Blocks.Length; i++) {
             for (int j = 0; j < Data.Blocks[i].Transponder.Length; j++) {
                 if (Data.Blocks[i].Transponder[j].Type != -1) {
                     int n = i - Data.FirstUsedBlock;
                     int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
                     Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
                     double d = Data.Blocks[i].Transponder[j].TrackPosition - TrackManager.CurrentTrack.Elements[n].StartingTrackPosition;
                     int s = Data.Blocks[i].Transponder[j].Section;
                     if (s >= 0) s = -1;
                     TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.TransponderEvent(d, Data.Blocks[i].Transponder[j].Type, Data.Blocks[i].Transponder[j].Data, s);
                     Data.Blocks[i].Transponder[j].Type = -1;
                 }
             }
         }
     }
     // insert station end events
     for (int i = 0; i < Game.Stations.Length; i++) {
         int j = Game.Stations[i].Stops.Length - 1;
         if (j >= 0) {
             double p = Game.Stations[i].Stops[j].TrackPosition + Game.Stations[i].Stops[j].ForwardTolerance + Data.BlockInterval;
             int k = (int)Math.Floor(p / (double)Data.BlockInterval) - Data.FirstUsedBlock;
             if (k >= 0 & k < Data.Blocks.Length) {
                 double d = p - (double)(k + Data.FirstUsedBlock) * (double)Data.BlockInterval;
                 int m = TrackManager.CurrentTrack.Elements[k].Events.Length;
                 Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[k].Events, m + 1);
                 TrackManager.CurrentTrack.Elements[k].Events[m] = new TrackManager.StationEndEvent(d, i);
             }
         }
     }
     // create default point of interests
     if (Game.PointsOfInterest.Length == 0) {
         Game.PointsOfInterest = new OpenBve.Game.PointOfInterest[Game.Stations.Length];
         int n = 0;
         for (int i = 0; i < Game.Stations.Length; i++) {
             if (Game.Stations[i].Stops.Length != 0) {
                 Game.PointsOfInterest[n].Text = Game.Stations[i].Name;
                 Game.PointsOfInterest[n].TrackPosition = Game.Stations[i].Stops[0].TrackPosition;
                 Game.PointsOfInterest[n].TrackOffset = new Vector3(0.0, 2.8, 0.0);
                 if (Game.Stations[i].OpenLeftDoors & !Game.Stations[i].OpenRightDoors) {
                     Game.PointsOfInterest[n].TrackOffset.X = -2.5;
                 } else if (!Game.Stations[i].OpenLeftDoors & Game.Stations[i].OpenRightDoors) {
                     Game.PointsOfInterest[n].TrackOffset.X = 2.5;
                 }
                 n++;
             }
         }
         Array.Resize<Game.PointOfInterest>(ref Game.PointsOfInterest, n);
     }
     // convert block-based cant into point-based cant
     for (int i = CurrentTrackLength - 1; i >= 1; i--) {
         if (TrackManager.CurrentTrack.Elements[i].CurveCant == 0.0) {
             TrackManager.CurrentTrack.Elements[i].CurveCant = TrackManager.CurrentTrack.Elements[i - 1].CurveCant;
         } else if (TrackManager.CurrentTrack.Elements[i - 1].CurveCant != 0.0) {
             if (Math.Sign(TrackManager.CurrentTrack.Elements[i - 1].CurveCant) == Math.Sign(TrackManager.CurrentTrack.Elements[i].CurveCant)) {
                 if (Math.Abs(TrackManager.CurrentTrack.Elements[i - 1].CurveCant) > Math.Abs(TrackManager.CurrentTrack.Elements[i].CurveCant)) {
                     TrackManager.CurrentTrack.Elements[i].CurveCant = TrackManager.CurrentTrack.Elements[i - 1].CurveCant;
                 }
             } else {
                 TrackManager.CurrentTrack.Elements[i].CurveCant = 0.5 * (TrackManager.CurrentTrack.Elements[i].CurveCant + TrackManager.CurrentTrack.Elements[i - 1].CurveCant);
             }
         }
     }
     // finalize
     Array.Resize<TrackManager.TrackElement>(ref TrackManager.CurrentTrack.Elements, CurrentTrackLength);
     for (int i = 0; i < Game.Stations.Length; i++) {
         if (Game.Stations[i].Stops.Length == 0 & Game.Stations[i].StopMode != Game.StationStopMode.AllPass) {
             Interface.AddMessage(Interface.MessageType.Warning, false, "Station " + Game.Stations[i].Name + " expects trains to stop but does not define stop points at track position " + Game.Stations[i].DefaultTrackPosition.ToString(Culture) + " in file " + FileName);
             Game.Stations[i].StopMode = Game.StationStopMode.AllPass;
         }
         if (Game.Stations[i].StationType == Game.StationType.ChangeEnds) {
             if (i < Game.Stations.Length - 1) {
                 if (Game.Stations[i + 1].StopMode != Game.StationStopMode.AllStop) {
                     Interface.AddMessage(Interface.MessageType.Warning, false, "Station " + Game.Stations[i].Name + " is marked as \"change ends\" but the subsequent station does not expect all trains to stop in file " + FileName);
                     Game.Stations[i + 1].StopMode = Game.StationStopMode.AllStop;
                 }
             } else {
                 Interface.AddMessage(Interface.MessageType.Warning, false, "Station " + Game.Stations[i].Name + " is marked as \"change ends\" but there is no subsequent station defined in file " + FileName);
                 Game.Stations[i].StationType = Game.StationType.Terminal;
             }
         }
     }
     if (Game.Stations.Length != 0) {
         Game.Stations[Game.Stations.Length - 1].StationType = Game.StationType.Terminal;
     }
     if (TrackManager.CurrentTrack.Elements.Length != 0) {
         int n = TrackManager.CurrentTrack.Elements.Length - 1;
         int m = TrackManager.CurrentTrack.Elements[n].Events.Length;
         Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[n].Events, m + 1);
         TrackManager.CurrentTrack.Elements[n].Events[m] = new TrackManager.TrackEndEvent(Data.BlockInterval);
     }
     // insert compatibility beacons
     if (!PreviewOnly) {
         List<TrackManager.TransponderEvent> transponders = new List<TrackManager.TransponderEvent>();
         bool atc = false;
         for (int i = 0; i < TrackManager.CurrentTrack.Elements.Length; i++) {
             for (int j = 0; j < TrackManager.CurrentTrack.Elements[i].Events.Length; j++) {
                 if (!atc) {
                     if (TrackManager.CurrentTrack.Elements[i].Events[j] is TrackManager.StationStartEvent) {
                         TrackManager.StationStartEvent station = (TrackManager.StationStartEvent)TrackManager.CurrentTrack.Elements[i].Events[j];
                         if (Game.Stations[station.StationIndex].SafetySystem == Game.SafetySystem.Atc) {
                             Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[i].Events, TrackManager.CurrentTrack.Elements[i].Events.Length + 2);
                             TrackManager.CurrentTrack.Elements[i].Events[TrackManager.CurrentTrack.Elements[i].Events.Length - 2] = new TrackManager.TransponderEvent(0.0, TrackManager.SpecialTransponderTypes.AtcTrackStatus, 0, 0);
                             TrackManager.CurrentTrack.Elements[i].Events[TrackManager.CurrentTrack.Elements[i].Events.Length - 1] = new TrackManager.TransponderEvent(0.0, TrackManager.SpecialTransponderTypes.AtcTrackStatus, 1, 0);
                             atc = true;
                         }
                     }
                 } else {
                     if (TrackManager.CurrentTrack.Elements[i].Events[j] is TrackManager.StationStartEvent) {
                         TrackManager.StationStartEvent station = (TrackManager.StationStartEvent)TrackManager.CurrentTrack.Elements[i].Events[j];
                         if (Game.Stations[station.StationIndex].SafetySystem == Game.SafetySystem.Ats) {
                             Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[i].Events, TrackManager.CurrentTrack.Elements[i].Events.Length + 2);
                             TrackManager.CurrentTrack.Elements[i].Events[TrackManager.CurrentTrack.Elements[i].Events.Length - 2] = new TrackManager.TransponderEvent(0.0, TrackManager.SpecialTransponderTypes.AtcTrackStatus, 2, 0);
                             TrackManager.CurrentTrack.Elements[i].Events[TrackManager.CurrentTrack.Elements[i].Events.Length - 1] = new TrackManager.TransponderEvent(0.0, TrackManager.SpecialTransponderTypes.AtcTrackStatus, 3, 0);
                         }
                     } else if (TrackManager.CurrentTrack.Elements[i].Events[j] is TrackManager.StationEndEvent) {
                         TrackManager.StationEndEvent station = (TrackManager.StationEndEvent)TrackManager.CurrentTrack.Elements[i].Events[j];
                         if (Game.Stations[station.StationIndex].SafetySystem == Game.SafetySystem.Atc) {
                             Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[i].Events, TrackManager.CurrentTrack.Elements[i].Events.Length + 2);
                             TrackManager.CurrentTrack.Elements[i].Events[TrackManager.CurrentTrack.Elements[i].Events.Length - 2] = new TrackManager.TransponderEvent(0.0, TrackManager.SpecialTransponderTypes.AtcTrackStatus, 1, 0);
                             TrackManager.CurrentTrack.Elements[i].Events[TrackManager.CurrentTrack.Elements[i].Events.Length - 1] = new TrackManager.TransponderEvent(0.0, TrackManager.SpecialTransponderTypes.AtcTrackStatus, 2, 0);
                         } else if (Game.Stations[station.StationIndex].SafetySystem == Game.SafetySystem.Ats) {
                             Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[i].Events, TrackManager.CurrentTrack.Elements[i].Events.Length + 2);
                             TrackManager.CurrentTrack.Elements[i].Events[TrackManager.CurrentTrack.Elements[i].Events.Length - 2] = new TrackManager.TransponderEvent(0.0, TrackManager.SpecialTransponderTypes.AtcTrackStatus, 3, 0);
                             TrackManager.CurrentTrack.Elements[i].Events[TrackManager.CurrentTrack.Elements[i].Events.Length - 1] = new TrackManager.TransponderEvent(0.0, TrackManager.SpecialTransponderTypes.AtcTrackStatus, 0, 0);
                             atc = false;
                         }
                     } else if (TrackManager.CurrentTrack.Elements[i].Events[j] is TrackManager.LimitChangeEvent) {
                         TrackManager.LimitChangeEvent limit = (TrackManager.LimitChangeEvent)TrackManager.CurrentTrack.Elements[i].Events[j];
                         int speed = (int)Math.Round(Math.Min(4095.0, 3.6 * limit.NextSpeedLimit));
                         int distance = Math.Min(1048575, (int)Math.Round(TrackManager.CurrentTrack.Elements[i].StartingTrackPosition + limit.TrackPositionDelta));
                         unchecked {
                             int value = (int)((uint)speed | ((uint)distance << 12));
                             transponders.Add(new TrackManager.TransponderEvent(0.0, TrackManager.SpecialTransponderTypes.AtcSpeedLimit, value, 0));
                         }
                     }
                 }
                 if (TrackManager.CurrentTrack.Elements[i].Events[j] is TrackManager.TransponderEvent) {
                     TrackManager.TransponderEvent transponder = TrackManager.CurrentTrack.Elements[i].Events[j] as TrackManager.TransponderEvent;
                     if (transponder.Type == TrackManager.SpecialTransponderTypes.InternalAtsPTemporarySpeedLimit) {
                         int speed = Math.Min(4095, transponder.Data);
                         int distance = Math.Min(1048575, (int)Math.Round(TrackManager.CurrentTrack.Elements[i].StartingTrackPosition + transponder.TrackPositionDelta));
                         unchecked {
                             int value = (int)((uint)speed | ((uint)distance << 12));
                             transponder.DontTriggerAnymore = true;
                         }
                     }
                 }
             }
         }
         int n = TrackManager.CurrentTrack.Elements[0].Events.Length;
         Array.Resize<TrackManager.GeneralEvent>(ref TrackManager.CurrentTrack.Elements[0].Events, n + transponders.Count);
         for (int i = 0; i < transponders.Count; i++) {
             TrackManager.CurrentTrack.Elements[0].Events[n + i] = transponders[i];
         }
     }
     // cant
     if (!PreviewOnly) {
         ComputeCantTangents();
         int subdivisions = (int)Math.Floor(Data.BlockInterval / 5.0);
         if (subdivisions >= 2) {
             SmoothenOutTurns(subdivisions);
             ComputeCantTangents();
         }
     }
 }
Exemplo n.º 56
0
        private static async Task <IHtmlContent> RenderActionAsync(this IHtmlHelper helper, string action, string controller, string area, object parameters = null)
        {
            // fetching required services for invocation
            var serviceProvider       = helper.ViewContext.HttpContext.RequestServices;
            var actionContextAccessor = helper.ViewContext.HttpContext.RequestServices.GetRequiredService <IActionContextAccessor>();
            var httpContextAccessor   = helper.ViewContext.HttpContext.RequestServices.GetRequiredService <IHttpContextAccessor>();
            var actionSelector        = serviceProvider.GetRequiredService <IActionSelector>();

            // creating new action invocation context
            var routeData = new RouteData();

            foreach (var router in helper.ViewContext.RouteData.Routers)
            {
                routeData.PushState(router, null, null);
            }
            routeData.PushState(null, new RouteValueDictionary(new { controller = controller, action = action, area = area }), null);
            routeData.PushState(null, new RouteValueDictionary(parameters ?? new { }), null);

            //get the actiondescriptor
            RouteContext routeContext = new RouteContext(helper.ViewContext.HttpContext)
            {
                RouteData = routeData
            };
            var candidates       = actionSelector.SelectCandidates(routeContext);
            var actionDescriptor = actionSelector.SelectBestCandidate(routeContext, candidates);

            var originalActionContext = actionContextAccessor.ActionContext;
            var originalhttpContext   = httpContextAccessor.HttpContext;

            try
            {
                var newHttpContext = serviceProvider.GetRequiredService <IHttpContextFactory>().Create(helper.ViewContext.HttpContext.Features);
                if (newHttpContext.Items.ContainsKey(typeof(IUrlHelper)))
                {
                    newHttpContext.Items.Remove(typeof(IUrlHelper));
                }
                newHttpContext.Response.Body = new MemoryStream();
                var actionContext = new ActionContext(newHttpContext, routeData, actionDescriptor);
                actionContextAccessor.ActionContext = actionContext;
                var invoker = serviceProvider.GetRequiredService <IActionInvokerFactory>().CreateInvoker(actionContext);
                await invoker.InvokeAsync();

                newHttpContext.Response.Body.Position = 0;
                using (var reader = new StreamReader(newHttpContext.Response.Body))
                {
                    return(new HtmlString(reader.ReadToEnd()));
                }
            }
            catch (Exception ex)
            {
                return(new HtmlString(ex.Message));
            }
            finally
            {
                actionContextAccessor.ActionContext = originalActionContext;
                httpContextAccessor.HttpContext     = originalhttpContext;
                if (helper.ViewContext.HttpContext.Items.ContainsKey(typeof(IUrlHelper)))
                {
                    helper.ViewContext.HttpContext.Items.Remove(typeof(IUrlHelper));
                }
            }
        }
Exemplo n.º 57
0
 // preprocess options
 private static void PreprocessOptions(string FileName, bool IsRW, System.Text.Encoding Encoding, Expression[] Expressions, ref RouteData Data, ref double[] UnitOfLength)
 {
     System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
     string Section = "";
     bool SectionAlwaysPrefix = false;
     // process expressions
     for (int j = 0; j < Expressions.Length; j++) {
         if (IsRW && Expressions[j].Text.StartsWith("[") && Expressions[j].Text.EndsWith("]")) {
             Section = Expressions[j].Text.Substring(1, Expressions[j].Text.Length - 2).Trim();
             if (string.Compare(Section, "object", StringComparison.OrdinalIgnoreCase) == 0) {
                 Section = "Structure";
             } else if (string.Compare(Section, "railway", StringComparison.OrdinalIgnoreCase) == 0) {
                 Section = "Track";
             }
             SectionAlwaysPrefix = true;
         } else {
             // find equals
             int Equals = Expressions[j].Text.IndexOf('=');
             if (Equals >= 0) {
                 // handle RW cycle syntax
                 string t = Expressions[j].Text.Substring(0, Equals);
                 if (Section.ToLowerInvariant() == "cycle" & SectionAlwaysPrefix) {
                     double b; if (Interface.TryParseDoubleVb6(t, out b)) {
                         t = ".Ground(" + t + ")";
                     }
                 } else if (Section.ToLowerInvariant() == "signal" & SectionAlwaysPrefix) {
                     double b; if (Interface.TryParseDoubleVb6(t, out b)) {
                         t = ".Void(" + t + ")";
                     }
                 }
                 // convert RW style into CSV style
                 Expressions[j].Text = t + " " + Expressions[j].Text.Substring(Equals + 1);
             }
             // separate command and arguments
             string Command, ArgumentSequence;
             SeparateCommandsAndArguments(Expressions[j], out Command, out ArgumentSequence, Culture, Expressions[j].File, j, true);
             // process command
             double Number;
             bool NumberCheck = !IsRW || string.Compare(Section, "track", StringComparison.OrdinalIgnoreCase) == 0;
             if (!NumberCheck || !Interface.TryParseDoubleVb6(Command, UnitOfLength, out Number)) {
                 // split arguments
                 string[] Arguments;
                 {
                     int n = 0;
                     for (int k = 0; k < ArgumentSequence.Length; k++) {
                         if (IsRW & ArgumentSequence[k] == ',') {
                             n++;
                         } else if (ArgumentSequence[k] == ';') {
                             n++;
                         }
                     }
                     Arguments = new string[n + 1];
                     int a = 0, h = 0;
                     for (int k = 0; k < ArgumentSequence.Length; k++) {
                         if (IsRW & ArgumentSequence[k] == ',') {
                             Arguments[h] = ArgumentSequence.Substring(a, k - a).Trim();
                             a = k + 1; h++;
                         } else if (ArgumentSequence[k] == ';') {
                             Arguments[h] = ArgumentSequence.Substring(a, k - a).Trim();
                             a = k + 1; h++;
                         }
                     }
                     if (ArgumentSequence.Length - a > 0) {
                         Arguments[h] = ArgumentSequence.Substring(a).Trim();
                         h++;
                     }
                     Array.Resize<string>(ref Arguments, h);
                 }
                 // preprocess command
                 if (Command.ToLowerInvariant() == "with") {
                     if (Arguments.Length >= 1) {
                         Section = Arguments[0];
                         SectionAlwaysPrefix = false;
                     } else {
                         Section = "";
                         SectionAlwaysPrefix = false;
                     }
                     Command = null;
                 } else {
                     if (Command.StartsWith(".")) {
                         Command = Section + Command;
                     } else if (SectionAlwaysPrefix) {
                         Command = Section + "." + Command;
                     }
                     Command = Command.Replace(".Void", "");
                 }
                 // handle indices
                 int CommandIndex1 = 0, CommandIndex2 = 0;
                 if (Command != null && Command.EndsWith(")")) {
                     for (int k = Command.Length - 2; k >= 0; k--) {
                         if (Command[k] == '(') {
                             string Indices = Command.Substring(k + 1, Command.Length - k - 2).TrimStart();
                             Command = Command.Substring(0, k).TrimEnd();
                             int h = Indices.IndexOf(";");
                             if (h >= 0) {
                                 string a = Indices.Substring(0, h).TrimEnd();
                                 string b = Indices.Substring(h + 1).TrimStart();
                                 if (a.Length > 0 && !Interface.TryParseIntVb6(a, out CommandIndex1)) {
                                     Command = null; break;
                                 } else if (b.Length > 0 && !Interface.TryParseIntVb6(b, out CommandIndex2)) {
                                     Command = null; break;
                                 }
                             } else {
                                 if (Indices.Length > 0 && !Interface.TryParseIntVb6(Indices, out CommandIndex1)) {
                                     Command = null; break;
                                 }
                             }
                             break;
                         }
                     }
                 }
                 // process command
                 if (Command != null) {
                     switch (Command.ToLowerInvariant()) {
                             // options
                         case "options.unitoflength":
                             {
                                 if (Arguments.Length == 0) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "At least 1 argument is expected in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     UnitOfLength = new double[Arguments.Length];
                                     for (int i = 0; i < Arguments.Length; i++) {
                                         UnitOfLength[i] = i == Arguments.Length - 1 ? 1.0 : 0.0;
                                         if (Arguments[i].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[i], out UnitOfLength[i])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FactorInMeters" + i.ToString(Culture) + " is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             UnitOfLength[i] = i == 0 ? 1.0 : 0.0;
                                         } else if (UnitOfLength[i] <= 0.0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FactorInMeters" + i.ToString(Culture) + " is expected to be positive in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             UnitOfLength[i] = i == Arguments.Length - 1 ? 1.0 : 0.0;
                                         }
                                     }
                                 }
                             } break;
                         case "options.unitofspeed":
                             {
                                 if (Arguments.Length < 1) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Exactly 1 argument is expected in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     if (Arguments.Length > 1) {
                                         Interface.AddMessage(Interface.MessageType.Warning, false, "Exactly 1 argument is expected in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     }
                                     if (Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], out Data.UnitOfSpeed)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FactorInKmph is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         Data.UnitOfSpeed = 0.277777777777778;
                                     } else if (Data.UnitOfSpeed <= 0.0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FactorInKmph is expected to be positive in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         Data.UnitOfSpeed = 0.277777777777778;
                                     } else {
                                         Data.UnitOfSpeed *= 0.277777777777778;
                                     }
                                 }
                             } break;
                         case "options.objectvisibility":
                             {
                                 if (Arguments.Length == 0) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Exactly 1 argument is expected in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     if (Arguments.Length > 1) {
                                         Interface.AddMessage(Interface.MessageType.Warning, false, "Exactly 1 argument is expected in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     }
                                     int mode = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length != 0 && !Interface.TryParseIntVb6(Arguments[0], out mode)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Mode is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         mode = 0;
                                     } else if (mode != 0 & mode != 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "The specified Mode is not supported in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         mode = 0;
                                     }
                                     Data.AccurateObjectDisposal = mode == 1;
                                 }
                             } break;
                     }
                 }
             }
         }
     }
 }
Exemplo n.º 58
0
        public async Task SubnetRouteTableTest()
        {
            string resourceGroupName = Recording.GenerateAssetName("csmrg");

            string location      = TestEnvironment.Location;
            var    resourceGroup = await CreateResourceGroup(resourceGroupName);

            string routeTableName = Recording.GenerateAssetName("azsmnet");
            string route1Name     = Recording.GenerateAssetName("azsmnet");

            var routeTable = new RouteTableData()
            {
                Location = location,
            };

            var route1 = new RouteData()
            {
                AddressPrefix    = "192.168.1.0/24",
                Name             = route1Name,
                NextHopIpAddress = "23.108.1.1",
                NextHopType      = RouteNextHopType.VirtualAppliance
            };

            routeTable.Routes.Add(route1);

            // Put RouteTable
            var routeTableCollection           = resourceGroup.GetRouteTables();
            var putRouteTableResponseOperation = await routeTableCollection.CreateOrUpdateAsync(routeTableName, routeTable);

            Response <RouteTable> putRouteTableResponse = await putRouteTableResponseOperation.WaitForCompletionAsync();;

            Assert.AreEqual("Succeeded", putRouteTableResponse.Value.Data.ProvisioningState.ToString());

            // Get RouteTable
            Response <RouteTable> getRouteTableResponse = await routeTableCollection.GetAsync(routeTableName);

            // Verify that the subnet reference is null
            Assert.IsEmpty(getRouteTableResponse.Value.Data.Subnets);

            // Create Vnet with subnet and add a route table
            string vnetName   = Recording.GenerateAssetName("azsmnet");
            string subnetName = Recording.GenerateAssetName("azsmnet");

            var vnet = new VirtualNetworkData()
            {
                Location = location,

                AddressSpace = new AddressSpace()
                {
                    AddressPrefixes = { "10.0.0.0/16", }
                },
                DhcpOptions = new DhcpOptions()
                {
                    DnsServers = { "10.1.1.1", "10.1.2.4" }
                },
                Subnets =
                {
                    new SubnetData()
                    {
                        Name          = subnetName,
                        AddressPrefix = "10.0.0.0/24",
                        RouteTable    = new RouteTableData()
                        {
                            Id = getRouteTableResponse.Value.Id,
                        }
                    }
                }
            };

            var putVnetResponseOperation = await resourceGroup.GetVirtualNetworks().CreateOrUpdateAsync(vnetName, vnet);

            Response <VirtualNetwork> putVnetResponse = await putVnetResponseOperation.WaitForCompletionAsync();;

            Assert.AreEqual("Succeeded", putVnetResponse.Value.Data.ProvisioningState.ToString());

            Response <Subnet> getSubnetResponse = await putVnetResponse.Value.GetSubnets().GetAsync(subnetName);

            Assert.AreEqual(getSubnetResponse.Value.Data.RouteTable.Id, getRouteTableResponse.Value.Id.ToString());

            // Get RouteTable
            getRouteTableResponse = await routeTableCollection.GetAsync(routeTableName);

            Assert.AreEqual(1, getRouteTableResponse.Value.Data.Subnets.Count);
            Assert.AreEqual(getSubnetResponse.Value.Id.ToString(), getRouteTableResponse.Value.Data.Subnets[0].Id);
        }
Exemplo n.º 59
0
        public async Task RouteTableApiTest()
        {
            string resourceGroupName = Recording.GenerateAssetName("csmrg");

            string location      = TestEnvironment.Location;
            var    resourceGroup = await CreateResourceGroup(resourceGroupName);

            string routeTableName = Recording.GenerateAssetName("azsmnet");
            string route1Name     = Recording.GenerateAssetName("azsmnet");
            string route2Name     = Recording.GenerateAssetName("azsmnet");

            var routeTable = new RouteTableData()
            {
                Location = location,
            };

            // Add a route
            var route1 = new RouteData()
            {
                AddressPrefix    = "192.168.1.0/24",
                Name             = route1Name,
                NextHopIpAddress = "23.108.1.1",
                NextHopType      = RouteNextHopType.VirtualAppliance
            };

            routeTable.Routes.Add(route1);

            // Put RouteTable
            var routeTableCollection           = resourceGroup.GetRouteTables();
            var putRouteTableResponseOperation = await routeTableCollection.CreateOrUpdateAsync(routeTableName, routeTable);

            Response <RouteTable> putRouteTableResponse = await putRouteTableResponseOperation.WaitForCompletionAsync();;

            Assert.AreEqual("Succeeded", putRouteTableResponse.Value.Data.ProvisioningState.ToString());

            // Get RouteTable
            Response <RouteTable> getRouteTableResponse = await routeTableCollection.GetAsync(routeTableName);

            Assert.AreEqual(routeTableName, getRouteTableResponse.Value.Data.Name);
            Assert.AreEqual(1, getRouteTableResponse.Value.Data.Routes.Count);
            Assert.AreEqual(route1Name, getRouteTableResponse.Value.Data.Routes[0].Name);
            Assert.AreEqual("192.168.1.0/24", getRouteTableResponse.Value.Data.Routes[0].AddressPrefix);
            Assert.AreEqual("23.108.1.1", getRouteTableResponse.Value.Data.Routes[0].NextHopIpAddress);
            Assert.AreEqual(RouteNextHopType.VirtualAppliance, getRouteTableResponse.Value.Data.Routes[0].NextHopType);

            // Add another route
            var route2 = new RouteData()
            {
                AddressPrefix = "10.0.1.0/24",
                Name          = route2Name,
                NextHopType   = RouteNextHopType.VnetLocal
            };

            getRouteTableResponse.Value.Data.Routes.Add(route2);

            await routeTableCollection.CreateOrUpdateAsync(routeTableName, getRouteTableResponse.Value.Data);

            getRouteTableResponse = await routeTableCollection.GetAsync(routeTableName);

            Assert.AreEqual(routeTableName, getRouteTableResponse.Value.Data.Name);
            Assert.AreEqual(2, getRouteTableResponse.Value.Data.Routes.Count);
            Assert.AreEqual(route2Name, getRouteTableResponse.Value.Data.Routes[1].Name);
            Assert.AreEqual("10.0.1.0/24", getRouteTableResponse.Value.Data.Routes[1].AddressPrefix);
            Assert.True(string.IsNullOrEmpty(getRouteTableResponse.Value.Data.Routes[1].NextHopIpAddress));
            Assert.AreEqual(RouteNextHopType.VnetLocal, getRouteTableResponse.Value.Data.Routes[1].NextHopType);

            // Delete a route
            getRouteTableResponse.Value.Data.Routes.RemoveAt(0);

            await routeTableCollection.CreateOrUpdateAsync(routeTableName, getRouteTableResponse.Value.Data);

            getRouteTableResponse = await routeTableCollection.GetAsync(routeTableName);

            Assert.AreEqual(routeTableName, getRouteTableResponse.Value.Data.Name);
            Assert.AreEqual(1, getRouteTableResponse.Value.Data.Routes.Count);
            Assert.AreEqual(route2Name, getRouteTableResponse.Value.Data.Routes[0].Name);
            Assert.AreEqual("10.0.1.0/24", getRouteTableResponse.Value.Data.Routes[0].AddressPrefix);
            Assert.True(string.IsNullOrEmpty(getRouteTableResponse.Value.Data.Routes[0].NextHopIpAddress));
            Assert.AreEqual(RouteNextHopType.VnetLocal, getRouteTableResponse.Value.Data.Routes[0].NextHopType);

            // Delete RouteTable
            var deleteOperation = await getRouteTableResponse.Value.DeleteAsync();

            await deleteOperation.WaitForCompletionResponseAsync();;

            // Verify delete
            AsyncPageable <RouteTable> listRouteTableResponseAP = routeTableCollection.GetAllAsync();
            List <RouteTable>          listRouteTableResponse   = await listRouteTableResponseAP.ToEnumerableAsync();

            Assert.IsEmpty(listRouteTableResponse);
        }
Exemplo n.º 60
0
 protected abstract Task<IArguments> CreateArgumentsAsync(IRequest request, RouteData routeData, Context context);