diff --git a/src/depot_gui.cpp b/src/depot_gui.cpp index 1207d02168..941fe00f59 100644 --- a/src/depot_gui.cpp +++ b/src/depot_gui.cpp @@ -507,15 +507,12 @@ struct DepotWindow : Window { this->sel = INVALID_VEHICLE; TrainDepotMoveVehicle(v, sel, gdvp.head); } else if (v != NULL) { - bool rtl = _current_text_dir == TD_RTL; - int image = v->GetImage(rtl ? DIR_E : DIR_W, EIT_IN_DEPOT); - SetObjectToPlaceWnd(image, GetVehiclePalette(v), HT_DRAG, this); + SetObjectToPlaceWnd(SPR_CURSOR_MOUSE, PAL_NONE, HT_DRAG, this); + SetMouseCursorVehicle(v, EIT_IN_DEPOT); + _cursor.vehchain = _ctrl_pressed; this->sel = v->index; this->SetDirty(); - - _cursor.short_vehicle_offset = v->IsGroundVehicle() ? (16 - v->GetGroundVehicleCache()->cached_veh_length * 2) * (rtl ? -1 : 1) : 0; - _cursor.vehchain = _ctrl_pressed; } break; } diff --git a/src/genworld.cpp b/src/genworld.cpp index ec237d326a..e6f305631c 100644 --- a/src/genworld.cpp +++ b/src/genworld.cpp @@ -77,7 +77,7 @@ static void CleanupGeneration() { _generating_world = false; - if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE); + SetMouseCursorBusy(false); /* Show all vital windows again, because we have hidden them */ if (_gw.threaded && _game_mode != GM_MENU) ShowVitalWindows(); SetModalProgress(false); diff --git a/src/genworld_gui.cpp b/src/genworld_gui.cpp index 0bc0d708da..d62de21673 100644 --- a/src/genworld_gui.cpp +++ b/src/genworld_gui.cpp @@ -1248,7 +1248,7 @@ struct GenerateProgressWindow : public Window { { switch (widget) { case WID_GP_ABORT: - if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE); + SetMouseCursorBusy(false); ShowQuery( STR_GENERATION_ABORT_CAPTION, STR_GENERATION_ABORT_MESSAGE, diff --git a/src/gfx.cpp b/src/gfx.cpp index c5f558e9db..4904e88e7f 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -1226,10 +1226,6 @@ void DrawMouseCursor() if (_screen.dst_ptr == NULL) return; Blitter *blitter = BlitterFactory::GetCurrentBlitter(); - int x; - int y; - int w; - int h; /* Redraw mouse cursor but only when it's inside the window */ if (!_cursor.in_window) return; @@ -1240,36 +1236,44 @@ void DrawMouseCursor() UndrawMouseCursor(); } - w = _cursor.size.x; - x = _cursor.pos.x + _cursor.offs.x + _cursor.short_vehicle_offset; - if (x < 0) { - w += x; - x = 0; + /* Determine visible area */ + int left = _cursor.pos.x + _cursor.total_offs.x; + int width = _cursor.total_size.x; + if (left < 0) { + width += left; + left = 0; } - if (w > _screen.width - x) w = _screen.width - x; - if (w <= 0) return; - _cursor.draw_pos.x = x; - _cursor.draw_size.x = w; - - h = _cursor.size.y; - y = _cursor.pos.y + _cursor.offs.y; - if (y < 0) { - h += y; - y = 0; + if (left + width > _screen.width) { + width = _screen.width - left; } - if (h > _screen.height - y) h = _screen.height - y; - if (h <= 0) return; - _cursor.draw_pos.y = y; - _cursor.draw_size.y = h; + if (width <= 0) return; - uint8 *buffer = _cursor_backup.Allocate(blitter->BufferSize(w, h)); + int top = _cursor.pos.y + _cursor.total_offs.y; + int height = _cursor.total_size.y; + if (top < 0) { + height += top; + top = 0; + } + if (top + height > _screen.height) { + height = _screen.height - top; + } + if (height <= 0) return; + + _cursor.draw_pos.x = left; + _cursor.draw_pos.y = top; + _cursor.draw_size.x = width; + _cursor.draw_size.y = height; + + uint8 *buffer = _cursor_backup.Allocate(blitter->BufferSize(_cursor.draw_size.x, _cursor.draw_size.y)); /* Make backup of stuff below cursor */ blitter->CopyToBuffer(blitter->MoveTo(_screen.dst_ptr, _cursor.draw_pos.x, _cursor.draw_pos.y), buffer, _cursor.draw_size.x, _cursor.draw_size.y); /* Draw cursor on screen */ _cur_dpi = &_screen; - DrawSprite(_cursor.sprite, _cursor.pal, _cursor.pos.x + _cursor.short_vehicle_offset, _cursor.pos.y); + for (uint i = 0; i < _cursor.sprite_count; ++i) { + DrawSprite(_cursor.sprite_seq[i].sprite, _cursor.sprite_seq[i].pal, _cursor.pos.x + _cursor.sprite_pos[i].x, _cursor.pos.y + _cursor.sprite_pos[i].y); + } VideoDriver::GetInstance()->MakeDirty(_cursor.draw_pos.x, _cursor.draw_pos.y, _cursor.draw_size.x, _cursor.draw_size.y); @@ -1528,15 +1532,33 @@ bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int heigh */ void UpdateCursorSize() { - CursorVars *cv = &_cursor; - const Sprite *p = GetSprite(GB(cv->sprite, 0, SPRITE_WIDTH), ST_NORMAL); + /* Ignore setting any cursor before the sprites are loaded. */ + if (GetMaxSpriteID() == 0) return; - cv->size.y = UnScaleGUI(p->height); - cv->size.x = UnScaleGUI(p->width); - cv->offs.x = UnScaleGUI(p->x_offs); - cv->offs.y = UnScaleGUI(p->y_offs); + assert_compile(lengthof(_cursor.sprite_seq) == lengthof(_cursor.sprite_pos)); + assert(_cursor.sprite_count <= lengthof(_cursor.sprite_seq)); + for (uint i = 0; i < _cursor.sprite_count; ++i) { + const Sprite *p = GetSprite(GB(_cursor.sprite_seq[i].sprite, 0, SPRITE_WIDTH), ST_NORMAL); + Point offs, size; + offs.x = UnScaleGUI(p->x_offs) + _cursor.sprite_pos[i].x; + offs.y = UnScaleGUI(p->y_offs) + _cursor.sprite_pos[i].y; + size.x = UnScaleGUI(p->width); + size.y = UnScaleGUI(p->height); - cv->dirty = true; + if (i == 0) { + _cursor.total_offs = offs; + _cursor.total_size = size; + } else { + int right = max(_cursor.total_offs.x + _cursor.total_size.x, offs.x + size.x); + int bottom = max(_cursor.total_offs.y + _cursor.total_size.y, offs.y + size.y); + if (offs.x < _cursor.total_offs.x) _cursor.total_offs.x = offs.x; + if (offs.y < _cursor.total_offs.y) _cursor.total_offs.y = offs.y; + _cursor.total_size.x = right - _cursor.total_offs.x; + _cursor.total_size.y = bottom - _cursor.total_offs.y; + } + } + + _cursor.dirty = true; } /** @@ -1546,14 +1568,15 @@ void UpdateCursorSize() */ static void SetCursorSprite(CursorID cursor, PaletteID pal) { - CursorVars *cv = &_cursor; - if (cv->sprite == cursor) return; + if (_cursor.sprite_count == 1 && _cursor.sprite_seq[0].sprite == cursor && _cursor.sprite_seq[0].pal == pal) return; + + _cursor.sprite_count = 1; + _cursor.sprite_seq[0].sprite = cursor; + _cursor.sprite_seq[0].pal = pal; + _cursor.sprite_pos[0].x = 0; + _cursor.sprite_pos[0].y = 0; - cv->sprite = cursor; - cv->pal = pal; UpdateCursorSize(); - - cv->short_vehicle_offset = 0; } static void SwitchAnimatedCursor() @@ -1562,7 +1585,7 @@ static void SwitchAnimatedCursor() if (cur == NULL || cur->sprite == AnimCursor::LAST) cur = _cursor.animate_list; - SetCursorSprite(cur->sprite, _cursor.pal); + SetCursorSprite(cur->sprite, _cursor.sprite_seq[0].pal); _cursor.animate_timeout = cur->display_time; _cursor.animate_cur = cur + 1; @@ -1575,6 +1598,19 @@ void CursorTick() } } +/** + * Set or unset the ZZZ cursor. + * @param busy Whether to show the ZZZ cursor. + */ +void SetMouseCursorBusy(bool busy) +{ + if (busy) { + if (_cursor.sprite_seq[0].sprite == SPR_CURSOR_MOUSE) SetMouseCursor(SPR_CURSOR_ZZZ, PAL_NONE); + } else { + if (_cursor.sprite_seq[0].sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE); + } +} + /** * Assign a single non-animated sprite to the cursor. * @param sprite Sprite to draw for the cursor. @@ -1598,7 +1634,7 @@ void SetAnimatedMouseCursor(const AnimCursor *table) { _cursor.animate_list = table; _cursor.animate_cur = NULL; - _cursor.pal = PAL_NONE; + _cursor.sprite_seq[0].pal = PAL_NONE; SwitchAnimatedCursor(); } diff --git a/src/gfx_func.h b/src/gfx_func.h index 4162ad370a..58d9b47e9a 100644 --- a/src/gfx_func.h +++ b/src/gfx_func.h @@ -145,6 +145,7 @@ bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int heigh /* window.cpp */ void DrawOverlappedWindowForAll(int left, int top, int right, int bottom); +void SetMouseCursorBusy(bool busy); void SetMouseCursor(CursorID cursor, PaletteID pal); void SetAnimatedMouseCursor(const AnimCursor *table); void CursorTick(); diff --git a/src/gfx_type.h b/src/gfx_type.h index d25abff218..ca9bf9fcef 100644 --- a/src/gfx_type.h +++ b/src/gfx_type.h @@ -115,29 +115,35 @@ struct AnimCursor { /** Collection of variables for cursor-display and -animation */ struct CursorVars { - Point pos, size, offs, delta; ///< position, size, offset from top-left, and movement - Point draw_pos, draw_size; ///< position and size bounding-box for drawing - int short_vehicle_offset; ///< offset of the X for short vehicles - CursorID sprite; ///< current image of cursor - PaletteID pal; - - int wheel; ///< mouse wheel movement + /* Logical mouse position */ + Point pos; ///< logical mouse position + Point delta; ///< relative mouse movement in this tick + int wheel; ///< mouse wheel movement + bool fix_at; ///< mouse is moving, but cursor is not (used for scrolling) /* We need two different vars to keep track of how far the scrollwheel moved. * OSX uses this for scrolling around the map. */ int v_wheel; int h_wheel; + /* Mouse appearance */ + PalSpriteID sprite_seq[16]; ///< current image of cursor + Point sprite_pos[16]; ///< relative position of individual sprites + uint sprite_count; ///< number of sprites to draw + Point total_offs, total_size; ///< union of sprite properties + + Point draw_pos, draw_size; ///< position and size bounding-box for drawing + const AnimCursor *animate_list; ///< in case of animated cursor, list of frames const AnimCursor *animate_cur; ///< in case of animated cursor, current frame uint animate_timeout; ///< in case of animated cursor, number of ticks to show the current cursor - bool visible; ///< cursor is visible - bool dirty; ///< the rect occupied by the mouse is dirty (redraw) - bool fix_at; ///< mouse is moving, but cursor is not (used for scrolling) - bool in_window; ///< mouse inside this window, determines drawing logic + bool visible; ///< cursor is visible + bool dirty; ///< the rect occupied by the mouse is dirty (redraw) + bool in_window; ///< mouse inside this window, determines drawing logic - bool vehchain; ///< vehicle chain is dragged + /* Drag data */ + bool vehchain; ///< vehicle chain is dragged bool UpdateCursorPosition(int x, int y, bool queued_warp); diff --git a/src/group_gui.cpp b/src/group_gui.cpp index 638f65d696..e583013036 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -737,8 +737,8 @@ public: this->vehicle_sel = v->index; - int image = v->GetImage(_current_text_dir == TD_RTL ? DIR_E : DIR_W, EIT_IN_LIST); - SetObjectToPlaceWnd(image, GetVehiclePalette(v), HT_DRAG, this); + SetObjectToPlaceWnd(SPR_CURSOR_MOUSE, PAL_NONE, HT_DRAG, this); + SetMouseCursorVehicle(v, EIT_IN_LIST); _cursor.vehchain = true; this->SetDirty(); diff --git a/src/lang/spanish_MX.txt b/src/lang/spanish_MX.txt index 5b265ce8b5..aed6cf20f5 100644 --- a/src/lang/spanish_MX.txt +++ b/src/lang/spanish_MX.txt @@ -379,7 +379,7 @@ STR_SETTINGS_MENU_NEWGRF_SETTINGS :Configuración STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS :Opciones de transparencia STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED :Mostrar nombres de pueblos STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED :Mostrar nombres de estaciones -STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED :Mostrar puestos guías +STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED :Mostrar puntos guías STR_SETTINGS_MENU_SIGNS_DISPLAYED :Mostrar carteles propios STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS :Mostrar carteles y nombres del competidor STR_SETTINGS_MENU_FULL_ANIMATION :Animación completa @@ -1148,7 +1148,7 @@ STR_CONFIG_SETTING_RUNNING_COSTS :Costos de opera STR_CONFIG_SETTING_RUNNING_COSTS_HELPTEXT :Nivel de los costos de mantenimiento y operación de vehículos e infraestructura STR_CONFIG_SETTING_CONSTRUCTION_SPEED :Velocidad de construcción: {STRING} STR_CONFIG_SETTING_CONSTRUCTION_SPEED_HELPTEXT :Restringir la velocidad de las acciones de construcción de jugadores no humanos -STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Descomposturas de vehículos: {STRING} +STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Averías de vehículos: {STRING} STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :Controlar cada cuánto los vehículos con poco mantenimiento sufren fallas STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Multiplicador de subsidio: {STRING} STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Establecer cuánto se paga por subsidios conectados @@ -1473,8 +1473,8 @@ STR_CONFIG_SETTING_SERVINT_AIRCRAFT :Intervalo de ma STR_CONFIG_SETTING_SERVINT_AIRCRAFT_HELPTEXT :Intervalo de mantenimiento predeterminado para nuevas aeronaves, en caso de no definirse otro explícitamente STR_CONFIG_SETTING_SERVINT_SHIPS :Intervalo de mantenimiento predeterminado para barcos: {STRING} STR_CONFIG_SETTING_SERVINT_SHIPS_HELPTEXT :Intervalo de mantenimiento predeterminado para nuevos barcos, en caso de no definirse otro explícitamente -STR_CONFIG_SETTING_NOSERVICE :Desactivar mantenimiento si las descomposturas están desactivadas: {STRING} -STR_CONFIG_SETTING_NOSERVICE_HELPTEXT :Al activarse, los vehículos no recibirán mantenimiento si no pueden descomponerse +STR_CONFIG_SETTING_NOSERVICE :Desactivar mantenimiento si las averías están desactivadas: {STRING} +STR_CONFIG_SETTING_NOSERVICE_HELPTEXT :Al activarse, los vehículos no recibirán mantenimiento si no pueden averiarse STR_CONFIG_SETTING_WAGONSPEEDLIMITS :Activar límites de velocidad para vagones: {STRING} STR_CONFIG_SETTING_WAGONSPEEDLIMITS_HELPTEXT :Al activarse, se tienen en cuenta los límites de velocidad de los vagones para decidir la máxima velocidad de un tren STR_CONFIG_SETTING_DISABLE_ELRAILS :Desactivar ferrocarriles eléctricos: {STRING} @@ -2271,7 +2271,7 @@ STR_TRANSPARENT_SIGNS_TOOLTIP :{BLACK}Activar STR_TRANSPARENT_TREES_TOOLTIP :{BLACK}Activar o desactivar transparencia para árboles. Ctrl+Clic para excluir de tecla rápida 'X' STR_TRANSPARENT_HOUSES_TOOLTIP :{BLACK}Activar o desactivar transparencia para casas. Ctrl+Clic para excluir de tecla rápida 'X' STR_TRANSPARENT_INDUSTRIES_TOOLTIP :{BLACK}Activar o desactivar transparencia para industrias. Ctrl+Clic para excluir de tecla rápida 'X' -STR_TRANSPARENT_BUILDINGS_TOOLTIP :{BLACK}Activar o desactivar transparencia para edificios como estaciones, depósitos o puestos guías. Ctrl+Clic para excluir de tecla rápida 'X' +STR_TRANSPARENT_BUILDINGS_TOOLTIP :{BLACK}Activar o desactivar transparencia para edificios como estaciones, depósitos o puntos guías. Ctrl+Clic para excluir de tecla rápida 'X' STR_TRANSPARENT_BRIDGES_TOOLTIP :{BLACK}Activar o desactivar transparencia para puentes. Ctrl+Clic para excluir de tecla rápida 'X' STR_TRANSPARENT_STRUCTURES_TOOLTIP :{BLACK}Activar o desactivar transparencia para estructuras como faros o antenas. Ctrl+Clic para excluir de tecla rápida 'X' STR_TRANSPARENT_CATENARY_TOOLTIP :{BLACK}Activar o desactivar transparencia para catenaria. Ctrl+Clic para excluir de tecla rápida 'X' @@ -2302,7 +2302,7 @@ STR_STATION_BUILD_SUPPLIES_CARGO :{BLACK}Provee: STR_JOIN_STATION_CAPTION :{WHITE}Ampliar estación STR_JOIN_STATION_CREATE_SPLITTED_STATION :{YELLOW}Construir aparte -STR_JOIN_WAYPOINT_CAPTION :{WHITE}Unir puestos guías +STR_JOIN_WAYPOINT_CAPTION :{WHITE}Unir puntos guías STR_JOIN_WAYPOINT_CREATE_SPLITTED_WAYPOINT :{YELLOW}Construir aparte # Rail construction toolbar @@ -2332,8 +2332,8 @@ STR_BUILD_DEPOT_TRAIN_ORIENTATION_CAPTION :{WHITE}Orientac STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP :{BLACK}Elegir la orientación del depósito de trenes # Rail waypoint construction window -STR_WAYPOINT_CAPTION :{WHITE}Puesto guía -STR_WAYPOINT_GRAPHICS_TOOLTIP :{BLACK}Elegir el tipo de puesto guía +STR_WAYPOINT_CAPTION :{WHITE}Punto guía +STR_WAYPOINT_GRAPHICS_TOOLTIP :{BLACK}Elegir el tipo de punto guía # Rail station construction window STR_STATION_BUILD_RAIL_CAPTION :{WHITE}Selección de estación @@ -2350,7 +2350,7 @@ STR_STATION_BUILD_STATION_CLASS_TOOLTIP :{BLACK}Mostrar STR_STATION_BUILD_STATION_TYPE_TOOLTIP :{BLACK}Construir el tipo de estación elegida STR_STATION_CLASS_DFLT :Estación predeterminada -STR_STATION_CLASS_WAYP :Puestos guías +STR_STATION_CLASS_WAYP :Puntos guías # Signal window STR_BUILD_SIGNAL_CAPTION :{WHITE}Selección de señales @@ -2431,7 +2431,7 @@ STR_WATERWAYS_TOOLBAR_BUILD_CANALS_TOOLTIP :{BLACK}Construi STR_WATERWAYS_TOOLBAR_BUILD_LOCKS_TOOLTIP :{BLACK}Construir esclusa. Mayús muestra una estimación del precio STR_WATERWAYS_TOOLBAR_BUILD_DEPOT_TOOLTIP :{BLACK}Construir astillero (para comprar y dar mantenimiento a barcos). Mayús muestra una estimación del precio STR_WATERWAYS_TOOLBAR_BUILD_DOCK_TOOLTIP :{BLACK}Construir muelles. Ctrl activa la ampliación de estaciones. Mayús muestra una estimación del precio -STR_WATERWAYS_TOOLBAR_BUOY_TOOLTIP :{BLACK}Colocar boya para utilizar como puesto guía marítimo. Mayús muestra una estimación del precio +STR_WATERWAYS_TOOLBAR_BUOY_TOOLTIP :{BLACK}Colocar boya para utilizar como punto guía marítimo. Mayús muestra una estimación del precio STR_WATERWAYS_TOOLBAR_BUILD_AQUEDUCT_TOOLTIP :{BLACK}Construir acueducto. Mayús muestra una estimación del precio STR_WATERWAYS_TOOLBAR_CREATE_LAKE_TOOLTIP :{BLACK}Definir cuerpo de agua.{}Crea un canal, a menos que se pulse Ctrl en un área al nivel del mar, en cuyo caso se inundarán los alrededores STR_WATERWAYS_TOOLBAR_CREATE_RIVER_TOOLTIP :{BLACK}Colocar ríos @@ -2647,7 +2647,7 @@ STR_LAI_STATION_DESCRIPTION_TRUCK_LOADING_AREA :Estación de ca STR_LAI_STATION_DESCRIPTION_BUS_STATION :Parada de autobús STR_LAI_STATION_DESCRIPTION_SHIP_DOCK :Muelle STR_LAI_STATION_DESCRIPTION_BUOY :Boya -STR_LAI_STATION_DESCRIPTION_WAYPOINT :puesto guía +STR_LAI_STATION_DESCRIPTION_WAYPOINT :Punto guía STR_LAI_WATER_DESCRIPTION_WATER :Agua STR_LAI_WATER_DESCRIPTION_CANAL :Canal @@ -3172,12 +3172,12 @@ STR_STATION_VIEW_CLOSE_AIRPORT_TOOLTIP :{BLACK}No permi # Waypoint/buoy view window STR_WAYPOINT_VIEW_CAPTION :{WHITE}{WAYPOINT} -STR_WAYPOINT_VIEW_CENTER_TOOLTIP :{BLACK}Centrar vista en ubicación del puesto guía. Ctrl+Clic abre una ventana de vista en dicha ubicación -STR_WAYPOINT_VIEW_CHANGE_WAYPOINT_NAME :{BLACK}Cambiar nombre de puesto guía +STR_WAYPOINT_VIEW_CENTER_TOOLTIP :{BLACK}Centrar vista en ubicación del punto guía. Ctrl+Clic abre una ventana de vista en dicha ubicación +STR_WAYPOINT_VIEW_CHANGE_WAYPOINT_NAME :{BLACK}Cambiar nombre de punto guía STR_BUOY_VIEW_CENTER_TOOLTIP :{BLACK}Centrar la vista en la ubicación de la boya. Ctrl+Clic abre una ventana de vista en dicha ubicación STR_BUOY_VIEW_CHANGE_BUOY_NAME :{BLACK}Cambiar nombre de boya -STR_EDIT_WAYPOINT_NAME :{WHITE}Cambiar nombre de puesto guía +STR_EDIT_WAYPOINT_NAME :{WHITE}Cambiar nombre de punto guía # Finances window STR_FINANCES_CAPTION :{WHITE}Finanzas de {COMPANY} {BLACK}{COMPANY_NUM} @@ -3620,7 +3620,7 @@ STR_VEHICLE_VIEW_AIRCRAFT_STATE_START_STOP_TOOLTIP :{BLACK}Activida STR_VEHICLE_STATUS_LOADING_UNLOADING :{LTBLUE}Cargando/Descargando STR_VEHICLE_STATUS_LEAVING :{LTBLUE}Partiendo STR_VEHICLE_STATUS_CRASHED :{RED}¡Accidentado! -STR_VEHICLE_STATUS_BROKEN_DOWN :{RED}Descompuesto +STR_VEHICLE_STATUS_BROKEN_DOWN :{RED}Averiado STR_VEHICLE_STATUS_STOPPED :{RED}Detenido STR_VEHICLE_STATUS_TRAIN_STOPPING_VEL :{RED}Deteniéndose, {VELOCITY} STR_VEHICLE_STATUS_TRAIN_NO_POWER :{RED}Sin potencia @@ -3659,7 +3659,7 @@ STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}Peso: {L STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}Peso: {LTBLUE}{WEIGHT_SHORT} {BLACK}Potencia: {LTBLUE}{POWER}{BLACK} Velocidad máx.: {LTBLUE}{VELOCITY} {BLACK}F.T. máx.: {LTBLUE}{FORCE} STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Utilidad este año: {LTBLUE}{CURRENCY_LONG} (año pasado: {CURRENCY_LONG}) -STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS :{BLACK}Fiabilidad: {LTBLUE}{COMMA}% {BLACK}Descomposturas desde el último mantenimiento: {LTBLUE}{COMMA} +STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS :{BLACK}Fiabilidad: {LTBLUE}{COMMA}% {BLACK}Averías desde el último mantenimiento: {LTBLUE}{COMMA} STR_VEHICLE_INFO_BUILT_VALUE :{LTBLUE}{ENGINE} {BLACK}Construido: {LTBLUE}{NUM}{BLACK} Valor: {LTBLUE}{CURRENCY_LONG} STR_VEHICLE_INFO_NO_CAPACITY :{BLACK}Capacidad: {LTBLUE}Ninguna{STRING} @@ -3816,7 +3816,7 @@ STR_ORDER_GO_TO_NEAREST_DEPOT :Ir al depósito STR_ORDER_GO_TO_NEAREST_HANGAR :Ir al hangar más cercano STR_ORDER_CONDITIONAL :Salto de orden condicional STR_ORDER_SHARE :Compartir órdenes -STR_ORDERS_GO_TO_TOOLTIP :{BLACK}Añadir nueva orden antes de la orden marcada o añadirla al final de la lista. Ctrl+Clic sobre una estación para establecer la orden a 'Cargar máx. cualquier carga', sobre un puesto guía para 'Sin paradas' y sobre un depósito para 'Mantenimiento' (esta última desactivará el mantenimiento automático). Ctrl+Clic sobre otro vehículo para hacer que ambos compartan siempre las mismas órdenes. Clic sobre un vehículo para copiar sus órdenes (sin compartirlas). +STR_ORDERS_GO_TO_TOOLTIP :{BLACK}Añadir nueva orden antes de la orden marcada o añadirla al final de la lista. Ctrl+Clic sobre una estación para establecer la orden a 'Cargar máx. cualquier carga', sobre un punto guía para 'Sin paradas' y sobre un depósito para 'Mantenimiento' (esta última desactivará el mantenimiento automático). Ctrl+Clic sobre otro vehículo para hacer que ambos compartan siempre las mismas órdenes. Clic sobre un vehículo para copiar sus órdenes (sin compartirlas). STR_ORDERS_VEH_WITH_SHARED_ORDERS_LIST_TOOLTIP :{BLACK}Ver todos los vehículos que comparten el mismo itinerario @@ -4241,15 +4241,15 @@ STR_ERROR_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Primero STR_ERROR_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Primero se debe demoler el aeropuerto # Waypoint related errors -STR_ERROR_WAYPOINT_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Se amplía más de un puesto guía existente -STR_ERROR_TOO_CLOSE_TO_ANOTHER_WAYPOINT :{WHITE}Demasiado cerca de otro puesto guía +STR_ERROR_WAYPOINT_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Se amplía más de un punto guía existente +STR_ERROR_TOO_CLOSE_TO_ANOTHER_WAYPOINT :{WHITE}Demasiado cerca de otro punto guía -STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT :{WHITE}No se puede construir el puesto guía aquí... +STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT :{WHITE}No se puede construir el punto guía aquí... STR_ERROR_CAN_T_POSITION_BUOY_HERE :{WHITE}No se puede colocar la boya aquí... -STR_ERROR_CAN_T_CHANGE_WAYPOINT_NAME :{WHITE}No se puede cambiar nombre del puesto guía... +STR_ERROR_CAN_T_CHANGE_WAYPOINT_NAME :{WHITE}No se puede cambiar nombre del punto guía... -STR_ERROR_CAN_T_REMOVE_TRAIN_WAYPOINT :{WHITE}No se puede quitar el puesto guía de aquí... -STR_ERROR_MUST_REMOVE_RAILWAYPOINT_FIRST :{WHITE}Primero se debe retirar el puesto guía +STR_ERROR_CAN_T_REMOVE_TRAIN_WAYPOINT :{WHITE}No se puede quitar el punto guía de aquí... +STR_ERROR_MUST_REMOVE_RAILWAYPOINT_FIRST :{WHITE}Primero se debe retirar el punto guía STR_ERROR_BUOY_IN_THE_WAY :{WHITE}... una boya obstaculiza STR_ERROR_BUOY_IS_IN_USE :{WHITE}... ¡boya en uso por otra empresa! @@ -4861,7 +4861,7 @@ STR_FORMAT_BUOY_NAME_SERIAL :Boya {TOWN} #{C STR_FORMAT_COMPANY_NUM :(Empresa {COMMA}) STR_FORMAT_GROUP_NAME :Grupo {COMMA} STR_FORMAT_INDUSTRY_NAME :{1:STRING}, {0:TOWN} -STR_FORMAT_WAYPOINT_NAME :Puesto guía {TOWN} +STR_FORMAT_WAYPOINT_NAME :Punto guía, {TOWN} STR_FORMAT_WAYPOINT_NAME_SERIAL :Puesto guía #{1:COMMA}, {0:TOWN} STR_FORMAT_DEPOT_NAME_TRAIN :Depósito de trenes, {TOWN} diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 794270085d..8e315c1fe8 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -675,8 +675,8 @@ struct TooltipsWindow : public Window /* Correctly position the tooltip position, watch out for window and cursor size * Clamp value to below main toolbar and above statusbar. If tooltip would * go below window, flip it so it is shown above the cursor */ - pt.y = Clamp(_cursor.pos.y + _cursor.size.y + _cursor.offs.y + 5, scr_top, scr_bot); - if (pt.y + sm_height > scr_bot) pt.y = min(_cursor.pos.y + _cursor.offs.y - 5, scr_bot) - sm_height; + pt.y = Clamp(_cursor.pos.y + _cursor.total_size.y + _cursor.total_offs.y + 5, scr_top, scr_bot); + if (pt.y + sm_height > scr_bot) pt.y = min(_cursor.pos.y + _cursor.total_offs.y - 5, scr_bot) - sm_height; pt.x = sm_width >= _screen.width ? 0 : Clamp(_cursor.pos.x - (sm_width >> 1), 0, _screen.width - sm_width); return pt; diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index a107080d48..379332a168 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -2568,7 +2568,7 @@ static void SaveFileStart() { _sl.ff_state = _fast_forward; _fast_forward = 0; - if (_cursor.sprite == SPR_CURSOR_MOUSE) SetMouseCursor(SPR_CURSOR_ZZZ, PAL_NONE); + SetMouseCursorBusy(true); InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_START); _sl.saveinprogress = true; @@ -2578,7 +2578,7 @@ static void SaveFileStart() static void SaveFileDone() { if (_game_mode != GM_MENU) _fast_forward = _sl.ff_state; - if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE); + SetMouseCursorBusy(false); InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_FINISH); _sl.saveinprogress = false; diff --git a/src/tbtr_template_gui_create.cpp b/src/tbtr_template_gui_create.cpp index 1b858c8e1c..ee404d14fe 100644 --- a/src/tbtr_template_gui_create.cpp +++ b/src/tbtr_template_gui_create.cpp @@ -134,6 +134,7 @@ private: bool *create_window_open; /// used to notify main window of progress (dummy way of disabling 'delete' while editing a template) VehicleID sel; VehicleID vehicle_over; + bool sell_hovered; ///< A vehicle is being dragged/hovered over the sell button. uint32 template_index; public: @@ -154,6 +155,7 @@ public: this->sel = INVALID_VEHICLE; this->vehicle_over = INVALID_VEHICLE; + this->sell_hovered = false; if (to_edit != NULL) { DoCommandP(0, to_edit->index, 0, CMD_VIRTUAL_TRAIN_FROM_TEMPLATE_VEHICLE | CMD_MSG(STR_TMPL_CANT_CREATE), CcSetVirtualTrain); @@ -277,7 +279,10 @@ public: virtual void OnPlaceObjectAbort() { + this->sel = INVALID_VEHICLE; + this->vehicle_over = INVALID_VEHICLE; this->RaiseButtons(); + this->SetDirty(); } virtual void DrawWidget(const Rect &r, int widget) const @@ -378,6 +383,7 @@ public: this->SetDirty(); break; } + this->sell_hovered = false; _cursor.vehchain = false; this->sel = INVALID_VEHICLE; this->SetDirty(); @@ -386,6 +392,14 @@ public: virtual void OnMouseDrag(Point pt, int widget) { if (this->sel == INVALID_VEHICLE) return; + + bool is_sell_widget = widget == TCW_SELL_TMPL; + if (is_sell_widget != this->sell_hovered) { + this->sell_hovered = is_sell_widget; + this->SetWidgetLoweredState(TCW_SELL_TMPL, is_sell_widget); + this->SetWidgetDirty(TCW_SELL_TMPL); + } + /* A rail vehicle is dragged.. */ if (widget != TCW_NEW_TMPL_PANEL) { // ..outside of the depot matrix. if (this->vehicle_over != INVALID_VEHICLE) { @@ -516,14 +530,12 @@ public: this->sel = INVALID_VEHICLE; TrainDepotMoveVehicle(v, sel, gdvp.head); } else if (v != NULL) { - int image = v->GetImage(_current_text_dir == TD_RTL ? DIR_E : DIR_W, EIT_PURCHASE); - SetObjectToPlaceWnd(image, GetVehiclePalette(v), HT_DRAG, this); + SetObjectToPlaceWnd(SPR_CURSOR_MOUSE, PAL_NONE, HT_DRAG, this); + SetMouseCursorVehicle(v, EIT_PURCHASE); + _cursor.vehchain = _ctrl_pressed; this->sel = v->index; this->SetDirty(); - - _cursor.short_vehicle_offset = v->IsGroundVehicle() ? 16 - v->GetGroundVehicleCache()->cached_veh_length * 2 : 0; - _cursor.vehchain = _ctrl_pressed; } } diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index 9207a18b72..d9b3ba3607 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -81,6 +81,9 @@ enum CallBackFunction { CBF_PLACE_LANDINFO, }; +static CallBackFunction _last_started_action = CBF_NONE; ///< Last started user action. + + /** * Drop down list entry for showing a checked/unchecked toggle item. */ @@ -254,7 +257,7 @@ static ToolbarMode _toolbar_mode; static CallBackFunction SelectSignTool() { - if (_cursor.sprite == SPR_CURSOR_SIGN) { + if (_last_started_action == CBF_PLACE_SIGN) { ResetObjectToPlace(); return CBF_NONE; } else { @@ -1044,7 +1047,7 @@ static CallBackFunction MenuClickNewspaper(int index) static CallBackFunction PlaceLandBlockInfo() { - if (_cursor.sprite == SPR_CURSOR_QUERY) { + if (_last_started_action == CBF_PLACE_LANDINFO) { ResetObjectToPlace(); return CBF_NONE; } else { @@ -1670,13 +1673,11 @@ enum MainToolbarHotkeys { /** Main toolbar. */ struct MainToolbarWindow : Window { - CallBackFunction last_started_action; ///< Last started user action. - MainToolbarWindow(WindowDesc *desc) : Window(desc) { this->InitNested(0); - this->last_started_action = CBF_NONE; + _last_started_action = CBF_NONE; CLRBITS(this->flags, WF_WHITE_BORDER); this->SetWidgetDisabledState(WID_TN_PAUSE, _networking && !_network_server); // if not server, disable pause button this->SetWidgetDisabledState(WID_TN_FAST_FORWARD, _networking); // if networking, disable fast-forward button @@ -1715,7 +1716,7 @@ struct MainToolbarWindow : Window { virtual void OnDropdownSelect(int widget, int index) { CallBackFunction cbf = _menu_clicked_procs[widget](index); - if (cbf != CBF_NONE) this->last_started_action = cbf; + if (cbf != CBF_NONE) _last_started_action = cbf; } virtual EventState OnHotkey(int hotkey) @@ -1769,7 +1770,7 @@ struct MainToolbarWindow : Window { virtual void OnPlaceObject(Point pt, TileIndex tile) { - switch (this->last_started_action) { + switch (_last_started_action) { case CBF_PLACE_SIGN: PlaceProc_Sign(tile); break; @@ -1782,6 +1783,11 @@ struct MainToolbarWindow : Window { } } + virtual void OnPlaceObjectAbort() + { + _last_started_action = CBF_NONE; + } + virtual void OnTick() { if (this->IsWidgetLowered(WID_TN_PAUSE) != !!_pause_mode) { @@ -1994,13 +2000,11 @@ enum MainToolbarEditorHotkeys { }; struct ScenarioEditorToolbarWindow : Window { - CallBackFunction last_started_action; ///< Last started user action. - ScenarioEditorToolbarWindow(WindowDesc *desc) : Window(desc) { this->InitNested(0); - this->last_started_action = CBF_NONE; + _last_started_action = CBF_NONE; CLRBITS(this->flags, WF_WHITE_BORDER); PositionMainToolbar(this); DoZoomInOutWindow(ZOOM_NONE, this); @@ -2059,7 +2063,7 @@ struct ScenarioEditorToolbarWindow : Window { { if (_game_mode == GM_MENU) return; CallBackFunction cbf = _scen_toolbar_button_procs[widget](this); - if (cbf != CBF_NONE) this->last_started_action = cbf; + if (cbf != CBF_NONE) _last_started_action = cbf; } virtual void OnDropdownSelect(int widget, int index) @@ -2068,7 +2072,7 @@ struct ScenarioEditorToolbarWindow : Window { * editor toolbar, so we need to adjust for it. */ if (widget == WID_TE_SMALL_MAP) widget = WID_TN_SMALL_MAP; CallBackFunction cbf = _menu_clicked_procs[widget](index); - if (cbf != CBF_NONE) this->last_started_action = cbf; + if (cbf != CBF_NONE) _last_started_action = cbf; if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); } @@ -2100,13 +2104,13 @@ struct ScenarioEditorToolbarWindow : Window { case MTEHK_EXTRA_VIEWPORT: ShowExtraViewPortWindowForTileUnderCursor(); break; default: return ES_NOT_HANDLED; } - if (cbf != CBF_NONE) this->last_started_action = cbf; + if (cbf != CBF_NONE) _last_started_action = cbf; return ES_HANDLED; } virtual void OnPlaceObject(Point pt, TileIndex tile) { - switch (this->last_started_action) { + switch (_last_started_action) { case CBF_PLACE_SIGN: PlaceProc_Sign(tile); break; @@ -2119,6 +2123,11 @@ struct ScenarioEditorToolbarWindow : Window { } } + virtual void OnPlaceObjectAbort() + { + _last_started_action = CBF_NONE; + } + virtual void OnTimeout() { this->SetWidgetsLoweredState(false, WID_TE_DATE_BACKWARD, WID_TE_DATE_FORWARD, WIDGET_LIST_END); diff --git a/src/train_gui.cpp b/src/train_gui.cpp index 55b26defa3..bafaf0296b 100644 --- a/src/train_gui.cpp +++ b/src/train_gui.cpp @@ -58,15 +58,16 @@ void CcBuildWagon(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p * @param px The current x position to draw from. * @param max_width The maximum space available to draw. * @param selection Selected vehicle that is dragged. + * @param chain Whether a whole chain is dragged. * @return The width of the highlight mark. */ -static int HighlightDragPosition(int px, int max_width, VehicleID selection) +static int HighlightDragPosition(int px, int max_width, VehicleID selection, bool chain) { bool rtl = _current_text_dir == TD_RTL; assert(selection != INVALID_VEHICLE); int dragged_width = WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT; - for (Train *t = Train::Get(selection); t != NULL; t = t->HasArticulatedPart() ? t->GetNextArticulatedPart() : NULL) { + for (Train *t = Train::Get(selection); t != NULL; t = chain ? t->Next() : (t->HasArticulatedPart() ? t->GetNextArticulatedPart() : NULL)) { dragged_width += t->GetDisplayImageWidth(NULL); } @@ -116,7 +117,7 @@ void DrawTrainImage(const Train *v, int left, int right, int y, VehicleID select for (; v != NULL && (rtl ? px > 0 : px < max_width); v = v->Next()) { if (dragging && !drag_at_end_of_train && drag_dest == v->index) { /* Highlight the drag-and-drop destination inside the train. */ - int drag_hlight_width = HighlightDragPosition(px, max_width, selection); + int drag_hlight_width = HighlightDragPosition(px, max_width, selection, _cursor.vehchain); px += rtl ? -drag_hlight_width : drag_hlight_width; } @@ -148,7 +149,7 @@ void DrawTrainImage(const Train *v, int left, int right, int y, VehicleID select if (dragging && drag_at_end_of_train) { /* Highlight the drag-and-drop destination at the end of the train. */ - HighlightDragPosition(px, max_width, selection); + HighlightDragPosition(px, max_width, selection, _cursor.vehchain); } if (highlight_l != highlight_r) { diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index b228a50700..7c9a9d0d2f 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -3186,35 +3186,74 @@ void CcBuildPrimaryVehicle(const CommandCost &result, TileIndex tile, uint32 p1, } /** - * Get the width of a vehicle (including all parts of the consist) in pixels. + * Get the width of a vehicle (part) in pixels. * @param v Vehicle to get the width for. * @return Width of the vehicle. */ -int GetVehicleWidth(Vehicle *v, EngineImageType image_type) +int GetSingleVehicleWidth(const Vehicle *v, EngineImageType image_type) { - int vehicle_width = 0; - switch (v->type) { case VEH_TRAIN: - for (const Train *u = Train::From(v); u != NULL; u = u->Next()) { - vehicle_width += u->GetDisplayImageWidth(); - } - break; + return Train::From(v)->GetDisplayImageWidth(); case VEH_ROAD: - for (const RoadVehicle *u = RoadVehicle::From(v); u != NULL; u = u->Next()) { - vehicle_width += u->GetDisplayImageWidth(); - } - break; + return RoadVehicle::From(v)->GetDisplayImageWidth(); default: bool rtl = _current_text_dir == TD_RTL; SpriteID sprite = v->GetImage(rtl ? DIR_E : DIR_W, image_type); const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL); - vehicle_width = UnScaleGUI(real_sprite->width); + return UnScaleGUI(real_sprite->width); + } +} - break; +/** + * Get the width of a vehicle (including all parts of the consist) in pixels. + * @param v Vehicle to get the width for. + * @return Width of the vehicle. + */ +int GetVehicleWidth(const Vehicle *v, EngineImageType image_type) +{ + if (v->type == VEH_TRAIN || v->type == VEH_ROAD) { + int vehicle_width = 0; + for (const Vehicle *u = v; u != NULL; u = u->Next()) { + vehicle_width += GetSingleVehicleWidth(u, image_type); + } + return vehicle_width; + } else { + return GetSingleVehicleWidth(v, image_type); + } +} + +/** + * Set the mouse cursor to look like a vehicle. + * @param v Vehicle + * @param image_type Type of vehicle image to use. + */ +void SetMouseCursorVehicle(const Vehicle *v, EngineImageType image_type) +{ + bool rtl = _current_text_dir == TD_RTL; + + _cursor.sprite_count = 0; + int total_width = 0; + for (; v != NULL; v = v->HasArticulatedPart() ? v->GetNextArticulatedPart() : NULL) { + if (_cursor.sprite_count == lengthof(_cursor.sprite_seq)) break; + if (total_width >= 2 * (int)VEHICLEINFO_FULL_VEHICLE_WIDTH) break; + + _cursor.sprite_seq[_cursor.sprite_count].sprite = v->GetImage(rtl ? DIR_E : DIR_W, image_type); + _cursor.sprite_seq[_cursor.sprite_count].pal = GetVehiclePalette(v); + _cursor.sprite_pos[_cursor.sprite_count].x = rtl ? -total_width : total_width; + _cursor.sprite_pos[_cursor.sprite_count].y = 0; + + total_width += GetSingleVehicleWidth(v, image_type); + _cursor.sprite_count++; } - return vehicle_width; + int offs = ((int)VEHICLEINFO_FULL_VEHICLE_WIDTH - total_width) / 2; + if (rtl) offs = -offs; + for (uint i = 0; i < _cursor.sprite_count; ++i) { + _cursor.sprite_pos[i].x += offs; + } + + UpdateCursorSize(); } diff --git a/src/vehicle_gui.h b/src/vehicle_gui.h index e7ca9cf20f..7d131c4dbc 100644 --- a/src/vehicle_gui.h +++ b/src/vehicle_gui.h @@ -65,7 +65,8 @@ static inline uint GetVehicleHeight(VehicleType type) return (type == VEH_TRAIN || type == VEH_ROAD) ? 14 : 24; } -int GetVehicleWidth(Vehicle *v, EngineImageType image_type); +int GetSingleVehicleWidth(const Vehicle *v, EngineImageType image_type); +int GetVehicleWidth(const Vehicle *v, EngineImageType image_type); /** Dimensions of a cell in the purchase/depot windows. */ struct VehicleCellSize { @@ -101,6 +102,7 @@ void StartStopVehicle(const Vehicle *v, bool texteffect); Vehicle *CheckClickOnVehicle(const struct ViewPort *vp, int x, int y); void DrawVehicleImage(const Vehicle *v, int left, int right, int y, VehicleID selection, EngineImageType image_type, int skip); +void SetMouseCursorVehicle(const Vehicle *v, EngineImageType image_type); /** * Tell if the focused window concerns the specified vehicle. diff --git a/src/window.cpp b/src/window.cpp index 0ab28f568e..cef824f20e 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -2845,7 +2845,6 @@ static void MouseLoop(MouseClick click, int mousewheel) if (HandleViewportDoubleClicked(w, x, y)) break; /* FALL THROUGH */ case MC_LEFT: - DEBUG(misc, 2, "Cursor: 0x%X (%d)", _cursor.sprite, _cursor.sprite); if (!HandleViewportClicked(vp, x, y, click == MC_DOUBLE_LEFT) && !(w->flags & WF_DISABLE_VP_SCROLL) && _settings_client.gui.left_mouse_btn_scrolling) {