Added native Cocoa back-end implementation

This commit is contained in:
alexey.lysiuk 2014-08-03 12:36:02 +03:00
parent fecd1b6401
commit e12f860f1b
6 changed files with 3632 additions and 0 deletions

1744
src/cocoa/i_backend_cocoa.mm Normal file

File diff suppressed because it is too large Load Diff

776
src/cocoa/i_joystick.cpp Normal file
View File

@ -0,0 +1,776 @@
/*
** i_joystick.cpp
**
**---------------------------------------------------------------------------
** Copyright 2012-2014 Alexey Lysiuk
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include "m_joy.h"
#include "HID_Utilities_External.h"
#include "d_event.h"
#include "doomdef.h"
#include "templates.h"
namespace
{
FString ToFString( const CFStringRef string )
{
if ( NULL == string )
{
return FString();
}
const CFIndex stringLength = CFStringGetLength( string );
if ( 0 == stringLength )
{
return FString();
}
const size_t bufferSize = CFStringGetMaximumSizeForEncoding( stringLength, kCFStringEncodingUTF8 ) + 1;
char buffer[ bufferSize ];
memset( buffer, 0, bufferSize );
CFStringGetCString( string, buffer, bufferSize, kCFStringEncodingUTF8 );
return FString( buffer );
}
class IOKitJoystick : public IJoystickConfig
{
public:
explicit IOKitJoystick( IOHIDDeviceRef device );
virtual ~IOKitJoystick();
virtual FString GetName();
virtual float GetSensitivity();
virtual void SetSensitivity( float scale );
virtual int GetNumAxes();
virtual float GetAxisDeadZone( int axis );
virtual EJoyAxis GetAxisMap( int axis );
virtual const char* GetAxisName( int axis );
virtual float GetAxisScale( int axis );
virtual void SetAxisDeadZone( int axis, float deadZone );
virtual void SetAxisMap( int axis, EJoyAxis gameAxis );
virtual void SetAxisScale( int axis, float scale );
virtual bool IsSensitivityDefault();
virtual bool IsAxisDeadZoneDefault( int axis );
virtual bool IsAxisMapDefault( int axis );
virtual bool IsAxisScaleDefault( int axis );
virtual void SetDefaultConfig();
virtual FString GetIdentifier();
void AddAxes( float axes[ NUM_JOYAXIS ] ) const;
void Update();
private:
IOHIDDeviceRef m_device;
float m_sensitivity;
struct AxisInfo
{
char name[ 64 ];
float value;
float deadZone;
float defaultDeadZone;
float sensitivity;
float defaultSensitivity;
EJoyAxis gameAxis;
EJoyAxis defaultGameAxis;
IOHIDElementRef element;
};
TArray< AxisInfo > m_axes;
TArray< IOHIDElementRef > m_buttons;
TArray< IOHIDElementRef > m_POVs;
static const float DEFAULT_DEADZONE;
static const float DEFAULT_SENSITIVITY;
bool ProcessAxis ( const IOHIDValueRef value );
bool ProcessButton( const IOHIDValueRef value );
bool ProcessPOV ( const IOHIDValueRef value );
};
const float IOKitJoystick::DEFAULT_DEADZONE = 0.25f;
const float IOKitJoystick::DEFAULT_SENSITIVITY = 1.0f;
IOKitJoystick::IOKitJoystick( IOHIDDeviceRef device )
: m_device( device )
, m_sensitivity( DEFAULT_SENSITIVITY )
{
IOHIDElementRef element = HIDGetFirstDeviceElement( device, kHIDElementTypeInput );
while ( NULL != element )
{
const uint32_t usagePage = IOHIDElementGetUsagePage( element );
if ( kHIDPage_GenericDesktop == usagePage )
{
const uint32_t usage = IOHIDElementGetUsage( element );
if ( kHIDUsage_GD_Slider == usage
|| kHIDUsage_GD_X == usage || kHIDUsage_GD_Y == usage || kHIDUsage_GD_Z == usage
|| kHIDUsage_GD_Rx == usage || kHIDUsage_GD_Ry == usage || kHIDUsage_GD_Rz == usage )
{
AxisInfo axis;
memset( &axis, 0, sizeof( axis ) );
if ( const CFStringRef name = IOHIDElementGetName( element ) )
{
CFStringGetCString( name, axis.name, sizeof( axis.name ) - 1, kCFStringEncodingUTF8 );
}
else
{
snprintf( axis.name, sizeof( axis.name ), "Axis %i", m_axes.Size() + 1 );
}
axis.element = element;
m_axes.Push( axis );
IOHIDElement_SetCalibrationMin( element, -1 );
IOHIDElement_SetCalibrationMax( element, 1 );
HIDQueueElement( m_device, element );
}
else if ( kHIDUsage_GD_Hatswitch == usage && m_POVs.Size() < 4 )
{
m_POVs.Push( element );
HIDQueueElement( m_device, element );
}
}
else if ( kHIDPage_Button == usagePage )
{
m_buttons.Push( element );
HIDQueueElement( m_device, element );
}
element = HIDGetNextDeviceElement( element, kHIDElementTypeInput );
}
SetDefaultConfig();
}
IOKitJoystick::~IOKitJoystick()
{
M_SaveJoystickConfig( this );
}
FString IOKitJoystick::GetName()
{
FString result;
result += ToFString( IOHIDDevice_GetManufacturer( m_device ) );
result += " ";
result += ToFString( IOHIDDevice_GetProduct( m_device ) );
return result;
}
float IOKitJoystick::GetSensitivity()
{
return m_sensitivity;
}
void IOKitJoystick::SetSensitivity( float scale )
{
m_sensitivity = scale;
}
int IOKitJoystick::GetNumAxes()
{
return static_cast< int >( m_axes.Size() );
}
#define IS_AXIS_VALID ( static_cast< unsigned int >( axis ) < m_axes.Size() )
float IOKitJoystick::GetAxisDeadZone( int axis )
{
return IS_AXIS_VALID ? m_axes[ axis ].deadZone : 0.0f;
}
EJoyAxis IOKitJoystick::GetAxisMap( int axis )
{
return IS_AXIS_VALID ? m_axes[ axis ].gameAxis : JOYAXIS_None;
}
const char* IOKitJoystick::GetAxisName( int axis )
{
return IS_AXIS_VALID ? m_axes[ axis ].name : "Invalid";
}
float IOKitJoystick::GetAxisScale( int axis )
{
return IS_AXIS_VALID ? m_axes[ axis ].sensitivity : 0.0f;
}
void IOKitJoystick::SetAxisDeadZone( int axis, float deadZone )
{
if ( IS_AXIS_VALID )
{
m_axes[ axis ].deadZone = clamp( deadZone, 0.0f, 1.0f );
}
}
void IOKitJoystick::SetAxisMap( int axis, EJoyAxis gameAxis )
{
if ( IS_AXIS_VALID )
{
m_axes[ axis ].gameAxis = ( gameAxis > JOYAXIS_None && gameAxis < NUM_JOYAXIS )
? gameAxis
: JOYAXIS_None;
}
}
void IOKitJoystick::SetAxisScale( int axis, float scale )
{
if ( IS_AXIS_VALID )
{
m_axes[ axis ].sensitivity = scale;
}
}
bool IOKitJoystick::IsSensitivityDefault()
{
return DEFAULT_SENSITIVITY == m_sensitivity;
}
bool IOKitJoystick::IsAxisDeadZoneDefault( int axis )
{
return IS_AXIS_VALID
? ( m_axes[ axis ].deadZone == m_axes[ axis ].defaultDeadZone )
: true;
}
bool IOKitJoystick::IsAxisMapDefault( int axis )
{
return IS_AXIS_VALID
? ( m_axes[ axis ].gameAxis == m_axes[ axis ].defaultGameAxis )
: true;
}
bool IOKitJoystick::IsAxisScaleDefault( int axis )
{
return IS_AXIS_VALID
? ( m_axes[ axis ].sensitivity == m_axes[ axis ].defaultSensitivity )
: true;
}
#undef IS_AXIS_VALID
void IOKitJoystick::SetDefaultConfig()
{
m_sensitivity = DEFAULT_SENSITIVITY;
const size_t axisCount = m_axes.Size();
for ( size_t i = 0; i < axisCount; ++i )
{
m_axes[i].deadZone = DEFAULT_DEADZONE;
m_axes[i].sensitivity = DEFAULT_SENSITIVITY;
m_axes[i].gameAxis = JOYAXIS_None;
}
// Two axes? Horizontal is yaw and vertical is forward.
if ( 2 == axisCount)
{
m_axes[0].gameAxis = JOYAXIS_Yaw;
m_axes[1].gameAxis = JOYAXIS_Forward;
}
// Three axes? First two are movement, third is yaw.
else if ( axisCount >= 3 )
{
m_axes[0].gameAxis = JOYAXIS_Side;
m_axes[1].gameAxis = JOYAXIS_Forward;
m_axes[2].gameAxis = JOYAXIS_Yaw;
// Four axes? First two are movement, last two are looking around.
if ( axisCount >= 4 )
{
m_axes[3].gameAxis = JOYAXIS_Pitch;
// ??? m_axes[3].sensitivity = 0.75f;
// Five axes? Use the fifth one for moving up and down.
if ( axisCount >= 5 )
{
m_axes[4].gameAxis = JOYAXIS_Up;
}
}
}
// If there is only one axis, then we make no assumptions about how
// the user might want to use it.
// Preserve defaults for config saving.
for ( size_t i = 0; i < axisCount; ++i )
{
m_axes[i].defaultDeadZone = m_axes[i].deadZone;
m_axes[i].defaultSensitivity = m_axes[i].sensitivity;
m_axes[i].defaultGameAxis = m_axes[i].gameAxis;
}
}
FString IOKitJoystick::GetIdentifier()
{
char identifier[ 32 ] = {0};
snprintf( identifier, sizeof( identifier ), "VID_%04lx_PID_%04lx",
IOHIDDevice_GetVendorID( m_device ), IOHIDDevice_GetProductID( m_device ) );
return FString( identifier );
}
void IOKitJoystick::AddAxes( float axes[ NUM_JOYAXIS ] ) const
{
for ( size_t i = 0, count = m_axes.Size(); i < count; ++i )
{
const EJoyAxis axis = m_axes[i].gameAxis;
if ( JOYAXIS_None == axis )
{
continue;
}
axes[ axis ] -= m_axes[i].value;
}
}
void IOKitJoystick::Update()
{
IOHIDValueRef value = NULL;
while ( HIDGetEvent( m_device, &value ) && NULL != value )
{
ProcessAxis( value ) || ProcessButton( value ) || ProcessPOV( value );
CFRelease( value );
}
}
bool IOKitJoystick::ProcessAxis( const IOHIDValueRef value )
{
const IOHIDElementRef element = IOHIDValueGetElement( value );
if ( NULL == element )
{
return false;
}
for ( size_t i = 0, count = m_axes.Size(); i < count; ++i )
{
if ( element != m_axes[i].element )
{
continue;
}
AxisInfo& axis = m_axes[i];
const double scaledValue = IOHIDValueGetScaledValue( value, kIOHIDValueScaleTypeCalibrated );
const double filteredValue = Joy_RemoveDeadZone( scaledValue, axis.deadZone, NULL );
axis.value = static_cast< float >( filteredValue * m_sensitivity * axis.sensitivity );
return true;
}
return false;
}
bool IOKitJoystick::ProcessButton( const IOHIDValueRef value )
{
const IOHIDElementRef element = IOHIDValueGetElement( value );
if ( NULL == element )
{
return false;
}
for ( size_t i = 0, count = m_buttons.Size(); i < count; ++i )
{
if ( element != m_buttons[i] )
{
continue;
}
const int newButton = IOHIDValueGetIntegerValue( value ) & 1;
const int oldButton = ~newButton;
Joy_GenerateButtonEvents( oldButton, newButton, 1,
static_cast< int >( KEY_FIRSTJOYBUTTON + i ) );
return true;
}
return false;
}
bool IOKitJoystick::ProcessPOV( const IOHIDValueRef value )
{
const IOHIDElementRef element = IOHIDValueGetElement( value );
if ( NULL == element )
{
return false;
}
for ( size_t i = 0, count = m_POVs.Size(); i < count; ++i )
{
if ( element != m_POVs[i] )
{
continue;
}
const CFIndex direction = IOHIDValueGetIntegerValue( value );
// Default values is for Up/North
int oldButtons = 0;
int newButtons = 1;
int numButtons = 1;
int baseButton = KEY_JOYPOV1_UP;
switch ( direction )
{
case 0: // N
break;
case 1: // NE
newButtons = 3;
numButtons = 2;
break;
case 2: // E
baseButton = KEY_JOYPOV1_RIGHT;
break;
case 3: // SE
newButtons = 3;
numButtons = 2;
baseButton = KEY_JOYPOV1_RIGHT;
break;
case 4: // S
baseButton = KEY_JOYPOV1_DOWN;
break;
case 5: // SW
newButtons = 3;
numButtons = 2;
baseButton = KEY_JOYPOV1_DOWN;
break;
case 6: // W
baseButton = KEY_JOYPOV1_LEFT;
break;
case 7: // NW
newButtons = 9; // UP and LEFT
numButtons = 4;
break;
default:
// release all four directions
oldButtons = 15;
newButtons = 0;
numButtons = 4;
break;
}
Joy_GenerateButtonEvents( oldButtons, newButtons, numButtons,
static_cast< int >( baseButton + i * 4 ) );
}
return false;
}
// ---------------------------------------------------------------------------
class IOKitJoystickManager
{
public:
IOKitJoystickManager();
~IOKitJoystickManager();
void GetJoysticks( TArray< IJoystickConfig* >& joysticks ) const;
void AddAxes( float axes[ NUM_JOYAXIS ] ) const;
// Updates axes/buttons states
void Update();
// Rebuilds device list
void Rescan();
private:
TArray< IOKitJoystick* > m_joysticks;
static void OnDeviceChanged( void* context, IOReturn result, void* sender, IOHIDDeviceRef device );
void ReleaseJoysticks();
void EnableCallbacks();
void DisableCallbacks();
};
IOKitJoystickManager::IOKitJoystickManager()
{
Rescan();
}
IOKitJoystickManager::~IOKitJoystickManager()
{
ReleaseJoysticks();
DisableCallbacks();
HIDReleaseDeviceList();
}
void IOKitJoystickManager::GetJoysticks( TArray< IJoystickConfig* >& joysticks ) const
{
const size_t joystickCount = m_joysticks.Size();
joysticks.Resize( joystickCount );
for ( size_t i = 0; i < joystickCount; ++i )
{
M_LoadJoystickConfig( m_joysticks[i] );
joysticks[i] = m_joysticks[i];
}
}
void IOKitJoystickManager::AddAxes( float axes[ NUM_JOYAXIS ] ) const
{
for ( size_t i = 0, count = m_joysticks.Size(); i < count; ++i )
{
m_joysticks[i]->AddAxes( axes );
}
}
void IOKitJoystickManager::Update()
{
for ( size_t i = 0, count = m_joysticks.Size(); i < count; ++i )
{
m_joysticks[i]->Update();
}
}
void IOKitJoystickManager::Rescan()
{
ReleaseJoysticks();
DisableCallbacks();
const int usageCount = 2;
const UInt32 usagePages[ usageCount ] =
{
kHIDPage_GenericDesktop,
kHIDPage_GenericDesktop
};
const UInt32 usages[ usageCount ] =
{
kHIDUsage_GD_Joystick,
kHIDUsage_GD_GamePad
};
if ( HIDUpdateDeviceList( usagePages, usages, usageCount ) )
{
IOHIDDeviceRef device = HIDGetFirstDevice();
while ( NULL != device )
{
IOKitJoystick* joystick = new IOKitJoystick( device );
m_joysticks.Push( joystick );
device = HIDGetNextDevice( device );
}
}
else
{
Printf( "IOKitJoystickManager: Failed to build gamepad/joystick device list.\n" );
}
EnableCallbacks();
}
void IOKitJoystickManager::OnDeviceChanged( void* context, IOReturn result, void* sender, IOHIDDeviceRef device )
{
event_t event;
memset( &event, 0, sizeof( event ) );
event.type = EV_DeviceChange;
D_PostEvent( &event );
}
void IOKitJoystickManager::ReleaseJoysticks()
{
for ( size_t i = 0, count = m_joysticks.Size(); i < count; ++i )
{
delete m_joysticks[i];
}
m_joysticks.Clear();
}
void IOKitJoystickManager::EnableCallbacks()
{
if ( NULL == gIOHIDManagerRef )
{
return;
}
IOHIDManagerRegisterDeviceMatchingCallback( gIOHIDManagerRef, OnDeviceChanged, this );
IOHIDManagerRegisterDeviceRemovalCallback ( gIOHIDManagerRef, OnDeviceChanged, this );
IOHIDManagerScheduleWithRunLoop( gIOHIDManagerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode );
}
void IOKitJoystickManager::DisableCallbacks()
{
if ( NULL == gIOHIDManagerRef )
{
return;
}
IOHIDManagerUnscheduleFromRunLoop( gIOHIDManagerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode );
IOHIDManagerRegisterDeviceMatchingCallback( gIOHIDManagerRef, NULL, NULL );
IOHIDManagerRegisterDeviceRemovalCallback ( gIOHIDManagerRef, NULL, NULL );
}
IOKitJoystickManager* s_joystickManager;
} // unnamed namespace
// ---------------------------------------------------------------------------
void I_StartupJoysticks()
{
s_joystickManager = new IOKitJoystickManager;
}
void I_ShutdownJoysticks()
{
delete s_joystickManager;
}
void I_GetJoysticks( TArray< IJoystickConfig* >& sticks )
{
if ( NULL != s_joystickManager )
{
s_joystickManager->GetJoysticks( sticks );
}
}
void I_GetAxes( float axes[ NUM_JOYAXIS ] )
{
for ( size_t i = 0; i < NUM_JOYAXIS; ++i )
{
axes[i] = 0.0f;
}
if ( use_joystick && NULL != s_joystickManager )
{
s_joystickManager->AddAxes( axes );
}
}
IJoystickConfig* I_UpdateDeviceList()
{
if ( use_joystick && NULL != s_joystickManager )
{
s_joystickManager->Rescan();
}
return NULL;
}
// ---------------------------------------------------------------------------
void I_ProcessJoysticks()
{
if ( use_joystick && NULL != s_joystickManager )
{
s_joystickManager->Update();
}
}

191
src/cocoa/i_timer.cpp Normal file
View File

@ -0,0 +1,191 @@
#include <assert.h>
#include <sys/time.h>
#include <pthread.h>
#include <SDL.h>
#include "basictypes.h"
#include "basicinlines.h"
#include "doomdef.h"
#include "i_system.h"
#include "templates.h"
unsigned int I_MSTime()
{
return SDL_GetTicks();
}
unsigned int I_FPSTime()
{
return SDL_GetTicks();
}
bool g_isTicFrozen;
namespace
{
timespec GetNextTickTime()
{
static const long MILLISECONDS_IN_SECOND = 1000;
static const long MICROSECONDS_IN_SECOND = 1000 * MILLISECONDS_IN_SECOND;
static const long NANOSECONDS_IN_SECOND = 1000 * MICROSECONDS_IN_SECOND;
static timespec ts = {};
if (__builtin_expect((0 == ts.tv_sec), 0))
{
timeval tv;
gettimeofday(&tv, NULL);
ts.tv_sec = tv.tv_sec;
ts.tv_nsec = (tv.tv_usec + MICROSECONDS_IN_SECOND / TICRATE) * MILLISECONDS_IN_SECOND;
}
else
{
ts.tv_nsec += (MICROSECONDS_IN_SECOND / TICRATE) * MILLISECONDS_IN_SECOND;
}
if (ts.tv_nsec >= NANOSECONDS_IN_SECOND)
{
ts.tv_sec++;
ts.tv_nsec -= NANOSECONDS_IN_SECOND;
}
return ts;
}
pthread_cond_t s_timerEvent;
pthread_mutex_t s_timerMutex;
pthread_t s_timerThread;
bool s_timerInitialized;
bool s_timerExitRequested;
uint32_t s_ticStart;
uint32_t s_ticNext;
uint32_t s_timerStart;
uint32_t s_timerNext;
int s_tics;
void* TimerThreadFunc(void*)
{
assert(s_timerInitialized);
assert(!s_timerExitRequested);
while (true)
{
if (s_timerExitRequested)
{
break;
}
const timespec timeToNextTick = GetNextTickTime();
pthread_mutex_lock(&s_timerMutex);
pthread_cond_timedwait(&s_timerEvent, &s_timerMutex, &timeToNextTick);
if (!g_isTicFrozen)
{
__sync_add_and_fetch(&s_tics, 1);
}
s_timerStart = SDL_GetTicks();
s_timerNext = Scale(Scale(s_timerStart, TICRATE, 1000) + 1, 1000, TICRATE);
pthread_cond_broadcast(&s_timerEvent);
pthread_mutex_unlock(&s_timerMutex);
}
return NULL;
}
int GetTimeThreaded(bool saveMS)
{
if (saveMS)
{
s_ticStart = s_timerStart;
s_ticNext = s_timerNext;
}
return s_tics;
}
int WaitForTicThreaded(int prevTic)
{
assert(!g_isTicFrozen);
while (s_tics <= prevTic)
{
pthread_mutex_lock(&s_timerMutex);
pthread_cond_wait(&s_timerEvent, &s_timerMutex);
pthread_mutex_unlock(&s_timerMutex);
}
return s_tics;
}
void FreezeTimeThreaded(bool frozen)
{
g_isTicFrozen = frozen;
}
} // unnamed namespace
fixed_t I_GetTimeFrac(uint32* ms)
{
const uint32_t now = SDL_GetTicks();
if (NULL != ms)
{
*ms = s_ticNext;
}
const uint32_t step = s_ticNext - s_ticStart;
return 0 == step
? FRACUNIT
: clamp<fixed_t>( (now - s_ticStart) * FRACUNIT / step, 0, FRACUNIT);
}
void I_InitTimer ()
{
assert(!s_timerInitialized);
s_timerInitialized = true;
pthread_cond_init (&s_timerEvent, NULL);
pthread_mutex_init(&s_timerMutex, NULL);
pthread_create(&s_timerThread, NULL, TimerThreadFunc, NULL);
I_GetTime = GetTimeThreaded;
I_WaitForTic = WaitForTicThreaded;
I_FreezeTime = FreezeTimeThreaded;
}
void I_ShutdownTimer ()
{
if (!s_timerInitialized)
{
// This might happen if Cancel button was pressed
// in the IWAD selector window
return;
}
s_timerExitRequested = true;
pthread_join(s_timerThread, NULL);
pthread_mutex_destroy(&s_timerMutex);
pthread_cond_destroy (&s_timerEvent);
}

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string>zdoom.icns</string>
<key>CFBundleIdentifier</key>
<string>org.zdoom.zdoom</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>ZDoom</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>Version 2.8.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.action-games</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>Doom Resource File</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>wad</string>
<string>pk3</string>
<string>zip</string>
<string>pk7</string>
<string>7z</string>
</array>
</dict>
</array>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

BIN
src/cocoa/zdoom.icns Normal file

Binary file not shown.

874
src/cocoa/zdoom.xib Normal file
View File

@ -0,0 +1,874 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
<data>
<int key="IBDocument.SystemTarget">1060</int>
<string key="IBDocument.SystemVersion">11C74</string>
<string key="IBDocument.InterfaceBuilderVersion">851</string>
<string key="IBDocument.AppKitVersion">1138.23</string>
<string key="IBDocument.HIToolboxVersion">567.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">851</string>
</object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
<integer value="29"/>
</object>
<object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
</object>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
<object class="NSMutableArray" key="IBDocument.RootObjects" id="1048">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSCustomObject" id="1021">
<string key="NSClassName">NSApplication</string>
</object>
<object class="NSCustomObject" id="1014">
<string key="NSClassName">FirstResponder</string>
</object>
<object class="NSCustomObject" id="1050">
<string key="NSClassName">NSApplication</string>
</object>
<object class="NSCustomObject" id="979998279">
<string key="NSClassName">NSFontManager</string>
</object>
<object class="NSMenu" id="649796088">
<string key="NSTitle">Main Menu</string>
<object class="NSMutableArray" key="NSMenuItems">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMenuItem" id="694149608">
<reference key="NSMenu" ref="649796088"/>
<string key="NSTitle">ZDoom</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<object class="NSCustomResource" key="NSOnImage" id="90941078">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">NSMenuCheckmark</string>
</object>
<object class="NSCustomResource" key="NSMixedImage" id="675015698">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">NSMenuMixedState</string>
</object>
<string key="NSAction">submenuAction:</string>
<object class="NSMenu" key="NSSubmenu" id="110575045">
<string key="NSTitle">ZDoom</string>
<object class="NSMutableArray" key="NSMenuItems">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMenuItem" id="238522557">
<reference key="NSMenu" ref="110575045"/>
<string key="NSTitle">About ZDoom</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
<object class="NSMenuItem" id="304266470">
<reference key="NSMenu" ref="110575045"/>
<bool key="NSIsDisabled">YES</bool>
<bool key="NSIsSeparator">YES</bool>
<string key="NSTitle"/>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
<object class="NSMenuItem" id="609285721">
<reference key="NSMenu" ref="110575045"/>
<string key="NSTitle">Preferences…</string>
<string key="NSKeyEquiv">,</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
<object class="NSMenuItem" id="481834944">
<reference key="NSMenu" ref="110575045"/>
<bool key="NSIsDisabled">YES</bool>
<bool key="NSIsSeparator">YES</bool>
<string key="NSTitle"/>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
<object class="NSMenuItem" id="1046388886">
<reference key="NSMenu" ref="110575045"/>
<string key="NSTitle">Services</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
<string key="NSAction">submenuAction:</string>
<object class="NSMenu" key="NSSubmenu" id="752062318">
<string key="NSTitle">Services</string>
<object class="NSMutableArray" key="NSMenuItems">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<string key="NSName">_NSServicesMenu</string>
</object>
</object>
<object class="NSMenuItem" id="646227648">
<reference key="NSMenu" ref="110575045"/>
<bool key="NSIsDisabled">YES</bool>
<bool key="NSIsSeparator">YES</bool>
<string key="NSTitle"/>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
<object class="NSMenuItem" id="755159360">
<reference key="NSMenu" ref="110575045"/>
<string key="NSTitle">Hide ZDoom</string>
<string key="NSKeyEquiv">h</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
<object class="NSMenuItem" id="342932134">
<reference key="NSMenu" ref="110575045"/>
<string key="NSTitle">Hide Others</string>
<string key="NSKeyEquiv">h</string>
<int key="NSKeyEquivModMask">1572864</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
<object class="NSMenuItem" id="908899353">
<reference key="NSMenu" ref="110575045"/>
<string key="NSTitle">Show All</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
<object class="NSMenuItem" id="1056857174">
<reference key="NSMenu" ref="110575045"/>
<bool key="NSIsDisabled">YES</bool>
<bool key="NSIsSeparator">YES</bool>
<string key="NSTitle"/>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
<object class="NSMenuItem" id="632727374">
<reference key="NSMenu" ref="110575045"/>
<string key="NSTitle">Quit ZDoom</string>
<string key="NSKeyEquiv">q</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
</object>
<string key="NSName">_NSAppleMenu</string>
</object>
</object>
<object class="NSMenuItem" id="589253321">
<reference key="NSMenu" ref="649796088"/>
<string key="NSTitle">Edit</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
<string key="NSAction">submenuAction:</string>
<object class="NSMenu" key="NSSubmenu" id="428984785">
<string key="NSTitle">Edit</string>
<object class="NSMutableArray" key="NSMenuItems">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMenuItem" id="320931528">
<reference key="NSMenu" ref="428984785"/>
<string key="NSTitle">Undo</string>
<string key="NSKeyEquiv">z</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
<object class="NSMenuItem" id="1061671858">
<reference key="NSMenu" ref="428984785"/>
<string key="NSTitle">Redo</string>
<string key="NSKeyEquiv">Z</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
<object class="NSMenuItem" id="107056348">
<reference key="NSMenu" ref="428984785"/>
<bool key="NSIsDisabled">YES</bool>
<bool key="NSIsSeparator">YES</bool>
<string key="NSTitle"/>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
<object class="NSMenuItem" id="371963350">
<reference key="NSMenu" ref="428984785"/>
<string key="NSTitle">Cut</string>
<string key="NSKeyEquiv">x</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
<object class="NSMenuItem" id="258168612">
<reference key="NSMenu" ref="428984785"/>
<string key="NSTitle">Copy</string>
<string key="NSKeyEquiv">c</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
<object class="NSMenuItem" id="440869574">
<reference key="NSMenu" ref="428984785"/>
<string key="NSTitle">Paste</string>
<string key="NSKeyEquiv">v</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
<object class="NSMenuItem" id="331134633">
<reference key="NSMenu" ref="428984785"/>
<string key="NSTitle">Delete</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
<object class="NSMenuItem" id="255637833">
<reference key="NSMenu" ref="428984785"/>
<string key="NSTitle">Select All</string>
<string key="NSKeyEquiv">a</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
</object>
</object>
</object>
<object class="NSMenuItem" id="713487014">
<reference key="NSMenu" ref="649796088"/>
<string key="NSTitle">Window</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
<string key="NSAction">submenuAction:</string>
<object class="NSMenu" key="NSSubmenu" id="835318025">
<string key="NSTitle">Window</string>
<object class="NSMutableArray" key="NSMenuItems">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMenuItem" id="1011231497">
<reference key="NSMenu" ref="835318025"/>
<string key="NSTitle">Minimize</string>
<string key="NSKeyEquiv">m</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
<object class="NSMenuItem" id="575023229">
<reference key="NSMenu" ref="835318025"/>
<string key="NSTitle">Zoom</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
<object class="NSMenuItem" id="299356726">
<reference key="NSMenu" ref="835318025"/>
<bool key="NSIsDisabled">YES</bool>
<bool key="NSIsSeparator">YES</bool>
<string key="NSTitle"/>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
<object class="NSMenuItem" id="625202149">
<reference key="NSMenu" ref="835318025"/>
<string key="NSTitle">Bring All to Front</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="90941078"/>
<reference key="NSMixedImage" ref="675015698"/>
</object>
</object>
<string key="NSName">_NSWindowsMenu</string>
</object>
</object>
</object>
<string key="NSName">_NSMainMenu</string>
</object>
</object>
<object class="IBObjectContainer" key="IBDocument.Objects">
<object class="NSMutableArray" key="connectionRecords">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">performMiniaturize:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="1011231497"/>
</object>
<int key="connectionID">37</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">arrangeInFront:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="625202149"/>
</object>
<int key="connectionID">39</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">orderFrontStandardAboutPanel:</string>
<reference key="source" ref="1021"/>
<reference key="destination" ref="238522557"/>
</object>
<int key="connectionID">142</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">performZoom:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="575023229"/>
</object>
<int key="connectionID">240</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">hide:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="755159360"/>
</object>
<int key="connectionID">367</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">hideOtherApplications:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="342932134"/>
</object>
<int key="connectionID">368</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">terminate:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="632727374"/>
</object>
<int key="connectionID">369</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">unhideAllApplications:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="908899353"/>
</object>
<int key="connectionID">370</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">cut:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="371963350"/>
</object>
<int key="connectionID">738</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">paste:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="440869574"/>
</object>
<int key="connectionID">739</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">redo:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="1061671858"/>
</object>
<int key="connectionID">742</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">undo:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="320931528"/>
</object>
<int key="connectionID">746</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">copy:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="258168612"/>
</object>
<int key="connectionID">752</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">delete:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="331134633"/>
</object>
<int key="connectionID">753</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">selectAll:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="255637833"/>
</object>
<int key="connectionID">755</int>
</object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBObjectRecord">
<int key="objectID">0</int>
<object class="NSArray" key="object" id="0">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<reference key="children" ref="1048"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="1021"/>
<reference key="parent" ref="0"/>
<string key="objectName">File's Owner</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="1014"/>
<reference key="parent" ref="0"/>
<string key="objectName">First Responder</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-3</int>
<reference key="object" ref="1050"/>
<reference key="parent" ref="0"/>
<string key="objectName">Application</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">29</int>
<reference key="object" ref="649796088"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="713487014"/>
<reference ref="694149608"/>
<reference ref="589253321"/>
</object>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">19</int>
<reference key="object" ref="713487014"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="835318025"/>
</object>
<reference key="parent" ref="649796088"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">56</int>
<reference key="object" ref="694149608"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="110575045"/>
</object>
<reference key="parent" ref="649796088"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">57</int>
<reference key="object" ref="110575045"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="238522557"/>
<reference ref="755159360"/>
<reference ref="908899353"/>
<reference ref="632727374"/>
<reference ref="646227648"/>
<reference ref="609285721"/>
<reference ref="481834944"/>
<reference ref="304266470"/>
<reference ref="1046388886"/>
<reference ref="1056857174"/>
<reference ref="342932134"/>
</object>
<reference key="parent" ref="694149608"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">58</int>
<reference key="object" ref="238522557"/>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">134</int>
<reference key="object" ref="755159360"/>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">150</int>
<reference key="object" ref="908899353"/>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">136</int>
<reference key="object" ref="632727374"/>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">144</int>
<reference key="object" ref="646227648"/>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">129</int>
<reference key="object" ref="609285721"/>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">143</int>
<reference key="object" ref="481834944"/>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">236</int>
<reference key="object" ref="304266470"/>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">131</int>
<reference key="object" ref="1046388886"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="752062318"/>
</object>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">149</int>
<reference key="object" ref="1056857174"/>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">145</int>
<reference key="object" ref="342932134"/>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">130</int>
<reference key="object" ref="752062318"/>
<reference key="parent" ref="1046388886"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">24</int>
<reference key="object" ref="835318025"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="299356726"/>
<reference ref="625202149"/>
<reference ref="575023229"/>
<reference ref="1011231497"/>
</object>
<reference key="parent" ref="713487014"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">92</int>
<reference key="object" ref="299356726"/>
<reference key="parent" ref="835318025"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">5</int>
<reference key="object" ref="625202149"/>
<reference key="parent" ref="835318025"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">239</int>
<reference key="object" ref="575023229"/>
<reference key="parent" ref="835318025"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">23</int>
<reference key="object" ref="1011231497"/>
<reference key="parent" ref="835318025"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">371</int>
<reference key="object" ref="979998279"/>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">681</int>
<reference key="object" ref="589253321"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="428984785"/>
</object>
<reference key="parent" ref="649796088"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">682</int>
<reference key="object" ref="428984785"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="320931528"/>
<reference ref="1061671858"/>
<reference ref="107056348"/>
<reference ref="371963350"/>
<reference ref="258168612"/>
<reference ref="440869574"/>
<reference ref="331134633"/>
<reference ref="255637833"/>
</object>
<reference key="parent" ref="589253321"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">683</int>
<reference key="object" ref="320931528"/>
<reference key="parent" ref="428984785"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">684</int>
<reference key="object" ref="1061671858"/>
<reference key="parent" ref="428984785"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">685</int>
<reference key="object" ref="107056348"/>
<reference key="parent" ref="428984785"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">686</int>
<reference key="object" ref="371963350"/>
<reference key="parent" ref="428984785"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">687</int>
<reference key="object" ref="258168612"/>
<reference key="parent" ref="428984785"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">688</int>
<reference key="object" ref="440869574"/>
<reference key="parent" ref="428984785"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">690</int>
<reference key="object" ref="331134633"/>
<reference key="parent" ref="428984785"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">691</int>
<reference key="object" ref="255637833"/>
<reference key="parent" ref="428984785"/>
</object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>-3.IBPluginDependency</string>
<string>129.IBPluginDependency</string>
<string>129.ImportedFromIB2</string>
<string>130.IBPluginDependency</string>
<string>130.ImportedFromIB2</string>
<string>130.editorWindowContentRectSynchronizationRect</string>
<string>131.IBPluginDependency</string>
<string>131.ImportedFromIB2</string>
<string>134.IBPluginDependency</string>
<string>134.ImportedFromIB2</string>
<string>136.IBPluginDependency</string>
<string>136.ImportedFromIB2</string>
<string>143.IBPluginDependency</string>
<string>143.ImportedFromIB2</string>
<string>144.IBPluginDependency</string>
<string>144.ImportedFromIB2</string>
<string>145.IBPluginDependency</string>
<string>145.ImportedFromIB2</string>
<string>149.IBPluginDependency</string>
<string>149.ImportedFromIB2</string>
<string>150.IBPluginDependency</string>
<string>150.ImportedFromIB2</string>
<string>19.IBPluginDependency</string>
<string>19.ImportedFromIB2</string>
<string>23.IBPluginDependency</string>
<string>23.ImportedFromIB2</string>
<string>236.IBPluginDependency</string>
<string>236.ImportedFromIB2</string>
<string>239.IBPluginDependency</string>
<string>239.ImportedFromIB2</string>
<string>24.IBEditorWindowLastContentRect</string>
<string>24.IBPluginDependency</string>
<string>24.ImportedFromIB2</string>
<string>24.editorWindowContentRectSynchronizationRect</string>
<string>29.IBEditorWindowLastContentRect</string>
<string>29.IBPluginDependency</string>
<string>29.ImportedFromIB2</string>
<string>29.WindowOrigin</string>
<string>29.editorWindowContentRectSynchronizationRect</string>
<string>5.IBPluginDependency</string>
<string>5.ImportedFromIB2</string>
<string>56.IBPluginDependency</string>
<string>56.ImportedFromIB2</string>
<string>57.IBEditorWindowLastContentRect</string>
<string>57.IBPluginDependency</string>
<string>57.ImportedFromIB2</string>
<string>57.editorWindowContentRectSynchronizationRect</string>
<string>58.IBPluginDependency</string>
<string>58.ImportedFromIB2</string>
<string>681.IBPluginDependency</string>
<string>682.IBEditorWindowLastContentRect</string>
<string>682.IBPluginDependency</string>
<string>683.IBPluginDependency</string>
<string>684.IBPluginDependency</string>
<string>685.IBPluginDependency</string>
<string>686.IBPluginDependency</string>
<string>687.IBPluginDependency</string>
<string>688.IBPluginDependency</string>
<string>690.IBPluginDependency</string>
<string>691.IBPluginDependency</string>
<string>92.IBPluginDependency</string>
<string>92.ImportedFromIB2</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>{{436, 809}, {64, 6}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>{{651, 262}, {194, 73}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>{{525, 802}, {197, 73}}</string>
<string>{{514, 335}, {220, 20}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>{74, 862}</string>
<string>{{11, 977}, {478, 20}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>{{487, 217}, {195, 183}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>{{23, 794}, {245, 183}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{607, 182}, {151, 153}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
</object>
</object>
<object class="NSMutableDictionary" key="unlocalizedProperties">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference key="dict.sortedKeys" ref="0"/>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
</object>
<nil key="activeLocalization"/>
<object class="NSMutableDictionary" key="localizations">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference key="dict.sortedKeys" ref="0"/>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
</object>
<nil key="sourceID"/>
<int key="maxID">842</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Print.framework/Headers/PDEPluginInterface.h</string>
</object>
</object>
</object>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
<integer value="1060" key="NS.object.0"/>
</object>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
<integer value="3000" key="NS.object.0"/>
</object>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<string key="IBDocument.LastKnownRelativeProjectPath">ZDoom.xcodeproj</string>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>NSMenuCheckmark</string>
<string>NSMenuMixedState</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>{9, 8}</string>
<string>{7, 2}</string>
</object>
</object>
</data>
</archive>