openclonk/src/editor/C4ConsoleCocoa.mm

463 lines
12 KiB
Plaintext
Raw Normal View History

2010-12-27 03:49:02 +00:00
/*
* OpenClonk, http://www.openclonk.org
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
#include <C4Include.h>
#include <C4Console.h>
#include <C4Application.h>
#include <C4GameSave.h>
#include <C4Game.h>
#include <C4MessageInput.h>
#include <C4UserMessages.h>
#include <C4Version.h>
#include <C4Language.h>
#include <C4Player.h>
#include <C4Landscape.h>
#include <C4GraphicsSystem.h>
#include <C4PlayerList.h>
#include <C4GameControl.h>
#include <C4Texture.h>
#include <StdFile.h>
#include <StdRegistry.h>
#include <StdGL.h>
#import <Cocoa/Cocoa.h>
#import "ClonkAppDelegate.h"
#import "ConsoleWindowController.h"
#import "ClonkOpenGLView.h"
// implementation of C4Console GUI for Mac OS X
static inline ConsoleWindowController* ctrler(C4ConsoleGUI* gui) {return (ConsoleWindowController*)gui->GetController();}
2010-12-27 03:49:02 +00:00
class C4ConsoleGUI::State: public C4ConsoleGUI::InternalState<class C4ConsoleGUI>
{
public:
State(C4ConsoleGUI *console): Super(console) {}
};
class C4ToolsDlg::State: public C4ConsoleGUI::InternalState<class C4ToolsDlg>
{
public:
State(C4ToolsDlg *toolsDlg): Super(toolsDlg) {}
~State()
{
[ctrler(&Console).toolsPanel orderOut:nil];
}
CGImageRef CreatePreviewImage();
void Default() {}
void Clear() {}
};
CStdWindow* C4ConsoleGUI::CreateConsoleWindow(CStdApp *application)
{
ClonkWindowController* controller = [ConsoleWindowController new];
this->controller = controller;
[NSBundle loadNibNamed:@"ConsoleWindow" owner:controller];
[controller setStdWindow:this];
this->Active = true;
return this;
}
2011-01-04 15:27:38 +00:00
void C4ConsoleGUI::Out(const char* message)
2010-12-27 03:49:02 +00:00
{
ConsoleWindowController* controller;
if (controller = ctrler(this))
{
NSTextStorage* textStorage = controller.outputTextView.textStorage;
[textStorage appendAttributedString:[[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%s\n", message]] autorelease]];
[controller.outputTextView scrollRangeToVisible:NSMakeRange([textStorage length]-1, 1)];
}
}
bool C4ConsoleGUI::ClearLog()
{
[ctrler(this).outputTextView.textStorage
replaceCharactersInRange:NSMakeRange(0, ctrler(this).outputTextView.textStorage.length)
withAttributedString:[[NSAttributedString alloc] initWithString:@""]];
return true;
}
void C4ConsoleGUI::DisplayInfoText(C4ConsoleGUI::InfoTextType type, StdStrBuf& text)
{
NSTextField* label;
switch (type)
{
case CONSOLE_FrameCounter:
label = ctrler(this).frameLabel;
break;
case CONSOLE_ScriptCounter:
label = ctrler(this).scriptLabel;
break;
case CONSOLE_TimeFPS:
label = ctrler(this).timeLabel;
break;
case CONSOLE_Cursor:
return;
default:
return;
}
[label setStringValue:[NSString stringWithUTF8String:text.getData()]];
}
void C4ConsoleGUI::SetCaptionToFileName(const char* file_name)
{
[ctrler(this).window setRepresentedFilename:[NSString stringWithUTF8String:file_name]];
}
bool C4ConsoleGUI::FileSelect(StdStrBuf *sFilename, const char * szFilter, DWORD dwFlags, bool fSave)
2010-12-27 03:49:02 +00:00
{
NSSavePanel* savePanel = fSave ? [NSSavePanel savePanel] : [NSOpenPanel openPanel];
if (!fSave)
{
[(NSOpenPanel*)savePanel setCanChooseFiles:YES];
[(NSOpenPanel*)savePanel setCanChooseDirectories:YES];
}
if ([savePanel runModal] == NSFileHandlingPanelOKButton && [[savePanel URL] isFileURL])
{
sFilename->Copy([[savePanel URL].path cStringUsingEncoding:NSUTF8StringEncoding]);
2010-12-27 03:49:02 +00:00
return true;
}
else
return false;
}
void C4ConsoleGUI::AddMenuItemForPlayer(C4Player* player, StdStrBuf& player_text)
{
NSMenuItem* item = [
[ClonkAppDelegate instance].newViewportForPlayerMenuItem.submenu
addItemWithTitle:[NSString stringWithUTF8String:player_text.getData()] action:@selector(newViewportForPlayer:) keyEquivalent:@""
];
[item setTag:player->Number];
[item setTarget: ClonkAppDelegate.instance];
}
void C4ConsoleGUI::ClearViewportMenu()
{
[[ClonkAppDelegate instance].newViewportForPlayerMenuItem.submenu removeAllItems];
}
bool C4ConsoleGUI::Message(const char *message, bool query)
{
NSAlert* alert = [NSAlert
alertWithMessageText:[NSString stringWithUTF8String:C4ENGINECAPTION]
defaultButton:query ? @"Yes" : nil
alternateButton:query ? @"No" : nil
otherButton:nil
informativeTextWithFormat:[NSString stringWithUTF8String:message]
];
[alert runModal];
return true;
}
bool C4ConsoleGUI::PropertyDlgOpen()
2010-12-27 03:49:02 +00:00
{
[ctrler(this).objectsPanel orderFront:nil];
return true;
}
void C4ConsoleGUI::PropertyDlgClose()
2010-12-27 03:49:02 +00:00
{
[ctrler(this).objectsPanel orderOut:nil];
}
void C4ConsoleGUI::PropertyDlgUpdate(C4ObjectList &rSelection)
{
if (![ctrler(this).objectsPanel isVisible])
return;
StdStrBuf text = rSelection.GetDataString();
2010-12-27 03:49:02 +00:00
[ctrler(this).objectPropertiesText.textStorage setAttributedString:[[[NSAttributedString alloc] initWithString:[NSString stringWithUTF8String:text.getData()]] autorelease]];
}
void C4ConsoleGUI::ToolsDlgClose()
2010-12-27 03:49:02 +00:00
{
[ctrler(this).toolsPanel orderOut:nil];
2010-12-27 03:49:02 +00:00
}
bool C4ConsoleGUI::ToolsDlgOpen(C4ToolsDlg *dlg)
{
[ctrler(this).toolsPanel orderFront:nil];
return true;
}
void C4ConsoleGUI::ToolsDlgInitMaterialCtrls(class C4ToolsDlg *dlg)
{
NSPopUpButton* materialsPopup = ctrler(this).materialsPopup;
[materialsPopup removeAllItems];
[materialsPopup addItemWithTitle:[NSString stringWithUTF8String:C4TLS_MatSky]];
NSMutableArray* ary = [[NSMutableArray alloc] initWithCapacity:MaterialMap.Num+1];
[ary addObject:[NSString stringWithUTF8String:C4TLS_MatSky]];
for (int32_t cnt = 0; cnt < ::MaterialMap.Num; cnt++)
{
[ary addObject:[NSString stringWithUTF8String: ::MaterialMap.Map[cnt].Name]];
}
[ary sortUsingComparator:^(id a, id b) {return [a compare:b];}];
for (NSString* s in ary)
{
[materialsPopup addItemWithTitle:s];
}
[ary release];
[materialsPopup selectItemWithTitle:[NSString stringWithUTF8String:dlg->Material]];
}
void C4ToolsDlg::UpdateToolCtrls()
{
[ctrler(&Console).toolSelector setSelectedSegment:Tool];
}
void C4ToolsDlg::UpdateTextures()
{
// Refill dlg
NSPopUpButton* texturesPopup = ctrler(&Console).texturesPopup;
[texturesPopup removeAllItems];
// bottom-most: any invalid textures
bool fAnyEntry = false; int32_t cnt; const char *szTexture;
if (::Landscape.Mode!=C4LSC_Exact)
for (cnt=0; (szTexture=::TextureMap.GetTexture(cnt)); cnt++)
{
if (!::TextureMap.GetIndex(Material, szTexture, false))
{
fAnyEntry = true;
[texturesPopup insertItemWithTitle:[NSString stringWithUTF8String:szTexture] atIndex:0];
}
}
// separator
if (fAnyEntry)
{
[texturesPopup insertItemWithTitle:@"-------" atIndex:0];
}
// atop: valid textures
for (cnt=0; (szTexture=::TextureMap.GetTexture(cnt)); cnt++)
{
// Current material-texture valid? Always valid for exact mode
if (::TextureMap.GetIndex(Material,szTexture,false) || ::Landscape.Mode==C4LSC_Exact)
{
[texturesPopup insertItemWithTitle:[NSString stringWithUTF8String:szTexture] atIndex:0];
}
}
// reselect current
[texturesPopup selectItemWithTitle:[NSString stringWithUTF8String:Texture]];
}
void C4ConsoleGUI::ToolsDlgSetTexture(class C4ToolsDlg *dlg, const char *texture)
{
[ctrler(this).texturesPopup selectItemWithTitle:[NSString stringWithUTF8String:texture]];
}
void C4ToolsDlg::NeedPreviewUpdate()
{
CGImageRef image = state->CreatePreviewImage();
[ctrler(&Console).previewView setImage:image imageProperties:[NSDictionary dictionary]];
CGImageRelease(image);
}
namespace
{
// copy-pasta from http://stackoverflow.com/questions/2395650/fastest-way-to-draw-a-screen-buffer-on-the-iphone
const void* GetBytePointer(void* info)
{
// this is currently only called once
return info; // info is a pointer to the buffer
}
void ReleaseBytePointer(void*info, const void* pointer)
{
// don't care, just using the one static buffer at the moment
}
size_t GetBytesAtPosition(void* info, void* buffer, off_t position, size_t count)
{
// I don't think this ever gets called
memcpy(buffer, ((char*)info) + position, count);
return count;
}
}
CGImageRef C4ToolsDlg::State::CreatePreviewImage()
{
SURFACE sfcPreview;
int32_t iPrvWdt,iPrvHgt;
iPrvWdt = [ctrler(&Console).previewView frame].size.width;
iPrvHgt = [ctrler(&Console).previewView frame].size.height;
2010-12-27 03:49:02 +00:00
if (!(sfcPreview=new CSurface(iPrvWdt,iPrvHgt))) return NULL;
// fill bg
BYTE bCol = 0;
CPattern Pattern;
// Sky material: sky as pattern only
if (SEqual(GetOwner()->Material,C4TLS_MatSky))
{
Pattern.Set(::Landscape.Sky.Surface, 0);
}
// Material-Texture
else
{
bCol=Mat2PixColDefault(::MaterialMap.Get(GetOwner()->Material));
// Get/Create TexMap entry
BYTE iTex = ::TextureMap.GetIndex(GetOwner()->Material, GetOwner()->Texture, true);
if (iTex)
{
// Define texture pattern
const C4TexMapEntry *pTex = ::TextureMap.GetEntry(iTex);
// Security
if (pTex)
{
// Set drawing pattern
Pattern = pTex->GetPattern();
}
}
}
lpDDraw->DrawPatternedCircle(
sfcPreview,
iPrvWdt/2,iPrvHgt/2,
GetOwner()->Grade,
bCol, Pattern, *::Landscape.GetPal()
);
//Application.DDraw->AttachPrimaryPalette(sfcPreview);
DWORD *pixels = new DWORD[iPrvWdt*iPrvHgt];
for (int x = 0; x < iPrvWdt; x++) for (int y = 0; y < iPrvHgt; y++)
{
pixels[x+y*iPrvWdt] = sfcPreview->GetPixDw(x, y, true);
}
CGDataProviderDirectCallbacks callbacks = {0, ::GetBytePointer, ::ReleaseBytePointer, ::GetBytesAtPosition, 0};
CGDataProviderRef pixelData = CGDataProviderCreateDirect(pixels, iPrvWdt*iPrvHgt*sizeof(DWORD), &callbacks);
CGImageRef image = CGImageCreate(iPrvWdt, iPrvHgt, 8, 4*8, iPrvWdt*4, [[NSColorSpace deviceRGBColorSpace] CGColorSpace], kCGBitmapByteOrder32Little, pixelData, NULL, true, kCGRenderingIntentDefault);
CGDataProviderRelease(pixelData);
delete sfcPreview;
return image;
}
void C4ConsoleGUI::ToolsDlgSetMaterial(class C4ToolsDlg *dlg, const char *material)
{
[ctrler(this).texturesPopup selectItemWithTitle:[NSString stringWithUTF8String:material]];
}
void C4ToolsDlg::InitGradeCtrl()
{
}
bool C4ToolsDlg::PopMaterial()
{
return true;
}
void C4ConsoleGUI::ShowAboutWithCopyright(StdStrBuf &copyright)
{
StdStrBuf strMessage; strMessage.Format("%s %s\n\n%s", C4ENGINECAPTION, C4VERSION, copyright.getData());
Message(strMessage.getData(), false);
}
void C4ConsoleGUI::ToolsDlgSelectTexture(C4ToolsDlg *dlg, const char *texture)
{
[ctrler(this).texturesPopup selectItemWithTitle:[NSString stringWithUTF8String:texture]];
}
void C4ConsoleGUI::ToolsDlgSelectMaterial(C4ToolsDlg *dlg, const char *material)
{
[ctrler(this).materialsPopup selectItemWithTitle:[NSString stringWithUTF8String:material]];
}
void C4ToolsDlg::UpdateIFTControls()
{
}
void C4ConsoleGUI::SetCursor(C4ConsoleGUI::Cursor cursor)
{
}
void C4ConsoleGUI::RecordingEnabled()
{
[[[ClonkAppDelegate instance] recordMenuItem] setEnabled:NO];
}
2011-01-04 19:31:55 +00:00
void C4ConsoleGUI::AddNetMenu()
2010-12-27 03:49:02 +00:00
{
2011-01-04 19:31:55 +00:00
[ClonkAppDelegate.instance.netMenu setHidden:NO];
2010-12-27 03:49:02 +00:00
}
2011-01-04 19:31:55 +00:00
void C4ConsoleGUI::ClearNetMenu()
2010-12-27 03:49:02 +00:00
{
2011-01-04 19:31:55 +00:00
[ClonkAppDelegate.instance.netMenu setHidden:YES];
2010-12-27 03:49:02 +00:00
}
void C4ConsoleGUI::DoEnableControls(bool fEnable)
{
[ctrler(this).modeSelector setEnabled:fEnable];
2010-12-27 03:49:02 +00:00
}
bool C4ConsoleGUI::DoUpdateHaltCtrls(bool fHalt)
{
return true;
}
void C4ToolsDlg::EnableControls()
2010-12-27 03:49:02 +00:00
{
NeedPreviewUpdate();
2010-12-27 03:49:02 +00:00
}
void C4ConsoleGUI::ClearInput()
{
[ctrler(this).consoleCombo setStringValue:[NSString string]];
}
void C4ConsoleGUI::ClearPlayerMenu()
{
}
void C4ConsoleGUI::AddNetMenuItemForPlayer(int32_t index, StdStrBuf &text)
{
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[NSString stringWithCString:text.getData() encoding:NSUTF8StringEncoding] action:@selector(kickPlayer:) keyEquivalent:[NSString string]];
[item setTarget:ctrler(this)];
[ClonkAppDelegate.instance.netMenu.submenu addItem:item];
}
void C4ConsoleGUI::SetInputFunctions(std::list<char*> &functions)
2010-12-27 03:49:02 +00:00
{
}
void C4ConsoleGUI::AddKickPlayerMenuItem(C4Player *player, StdStrBuf& player_text, bool enabled)
{
NSMenuItem* item = [
[ClonkAppDelegate instance].kickPlayerMenuItem.submenu
addItemWithTitle:[NSString stringWithUTF8String:player_text.getData()] action:@selector(kickPlayer:) keyEquivalent:@""
];
[item setEnabled:enabled];
[item setTag:player->Number];
[item setTarget: ctrler(this)];
}
bool C4ToolsDlg::PopTextures()
{
return true;
}
void C4ToolsDlg::UpdateLandscapeModeCtrls()
{
}
bool C4ConsoleGUI::UpdateModeCtrls(int iMode)
{
return true;
}
#define CONSOLEGUICOMMONINCLUDE
#include "C4ConsoleGUICommon.h"