Feature: Add selected toolbar buttons to MacBook Pro Touch Bar

pull/332/head
Danny de Bruijne 3 years ago committed by Michael Lutz
parent 16aac9c341
commit 753b1d7e15

@ -1059,18 +1059,19 @@ void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub,
/**
* The code for setting up the blitter mode and sprite information before finally drawing the sprite.
* @param sprite The sprite to draw.
* @param x The X location to draw.
* @param y The Y location to draw.
* @param mode The settings for the blitter to pass.
* @param sub Whether to only draw a sub set of the sprite.
* @param zoom The zoom level at which to draw the sprites.
* @param x The X location to draw.
* @param y The Y location to draw.
* @param mode The settings for the blitter to pass.
* @param sub Whether to only draw a sub set of the sprite.
* @param zoom The zoom level at which to draw the sprites.
* @param dst Optional parameter for a different blitting destination.
* @tparam ZOOM_BASE The factor required to get the sub sprite information into the right size.
* @tparam SCALED_XY Whether the X and Y are scaled or unscaled.
*/
template <int ZOOM_BASE, bool SCALED_XY>
static void GfxBlitter(const Sprite * const sprite, int x, int y, BlitterMode mode, const SubSprite * const sub, SpriteID sprite_id, ZoomLevel zoom)
static void GfxBlitter(const Sprite * const sprite, int x, int y, BlitterMode mode, const SubSprite * const sub, SpriteID sprite_id, ZoomLevel zoom, const DrawPixelInfo *dst = nullptr)
{
const DrawPixelInfo *dpi = _cur_dpi;
const DrawPixelInfo *dpi = (dst != nullptr) ? dst : _cur_dpi;
Blitter::BlitterParams bp;
if (SCALED_XY) {
@ -1185,6 +1186,47 @@ static void GfxBlitter(const Sprite * const sprite, int x, int y, BlitterMode mo
BlitterFactory::GetCurrentBlitter()->Draw(&bp, mode, zoom);
}
/**
* Draws a sprite to a new RGBA buffer (see Colour union) instead of drawing to the screen.
*
* @param spriteId The sprite to draw.
* @return Pixel buffer, or nullptr if an 8bpp blitter is being used.
*/
std::unique_ptr<uint32[]> DrawSpriteToRgbaBuffer(SpriteID spriteId)
{
Blitter *blitter = BlitterFactory::GetCurrentBlitter();
if (!blitter->Is32BppSupported()) return nullptr;
/* Gather information about the sprite to write, reserve memory */
const SpriteID real_sprite = GB(spriteId, 0, SPRITE_WIDTH);
const Sprite *sprite = GetSprite(real_sprite, ST_NORMAL);
std::unique_ptr<uint32[]> result(new uint32[sprite->width * sprite->height]);
/* Prepare new DrawPixelInfo - Normally this would be the screen but we want to draw to another buffer here.
* Normally, pitch would be scaled screen width, but in our case our "screen" is only the sprite width wide. */
DrawPixelInfo dpi;
dpi.dst_ptr = result.get();
dpi.pitch = sprite->width;
dpi.left = 0;
dpi.top = 0;
dpi.width = sprite->width;
dpi.height = sprite->height;
dpi.zoom = ZOOM_LVL_NORMAL;
/* Zero out the allocated memory, there may be garbage present. */
uint32 *writeHead = (uint32*)result.get();
for (int i = 0; i < sprite->width * sprite->height; i++) {
writeHead[i] = 0;
}
/* Temporarily disable screen animations while blitting - This prevents 40bpp_anim from writing to the animation buffer. */
_screen_disable_anim = true;
GfxBlitter<1, false>(sprite, 0, 0, BM_NORMAL, nullptr, real_sprite, ZOOM_LVL_NORMAL, &dpi);
_screen_disable_anim = false;
return result;
}
static void GfxMainBlitterViewport(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub, SpriteID sprite_id)
{
GfxBlitter<ZOOM_LVL_BASE, false>(sprite, x, y, mode, sub, sprite_id, _cur_dpi->zoom);

@ -68,6 +68,7 @@ extern std::vector<Dimension> _resolutions;
extern Dimension _cur_resolution;
extern Palette _cur_palette; ///< Current palette
void HandleToolbarHotkey(int hotkey);
void HandleKeypress(uint keycode, WChar key);
void HandleTextInput(const char *str, bool marked = false, const char *caret = nullptr, const char *insert_location = nullptr, const char *replacement_end = nullptr);
void HandleCtrlChanged();
@ -90,6 +91,7 @@ void GfxScroll(int left, int top, int width, int height, int xo, int yo);
Dimension GetSpriteSize(SpriteID sprid, Point *offset = nullptr, ZoomLevel zoom = ZOOM_LVL_GUI);
void DrawSpriteViewport(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub = nullptr);
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub = nullptr, ZoomLevel zoom = ZOOM_LVL_GUI);
std::unique_ptr<uint32[]> DrawSpriteToRgbaBuffer(SpriteID spriteId);
int DrawString(int left, int right, int top, const char *str, TextColour colour = TC_FROMSTRING, StringAlignment align = SA_LEFT, bool underline = false, FontSize fontsize = FS_NORMAL);
int DrawString(int left, int right, int top, const std::string &str, TextColour colour = TC_FROMSTRING, StringAlignment align = SA_LEFT, bool underline = false, FontSize fontsize = FS_NORMAL);

@ -30,6 +30,10 @@
#define HAVE_OSX_1012_SDK
#endif
#ifdef MAC_OS_X_VERSION_10_15
#define HAVE_OSX_1015_SDK
#endif
/* It would seem that to ensure backward compatibility we have to ensure that we have defined MAC_OS_X_VERSION_10_x everywhere */
#ifndef MAC_OS_X_VERSION_10_3
#define MAC_OS_X_VERSION_10_3 1030

@ -1944,49 +1944,6 @@ static ToolbarButtonProc * const _toolbar_button_procs[] = {
ToolbarSwitchClick,
};
enum MainToolbarHotkeys {
MTHK_PAUSE,
MTHK_FASTFORWARD,
MTHK_SETTINGS,
MTHK_SAVEGAME,
MTHK_LOADGAME,
MTHK_SMALLMAP,
MTHK_TOWNDIRECTORY,
MTHK_SUBSIDIES,
MTHK_STATIONS,
MTHK_FINANCES,
MTHK_COMPANIES,
MTHK_STORY,
MTHK_GOAL,
MTHK_GRAPHS,
MTHK_LEAGUE,
MTHK_INDUSTRIES,
MTHK_TRAIN_LIST,
MTHK_ROADVEH_LIST,
MTHK_SHIP_LIST,
MTHK_AIRCRAFT_LIST,
MTHK_ZOOM_IN,
MTHK_ZOOM_OUT,
MTHK_BUILD_RAIL,
MTHK_BUILD_ROAD,
MTHK_BUILD_TRAM,
MTHK_BUILD_DOCKS,
MTHK_BUILD_AIRPORT,
MTHK_BUILD_TREES,
MTHK_MUSIC,
MTHK_LANDINFO,
MTHK_AI_DEBUG,
MTHK_SMALL_SCREENSHOT,
MTHK_ZOOMEDIN_SCREENSHOT,
MTHK_DEFAULTZOOM_SCREENSHOT,
MTHK_GIANT_SCREENSHOT,
MTHK_CHEATS,
MTHK_TERRAFORM,
MTHK_EXTRA_VIEWPORT,
MTHK_CLIENT_LIST,
MTHK_SIGN_LIST,
};
/** Main toolbar. */
struct MainToolbarWindow : Window {
GUITimer timer;

@ -10,6 +10,49 @@
#ifndef TOOLBAR_GUI_H
#define TOOLBAR_GUI_H
enum MainToolbarHotkeys {
MTHK_PAUSE,
MTHK_FASTFORWARD,
MTHK_SETTINGS,
MTHK_SAVEGAME,
MTHK_LOADGAME,
MTHK_SMALLMAP,
MTHK_TOWNDIRECTORY,
MTHK_SUBSIDIES,
MTHK_STATIONS,
MTHK_FINANCES,
MTHK_COMPANIES,
MTHK_STORY,
MTHK_GOAL,
MTHK_GRAPHS,
MTHK_LEAGUE,
MTHK_INDUSTRIES,
MTHK_TRAIN_LIST,
MTHK_ROADVEH_LIST,
MTHK_SHIP_LIST,
MTHK_AIRCRAFT_LIST,
MTHK_ZOOM_IN,
MTHK_ZOOM_OUT,
MTHK_BUILD_RAIL,
MTHK_BUILD_ROAD,
MTHK_BUILD_TRAM,
MTHK_BUILD_DOCKS,
MTHK_BUILD_AIRPORT,
MTHK_BUILD_TREES,
MTHK_MUSIC,
MTHK_LANDINFO,
MTHK_AI_DEBUG,
MTHK_SMALL_SCREENSHOT,
MTHK_ZOOMEDIN_SCREENSHOT,
MTHK_DEFAULTZOOM_SCREENSHOT,
MTHK_GIANT_SCREENSHOT,
MTHK_CHEATS,
MTHK_TERRAFORM,
MTHK_EXTRA_VIEWPORT,
MTHK_CLIENT_LIST,
MTHK_SIGN_LIST
};
void AllocateToolbar();
void ToggleBoundingBoxes();
void ToggleDirtyBlocks();

@ -11,6 +11,8 @@
#define COCOA_WND_H
#import <Cocoa/Cocoa.h>
#include "toolbar_gui.h"
#include "table/sprites.h"
class VideoDriver_Cocoa;
@ -28,8 +30,67 @@ extern NSString *OTTDMainLaunchGameEngine;
+ (NSCursor *) clearCocoaCursor;
@end
#ifdef HAVE_OSX_1015_SDK
/* 9 items can be displayed on the touch bar when using default buttons. */
static NSArray *touchBarButtonIdentifiers = @[
@"openttd.pause",
@"openttd.fastforward",
@"openttd.zoom_in",
@"openttd.zoom_out",
@"openttd.build_rail",
@"openttd.build_road",
@"openttd.build_tram",
@"openttd.build_docks",
@"openttd.build_airport",
NSTouchBarItemIdentifierOtherItemsProxy
];
static NSDictionary *touchBarButtonSprites = @{
@"openttd.pause": [NSNumber numberWithInt:SPR_IMG_PAUSE],
@"openttd.fastforward": [NSNumber numberWithInt:SPR_IMG_FASTFORWARD],
@"openttd.zoom_in": [NSNumber numberWithInt:SPR_IMG_ZOOMIN],
@"openttd.zoom_out": [NSNumber numberWithInt:SPR_IMG_ZOOMOUT],
@"openttd.build_rail": [NSNumber numberWithInt:SPR_IMG_BUILDRAIL],
@"openttd.build_road": [NSNumber numberWithInt:SPR_IMG_BUILDROAD],
@"openttd.build_tram": [NSNumber numberWithInt:SPR_IMG_BUILDTRAMS],
@"openttd.build_docks": [NSNumber numberWithInt:SPR_IMG_BUILDWATER],
@"openttd.build_airport": [NSNumber numberWithInt:SPR_IMG_BUILDAIR],
};
static NSDictionary *touchBarButtonActions = @{
@"openttd.pause": [NSNumber numberWithInt:MTHK_PAUSE],
@"openttd.fastforward": [NSNumber numberWithInt:MTHK_FASTFORWARD],
@"openttd.zoom_in": [NSNumber numberWithInt:MTHK_ZOOM_IN],
@"openttd.zoom_out": [NSNumber numberWithInt:MTHK_ZOOM_OUT],
@"openttd.build_rail": [NSNumber numberWithInt:MTHK_BUILD_RAIL],
@"openttd.build_road": [NSNumber numberWithInt:MTHK_BUILD_ROAD],
@"openttd.build_tram": [NSNumber numberWithInt:MTHK_BUILD_TRAM],
@"openttd.build_docks": [NSNumber numberWithInt:MTHK_BUILD_DOCKS],
@"openttd.build_airport": [NSNumber numberWithInt:MTHK_BUILD_AIRPORT],
};
static NSDictionary *touchBarFallbackText = @{
@"openttd.pause": @"Pause",
@"openttd.fastforward": @"Fast Forward",
@"openttd.zoom_in": @"Zoom In",
@"openttd.zoom_out": @"Zoom Out",
@"openttd.build_rail": @"Rail",
@"openttd.build_road": @"Road",
@"openttd.build_tram": @"Tram",
@"openttd.build_docks": @"Docks",
@"openttd.build_airport": @"Airport",
};
#endif
/** Subclass of NSWindow to cater our special needs */
#ifdef HAVE_OSX_1015_SDK
@interface OTTD_CocoaWindow : NSWindow <NSTouchBarDelegate>
@property (strong) NSSet *touchbarItems;
- (NSImage*)generateImage:(int)spriteId;
#else
@interface OTTD_CocoaWindow : NSWindow
#endif
- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag driver:(VideoDriver_Cocoa *)drv;
- (void)setFrame:(NSRect)frameRect display:(BOOL)flag;

@ -32,7 +32,7 @@
#include "../../gfx_func.h"
#include "../../window_func.h"
#include "../../window_gui.h"
#include "spritecache.h"
/* Table data for key mapping. */
#include "cocoa_keys.h"
@ -405,6 +405,87 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel
return self;
}
#ifdef HAVE_OSX_1015_SDK
- (void)touchBarButtonAction:(id)sender
{
if (@available(macOS 10.15, *)) {
NSButtonTouchBarItem *btn = (NSButtonTouchBarItem *)sender;
NSNumber *hotkeyIndex = [ touchBarButtonActions objectForKey:btn.identifier ];
HandleToolbarHotkey(hotkeyIndex.intValue);
}
}
#pragma mark NSTouchBarProvider
- (nullable NSTouchBar *)makeTouchBar
{
NSTouchBar *bar = [ [ NSTouchBar alloc ] init ];
bar.delegate = self;
bar.defaultItemIdentifiers = touchBarButtonIdentifiers;
return bar;
}
-(NSImage *)generateImage:(int)spriteId
{
if (!SpriteExists(spriteId)) {
return nullptr;
}
/* Fetch the sprite and create a new bitmap */
const Sprite *fullspr = GetSprite(spriteId, ST_NORMAL);
const std::unique_ptr<uint32[]> buffer = DrawSpriteToRgbaBuffer(spriteId);
if (!buffer) {
return nullptr; // failed to blit sprite or we're using an 8bpp blitter.
}
NSBitmapImageRep *bitmap = [ [ NSBitmapImageRep alloc ] initWithBitmapDataPlanes:nil pixelsWide:fullspr->width pixelsHigh:fullspr->height bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES isPlanar:NO colorSpaceName:NSCalibratedRGBColorSpace bytesPerRow:0 bitsPerPixel:0 ];
/* Copy the sprite to the NSBitmapImageRep image buffer */
const Colour *src = (const Colour *)buffer.get();
for (int y = 0; y < fullspr->height; y++) {
for (int x = 0; x < fullspr->width; x++) {
NSUInteger pixel[4];
pixel[0] = src->r;
pixel[1] = src->g;
pixel[2] = src->b;
pixel[3] = src->a;
[ bitmap setPixel:pixel atX:x y:y ];
src += 1;
}
}
/* Finally, convert the NSBitmapImageRep we created to a NSimage we can put on the button and clean up. */
NSImage *outImage = [ [ NSImage alloc ] initWithSize:NSMakeSize(fullspr->width, fullspr->height) ];
[ outImage addRepresentation:bitmap ];
[ bitmap release ];
return outImage;
}
#pragma mark NSTouchBarDelegate
- (nullable NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier
{
if (@available(macOS 10.15, *)) {
NSButtonTouchBarItem *button = [ [ NSButtonTouchBarItem alloc ] initWithIdentifier:identifier ];
button.target = self;
button.action = @selector(touchBarButtonAction:);
NSNumber *num = touchBarButtonSprites[identifier];
NSImage *generatedImage = [ self generateImage:num.unsignedIntValue ];
if (generatedImage != nullptr) {
button.image = generatedImage;
} else {
button.title = NSLocalizedString(touchBarFallbackText[identifier], @"");
}
return button;
} else {
return nullptr;
}
}
#endif
/**
* Define the rectangle we draw our window in
*/

@ -2586,6 +2586,22 @@ EventState Window::HandleEditBoxKey(int wid, WChar key, uint16 keycode)
return ES_HANDLED;
}
/**
* Handle Toolbar hotkey events - can come from a source like the MacBook Touch Bar.
* @param hotkey Hotkey code
*/
void HandleToolbarHotkey(int hotkey)
{
assert(HasModalProgress() || IsLocalCompany());
Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0);
if (w != nullptr) {
if (w->window_desc->hotkeys != nullptr) {
if (hotkey >= 0 && w->OnHotkey(hotkey) == ES_HANDLED) return;
}
}
}
/**
* Handle keyboard input.
* @param keycode Virtual keycode of the key.

Loading…
Cancel
Save