From 8507a3302b80998f166845257d841b2dc0015381 Mon Sep 17 00:00:00 2001 From: Celtic Minstrel Date: Tue, 26 May 2009 03:17:17 +0000 Subject: [PATCH] First version of the new dialog engine added to the repository. It compiles, and links with one error. Because of this, it is untested as yet. git-svn-id: http://openexile.googlecode.com/svn/trunk@73 4ebdad44-0ea0-11de-aab3-ff745001d230 --- osx/Blades of Exile-Info.plist | 134 +++- osx/BoE.xcodeproj/project.pbxproj | 167 ++++- osx/dialogxml/button.cpp | 210 ++++++ osx/dialogxml/button.h | 113 ++++ osx/dialogxml/control.cpp | 298 +++++++++ osx/dialogxml/control.h | 120 ++++ osx/dialogxml/dialog.cpp | 920 ++++++++++++++++++++++++++ osx/dialogxml/dialog.css | 145 ++++ osx/dialogxml/dialog.dtd | 77 +++ osx/dialogxml/dialog.h | 88 +++ osx/dialogxml/dialog.xsl | 164 +++++ osx/dialogxml/dlogutil.cpp | 14 + osx/dialogxml/dlogutil.h | 82 +++ osx/dialogxml/edit-terrain.dlg | 82 +++ osx/dialogxml/field.cpp | 87 +++ osx/dialogxml/field.h | 38 ++ osx/dialogxml/message.cpp | 140 ++++ osx/dialogxml/message.h | 37 ++ osx/dialogxml/pict.cpp | 1020 +++++++++++++++++++++++++++++ osx/dialogxml/pict.h | 160 +++++ 20 files changed, 4050 insertions(+), 46 deletions(-) create mode 100644 osx/dialogxml/button.cpp create mode 100644 osx/dialogxml/button.h create mode 100644 osx/dialogxml/control.cpp create mode 100644 osx/dialogxml/control.h create mode 100644 osx/dialogxml/dialog.cpp create mode 100644 osx/dialogxml/dialog.css create mode 100644 osx/dialogxml/dialog.dtd create mode 100644 osx/dialogxml/dialog.h create mode 100644 osx/dialogxml/dialog.xsl create mode 100644 osx/dialogxml/dlogutil.cpp create mode 100644 osx/dialogxml/dlogutil.h create mode 100644 osx/dialogxml/edit-terrain.dlg create mode 100644 osx/dialogxml/field.cpp create mode 100644 osx/dialogxml/field.h create mode 100644 osx/dialogxml/message.cpp create mode 100644 osx/dialogxml/message.h create mode 100644 osx/dialogxml/pict.cpp create mode 100644 osx/dialogxml/pict.h diff --git a/osx/Blades of Exile-Info.plist b/osx/Blades of Exile-Info.plist index c05a4177..e8b0b115 100644 --- a/osx/Blades of Exile-Info.plist +++ b/osx/Blades of Exile-Info.plist @@ -7,19 +7,67 @@ CFBundleDocumentTypes - CFBundleTypeIconFile - boesounds - CFBundleTypeName - Sounds - CFBundleTypeOSTypes + CFBundleTypeExtensions - beSN + .SAV + CFBundleTypeName + LegacyWinSaveGame CFBundleTypeRole - None + Editor LSItemContentTypes - com.spidweb.bladesofexile.oldsounds + com.spidweb.bladesofexile.oldwinsave + + LSTypeIsPackage + + NSPersistentStoreTypeKey + Binary + + + CFBundleTypeExtensions + + .boe + .mac + + CFBundleTypeName + LegacyMacSaveGame + CFBundleTypeOSTypes + + beSV + + CFBundleTypeRole + Editor + LSItemContentTypes + + com.spidweb.bladesofexile.oldmacsave + + LSTypeIsPackage + + NSPersistentStoreTypeKey + Binary + + + CFBundleTypeExtensions + + .bmp + + CFBundleTypeMIMETypes + + image/x-bmp + + CFBundleTypeName + LegacyWinGraphics + CFBundleTypeOSTypes + + BMPf + BMP + + CFBundleTypeRole + Viewer + LSItemContentTypes + + com.microsoft.bmp LSTypeIsPackage @@ -34,13 +82,13 @@ CFBundleTypeIconFile boegraphics CFBundleTypeName - Graphics + LegacyMacGraphics CFBundleTypeOSTypes beGR CFBundleTypeRole - None + Viewer LSItemContentTypes com.spidweb.bladesofexile.oldgraphics @@ -50,6 +98,26 @@ NSPersistentStoreTypeKey Binary + + CFBundleTypeIconFile + boesounds + CFBundleTypeName + LegacySounds + CFBundleTypeOSTypes + + beSN + + CFBundleTypeRole + Viewer + LSItemContentTypes + + com.spidweb.bladesofexile.oldsounds + + LSTypeIsPackage + + NSPersistentStoreTypeKey + Binary + CFBundleTypeExtensions @@ -61,7 +129,7 @@ Saved Game CFBundleTypeOSTypes - beSV + game CFBundleTypeRole Editor @@ -101,17 +169,17 @@ CFBundleTypeExtensions - .exd + .exr CFBundleTypeIconFile - boegraphics + boeresources CFBundleTypeName - Preset Graphics + Resource File CFBundleTypeRole - None + Viewer LSItemContentTypes - com.spidweb.bladesofexile.newgraphics + com.spidweb.bladesofexile.resources LSTypeIsPackage @@ -121,17 +189,35 @@ CFBundleTypeExtensions - .exr + .dlg - CFBundleTypeIconFile - boeresources CFBundleTypeName - Resource File + EncounterDialog CFBundleTypeRole - None + Viewer LSItemContentTypes - com.spidweb.bladesofexile.resources + com.spidweb.bladesofexile.dialog + + LSTypeIsPackage + + NSPersistentStoreTypeKey + XML + + + CFBundleTypeExtensions + + .exd + + CFBundleTypeIconFile + boegraphics + CFBundleTypeName + Preset Graphics + CFBundleTypeRole + Viewer + LSItemContentTypes + + com.spidweb.bladesofexile.graphics LSTypeIsPackage @@ -148,10 +234,10 @@ CFBundleTypeName Preset Sounds CFBundleTypeRole - None + Viewer LSItemContentTypes - com.spidweb.bladesofexile.newsounds + com.spidweb.bladesofexile.sounds LSTypeIsPackage diff --git a/osx/BoE.xcodeproj/project.pbxproj b/osx/BoE.xcodeproj/project.pbxproj index 25a704d5..3ba57dbb 100644 --- a/osx/BoE.xcodeproj/project.pbxproj +++ b/osx/BoE.xcodeproj/project.pbxproj @@ -42,11 +42,6 @@ 2BF04B2D0BF51924006C0831 /* boe.text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BF04B070BF51924006C0831 /* boe.text.cpp */; }; 2BF04B2E0BF51924006C0831 /* boe.town.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BF04B090BF51924006C0831 /* boe.town.cpp */; }; 2BF04DE90BF7A6FE006C0831 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BF04DE80BF7A6FE006C0831 /* Carbon.framework */; }; - 910BBA470FB8E34E001E34EA /* ticpp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBA270FB8C459001E34EA /* ticpp.cpp */; }; - 910BBA480FB8E34E001E34EA /* tinystr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBA2E0FB8C459001E34EA /* tinystr.cpp */; }; - 910BBA490FB8E34F001E34EA /* tinyxml.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBA2A0FB8C459001E34EA /* tinyxml.cpp */; }; - 910BBA4A0FB8E350001E34EA /* tinyxmlerror.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBA2C0FB8C459001E34EA /* tinyxmlerror.cpp */; }; - 910BBA4B0FB8E351001E34EA /* tinyxmlparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBA2D0FB8C459001E34EA /* tinyxmlparser.cpp */; }; 9127903E0F9B7F49007B0D52 /* boe.actions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BF04ACF0BF51923006C0831 /* boe.actions.cpp */; }; 9127903F0F9B7F50007B0D52 /* boe.graphics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BF04AD30BF51923006C0831 /* boe.graphics.cpp */; }; 912793640F9C107B007B0D52 /* viewdlog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91B3EEF80F969BA700BF5B67 /* viewdlog.cpp */; }; @@ -93,6 +88,12 @@ 913D05BD0FA1EA0A00184C18 /* pc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 913D05BB0FA1EA0A00184C18 /* pc.cpp */; }; 913D05BE0FA1EA0A00184C18 /* pc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 913D05BB0FA1EA0A00184C18 /* pc.cpp */; }; 913D6C050FC57A8E00E12527 /* boeresources.icns in Resources */ = {isa = PBXBuildFile; fileRef = 913D6C040FC57A8E00E12527 /* boeresources.icns */; }; + 9141DAC00FCB95B80047D3A3 /* libticpp.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 9141DAB50FCB94900047D3A3 /* libticpp.dylib */; }; + 9141DAC20FCB95C90047D3A3 /* ticpp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBA270FB8C459001E34EA /* ticpp.cpp */; }; + 9141DAC30FCB95C90047D3A3 /* tinystr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBA2E0FB8C459001E34EA /* tinystr.cpp */; }; + 9141DAC40FCB95CA0047D3A3 /* tinyxml.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBA2A0FB8C459001E34EA /* tinyxml.cpp */; }; + 9141DAC50FCB95CA0047D3A3 /* tinyxmlerror.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBA2C0FB8C459001E34EA /* tinyxmlerror.cpp */; }; + 9141DAC60FCB95CB0047D3A3 /* tinyxmlparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBA2D0FB8C459001E34EA /* tinyxmlparser.cpp */; }; 91A79DC70FA797BF00A6A41F /* menu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 91A79DC60FA797BF00A6A41F /* menu.xib */; }; 91AC60800FA26A3B00EEAE67 /* regtown.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91AC607F0FA26A3B00EEAE67 /* regtown.cpp */; }; 91AC60810FA26A3B00EEAE67 /* regtown.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91AC607F0FA26A3B00EEAE67 /* regtown.cpp */; }; @@ -132,6 +133,12 @@ 91B3EF5B0F969F3000BF5B67 /* scen.dlgutil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91B3EEF60F969BA700BF5B67 /* scen.dlgutil.cpp */; }; 91B3EF5D0F969F3500BF5B67 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BF04DE80BF7A6FE006C0831 /* Carbon.framework */; }; 91B3F1850F97894A00BF5B67 /* scen.graphics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91B3EEF30F969BA700BF5B67 /* scen.graphics.cpp */; }; + 91C1FCA60FCB6F7000EBAA65 /* button.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBA890FB8EC57001E34EA /* button.cpp */; }; + 91C1FCA70FCB6F7100EBAA65 /* control.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBA3C0FB8DA8E001E34EA /* control.cpp */; }; + 91C1FCA80FCB6F7100EBAA65 /* dialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBA180FB8BECA001E34EA /* dialog.cpp */; }; + 91C1FCA90FCB6F7200EBAA65 /* field.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBAB50FB91A26001E34EA /* field.cpp */; }; + 91C1FCAA0FCB6F7200EBAA65 /* message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBAB90FB91ADB001E34EA /* message.cpp */; }; + 91C1FCAB0FCB6F7300EBAA65 /* pict.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBAA90FB8F733001E34EA /* pict.cpp */; }; 91D62F340F8EB84800674AB3 /* bladesofexile.rsrc in Resources */ = {isa = PBXBuildFile; fileRef = 91D62F330F8EB84800674AB3 /* bladesofexile.rsrc */; }; 91D634560F8FD77800674AB3 /* BoE.icns in Resources */ = {isa = PBXBuildFile; fileRef = 2B8F435C0C0973680012E4A8 /* BoE.icns */; }; 91D635B60F90E7D200674AB3 /* stealth.exs in CopyFiles */ = {isa = PBXBuildFile; fileRef = 91D635AA0F90E7B500674AB3 /* stealth.exs */; }; @@ -179,6 +186,13 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 9141DABB0FCB95030047D3A3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2BF04AA10BF51845006C0831 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9141DAB40FCB94900047D3A3 /* ticpp */; + remoteInfo = ticpp; + }; 91EBE9DD0F9A33A6002356F2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 2BF04AA10BF51845006C0831 /* Project object */; @@ -293,15 +307,15 @@ 2BF04DE80BF7A6FE006C0831 /* Carbon.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; name = Carbon.framework; path = /Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; 910BBA170FB8BECA001E34EA /* dialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dialog.h; path = dialogxml/dialog.h; sourceTree = ""; }; 910BBA180FB8BECA001E34EA /* dialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dialog.cpp; path = dialogxml/dialog.cpp; sourceTree = ""; }; - 910BBA270FB8C459001E34EA /* ticpp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ticpp.cpp; path = "dialogxml/TinyXML++/ticpp.cpp"; sourceTree = ""; }; - 910BBA280FB8C459001E34EA /* ticpp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ticpp.h; path = "dialogxml/TinyXML++/ticpp.h"; sourceTree = ""; }; - 910BBA290FB8C459001E34EA /* tinystr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tinystr.h; path = "dialogxml/TinyXML++/tinystr.h"; sourceTree = ""; }; - 910BBA2A0FB8C459001E34EA /* tinyxml.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tinyxml.cpp; path = "dialogxml/TinyXML++/tinyxml.cpp"; sourceTree = ""; }; - 910BBA2B0FB8C459001E34EA /* tinyxml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tinyxml.h; path = "dialogxml/TinyXML++/tinyxml.h"; sourceTree = ""; }; - 910BBA2C0FB8C459001E34EA /* tinyxmlerror.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tinyxmlerror.cpp; path = "dialogxml/TinyXML++/tinyxmlerror.cpp"; sourceTree = ""; }; - 910BBA2D0FB8C459001E34EA /* tinyxmlparser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tinyxmlparser.cpp; path = "dialogxml/TinyXML++/tinyxmlparser.cpp"; sourceTree = ""; }; - 910BBA2E0FB8C459001E34EA /* tinystr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tinystr.cpp; path = "dialogxml/TinyXML++/tinystr.cpp"; sourceTree = ""; }; - 910BBA2F0FB8C470001E34EA /* ticpprc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ticpprc.h; path = "dialogxml/TinyXML++/ticpprc.h"; sourceTree = ""; }; + 910BBA270FB8C459001E34EA /* ticpp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ticpp.cpp; path = "dialogxml/xml-parser/ticpp.cpp"; sourceTree = ""; }; + 910BBA280FB8C459001E34EA /* ticpp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ticpp.h; path = "dialogxml/xml-parser/ticpp.h"; sourceTree = ""; }; + 910BBA290FB8C459001E34EA /* tinystr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tinystr.h; path = "dialogxml/xml-parser/tinystr.h"; sourceTree = ""; }; + 910BBA2A0FB8C459001E34EA /* tinyxml.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tinyxml.cpp; path = "dialogxml/xml-parser/tinyxml.cpp"; sourceTree = ""; }; + 910BBA2B0FB8C459001E34EA /* tinyxml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tinyxml.h; path = "dialogxml/xml-parser/tinyxml.h"; sourceTree = ""; }; + 910BBA2C0FB8C459001E34EA /* tinyxmlerror.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tinyxmlerror.cpp; path = "dialogxml/xml-parser/tinyxmlerror.cpp"; sourceTree = ""; }; + 910BBA2D0FB8C459001E34EA /* tinyxmlparser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tinyxmlparser.cpp; path = "dialogxml/xml-parser/tinyxmlparser.cpp"; sourceTree = ""; }; + 910BBA2E0FB8C459001E34EA /* tinystr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tinystr.cpp; path = "dialogxml/xml-parser/tinystr.cpp"; sourceTree = ""; }; + 910BBA2F0FB8C470001E34EA /* ticpprc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ticpprc.h; path = "dialogxml/xml-parser/ticpprc.h"; sourceTree = ""; }; 910BBA3B0FB8DA8E001E34EA /* control.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = control.h; path = dialogxml/control.h; sourceTree = ""; }; 910BBA3C0FB8DA8E001E34EA /* control.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = control.cpp; path = dialogxml/control.cpp; sourceTree = ""; }; 910BBA880FB8EC57001E34EA /* button.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = button.h; path = dialogxml/button.h; sourceTree = ""; }; @@ -344,6 +358,7 @@ 913D05BA0FA1EA0A00184C18 /* pc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pc.h; path = classes/pc.h; sourceTree = ""; }; 913D05BB0FA1EA0A00184C18 /* pc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = pc.cpp; path = classes/pc.cpp; sourceTree = ""; }; 913D6C040FC57A8E00E12527 /* boeresources.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = boeresources.icns; sourceTree = ""; }; + 9141DAB50FCB94900047D3A3 /* libticpp.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libticpp.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; 91A79DC60FA797BF00A6A41F /* menu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = menu.xib; sourceTree = ""; }; 91A79DDD0FA79DEE00A6A41F /* dialogs.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = dialogs.xib; sourceTree = ""; }; 91AC607E0FA26A3B00EEAE67 /* regtown.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = regtown.h; path = classes/regtown.h; sourceTree = ""; }; @@ -445,6 +460,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 9141DAB30FCB94900047D3A3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 91B3EF160F969C2200BF5B67 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -458,6 +480,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 9141DAC00FCB95B80047D3A3 /* libticpp.dylib in Frameworks */, 91B3EF5D0F969F3500BF5B67 /* Carbon.framework in Frameworks */, 913D026A0FA0EB0500184C18 /* QuickTime.framework in Frameworks */, ); @@ -489,6 +512,7 @@ 91B3EF180F969C2200BF5B67 /* Blades of Exile Character Editor.app */, 91B3EF3F0F969F0000BF5B67 /* BoE Scenario Editor.app */, 912793480F9C0FE6007B0D52 /* ViewDlog.app */, + 9141DAB50FCB94900047D3A3 /* libticpp.dylib */, ); name = Products; sourceTree = ""; @@ -496,7 +520,7 @@ 910BBA130FB8BE66001E34EA /* dialogs */ = { isa = PBXGroup; children = ( - 910BBA190FB8C43E001E34EA /* TinyXML++ */, + 910BBA190FB8C43E001E34EA /* xml-parser */, 910BBA140FB8BE7D001E34EA /* headers */, 910BBA150FB8BE88001E34EA /* src */, 910BBA160FB8BE98001E34EA /* common */, @@ -539,7 +563,7 @@ name = common; sourceTree = ""; }; - 910BBA190FB8C43E001E34EA /* TinyXML++ */ = { + 910BBA190FB8C43E001E34EA /* xml-parser */ = { isa = PBXGroup; children = ( 910BBA270FB8C459001E34EA /* ticpp.cpp */, @@ -552,7 +576,7 @@ 910BBA2D0FB8C459001E34EA /* tinyxmlparser.cpp */, 910BBA2E0FB8C459001E34EA /* tinystr.cpp */, ); - name = "TinyXML++"; + name = "xml-parser"; sourceTree = ""; }; 91279BAB0F9CFB18007B0D52 /* classes */ = { @@ -871,6 +895,16 @@ }; /* End PBXGroup section */ +/* Begin PBXHeadersBuildPhase section */ + 9141DAB10FCB94900047D3A3 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + /* Begin PBXNativeTarget section */ 2BF04AC00BF518D4006C0831 /* Blades of Exile */ = { isa = PBXNativeTarget; @@ -908,6 +942,23 @@ productReference = 912793480F9C0FE6007B0D52 /* ViewDlog.app */; productType = "com.apple.product-type.application"; }; + 9141DAB40FCB94900047D3A3 /* ticpp */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9141DAB80FCB94AE0047D3A3 /* Build configuration list for PBXNativeTarget "ticpp" */; + buildPhases = ( + 9141DAB10FCB94900047D3A3 /* Headers */, + 9141DAB20FCB94900047D3A3 /* Sources */, + 9141DAB30FCB94900047D3A3 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ticpp; + productName = ticpp; + productReference = 9141DAB50FCB94900047D3A3 /* libticpp.dylib */; + productType = "com.apple.product-type.library.dynamic"; + }; 91B3EF170F969C2200BF5B67 /* Blades of Exile Character Editor */ = { isa = PBXNativeTarget; buildConfigurationList = 91B3EF1D0F969C2400BF5B67 /* Build configuration list for PBXNativeTarget "Blades of Exile Character Editor" */; @@ -937,6 +988,7 @@ buildRules = ( ); dependencies = ( + 9141DABC0FCB95030047D3A3 /* PBXTargetDependency */, ); name = "BoE Scenario Editor"; productName = "BoE Scenario Editor"; @@ -964,6 +1016,7 @@ 91B3EF3E0F969F0000BF5B67 /* BoE Scenario Editor */, 912793470F9C0FE5007B0D52 /* ViewDlog */, 91EBE9DA0F9A33A1002356F2 /* All */, + 9141DAB40FCB94900047D3A3 /* ticpp */, ); }; /* End PBXProject section */ @@ -1080,6 +1133,18 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 9141DAB20FCB94900047D3A3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9141DAC20FCB95C90047D3A3 /* ticpp.cpp in Sources */, + 9141DAC30FCB95C90047D3A3 /* tinystr.cpp in Sources */, + 9141DAC40FCB95CA0047D3A3 /* tinyxml.cpp in Sources */, + 9141DAC50FCB95CA0047D3A3 /* tinyxmlerror.cpp in Sources */, + 9141DAC60FCB95CB0047D3A3 /* tinyxmlparser.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 91B3EF150F969C2200BF5B67 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1155,17 +1220,23 @@ 91AC60A90FA26C1B00EEAE67 /* tmpltown.cpp in Sources */, 91AC620C0FA2853700EEAE67 /* creatlist.cpp in Sources */, 91AC65520FA3441B00EEAE67 /* universe.cpp in Sources */, - 910BBA470FB8E34E001E34EA /* ticpp.cpp in Sources */, - 910BBA480FB8E34E001E34EA /* tinystr.cpp in Sources */, - 910BBA490FB8E34F001E34EA /* tinyxml.cpp in Sources */, - 910BBA4A0FB8E350001E34EA /* tinyxmlerror.cpp in Sources */, - 910BBA4B0FB8E351001E34EA /* tinyxmlparser.cpp in Sources */, + 91C1FCA60FCB6F7000EBAA65 /* button.cpp in Sources */, + 91C1FCA70FCB6F7100EBAA65 /* control.cpp in Sources */, + 91C1FCA80FCB6F7100EBAA65 /* dialog.cpp in Sources */, + 91C1FCA90FCB6F7200EBAA65 /* field.cpp in Sources */, + 91C1FCAA0FCB6F7200EBAA65 /* message.cpp in Sources */, + 91C1FCAB0FCB6F7300EBAA65 /* pict.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 9141DABC0FCB95030047D3A3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 9141DAB40FCB94900047D3A3 /* ticpp */; + targetProxy = 9141DABB0FCB95030047D3A3 /* PBXContainerItemProxy */; + }; 91EBE9DE0F9A33A6002356F2 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 2BF04AC00BF518D4006C0831 /* Blades of Exile */; @@ -1381,6 +1452,39 @@ }; name = Release; }; + 9141DAB60FCB94900047D3A3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + EXECUTABLE_PREFIX = lib; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = TIXML_USE_TICPP; + INSTALL_PATH = /usr/local/lib; + PREBINDING = NO; + PRODUCT_NAME = ticpp; + ZERO_LINK = YES; + }; + name = Debug; + }; + 9141DAB70FCB94900047D3A3 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + EXECUTABLE_PREFIX = lib; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + GCC_PREPROCESSOR_DEFINITIONS = TIXML_USE_TICPP; + INSTALL_PATH = /usr/local/lib; + PREBINDING = NO; + PRODUCT_NAME = ticpp; + ZERO_LINK = NO; + }; + name = Release; + }; 91B3EF1B0F969C2300BF5B67 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1464,6 +1568,11 @@ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h"; INFOPLIST_FILE = "Scenario Editor/BoE Scenario Editor-Info.plist"; INSTALL_PATH = "$(HOME)/Applications"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + ); + LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/build/Debug\""; MACOSX_DEPLOYMENT_TARGET_i386 = 10.4; OTHER_CFLAGS = "-fpack-struct=2"; OTHER_CPLUSPLUSFLAGS = "-fpack-struct=2"; @@ -1500,6 +1609,11 @@ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h"; INFOPLIST_FILE = "Scenario Editor/BoE Scenario Editor-Info.plist"; INSTALL_PATH = "$(HOME)/Applications"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + ); + LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/build/Debug\""; MACOSX_DEPLOYMENT_TARGET_i386 = 10.4; OTHER_CFLAGS = "-fpack-struct=2"; OTHER_CPLUSPLUSFLAGS = "-fpack-struct=2"; @@ -1568,6 +1682,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 9141DAB80FCB94AE0047D3A3 /* Build configuration list for PBXNativeTarget "ticpp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9141DAB60FCB94900047D3A3 /* Debug */, + 9141DAB70FCB94900047D3A3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 91B3EF1D0F969C2400BF5B67 /* Build configuration list for PBXNativeTarget "Blades of Exile Character Editor" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/osx/dialogxml/button.cpp b/osx/dialogxml/button.cpp new file mode 100644 index 00000000..c3dc0d3d --- /dev/null +++ b/osx/dialogxml/button.cpp @@ -0,0 +1,210 @@ +/* + * button.cpp + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#include +#include +using namespace std; + +#include "dialog.h" +#include "graphtool.h" + +void cButton::attachFocusHandler(focus_callback_t f __attribute__((unused))) throw(xHandlerNotSupported){ + throw xHandlerNotSupported(true); +} + +void cButton::attachClickHandler(click_callback_t f) throw(){ + onClick = f; +} + +bool cButton::triggerClickHandler(cDialog& me, std::string id, eKeyMod mods){ + if(onClick != NULL) return onClick(me,id,mods); + return false; +} + +cButton::cButton(cDialog* parent) : cControl(parent) {} + +bool cButton::isClickable(){ + return true; +} + +void cButton::draw(){ + GrafPtr old_port; + Rect from_rect, to_rect; + GWorldPtr from_gw, to_gw; + + GetPort(&old_port); + SetPortWindowPort(parent->win); + + if(visible){ + TextFont(font_nums[GENEVA]); + if(foundSilom())TextFace(normal); + else TextFace(bold); + if(type == BTN_TINY) TextSize(9); + else if(type == BTN_PUSH) TextSize(10); + else TextSize(12); + from_gw = buttons[btnGW[type]]; + to_gw = (GWorldPtr) parent->win; + from_rect = btnRects[btnGW[type]][depressed]; + to_rect = frame; + rect_draw_some_item(from_gw,from_rect,to_gw,to_rect,0,2); + RGBForeColor(&parent->defTextClr); + char_win_draw_string(parent->win,to_rect,lbl.c_str(),1,8,false); + // TODO: Adjust string location as appropriate + // Tiny button string location should be shifted right 20 pixels (or possibly 18) + // Push button string should be centred below the button + // Others may need adjustments too, not sure + ForeColor(blackColor); + if(key.spec && key.k == key_enter) drawFrame(2,0); // frame default button, to provide a visual cue that it's the default + }else{ + FillCRect(&frame,bg[parent->bg]); + } + + SetPort(old_port); +} + +void cButton::setFormat(eFormat prop, short val) throw(xUnsupportedProp){ + if(prop == TXT_WRAP) wrapLabel = val; + else throw xUnsupportedProp(prop); + if(isVisible()) draw(); +} + +short cButton::getFormat(eFormat prop) throw(xUnsupportedProp){ + if(prop == TXT_WRAP) return wrapLabel; + else throw xUnsupportedProp(prop); +} + +// Indices within the buttons array. +size_t cButton::btnGW[13] = { + 0, // BTN_SM + 1, // BTN_REG + 2, // BTN_LG + 4, // BTN_HELP + 1, // BTN_LEFT + 1, // BTN_RIGHT + 1, // BTN_UP + 1, // BTN_DOWN + 5, // BTN_TINY + 1, // BTN_DONE + 3, // BTN_TALL + 3, // BTN_TRAIT + 6, // BTN_PUSH +}; + +GWorldPtr cButton::buttons[7] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL}; +Rect cButton::btnRects[13][2]; + +void cButton::init(){ + for(int i = 0; i < 7; i++) + buttons[i] = load_pict(i + 2030); + SetRect(&btnRects[BTN_SM][0],0,0,23,23); + SetRect(&btnRects[BTN_REG][0],0,0,63,23); + SetRect(&btnRects[BTN_LEFT][0],0,23,63,46); + SetRect(&btnRects[BTN_RIGHT][0],0,46,63,69); + SetRect(&btnRects[BTN_UP][0],0,69,63,92); + SetRect(&btnRects[BTN_DOWN][0],0,92,63,115); + SetRect(&btnRects[BTN_DONE][0],0,115,63,138); + SetRect(&btnRects[BTN_LG][0],0,0,104,23); + SetRect(&btnRects[BTN_HELP][0],0,0,16,13); + SetRect(&btnRects[BTN_TINY][0],42,0,56,10); + SetRect(&btnRects[BTN_TALL][0],0,0,63,40); + SetRect(&btnRects[BTN_TRAIT][0],0,40,63,80); + SetRect(&btnRects[BTN_PUSH][0],0,0,30,30); + for(int j = 0; j < 12; j++) + btnRects[j][1] = btnRects[j][0]; + OffsetRect(&btnRects[BTN_SM][1],23,0); + OffsetRect(&btnRects[BTN_REG][1],63,0); + OffsetRect(&btnRects[BTN_LEFT][1],63,0); + OffsetRect(&btnRects[BTN_RIGHT][1],63,0); + OffsetRect(&btnRects[BTN_UP][1],63,0); + OffsetRect(&btnRects[BTN_DOWN][1],63,0); + OffsetRect(&btnRects[BTN_DONE][1],63,0); + OffsetRect(&btnRects[BTN_LG][1],104,0); + OffsetRect(&btnRects[BTN_HELP][1],16,0); + OffsetRect(&btnRects[BTN_TINY][1],0,10); + OffsetRect(&btnRects[BTN_TALL][1],63,0); + OffsetRect(&btnRects[BTN_TRAIT][1],63,0); + OffsetRect(&btnRects[BTN_PUSH][1],30,0); +} + +Rect cLed::ledRects[3][2]; + +void cLed::init(){ + Rect baseLed = {0,0,10,14}; + for(int i = 0; i < 3; i++) + for(int j = 0; j < 2; j++){ + ledRects[i][j] = baseLed; + OffsetRect(&ledRects[i][j],i * 14, j * 10); + } +} + +cLed::cLed(cDialog* parent) : cButton(parent) {} + +void cLed::attachClickHandler(click_callback_t f) throw(){ + onClick = f; +} + +void cLed::attachFocusHandler(focus_callback_t __attribute__((unused))) throw(xHandlerNotSupported){ + throw xHandlerNotSupported(true); +} + +bool cLed::triggerClickHandler(cDialog& me, std::string id, eKeyMod mods){ + if(onClick != NULL) return onClick(me,id,mods); + return false; +} + +void cLed::setFormat(eFormat prop __attribute__((unused)), short val __attribute__((unused))) throw(xUnsupportedProp){ + throw xUnsupportedProp(prop); +} + +short cLed::getFormat(eFormat prop __attribute__((unused))) throw(xUnsupportedProp){ + throw xUnsupportedProp(prop); +} + +void cLed::draw(){ + GrafPtr old_port; + Rect from_rect, to_rect; + GWorldPtr from_gw, to_gw; + + GetPort(&old_port); + SetPortWindowPort(parent->win); + + if(visible){ + TextFont(font_nums[GENEVA]); + if(foundSilom())TextFace(normal); + else TextFace(bold); + TextSize(9); + from_gw = buttons[BTN_LED]; + to_gw = (GWorldPtr) parent->win; + from_rect = ledRects[state][depressed]; + to_rect = frame; + rect_draw_some_item(from_gw,from_rect,to_gw,to_rect,0,2); + RGBForeColor(&parent->defTextClr); + char_win_draw_string(parent->win,to_rect,lbl.c_str(),1,8,false); + // TODO: Adjust string location as appropriate + // String location should be shifted right 20 pixels (or possibly 18) + ForeColor(blackColor); + }else{ + FillCRect(&frame,bg[parent->bg]); + } + + SetPort(old_port); +} + +cLedGroup::cLedGroup(cDialog* parent) : cControl(parent) {} + +cButton::~cButton() {} + +cLed::~cLed() {} + +cLedGroup::~cLedGroup(){ + ledIter iter = choices.begin(); + while(iter != choices.end()){ + delete iter->second; + iter++; + } +} diff --git a/osx/dialogxml/button.h b/osx/dialogxml/button.h new file mode 100644 index 00000000..b027c3b5 --- /dev/null +++ b/osx/dialogxml/button.h @@ -0,0 +1,113 @@ +/* + * button.h + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#ifndef BUTTON_H +#define BUTTON_H + +#include +#include +#include + +enum eBtnType { // w x h + BTN_SM = 0, // 23x23 (PICT id 2000 / 2001) + BTN_REG, // 63x23 (PICT id 2002 / 2003) + BTN_LG, // 102x23 (PICT id 2004 / 2005) + BTN_HELP, // 16x13 (PICT id 2006 / 2007) white bubble w/ ? mark + BTN_LEFT, // 63x23 (PICT id 2008 / 2009) with left arrow + BTN_RIGHT, // 63x23 (PICT id 2010 / 2011) with right arrow + BTN_UP, // 63x23 (PICT id 2012 / 2013) with up arrow + BTN_DOWN, // 63x23 (PICT id 2014 / 2015) with down arrow + BTN_TINY, // 14x10 (PICT id 2021) + BTN_DONE, // 63x23 (PICT id 2022 / 2023) says "Done" + BTN_TALL, // 63x40 (PICT id 2024 / 2025) + BTN_TRAIT, // 63x40 (PICT id 2026 / 2027) says "Race Good/Bad Traits" + BTN_PUSH, // 30x30 (PICT id 2028 / 2029) red round button + BTN_LED, // 14x10 (PICT id 2018 / 2019 / 2020) +}; + +enum eLedState {led_green = 0, led_red, led_off}; + +class cButton : public cControl { +public: + static void init(); + void attachClickHandler(click_callback_t f) throw(); + void attachFocusHandler(focus_callback_t f) throw(xHandlerNotSupported); + bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods); + //virtual void setPict(short pict, short type) = 0; + void setFormat(eFormat prop, short val) throw(xUnsupportedProp); + short getFormat(eFormat prop) throw(xUnsupportedProp); + cButton(cDialog* parent); + bool isClickable(); + virtual ~cButton(); +protected: + //friend class cDialog; + void draw(); +private: + friend class cDialog; + click_callback_t onClick; + bool wrapLabel; + bool labelWithKey; + bool pressed; + eBtnType type; + std::string fromList; + static Rect btnRects[13][2]; + static size_t btnGW[13]; +protected: + static GWorldPtr buttons[7]; +}; + +class cLed : public cButton { +public: + static void init(); + void attachClickHandler(click_callback_t f) throw(); + void attachFocusHandler(focus_callback_t f) throw(xHandlerNotSupported); + bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods); + void setFormat(eFormat prop, short val) throw(xUnsupportedProp); + short getFormat(eFormat prop) throw(xUnsupportedProp); + cLed(cDialog* parent); + virtual ~cLed(); +protected: + void draw(); +private: + friend class cDialog; + eLedState state; + eTextFont textFont; + RGBColor color; + short textSize; + static Rect ledRects[3][2]; + click_callback_t onClick; +}; + +class cLedGroup : public cControl { + std::vector btns; + click_callback_t onClick; + focus_callback_t onFocus; + std::map choices; + std::string fromList; + friend class cDialog; +public: + void attachClickHandler(click_callback_t f) throw(); // activated whenever a click is received, even on the currently active LED + void attachFocusHandler(focus_callback_t f) throw(); // activated only when the selection changes + bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods); + bool triggerFocusHandler(cDialog& me, std::string id, bool losingFocus); + void setSelected(std::string id); + std::string getSelected(); + void disable(std::string id); + void enable(std::string id); + void hide(std::string id); + void show(std::string id); + void setFormat(eFormat prop, short val) throw(xUnsupportedProp); + short getFormat(eFormat prop) throw(xUnsupportedProp); + cLedGroup(cDialog* parent); + bool isClickable(); + virtual ~cLedGroup(); + typedef std::map::iterator ledIter; +protected: + void draw(); +}; +#endif diff --git a/osx/dialogxml/control.cpp b/osx/dialogxml/control.cpp new file mode 100644 index 00000000..bd4da2d6 --- /dev/null +++ b/osx/dialogxml/control.cpp @@ -0,0 +1,298 @@ +/* + * control.cpp + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#include +#include "dialog.h" +#include "soundtool.h" + +extern bool play_sounds; + +void cControl::setLabel(std::string l){ + lbl = l; + if(isVisible()) draw(); +} + +std::string cControl::getLabel(){ + return lbl; +} + +static unsigned char applyShift(unsigned char c){ + static const char afterShift[] = { + ' ', '!', '"', '#', '$', '%', '&', '"', '(', ')', '*', '+', '<', '_', '>', '?', + ')', '!', '@', '#', '$', '%', '^', '&', '*', '(', ':', ':', '<', '+', '>', '?', + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '^', '_', + '~', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', + }; + return afterShift[c - ' ']; +} + +static unsigned char removeShift(unsigned char c){ + static const char afterUnShift[] = { + ' ', '1', '\'','3', '4', '5', '7', '\'','9', '0', '8', '=', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';', ';', ',', '=', '.', '/', + '2', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\',']', '6', '-', + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\',']', '`', + }; + return afterUnShift[c - ' ']; +} + +void cControl::setLabelToKey(){ + if(key.spec); // TODO: Handle this case + else{ + unsigned char c = key.c; + if(key.mod - mod_shift != key.mod) c = applyShift(c); + else c = removeShift(c); + if(key.mod - mod_ctrl != key.mod) lbl = "^" + c; + else if(key.mod - mod_alt != key.mod) lbl = "*" + c; + else lbl = c; + } + if(isVisible()) draw(); +} + +void cControl::attachKey(cKey key){ + this->key = key; +} + +const char* xHandlerNotSupported::focusMsg = "This control cannot handle focus events.\n"; +const char* xHandlerNotSupported::clickMsg = "This control cannot handle click events.\n"; + +xHandlerNotSupported::xHandlerNotSupported(bool isFocus){ + this->isFocus = isFocus; +} +const char* xHandlerNotSupported::what(){ + if(isFocus) return focusMsg; + else return clickMsg; +} + +xUnsupportedProp::xUnsupportedProp(eFormat prop) throw(){ + whichProp = prop; + msg = NULL; +} +xUnsupportedProp::~xUnsupportedProp() throw(){ + if(msg != NULL) delete msg; +} +const char* xUnsupportedProp::what() throw(){ + if(msg == NULL){ + msg = new char[60]; + std::string s; + switch(whichProp){ + case TXT_COLOR: + s = "TXT_COLOR"; + break; + case TXT_FRAME: + s = "TXT_FRAME"; + break; + case TXT_FONT: + s = "TXT_FONT"; + break; + case TXT_SIZE: + s = "TXT_SIZE"; + break; + case TXT_WRAP: + s = "TXT_WRAP"; + break; + } + sprintf(msg,"Format property %s not valid for this control.\n",s.c_str()); + } + return msg; +} + +eKeyMod operator + (eKeyMod lhs, eKeyMod rhs){ + if(lhs == rhs) return lhs; + else if(lhs == mod_none) return rhs; + else if(lhs == mod_alt){ + if(rhs == mod_shift || rhs == mod_altshift) return mod_altshift; + else if(rhs == mod_ctrl || rhs == mod_altctrl) return mod_altctrl; + else if(rhs == mod_shiftctrl || rhs == mod_all) return mod_all; + else return mod_alt; + }else if(lhs == mod_shift){ + if(rhs == mod_alt || rhs == mod_altshift) return mod_altshift; + else if(rhs == mod_ctrl || rhs == mod_shiftctrl) return mod_shiftctrl; + else if(rhs == mod_altctrl || rhs == mod_all) return mod_all; + else return mod_shift; + }else if(lhs == mod_ctrl){ + if(rhs == mod_alt || rhs == mod_altctrl) return mod_altctrl; + else if(rhs == mod_shift || rhs == mod_shiftctrl) return mod_shiftctrl; + else if(rhs == mod_altshift || rhs == mod_all) return mod_all; + else return mod_ctrl; + }else return rhs + lhs; +} + +eKeyMod operator - (eKeyMod lhs, eKeyMod rhs){ + if(lhs == rhs || lhs == mod_none || rhs == mod_all) return mod_none; + else if(rhs == mod_none) return lhs; + else if(lhs == mod_all){ + if(rhs == mod_alt) return mod_shiftctrl; + else if(rhs == mod_shift) return mod_altctrl; + else if(rhs == mod_ctrl) return mod_altshift; + else if(rhs == mod_altshift) return mod_ctrl; + else if(rhs == mod_altctrl) return mod_shift; + else if(rhs == mod_shiftctrl) return mod_alt; + else return mod_all; + }else if(lhs == mod_shiftctrl){ + if(rhs == mod_shift || rhs == mod_altshift) return mod_ctrl; + else if(rhs == mod_ctrl || rhs == mod_altctrl) return mod_shift; + else return mod_shiftctrl; + }else if(lhs == mod_altctrl){ + if(rhs == mod_alt || rhs == mod_altshift) return mod_ctrl; + else if(rhs == mod_ctrl || rhs == mod_shiftctrl) return mod_alt; + else return mod_altctrl; + }else if(lhs == mod_altshift){ + if(rhs == mod_alt || rhs == mod_altctrl) return mod_shift; + else if(rhs == mod_shift || rhs == mod_shiftctrl) return mod_alt; + else return mod_altshift; + }else if(lhs == mod_alt && (rhs == mod_altshift || rhs == mod_altctrl)) + return mod_none; + else if(lhs == mod_shift && (rhs == mod_altshift || rhs == mod_shiftctrl)) + return mod_none; + else if(lhs == mod_ctrl && (rhs == mod_altctrl || rhs == mod_shiftctrl)) + return mod_none; + else return lhs; +} + +eKeyMod& operator += (eKeyMod&lhs, eKeyMod rhs){ + lhs = lhs + rhs; + return lhs; +} + +eKeyMod& operator -= (eKeyMod&lhs, eKeyMod rhs){ + lhs = lhs - rhs; + return lhs; +} + +bool operator== (cKey& a, cKey& b){ + if(a.spec != b.spec) return false; + if(a.mod != b.mod) return false; + return a.spec ? a.k == b.k : a.c == b.c; +} + +void cControl::show(){ + visible = true; + if(isVisible()) draw(); +} + +void cControl::hide(){ + visible = false; + if(isVisible()) draw(); +} + +bool cControl::isVisible(){ + if(parent->dialogNotToast) + return visible; + else return false; +} + +bool cControl::handleClick(){ + EventRecord e; + unsigned long dummy; + bool done = false, clicked = false; + GrafPtr old_port; + GetPort(&old_port); + SetPortWindowPort(parent->win); + RgnHandle in_region = NewRgn(), out_region = NewRgn(); + RectRgn(in_region,&frame); + RectRgn(out_region,&parent->winRect); + DiffRgn(out_region,in_region,out_region); + depressed = true; + draw(); + while(!done){ + WaitNextEvent(mUpMask,&e,0L,depressed ? in_region : out_region); + if(e.what == mouseUp){ + done = true; + clicked = PtInRect(e.where, &frame); + depressed = false; + }else if(e.message >> 8 == mouseMovedMessage){ + depressed = !depressed; + draw(); + } + } + if (play_sounds) { + if(typeid(this) == typeid(cLed*)) + play_sound(34); + else play_sound(37); + Delay(6,&dummy); + } + else Delay(14,&dummy); + draw(); + SetPort(old_port); + return clicked; +} + +cControl::cControl(cDialog* p){ + parent = p; +} + +bool cControl::triggerClickHandler(cDialog& me __attribute__((unused)), std::string id __attribute__((unused)), eKeyMod mods __attribute__((unused))){ + return true; +} + +bool cControl::triggerFocusHandler(cDialog& me __attribute__((unused)), std::string id __attribute__((unused)), bool losingFocus __attribute__((unused))){ + return true; +} + +short cControl::font_nums[4]; + +void cControl::init(){ + Str255 fnGeneva = "\pGeneva"; + Str255 fnDungeon = "\pDungeon Bold"; + Str255 fnMaiden = "\pMaidenWord"; + Str255 fnSilom = "\pSilom"; + Str255 fnPalatino = "\pPalatino"; + Str255 fnChancery = "\pApple Chancery"; + + GetFNum(fnGeneva,&font_nums[GENEVA]); + if(font_nums[GENEVA] == 0) + GetFNum(fnPalatino,&font_nums[GENEVA]); + GetFNum(fnDungeon,&font_nums[DUNGEON]); + if(font_nums[DUNGEON] == 0) + GetFNum(fnChancery,&font_nums[DUNGEON]); + GetFNum(fnSilom,&font_nums[SILOM]); + if(font_nums[SILOM] == 0){ + GetFNum(fnPalatino,&font_nums[SILOM]); + found_silom = false; + }else found_silom = true; + GetFNum(fnMaiden,&font_nums[MAIDENWORD]); + if(font_nums[MAIDENWORD] == 0) + GetFNum(fnChancery,&font_nums[MAIDENWORD]); +} + +void cControl::drawFrame(short amt, short med_or_lt){ + static RGBColor lt_gray = {57344,57344,57344},dk_gray = {12287,12287,12287},med_gray = {24574,24574,24574}; + GrafPtr old_port; + Rect rect = frame; + + GetPort(&old_port); + SetPortWindowPort(parent->win); + + InsetRect(&rect,-1 * amt,-1 * amt); + + RGBForeColor(&dk_gray); + MoveTo(rect.left,rect.top); + LineTo(rect.right,rect.top); + if (med_or_lt == 1) // hDlg == GetWindowPort(mainPtr) // ie for the pc editor only + RGBForeColor(&med_gray); + else RGBForeColor(<_gray); + LineTo(rect.right,rect.bottom); + LineTo(rect.left,rect.bottom); + RGBForeColor(&dk_gray); + LineTo(rect.left,rect.top); + ForeColor(blackColor); + SetPort(old_port); +} + +bool cControl::found_silom; + +bool cControl::foundSilom(){ + return found_silom; +} + +cControl::~cControl() {} diff --git a/osx/dialogxml/control.h b/osx/dialogxml/control.h new file mode 100644 index 00000000..b38cf444 --- /dev/null +++ b/osx/dialogxml/control.h @@ -0,0 +1,120 @@ +/* + * control.h + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#ifndef CONTROL_H +#define CONTROL_H + +#include +#include + +//struct cPict { +// short pict; +// short type; +//}; +enum eKeyMod { + mod_none = 0, + mod_alt = 1, mod_shift = 2, mod_ctrl = 4, + mod_altshift = mod_alt + mod_shift, + mod_altctrl = mod_alt + mod_ctrl, + mod_shiftctrl = mod_shift + mod_ctrl, + mod_all = mod_alt + mod_shift + mod_ctrl, +}; + +enum eSpecKey { + key_left, key_right, key_up, key_down, + key_esc, key_enter, key_tab, key_help, // key_help should bind to the help key on Mac and the F1 key on Windows + key_bsp, key_del, key_home, key_end, key_pgup, key_pgdn, // TODO: Implement these + // On Mac, command-left should trigger key_home; command-right should trigger key_end; + // command-up should trigger key_pgup; and command-down should trigger key_pgdn. + // This is in addition to the home, end, pgup, pgdn keys triggering these. +}; + +struct cKey { + bool spec; + union { + unsigned char c; + eSpecKey k; + }; + eKeyMod mod; +}; + +bool operator== (cKey& a, cKey& b); + +enum eFormat { + TXT_COLOR, + TXT_FRAME, + TXT_FONT, + TXT_SIZE, + TXT_WRAP, +}; + +enum eTextFont {DUNGEON, GENEVA, SILOM, MAIDENWORD}; + +class cDialog; +typedef bool (*click_callback_t)(cDialog&/*me*/,std::string/*id*/, eKeyMod/*mods*/); +typedef bool (*focus_callback_t)(cDialog&/*me*/,std::string/*id*/,bool/*losing*/); // losing is true if losing focus, false if gaining focus. + +class xHandlerNotSupported : std::exception { + static const char* focusMsg; + static const char* clickMsg; + bool isFocus; +public: + xHandlerNotSupported(bool isFocus); + const char* what(); +}; + +class xUnsupportedProp : std::exception { + eFormat whichProp; + char* msg; +public: + xUnsupportedProp(eFormat prop) throw(); + ~xUnsupportedProp() throw(); + const char* what() throw(); +}; + +class cControl { +public: + static void init(); + void attachKey(cKey key); + virtual void attachClickHandler(click_callback_t f) throw(xHandlerNotSupported) = 0; + virtual void attachFocusHandler(focus_callback_t f) throw(xHandlerNotSupported) = 0; + virtual bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods); + virtual bool triggerFocusHandler(cDialog& me, std::string id, bool losingFocus); + //virtual void setPict(short pict, short type) = 0; + virtual void show(); // cd_activate_item true + virtual void hide(); // cd_activate_item false + bool isVisible(); // cd_get_active + void setLabel(std::string l); + std::string getLabel(); + void setLabelToKey(); + virtual void setFormat(eFormat prop, short val) throw(xUnsupportedProp) = 0; + virtual short getFormat(eFormat prop) throw(xUnsupportedProp) = 0; + virtual bool isClickable() = 0; + bool handleClick(); + cControl(cDialog* p); + virtual ~cControl(); +protected: + cDialog* parent; + std::string lbl; + cKey key; + bool visible, depressed; // depressed is only applicable for clickable controls + Rect frame; + friend class cDialog; + virtual void draw() = 0; + static bool foundSilom(); + static short font_nums[4]; + void drawFrame(short amt, short med_or_lt); +private: + static bool found_silom; +}; + +eKeyMod operator + (eKeyMod lhs, eKeyMod rhs); +eKeyMod operator - (eKeyMod lhs, eKeyMod rhs); +eKeyMod&operator += (eKeyMod&lhs, eKeyMod rhs); +eKeyMod&operator -= (eKeyMod&lhs, eKeyMod rhs); +#endif diff --git a/osx/dialogxml/dialog.cpp b/osx/dialogxml/dialog.cpp new file mode 100644 index 00000000..05e6d031 --- /dev/null +++ b/osx/dialogxml/dialog.cpp @@ -0,0 +1,920 @@ +/* + * dialog.cpp + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ +#define SLEEP_TICKS 2L +#define MOUSE_REGION 0L +#define IN_FRONT (WindowPtr)-1L + +#include "dialog.h" +#include "graphtool.h" +#include "soundtool.h" +using namespace std; +using namespace ticpp; + +extern bool play_sounds; +const short cDialog::BG_DARK = 5, cDialog::BG_LIGHT = 16; + +template<> pair cDialog::parse(Element& who /*pict*/){ + pair p; + Iterator attr; + string name, val; + int width = 0, height = 0; + bool wide = false, tall = false, custom = false; + p.second = new cPict(this); + for(attr = attr.begin(&who); attr != attr.end(); attr++){ + attr->GetName(&name); + attr->GetValue(&val); + if(name == "name") + p.first = val; + else if(name == "type"){ + if(val == "blank"){ + p.second->picType = PIC_TER; + p.second->picNum = -1; + }else if(val == "ter") + p.second->picType = PIC_TER; + else if(val == "teranim") + p.second->picType = PIC_TER_ANIM; + else if(val == "monst") + p.second->picType = PIC_MONST; + else if(val == "dlog") + p.second->picType = PIC_DLOG; + else if(val == "talk") + p.second->picType = PIC_TALK; + else if(val == "scen") + p.second->picType = PIC_SCEN; + else if(val == "item") + p.second->picType = PIC_ITEM; + else if(val == "pc") + p.second->picType = PIC_PC; + else if(val == "field") + p.second->picType = PIC_FIELD; + else if(val == "boom") + p.second->picType = PIC_BOOM; + else if(val == "missile") + p.second->picType = PIC_MISSILE; + else if(val == "full") + p.second->picType = PIC_FULL; + else throw xBadVal("pict",name,val); + }else if(name == "custom") if(val == "true") + custom = true; + else if(name == "clickable") if(val == "true") + p.second->clickable = true; + else if(name == "size"){ + if(val == "wide") wide = true; + else if(val == "tall") tall = true; + else if(val == "large") wide = tall = true; + else throw xBadVal("pict",name,val); + }else if(name == "num"){ + istringstream sin(val); + sin >> p.second->picNum; + }else if(name == "top"){ + istringstream sin(val); + sin >> p.second->frame.top; + }else if(name == "left"){ + istringstream sin(val); + sin >> p.second->frame.left; + }else if(name == "width"){ + istringstream sin(val); + sin >> width; + }else if(name == "height"){ + istringstream sin(val); + sin >> height; + }else throw xBadAttr("pict",name); + } + if(wide && !tall && p.second->picType == PIC_MONST) p.second->picType = PIC_MONST_WIDE; + else if(!wide && tall && p.second->picType == PIC_MONST) p.second->picType = PIC_MONST_TALL; + else if(wide && tall){ + if(p.second->picType == PIC_MONST) p.second->picType = PIC_MONST_LG; + else if(p.second->picType == PIC_SCEN) p.second->picType = PIC_SCEN_LG; + else if(p.second->picType == PIC_DLOG) p.second->picType = PIC_DLOG_LG; + } + if(width > 0 || height > 0 || p.second->picType == PIC_FULL){ + p.second->frame.right = p.second->frame.left + width; + p.second->frame.bottom = p.second->frame.top + height; + }else switch(p.second->picType){ + case PIC_DLOG: + p.second->frame.right = p.second->frame.left + 36; + p.second->frame.bottom = p.second->frame.top + 36; + break; + case PIC_DLOG_LG: + p.second->frame.right = p.second->frame.left + 72; + p.second->frame.bottom = p.second->frame.top + 72; + break; + case PIC_SCEN: + case PIC_TALK: + p.second->frame.right = p.second->frame.left + 32; + p.second->frame.bottom = p.second->frame.top + 32; + break; + case PIC_SCEN_LG: + p.second->frame.right = p.second->frame.left + 64; + p.second->frame.bottom = p.second->frame.top + 64; + break; + case PIC_MISSILE: + p.second->frame.right = p.second->frame.left + 18; + p.second->frame.bottom = p.second->frame.top + 18; + break; + default: + p.second->frame.right = p.second->frame.left + 28; + p.second->frame.bottom = p.second->frame.top + 36; + break; + } + if(custom) p.second->picType += PIC_CUSTOM; + return p; +} + +template<> pair cDialog::parse(Element& who /*text*/){ + pair p; + Iterator attr; + Iterator node; + string name, val; + int width = 0, height = 0; + p.second = new cTextMsg(this); + for(attr = attr.begin(&who); attr != attr.end(); attr++){ + attr->GetName(&name); + attr->GetValue(&val); + if(name == "name") + p.first = val; + else if(name == "framed") if(val == "true") + p.second->drawFramed = true; + else if(name == "clickable") if(val == "true") + p.second->clickable = true; + else if(name == "font"){ + if(val == "dungeon") + p.second->textFont = DUNGEON; + else if(val == "geneva") + p.second->textFont = GENEVA; + else if(val == "silom") + p.second->textFont = SILOM; + else if(val == "maidenword") + p.second->textFont = MAIDENWORD; + else throw xBadVal("text",name,val); + }else if(name == "size"){ + if(val == "large") + p.second->textSize = 12; + else if(val == "small") + p.second->textSize = 10; + else throw xBadVal("text",name,val); + }else if(name == "color" || name == "colour"){ + RGBColor clr; + try{ + clr = parseColor(val); + }catch(int){ + throw xBadVal("text",name,val); + } + p.second->color = clr; + }else if(name == "top"){ + istringstream sin(val); + sin >> p.second->frame.top; + }else if(name == "left"){ + istringstream sin(val); + sin >> p.second->frame.left; + }else if(name == "width"){ + istringstream sin(val); + sin >> width; + }else if(name == "height"){ + istringstream sin(val); + sin >> height; + }else if(name == "fromlist"){ + p.second->fromList = val; + }else throw xBadAttr("pict",name); + } + p.second->frame.right = p.second->frame.left + width; + p.second->frame.bottom = p.second->frame.top + height; + string content; + for(node = node.begin(&who); node != node.end(); node++){ + string val; + int type = node->Type(); + node->GetValue(&val); + if(type == TiXmlNode::ELEMENT && val == "br") content += '|'; // because vertical bar is replaced by a newline when drawing strings + else if(type == TiXmlNode::TEXT) content += val; + else{ + val = '<' + val + '>'; + throw xBadVal("text","",content + val); + } + } + p.second->lbl = content; + return p; +} + +/** + * Parses an HTML-style colour string, recognizing three-digit hex, six-digit hex, and HTML colour names. + */ +RGBColor cDialog::parseColor(string what){ + RGBColor clr; + if(what[0] == '#'){ + unsigned int r,g,b; + if(sscanf(what.c_str(),"#%2x%2x%2x",&r,&g,&b) < 3) + if(sscanf(what.c_str(),"#%1x%1x%1x",&r,&g,&b) < 3) + throw -1; + clr.red = r, clr.green = g, clr.blue = b; + }else if(what == "black") + clr.red = 0x00, clr.green = 0x00, clr.blue = 0x00; + else if(what == "red") + clr.red = 0xFF, clr.green = 0x00, clr.blue = 0x00; + else if(what == "lime") + clr.red = 0x00, clr.green = 0xFF, clr.blue = 0x00; + else if(what == "blue") + clr.red = 0x00, clr.green = 0x00, clr.blue = 0xFF; + else if(what == "yellow") + clr.red = 0xFF, clr.green = 0xFF, clr.blue = 0x00; + else if(what == "aqua") + clr.red = 0x00, clr.green = 0xFF, clr.blue = 0xFF; + else if(what == "fuchsia") + clr.red = 0xFF, clr.green = 0x00, clr.blue = 0xFF; + else if(what == "white") + clr.red = 0xFF, clr.green = 0xFF, clr.blue = 0xFF; + else if(what == "gray" || what == "grey") + clr.red = 0x80, clr.green = 0x80, clr.blue = 0x80; + else if(what == "maroon") + clr.red = 0x80, clr.green = 0x00, clr.blue = 0x00; + else if(what == "green") + clr.red = 0x00, clr.green = 0x80, clr.blue = 0x00; + else if(what == "navy") + clr.red = 0x00, clr.green = 0x00, clr.blue = 0x80; + else if(what == "olive") + clr.red = 0x80, clr.green = 0x80, clr.blue = 0x00; + else if(what == "teal") + clr.red = 0x00, clr.green = 0x80, clr.blue = 0x80; + else if(what == "purple") + clr.red = 0x80, clr.green = 0x00, clr.blue = 0x80; + else if(what == "silver") + clr.red = 0xC0, clr.green = 0xC0, clr.blue = 0xC0; + else throw -1; + clr.red *= clr.red; + clr.green *= clr.green; + clr.blue *= clr.blue; + return clr; +} + +template<> pair cDialog::parse(Element& who /*button*/){ + pair p; + Iterator attr; + Iterator node; + string name, val; + int width = 0, height = 0; + p.second = new cButton(this); + for(attr = attr.begin(&who); attr != attr.end(); attr++){ + attr->GetName(&name); + attr->GetValue(&val); + if(name == "name") + p.first = val; + else if(name == "wrap") if(val == "true") + p.second->wrapLabel = true; + else if(name == "type"){ + if(val == "small") + p.second->type = BTN_SM; + else if(val == "regular") + p.second->type = BTN_REG; + else if(val == "large") + p.second->type = BTN_LG; + else if(val == "help") + p.second->type = BTN_HELP; + else if(val == "left") + p.second->type = BTN_LEFT; + else if(val == "right") + p.second->type = BTN_RIGHT; + else if(val == "up") + p.second->type = BTN_UP; + else if(val == "down") + p.second->type = BTN_DOWN; + else if(val == "tiny") + p.second->type = BTN_TINY; + else if(val == "done") + p.second->type = BTN_DONE; + else if(val == "tall") + p.second->type = BTN_TALL; + else if(val == "trait") + p.second->type = BTN_TRAIT; + else if(val == "push") + p.second->type = BTN_PUSH; + }else if(name == "def-key"){ + try{ + p.second->key = parseKey(val); + }catch(int){ + throw xBadVal("button",name,val); + } + }else if(name == "fromlist") + p.second->fromList = val; + else if(name == "top"){ + istringstream sin(val); + sin >> p.second->frame.top; + }else if(name == "left"){ + istringstream sin(val); + sin >> p.second->frame.left; + }else if(name == "width"){ + istringstream sin; + sin >> width; + }else if(name == "height"){ + istringstream sin; + sin >> height; + }else throw xBadAttr("button",name); + } + if(width > 0 || height > 0) { + p.second->frame.right = p.second->frame.left + width; + p.second->frame.bottom = p.second->frame.top + height; + }else switch(p.second->type){ + case BTN_SM: + p.second->frame.right = p.second->frame.left + 23; + p.second->frame.bottom = p.second->frame.top + 23; + break; + case BTN_LG: + p.second->frame.right = p.second->frame.left + 102; + p.second->frame.bottom = p.second->frame.top + 23; + break; + case BTN_HELP: + p.second->frame.right = p.second->frame.left + 16; + p.second->frame.bottom = p.second->frame.top + 13; + break; + case BTN_TINY: + case BTN_LED: // this should never happen + p.second->frame.right = p.second->frame.left + 14; + p.second->frame.bottom = p.second->frame.top + 10; + break; + case BTN_TALL: + case BTN_TRAIT: + p.second->frame.right = p.second->frame.left + 63; + p.second->frame.bottom = p.second->frame.top + 40; + break; + case BTN_PUSH: + p.second->frame.right = p.second->frame.left + 30; + p.second->frame.bottom = p.second->frame.top + 30; + break; + default: + p.second->frame.right = p.second->frame.left + 63; + p.second->frame.bottom = p.second->frame.top + 23; + } + string content; + for(node = node.begin(&who); node != node.end(); node++){ + string val; + int type = node->Type(); + node->GetValue(&val); + if(type == TiXmlNode::ELEMENT && val == "key"){ + if(content.length() > 0) throw xBadVal("button","",content + val); + p.second->labelWithKey = true; + }else if(type == TiXmlNode::TEXT) content += val; + else{ + val = '<' + val + '>'; + throw xBadVal("text","",val); + } + } + p.second->lbl = content; + return p; +} + +cKey cDialog::parseKey(string what){ + cKey key; + key.spec = false; + key.c = 0; + key.mod = mod_none; + istringstream sin(what); + string parts[4]; + sin >> parts[0] >> parts[1] >> parts[2] >> parts[3]; + for(int i = 0; i < 4; i++){ + if(parts[i] == "ctrl") key.mod += mod_ctrl; + else if(parts[i] == "alt") key.mod += mod_alt; + else if(parts[i] == "shift") key.mod += mod_shift; + else if(parts[i] == "left") { + key.spec = true; + key.k = key_left; + break; + }else if(parts[i] == "right") { + key.spec = true; + key.k = key_right; + break; + }else if(parts[i] == "up") { + key.spec = true; + key.k = key_up; + break; + }else if(parts[i] == "down") { + key.spec = true; + key.k = key_down; + break; + }else if(parts[i] == "esc") { + key.spec = true; + key.k = key_esc; + break; + }else if(parts[i] == "enter" || parts[i] == "return") { + key.spec = true; + key.k = key_enter; + break; + }else if(parts[i] == "tab") { + key.spec = true; + key.k = key_tab; + break; + }else if(parts[i] == "help") { + key.spec = true; + key.k = key_help; + break; + }else if(parts[i] == "space") { + key.c = ' '; + break; + }else if(parts[i].length() == 1) { + key.c = parts[i][0]; + break; + }else throw -1; + } + return key; +} + +template<> pair cDialog::parse(Element& who /*LED*/){ + pair p; + Iterator attr; + Iterator node; + string name, val; + int width = 0, height = 0; + p.second = new cLed(this); + for(attr = attr.begin(&who); attr != attr.end(); attr++){ + attr->GetName(&name); + attr->GetValue(&val); + if(name == "name") + p.first = val; + else if(name == "state"){ + if(val == "red") p.second->state = led_red; + else if(val == "green") p.second->state = led_green; + else if(val == "off") p.second->state = led_off; + else throw xBadVal("led",name,val); + }else if(name == "fromlist") + p.second->fromList = val; + else if(name == "font"){ + if(val == "dungeon") + p.second->textFont = DUNGEON; + else if(val == "geneva") + p.second->textFont = GENEVA; + else if(val == "silom") + p.second->textFont = SILOM; + else if(val == "maidenword") + p.second->textFont = MAIDENWORD; + else throw xBadVal("text",name,val); + }else if(name == "size"){ + if(val == "large") + p.second->textSize = 12; + else if(val == "small") + p.second->textSize = 10; + else throw xBadVal("text",name,val); + }else if(name == "color" || name == "colour"){ + RGBColor clr; + try{ + clr = parseColor(val); + }catch(int){ + throw xBadVal("text",name,val); + } + p.second->color = clr; + }else if(name == "top"){ + istringstream sin(val); + sin >> p.second->frame.top; + }else if(name == "left"){ + istringstream sin(val); + sin >> p.second->frame.left; + }else if(name == "width"){ + istringstream sin; + sin >> width; + }else if(name == "height"){ + istringstream sin; + sin >> height; + }else throw xBadAttr("button",name); + } + if(width > 0 || height > 0) { + p.second->frame.right = p.second->frame.left + width; + p.second->frame.bottom = p.second->frame.top + height; + }else{ + p.second->frame.right = p.second->frame.left + 14; + p.second->frame.bottom = p.second->frame.top + 10; + } + string content; + for(node = node.begin(&who); node != node.end(); node++){ + string val; + int type = node->Type(); + node->GetValue(&val); + if(type == TiXmlNode::TEXT) content += val; + else{ + val = '<' + val + '>'; + throw xBadVal("text","",content + val); + } + } + p.second->lbl = content; + return p; +} + +template<> pair cDialog::parse(Element& who /*group*/){ + pair p; + Iterator attr; + Iterator node; + string name, val; + p.second = new cLedGroup(this); + for(attr = attr.begin(&who); attr != attr.end(); attr++){ + attr->GetName(&name); + attr->GetValue(&val); + if(name == "name") + p.first = val; + else if(name == "fromlist") + p.second->fromList = val; + else throw xBadAttr("button",name); + } + string content; + for(node = node.begin(&who); node != node.end(); node++){ + string val; + int type = node->Type(); + node->GetValue(&val); + if(type == TiXmlNode::ELEMENT && val == "led"){ + p.second->choices.insert(parse(*node)); + }else{ + val = '<' + val + '>'; + throw xBadVal("text","", content + val); + } + } + p.second->lbl = content; + return p; +} + +template<> pair cDialog::parse(Element& who /*field*/){ + pair p; + Iterator attr; + Iterator node; + string name, val; + int width = 0, height = 0; + p.second = new cTextField(this); + for(attr = attr.begin(&who); attr != attr.end(); attr++){ + attr->GetName(&name); + attr->GetValue(&val); + if(name == "name") + p.first = val; + else if(name == "type"){ + if(val == "num") + p.second->isNumericField = true; + else if(val == "text") + p.second->isNumericField = false; + else throw xBadVal("field",name,val); + }else if(name == "top"){ + istringstream sin(val); + sin >> p.second->frame.top; + }else if(name == "left"){ + istringstream sin(val); + sin >> p.second->frame.left; + }else if(name == "width"){ + istringstream sin; + sin >> width; + }else if(name == "height"){ + istringstream sin; + sin >> height; + }else throw xBadAttr("button",name); + } + p.second->frame.right = p.second->frame.left + width; + p.second->frame.bottom = p.second->frame.top + height; + return p; +} + +cDialog::cDialog(string path){ + try{ + Document xml(path); + xml.LoadFile(); + + Iterator attr; + Iterator node; + string type, name, val; + + xml.GetValue(&type); + if(type != "dialog") throw xBadNode(type); + for(attr = attr.begin(&xml); attr != attr.end(); attr++){ + attr->GetName(&name); + attr->GetValue(&val); + if(name == "skin"){ + if(val == "light") bg = BG_LIGHT; + else if(val == "dark") bg = BG_DARK; + else{ + istringstream sin(val); + sin >> bg; + if(sin.fail()) throw xBadVal(type,name,val); + } + }else if(name != "debug") + throw xBadAttr(type,name); + } + + for(node = node.begin(xml.FirstChildElement()); node != node.end(); node++){ + node->GetValue(&type); + // Yes, I'm using insert instead of [] to add elements to the map. + // In this situation, it's actually easier that way; the reason being, the + // map key is obtained from the name attribute of each element. + if(type == "field") + controls.insert(parse(*node)); + else if(type == "text") + controls.insert(parse(*node)); + else if(type == "pict") + controls.insert(parse(*node)); + else if(type == "button") + controls.insert(parse(*node)); + else if(type == "led") + controls.insert(parse(*node)); + else if(type == "group") + controls.insert(parse(*node)); + else throw xBadNode(type); + } + } catch(Exception& x){ // XML processing exception + printf(x.what()); + } catch(xBadVal& x){ // Invalid value for an attribute + printf(x.what()); + } catch(xBadAttr& x){ // Invalid attribute for an element + printf(x.what()); + } catch(xBadNode& x){ // Invalid element + printf(x.what()); + } + dialogNotToast = true; + bg = BG_DARK; // default is dark background + // now calculate window rect + SetRect(&winRect,0,0,0,0); + ctrlIter iter = controls.begin(); + currentFocus = NULL; + while(iter != controls.end()){ + if(iter->second->frame.right > winRect.right) + winRect.right = iter->second->frame.right; + if(iter->second->frame.bottom > winRect.bottom) + winRect.bottom = iter->second->frame.bottom; + if(typeid(iter->second) == typeid(cTextField*)){ + cTextField* fld = (cTextField*) iter->second; + if(currentFocus == NULL) currentFocus = fld; + // TODO: Should probably create controls and put them in the window? + } + iter++; + } + winRect.right += 4; + winRect.bottom += 4; + win = NewCWindow(NULL, &winRect, (unsigned char*) "", false, dBoxProc, IN_FRONT, false, 0); +} + +void cDialog::init(){ + cControl::init(); + cButton::init(); + cLed::init(); + cPict::init(); +} + +cDialog::~cDialog(){ + ctrlIter iter = controls.begin(); + while(iter != controls.end()){ + delete iter->second; + iter++; + } + DisposeWindow(win); +} + +bool cDialog::add(cControl* what, std::string key){ + // First make sure the key is not already present. + // If it is, we can't add the control, so return false. + if(controls.find(key) != controls.end()) return false; + controls.insert(std::make_pair(key,what)); + return true; +} + +bool cDialog::remove(std::string key){ + ctrlIter ctrl = controls.find(key); + if(ctrl == controls.end()) return false; + delete ctrl->second; + controls.erase(ctrl); + return true; +} + +void cDialog::run(){ + char c, k; + cKey key; + EventRecord currentEvent; + std::string itemHit = ""; + dialogNotToast = true; + ShowWindow(win); + BeginAppModalStateForWindow(win); + while(dialogNotToast){ + WaitNextEvent(everyEvent, ¤tEvent, SLEEP_TICKS, MOUSE_REGION); + switch(currentEvent.what){ + case updateEvt: + BeginUpdate(win); + draw(); + EndUpdate(win); + break; + case keyDown: + case autoKey: + c = currentEvent.message & charCodeMask; + k = (currentEvent.message & keyCodeMask) >> 8; + switch(k){ + case 126: + key.spec = true; + key.k = key_up; + break; + case 124: + key.spec = true; + key.k = key_right; + break; + case 123: + key.spec = true; + key.k = key_left; + break; + case 125: + key.spec = true; + key.k = key_down; + break; + case 53: + key.spec = true; + key.k = key_esc; + break; + case 36: case 76: + key.spec = true; + key.k = key_enter; + break; + // TODO: Add cases for key_tab and key_help + default: + key.spec = false; + key.c = c; + break; + } + key.mod = mod_none; + if(currentEvent.modifiers & cmdKey){ + if(key.spec){ + if(key.k == key_left) key.k = key_home; + else if(key.k == key_right) key.k = key_end; + else if(key.k == key_up) key.k = key_pgup; + else if(key.k == key_down) key.k = key_pgdn; + else key.mod += mod_ctrl; + }else key.mod += mod_ctrl; + }if(currentEvent.modifiers & shiftKey) key.mod += mod_shift; + if(currentEvent.modifiers & alphaLock) key.mod += mod_shift; + if(currentEvent.modifiers & optionKey) key.mod += mod_alt; + if(currentEvent.modifiers & controlKey) key.mod += mod_ctrl; + if(currentEvent.modifiers & rightShiftKey) key.mod += mod_shift; + if(currentEvent.modifiers & rightOptionKey) key.mod += mod_alt; + if(currentEvent.modifiers & rightControlKey) key.mod += mod_ctrl; + itemHit = process_keystroke(key); // TODO: This should be a separate check from the fields thing? + if(typeid(controls[itemHit]) == typeid(cTextField*)){ + if(!key.spec || key.k == key_bsp || key.k == key_del || key.k == key_home || + key.k == key_end || key.k == key_pgup || key.k == key_pgdn || + key.k == key_left || key.k == key_right || key.k == key_up || key.k == key_down){ + // TODO: If the dialog contains a field, handle it here. + // Basically, we should end up here if the user is typing into the field. + itemHit = ""; + }else if(key.spec && key.k == key_tab){ + // TODO: Tabbing through fields, and trigger focus events. + ctrlIter cur = controls.find(itemHit), iter; + if(!cur->second->triggerFocusHandler(*this,itemHit,true)) break; + iter = cur; + while(iter != cur){ + if(typeid(iter->second) == typeid(cTextField*)){ + if(iter->second->triggerFocusHandler(*this,iter->first,false)){ + currentFocus = (cTextField*) iter->second; + itemHit = ""; + break; + } + } + iter++; + if(iter == controls.end()) iter = controls.begin(); + } + if(iter == cur) // no focus change occured! + ; // TODO: Surely something should happen here? + } + } + break; + case mouseDown: + if(!PtInRect(currentEvent.where,&winRect)) break; // may be superfluous? + key.mod = mod_none; + if(currentEvent.modifiers & cmdKey) key.mod += mod_ctrl; + if(currentEvent.modifiers & shiftKey) key.mod += mod_shift; + if(currentEvent.modifiers & alphaLock) key.mod += mod_shift; + if(currentEvent.modifiers & optionKey) key.mod += mod_alt; + if(currentEvent.modifiers & controlKey) key.mod += mod_ctrl; + if(currentEvent.modifiers & rightShiftKey) key.mod += mod_shift; + if(currentEvent.modifiers & rightOptionKey) key.mod += mod_alt; + if(currentEvent.modifiers & rightControlKey) key.mod += mod_ctrl; + itemHit = process_click(currentEvent.where,key.mod); + break; + } + ctrlIter ctrl = controls.find(itemHit); + if(ctrl != controls.end()) ctrl->second->triggerClickHandler(*this,itemHit,key.mod); + } + EndAppModalStateForWindow(win); + HideWindow(win); +} + +void cDialog::setBg(short n){ + bg = n; +} + +void cDialog::setDefTextClr(RGBColor clr){ + defTextClr = clr; +} + +void cDialog::toast(){ + dialogNotToast = false; +} + +std::string cDialog::process_keystroke(cKey keyHit){ + unsigned long dummy; + ctrlIter iter = controls.begin(); + while(iter != controls.end()){ + if(iter->second->visible && iter->second->isClickable() && iter->second->key == keyHit){ + iter->second->depressed = true; + iter->second->draw(); + if (play_sounds) { + if(typeid(iter->second) == typeid(cLed*)) + play_sound(34); + else play_sound(37); + Delay(6,&dummy); + } + else Delay(14,&dummy); + iter->second->depressed = false; + iter->second->draw(); + Delay(8,&dummy); + return iter->first; + } + iter++; + } + // If you get an escape and it isn't processed, make it an enter. + if(keyHit.spec && keyHit.k == key_esc){ + keyHit.k = key_enter; + return process_keystroke(keyHit); + } + return ""; +} + +std::string cDialog::process_click(Point where, eKeyMod mods){ + ctrlIter iter = controls.begin(); + while(iter != controls.end()){ + if(iter->second->visible && iter->second->isClickable() && PtInRect(where,&iter->second->frame)){ + if(iter->second->handleClick()) + return iter->first; + else return ""; + } + iter++; + } + return ""; +} + +xBadNode::xBadNode(std::string t) throw() : type(t), msg(NULL) {} + +const char* xBadNode::what() throw() { + if(msg == NULL){ + char* s = new (nothrow) char[100]; + if(s == NULL){ + printf("Allocation of memory for error message failed, bailing out..."); + abort(); + } + sprintf(s,"XML Parse Error: Unknown element %s encountered.",type.c_str()); + msg = s; + } + return msg; +} + +xBadNode::~xBadNode() throw(){ + if(msg != NULL) delete msg; +} + +xBadAttr::xBadAttr(std::string t, std::string n) throw() : type(t), name(n), msg(NULL) {} + +const char* xBadAttr::what() throw() { + if(msg == NULL){ + char* s = new (nothrow) char[100]; + if(s == NULL){ + printf("Allocation of memory for error message failed, bailing out..."); + abort(); + } + sprintf(s,"XML Parse Error: Unknown attribute %s encountered on element %s.",name.c_str(),type.c_str()); + msg = s; + } + return msg; +} + +xBadAttr::~xBadAttr() throw(){ + if(msg != NULL) delete msg; +} + +xBadVal::xBadVal(std::string t, std::string n, std::string v) throw() : type(t), name(n), val(v), msg(NULL) {} + +const char* xBadVal::what() throw() { + if(msg == NULL){ + char* s = new (nothrow) char[100]; + if(s == NULL){ + printf("Allocation of memory for error message failed, bailing out..."); + abort(); + } + sprintf(s,"XML Parse Error: Invalid value %s for attribute %s encountered on element %s.",val.c_str(),name.c_str(),type.c_str()); + msg = s; + } + return msg; +} + +xBadVal::~xBadVal() throw(){ + if(msg != NULL) delete msg; +} + +void cDialog::draw(){ + GrafPtr old_port; + GetPort(&old_port); + SetPortWindowPort(win); + FillCRect(&winRect,::bg[bg]); + + ctrlIter iter = controls.begin(); + while(iter != controls.end()){ + iter->second->draw(); + iter++; + } + + SetPort(old_port); +} diff --git a/osx/dialogxml/dialog.css b/osx/dialogxml/dialog.css new file mode 100644 index 00000000..6d82b131 --- /dev/null +++ b/osx/dialogxml/dialog.css @@ -0,0 +1,145 @@ +* { + position: absolute; + display: block; + margin: 0px; +} + +.debug { + border: dotted black thin; +} + +title { + display:none; +} + +.dialog { + border: dashed green thin; +} + +.text, .led, .button, .field { + overflow: hidden ! important; +} + +.pict { + padding: 2px; + border: inset black thin; + background-repeat: no-repeat; + background-position: center; +} + +.pict.dlog { + width: 36px; + height: 36px; +} + +.pict.ter , .pict.teranim , .pict.item , +.pict.monst , .pict.field , .pict.boom , +.pict.pc { + width: 28px; + height: 36px; +} + +.pict.scen , .pict.talk { + width: 32px; + height: 32px; +} + +.pict.missile { + width: 18px; + height: 18px; +} + +.pict.scen.large { + width: 64px; + height: 64px; +} + +.pict.dlog.large { + width: 72px; + height: 72px; +} + +.button , .led { + padding: 0px; + background-repeat: no-repeat; + background-position: center; + text-align: center; + font-size: 12px; + font-family: Silom; + vertical-align: middle; + padding-top: 6px; +} + +.button.small { + width: 23px; + height: 23px; +} + +.button.regular , .button.left , .button.right , +.button.up , .button.down , .button.done { + width: 63px; + height: 23px; +} + +.button.large { + width: 102px; + height: 23px; +} + +.button.help { + width: 16px; + height: 13px; +} + +.button.tiny , .led { + min-width: 14px; + height: 10px; + text-align: left; + background-position: left center; + padding-left: 18px; + padding-top: 0px; + padding-bottom: 5px; + font-family: Geneva; + font-size: 10px; +} + +.button.tall , .button.trait { + width: 63px; + height: 40px; + padding-top: 22px; +} + +.button.push { + min-width: 30px; + height: 30px; + background-position: top center; + padding-top: 30px; +} + +.field { + padding: 2px; + border: solid black thin; +} + +.field-inner { + background-color:white; +} + +.text { + font-size: 10px; + font-family: Silom; + line-height: 12px; +} + +.text.framed { + padding: 2px; + border: inset thin black; +} + +.text.large { + font-size: 12px; +} + +.text.plain { + font-family: Geneva; +} \ No newline at end of file diff --git a/osx/dialogxml/dialog.dtd b/osx/dialogxml/dialog.dtd new file mode 100644 index 00000000..dde7cabb --- /dev/null +++ b/osx/dialogxml/dialog.dtd @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/osx/dialogxml/dialog.h b/osx/dialogxml/dialog.h new file mode 100644 index 00000000..ad6ebd23 --- /dev/null +++ b/osx/dialogxml/dialog.h @@ -0,0 +1,88 @@ +/* + * dialog.h + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#ifndef DIALOG_H +#define DIALOG_H + +#include +#include +#include + +#include "ticpp.h" + +#include "control.h" +#include "button.h" +#include "field.h" +#include "pict.h" +#include "message.h" + +class cDialog { + typedef std::map::iterator ctrlIter; + std::map controls; + short bg; + RGBColor defTextClr; + template std::pair parse(ticpp::Element& who); + RGBColor parseColor(std::string what); + cKey parseKey(std::string what); + WindowRef win; + cTextField* currentFocus; +public: + static const short BG_LIGHT, BG_DARK; + static void init(); // must call this before constructing any dialogs + cDialog(std::string path); // cd_create_dialog + cDialog(std::string path,cDialog parent); // cd_create_dialog_parent_num + ~cDialog(); // cd_kill_dialog + bool add(cControl* what, std::string key); // returns false if the key is used, true if the control was added + bool remove(std::string key); // returns true if the key existed and was removed, false if the key did not exist + void run(); // cd_run_dialog + //template type getResult(); // This seems like an unimplementable function + void setBg(short n); + void setDefTextClr(RGBColor clr); + void toast(); +private: + void draw(); + std::string process_keystroke(cKey keyHit); + std::string process_click(Point where, eKeyMod mods); + bool dialogNotToast; + Rect winRect; + friend class cControl; + friend class cButton; + friend class cLed; + friend class cLedGroup; + friend class cPict; + friend class cTextField; + friend class cTextMsg; +}; + +class xBadNode : std::exception { + std::string type; + const char* msg; +public: + xBadNode(std::string t) throw(); + ~xBadNode() throw(); + const char* what() throw(); +}; + +class xBadAttr : std::exception { + std::string type, name; + const char* msg; +public: + xBadAttr(std::string t,std::string n) throw(); + ~xBadAttr() throw(); + const char* what() throw(); +}; + +class xBadVal : std::exception { + std::string type, name, val; + const char* msg; +public: + xBadVal(std::string t,std::string n,std::string v) throw(); + ~xBadVal() throw(); + const char* what() throw(); +}; +#endif diff --git a/osx/dialogxml/dialog.xsl b/osx/dialogxml/dialog.xsl new file mode 100644 index 00000000..0c88a343 --- /dev/null +++ b/osx/dialogxml/dialog.xsl @@ -0,0 +1,164 @@ + + + + + + + + + + +Dialog Preview + + + + + +background-image: url('bg/.png'); + +
+ + + +
+ pict + + background-image: url('other/.png'); + left: px; top: px; + width: px; height: px; + +
+
+ +
+ pict + + background-color: black; + left: px; top: px; + +
+
+ +
+ pict large + + background-image: url('/large.png'); + left: px; top: px; + +
+
+ +
+ pict + + background-image: url('/.png'); + left: px; top: px; + +
+
+
+
+ + +
+ + button + + + background-image: url('button/.png'); + left: px; top: px; + width: ; + + +
+
+ + +
+ + led + debug + + + color: ; + font-family: + + Geneva + Silom + + ; + background-image: url('button/led-.png'); + left: px; top: px; + width: px; + + +
+
+ + +
+ + led + debug + + + color: ; + font-family: + + Geneva + Silom + + ; + border-color: red; + background-image: url('button/led-.png'); + left: px; top: px; + width: px; + + +
+
+ + +
+ + text + framed + large + debug + + + color: ; + font-family: ; + left: px; top: px; + width: px; height: px; + + +
+
+ + +
+ + left: px; top: px; + width: px; height: px; + +
+ + width: px; height: px; + font-family: Geneva; + font-size: 12px; + + () +
+
+
+
+ + + +
+ +
\ No newline at end of file diff --git a/osx/dialogxml/dlogutil.cpp b/osx/dialogxml/dlogutil.cpp new file mode 100644 index 00000000..b2153d6a --- /dev/null +++ b/osx/dialogxml/dlogutil.cpp @@ -0,0 +1,14 @@ +/* + * dlogutil.cpp + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#include +using namespace std; + +#include "dialog.h" +#include "dlogutil.h" + diff --git a/osx/dialogxml/dlogutil.h b/osx/dialogxml/dlogutil.h new file mode 100644 index 00000000..6e908fd5 --- /dev/null +++ b/osx/dialogxml/dlogutil.h @@ -0,0 +1,82 @@ +/* + * dlogutil.h + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#ifndef DIALOG_UTIL_H +#define DIALOG_UTIL_H + +#include +#include + +typedef void (*record_callback_t)(std::string,std::string); + +class cStrDlog { + cDialog dlg, *parent; + std::string str1, str2, title; + short sound; + record_callback_t rec_f; + bool onRecord(cDialog& me, std::string id); + bool onDismiss(cDialog& me, std::string id); +public: + cStrDlog(std::string str) : dlg("1str.xml") {} + cStrDlog(std::string str1, std::string str2, bool hasTitle) : dlg(hasTitle ? "1str-title.xml" : "2str.xml") {} + cStrDlog(std::string str1, std::string str2, std::string title) : dlg("2str-title.xml") {} + cStrDlog& setPict(short num, ePicType type); + cStrDlog& setSound(short num); + cStrDlog& setParent(cDialog* parent); + void show(); +}; + +class cChoiceDlog { + cDialog dlg, *parent; + bool onClick(cDialog& me, std::string id); +public: + cChoiceDlog(std::string str) : dlg(str) {} + cChoiceDlog& setParent(cDialog* parent); + std::string show(); +}; + +class cThreeChoice : public cChoiceDlog { +public: + cThreeChoice(std::string str) : cChoiceDlog("1str-3-c.xml") {} + cThreeChoice(std::string str1, std::string str2) : cChoiceDlog("2str-3-c.xml") {} + cThreeChoice(std::string str1, std::string str2, std::string str3) : cChoiceDlog("3str-3-c.xml") {} + cThreeChoice(std::string str1, std::string str2, std::string str3, std::string str4) : cChoiceDlog("4str-3-c.xml") {} + cThreeChoice(std::string str1, std::string str2, std::string str3, std::string str4, std::string str5) : cChoiceDlog("5str-3-c.xml") {} + cThreeChoice(std::string str1, std::string str2, std::string str3, std::string str4, std::string str5, std::string str6) : cChoiceDlog("6str-3-c.xml") {} + cThreeChoice& setPict(short num, ePicType type); + cThreeChoice& setParent(cDialog* parent); + string show(); +}; + +class cStringChoice { + cDialog dlg, *parent; + bool onLeft(cDialog& me, std::string id); + bool onRight(cDialog& me, std::string id); + bool onCancel(cDialog& me, std::string id); + bool onOkay(cDialog& me, std::string id); +public: + cStringChoice(std::vector& strs); + cStringChoice(std::vector::iterator begin, std::vector::iterator end); + size_t show(); // returns the _index_ of the chosen string +}; + +class cPictChoice { + cDialog dlg, *parent; + bool onLeft(cDialog& me, std::string id); + bool onRight(cDialog& me, std::string id); + bool onCancel(cDialog& me, std::string id); + bool onOkay(cDialog& me, std::string id); +public: + cPictChoice(std::vector& pics, ePicType type); + cPictChoice(std::vector::iterator begin, std::vector::iterator end, ePicType type); + short show(); // returns the _number_ of the chosen picture, _not_ the index; there's no way to distinguish between duplicates +}; +#endif + +void giveError(std::string str1, std::string str2, short err, cDialog* parent = NULL); +void oopsError(short error,short code = 0, short mode = 0); diff --git a/osx/dialogxml/edit-terrain.dlg b/osx/dialogxml/edit-terrain.dlg new file mode 100644 index 00000000..50e69ee5 --- /dev/null +++ b/osx/dialogxml/edit-terrain.dlg @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + Edit Terrain Type + Terrain number: + Terrain type name: + Terrain picture: + Terrain blockage: + + Clear + Walk through, opaque + Clear, special + Clear, blocked + Blocked, obstructed + Blocked, opaque + + Can fly over? + Can boat over? + Blocked to horses? + Step on sound: + + Footstep + Squish + Crunch + Silence + Big Splash + + Special properties: + + None + Change when step on + Damaging terrain + Is a bridge + Change while occupied + Dangerous terrain + Reserved + Crumbling terrain + Lockable terrain + Unlockable terrain + Reserved + Is a sign + Call special when step + Reserved + Is a container + Waterfall + Conveyor belt + Reserved + Reserved + Reserved + Blocked to monsters + Town entrance + Change when used + Call special when used + + Shortcut key: + Light radius: + Transform to what? + Extra values: + *flag1 + + *flag2 + + *flag3 + + Enter properties for this terrain type. For a detailed description of the fields, see the documentation. Note that, for terrain types 90 and below, only changes to the picture and shortcut key will be recorded. + + \ No newline at end of file diff --git a/osx/dialogxml/field.cpp b/osx/dialogxml/field.cpp new file mode 100644 index 00000000..21e013bd --- /dev/null +++ b/osx/dialogxml/field.cpp @@ -0,0 +1,87 @@ +/* + * field.cpp + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#include +#include "dialog.h" + +void cTextField::attachClickHandler(click_callback_t f __attribute__((unused))) throw(xHandlerNotSupported){ + throw xHandlerNotSupported(false); +} + +void cTextField::attachFocusHandler(focus_callback_t f __attribute__((unused))) throw(){ + onFocus = f; +} + +bool cTextField::triggerFocusHandler(cDialog& me, std::string id, bool losingFocus){ + // TODO: If isNumericField, verify that the contents are in fact a number. + if(onFocus != NULL) onFocus(me,id,losingFocus); + return true; +} + +void cTextField::setFormat(eFormat prop, short val __attribute__((unused))) throw(xUnsupportedProp){ + throw xUnsupportedProp(prop); +} + +short cTextField::getFormat(eFormat prop) throw(xUnsupportedProp){ + throw xUnsupportedProp(prop); +} + +void cTextField::setText(std::string what){ + char message[1024]; + strcpy(message,what.c_str()); + c2pstr(message); + OSErr err = SetControlData(theField,kControlEditTextPart,kControlEditTextTextTag,what.size() + 1,message); + if(isVisible()) draw(); +} + +std::string cTextField::getText(){ + unsigned char message[1024]; + OSErr err = GetControlData(theField,kControlEditTextPart,kControlEditTextTextTag,1024,message,NULL); + p2cstr(message); + return std::string((char*)message); +} + +void cTextField::setTextToNum(short what){ + std::ostringstream sout; + sout << what; + setText(sout.str()); +} + +short cTextField::getTextAsNum(){ + std::istringstream sin(getText()); + short n; + sin >> n; + return n; +} + +bool cTextField::isClickable(){ + return false; +} + +cTextField::cTextField(cDialog* parent) : cControl(parent) { + OSStatus err; + err = CreateEditTextControl(parent->win,&frame,NULL,false,true/*useInlineInput*/,NULL,&theField); +} + +cTextField::~cTextField(){ + DisposeControl(theField); +} + +void cTextField::show(){ + ShowControl(theField); + cControl::show(); +} + +void cTextField::hide(){ + HideControl(theField); + cControl::hide(); +} + +void cTextField::draw(){ + Draw1Control(theField); +} diff --git a/osx/dialogxml/field.h b/osx/dialogxml/field.h new file mode 100644 index 00000000..0f33da33 --- /dev/null +++ b/osx/dialogxml/field.h @@ -0,0 +1,38 @@ +/* + * field.h + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#ifndef FIELD_H +#define FIELD_H + +#include + +class cTextField : public cControl { +public: + void attachClickHandler(click_callback_t f) throw(xHandlerNotSupported); + void attachFocusHandler(focus_callback_t f) throw(); + bool triggerFocusHandler(cDialog& me, std::string id, bool losingFocus); + void setFormat(eFormat prop, short val) throw(xUnsupportedProp); + short getFormat(eFormat prop) throw(xUnsupportedProp); + std::string getText(); + void setText(std::string what); + short getTextAsNum(); + void setTextToNum(short what); + cTextField(cDialog* parent); + bool isClickable(); + virtual ~cTextField(); + void show(); + void hide(); +protected: + void draw(); +private: + friend class cDialog; + bool isNumericField; + focus_callback_t onFocus; + ControlRef theField; +}; +#endif diff --git a/osx/dialogxml/message.cpp b/osx/dialogxml/message.cpp new file mode 100644 index 00000000..fde47741 --- /dev/null +++ b/osx/dialogxml/message.cpp @@ -0,0 +1,140 @@ +/* + * message.cpp + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#include "graphtool.h" +#include "mathutil.h" +#include "dialog.h" + +void cTextMsg::attachClickHandler(click_callback_t f) throw(){ + onClick = f; +} + +void cTextMsg::attachFocusHandler(focus_callback_t f __attribute__((unused))) throw(xHandlerNotSupported){ + throw xHandlerNotSupported(true); +} + +bool cTextMsg::triggerClickHandler(cDialog& me, std::string id, eKeyMod mods){ + if(onClick != NULL) return onClick(me,id,mods); + return false; +} + +void cTextMsg::setFormat(eFormat prop, short val) throw(xUnsupportedProp){ + switch(prop){ + case TXT_COLOR: + { // TODO: Test this and see if it works as imagined + RGBColor clr; + unsigned char red, green, blue, bright; + red = (val & 0xF000) >> 12; + green = (val & 0x0F00) >> 8; + blue = (val & 0x00F0) >> 4; + bright = val & 0x000F; + red *= bright; + green *= bright; + blue *= bright; + clr.red = red * 257; + clr.green = green * 257; + clr.blue = blue * 257; + color = clr; + } + break; + case TXT_FRAME: + drawFramed = val; + break; + case TXT_SIZE: + textSize = val; + break; + case TXT_FONT: + if(val == DUNGEON) textFont = DUNGEON; + else if(val == GENEVA) textFont = GENEVA; + else if(val == MAIDENWORD) textFont = MAIDENWORD; + else textFont = SILOM; // Defaults to Silom if an invalid value is provided. + break; + case TXT_WRAP: + throw xUnsupportedProp(prop); + } +} + +short cTextMsg::getFormat(eFormat prop) throw(xUnsupportedProp){ + switch(prop){ + case TXT_COLOR: + { + unsigned char red, green, blue, bright; + short val; + red = color.red / 257; + green = color.green / 257; + blue = color.green / 257; + bright = gcd(red,gcd(green,blue)); + red /= bright; + green /= bright; + blue /= bright; + val |= bright; + val |= blue << 4; + val |= green << 8; + val |= red << 12; + return val; + } + case TXT_FRAME: + return drawFramed; + case TXT_SIZE: + return textSize; + case TXT_FONT: + return textFont; + case TXT_WRAP: + throw xUnsupportedProp(prop); + } + return 0; +} + +std::string cTextMsg::getText(){ + return getLabel(); +} + +void cTextMsg::setText(std::string what){ + setLabel(what); +} + +cTextMsg::cTextMsg(cDialog* parent) : cControl(parent) {} + +bool cTextMsg::isClickable(){ + return clickable; +} + +void cTextMsg::draw(){ + GrafPtr old_port; + Rect to_rect = frame; + + GetPort(&old_port); + SetPortWindowPort(parent->win); + FillCRect(&frame,bg[parent->bg]); + + if(visible){ + TextFont(font_nums[textFont]); + if(textFont == SILOM && !foundSilom()) TextFace(bold); + else TextFace(normal); + TextSize(textSize); + if(drawFramed) drawFrame(2,0); + RGBColor draw_color = color; + if(clickable && depressed){ + color.red = 65535 - color.red; + color.green = 65535 - color.green; + color.blue = 65535 - color.blue; + } + RGBForeColor(&draw_color); + if (to_rect.bottom - to_rect.top < 20) { // essentially, it's a single line + to_rect.left += 3; + char_win_draw_string(parent->win,to_rect,lbl.c_str(),3,12,false); + }else { + InsetRect(&to_rect,4,4); + char_win_draw_string(parent->win,to_rect,lbl.c_str(),0,textSize + 2,false); + } + } + + SetPort(old_port); +} + +cTextMsg::~cTextMsg() {} diff --git a/osx/dialogxml/message.h b/osx/dialogxml/message.h new file mode 100644 index 00000000..6bce28d6 --- /dev/null +++ b/osx/dialogxml/message.h @@ -0,0 +1,37 @@ +/* + * message.h + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#ifndef MESSAGE_H +#define MESSAGE_H + +#include + +class cTextMsg : public cControl { +public: + void attachClickHandler(click_callback_t f) throw(); + void attachFocusHandler(focus_callback_t f) throw(xHandlerNotSupported); + bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods); + void setFormat(eFormat prop, short val) throw(xUnsupportedProp); + short getFormat(eFormat prop) throw(xUnsupportedProp); + std::string getText(); + void setText(std::string what); + cTextMsg(cDialog* parent); + bool isClickable(); + virtual ~cTextMsg(); +protected: + void draw(); +private: + friend class cDialog; + bool drawFramed, clickable; + short textSize; + eTextFont textFont; + RGBColor color; + std::string fromList; + click_callback_t onClick; +}; +#endif diff --git a/osx/dialogxml/pict.cpp b/osx/dialogxml/pict.cpp new file mode 100644 index 00000000..b1d0e993 --- /dev/null +++ b/osx/dialogxml/pict.cpp @@ -0,0 +1,1020 @@ +/* + * pict.cpp + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#include +#include +#include + +#include "graphtool.h" +#include "dialog.h" + +void cPict::init(){ + // TODO: Load or otherwise acquire the various GWorlds. + teranim = dlog = talk = scen = largeScen = item = tinyItem = pc = field = boom = missile = save = header = map = NULL; + drawPict[PIC_TER] = drawPresetTer; + drawPict[PIC_TER_ANIM] = drawPresetTerAnim; + drawPict[PIC_MONST] = drawPresetMonstSm; + drawPict[PIC_DLOG] = drawPresetDlog; + drawPict[PIC_TALK] = drawPresetTalk; + drawPict[PIC_SCEN] = drawPresetScen; + drawPict[PIC_ITEM] = drawPresetItem; + drawPict[PIC_PC] = drawPresetPc; + drawPict[PIC_FIELD] = drawPresetField; + drawPict[PIC_BOOM] = drawPresetBoom; + drawPict[PIC_FULL] = drawFullSheet; + drawPict[PIC_MISSILE] = drawPresetMissile; + drawPict[PIC_DLOG_LG] = drawPresetDlogLg; + drawPict[PIC_SCEN_LG] = drawPresetScenLg; + drawPict[PIC_TER_MAP] = drawPresetTerMap; + drawPict[PIC_MONST_WIDE] = drawPresetMonstWide; + drawPict[PIC_MONST_TALL] = drawPresetMonstTall; + drawPict[PIC_MONST_LG] = drawPresetMonstLg; + drawPict[PIC_CUSTOM_TER] = drawCustomTer; + drawPict[PIC_CUSTOM_TER_ANIM] = drawCustomTerAnim; + drawPict[PIC_CUSTOM_MONST] = drawCustomMonstSm; + drawPict[PIC_CUSTOM_DLOG] = drawCustomDlog; + drawPict[PIC_CUSTOM_TALK] = drawCustomTalk; + drawPict[PIC_CUSTOM_SCEN] = drawCustomTalk; + drawPict[PIC_CUSTOM_ITEM] = drawCustomItem; + drawPict[PIC_CUSTOM_FULL] = drawFullSheet; + drawPict[PIC_CUSTOM_MISSILE] = drawCustomMissile; + drawPict[PIC_CUSTOM_DLOG_LG] = drawCustomDlogLg; + drawPict[PIC_CUSTOM_TER_MAP] = drawCustomTerMap; + drawPict[PIC_CUSTOM_MONST_WIDE] = drawCustomMonstWide; + drawPict[PIC_CUSTOM_MONST_TALL] = drawCustomMonstTall; + drawPict[PIC_CUSTOM_MONST_LG] = drawCustomMonstLg; + drawPict[PIC_PARTY_MONST] = drawPartyMonstSm; + drawPict[PIC_PARTY_SCEN] = drawPartyScen; + drawPict[PIC_PARTY_ITEM] = drawPartyItem; + drawPict[PIC_PARTY_PC] = drawPartyPc; + drawPict[PIC_PARTY_MONST_WIDE] = drawPartyMonstWide; + drawPict[PIC_PARTY_MONST_TALL] = drawPartyMonstTall; + drawPict[PIC_PARTY_MONST_LG] = drawPartyMonstLg; +} + +void cPict::attachClickHandler(click_callback_t f) throw(){ + if(f == NULL){ + onClick = NULL; + clickable = false; + }else{ + onClick = f; + clickable = true; + } +} + +void cPict::attachFocusHandler(focus_callback_t f __attribute__((unused))) throw(xHandlerNotSupported){ + throw xHandlerNotSupported(true); +} + +bool cPict::triggerClickHandler(cDialog& me, std::string id, eKeyMod mods){ + if(onClick != NULL) return onClick(me,id,mods); + else return false; +} + +void cPict::setFormat(eFormat prop, short val) throw(xUnsupportedProp){ + if(prop == TXT_FRAME) drawFramed = val; + else throw xUnsupportedProp(prop); + if(isVisible()) draw(); +} + +short cPict::getFormat(eFormat prop) throw(xUnsupportedProp){ + if(prop == TXT_FRAME) return drawFramed; + else throw xUnsupportedProp(prop); +} + +void cPict::setSheet(eSheetType type, short n, GWorldPtr sheet){ + // Step one: verify + if(n < -1) throw std::out_of_range("Negative values for n, other than -1, are invalid."); + if(n == -1 && type == SHEET_FULL) + throw std::out_of_range("The value -1 for n is not valid in conjunction with SHEET_FULL."); + // Step two: set + size_t numSheets, num; + switch(type){ + case SHEET_TER: + numSheets = ter.size(); + if(n == -1) num = numSheets; else num = n; + if(num < numSheets) ter[num] = sheet; + else if(num == numSheets) ter.push_back(sheet); + else{ + ter.reserve(num+1); + while(num > ter.size()) ter.push_back(NULL); + ter.push_back(sheet); + } + break; + case SHEET_TER_ANIM: + teranim = sheet; + break; + case SHEET_MONST: + numSheets = monst.size(); + if(n == -1) num = numSheets; else num = n; + if(num < numSheets) monst[num] = sheet; + else if(num == numSheets) monst.push_back(sheet); + else{ + monst.reserve(num+1); + while(num > monst.size()) monst.push_back(NULL); + monst.push_back(sheet); + } + break; + case SHEET_DLOG: + dlog = sheet; + break; + case SHEET_TALK: + talk = sheet; + break; + case SHEET_SCEN: + scen = sheet; + break; + case SHEET_ITEM: + item = sheet; + break; + case SHEET_TINY_ITEM: + tinyItem = sheet; + break; + case SHEET_PC: + pc = sheet; + break; + case SHEET_FIELD: + field = sheet; + break; + case SHEET_BOOM: + boom = sheet; + break; + case SHEET_FULL: + largeSheets[n] = sheet; + break; + case SHEET_MISSILE: + missile = sheet; + break; + case SHEET_SCEN_LG: + largeScen = sheet; + break; + case SHEET_TER_MAP: + map = sheet; + break; + case SHEET_CUSTOM: + numSheets = customSheets.size(); + if(n == -1) num = numSheets; else num = n; + if(num < numSheets) customSheets[num] = sheet; + else if(num == numSheets) customSheets.push_back(sheet); + else{ + customSheets.reserve(num+1); + while(num > customSheets.size()) customSheets.push_back(NULL); + customSheets.push_back(sheet); + } + break; + case SHEET_PARTY: + save = sheet; + break; + case SHEET_HEADER: + header = sheet; + break; + } +} + +bool cPict::isSheetSet(eSheetType type, size_t num){ + switch(type){ + case SHEET_TER: + if(ter.size() <= num) return false; + else return ter[num]; + case SHEET_TER_ANIM: + return teranim; + case SHEET_MONST: + if(monst.size() <= num) return false; + else return monst[num]; + case SHEET_DLOG: + return dlog; + case SHEET_TALK: + return talk; + case SHEET_SCEN: + return scen; + case SHEET_SCEN_LG: + return largeScen; + case SHEET_ITEM: + return item; + case SHEET_TINY_ITEM: + return tinyItem; + case SHEET_PC: + return pc; + case SHEET_FIELD: + return field; + case SHEET_BOOM: + return boom; + case SHEET_MISSILE: + return missile; + case SHEET_PARTY: + return save; + case SHEET_TER_MAP: + return map; + case SHEET_FULL: + if(largeSheets.size() <= num) return false; + else return largeSheets[num]; + case SHEET_CUSTOM: + if(customSheets.size() <= num) return false; + else return customSheets[num]; + case SHEET_HEADER: + return header; + } + return false; +} + +void cPict::setPict(short num, ePicType type){ + picNum = num; + picType = type; + if(isVisible()) draw(); +} + +cPict::cPict(cDialog* parent) : cControl(parent) {} + +bool cPict::isClickable(){ + return clickable; +} + +ePicType operator+ (ePicType lhs, ePicTypeMod rhs){ + switch(rhs){ + case PIC_PRESET: // Adding this actually clears the custom and party modifiers + switch(lhs){ + case PIC_CUSTOM_TER: + return PIC_TER; + case PIC_CUSTOM_TER_ANIM: + return PIC_TER_ANIM; + case PIC_CUSTOM_MONST: + case PIC_PARTY_MONST: + return PIC_MONST; + case PIC_CUSTOM_DLOG: + return PIC_DLOG; + case PIC_CUSTOM_TALK: + return PIC_TALK; + case PIC_CUSTOM_SCEN: + case PIC_PARTY_SCEN: + return PIC_SCEN; + case PIC_CUSTOM_ITEM: + case PIC_PARTY_ITEM: + return PIC_ITEM; + case PIC_CUSTOM_FULL: + return PIC_FULL; + case PIC_CUSTOM_MISSILE: + return PIC_MISSILE; + case PIC_CUSTOM_DLOG_LG: + return PIC_DLOG_LG; + case PIC_CUSTOM_MONST_WIDE: + case PIC_PARTY_MONST_WIDE: + return PIC_MONST_WIDE; + case PIC_CUSTOM_MONST_TALL: + case PIC_PARTY_MONST_TALL: + return PIC_MONST_TALL; + case PIC_CUSTOM_MONST_LG: + case PIC_PARTY_MONST_LG: + return PIC_MONST_LG; + case PIC_PARTY_PC: + return PIC_PC; + case PIC_CUSTOM_TER_MAP: + return PIC_TER_MAP; + default: + return lhs; + } + case PIC_WIDE: + switch(lhs){ + case PIC_MONST: + return PIC_MONST_WIDE; + case PIC_MONST_TALL: + return PIC_MONST_LG; + case PIC_CUSTOM_MONST: + return PIC_CUSTOM_MONST_WIDE; + case PIC_CUSTOM_MONST_TALL: + return PIC_CUSTOM_MONST_LG; + case PIC_PARTY_MONST: + return PIC_PARTY_MONST_WIDE; + case PIC_PARTY_MONST_TALL: + return PIC_PARTY_MONST_LG; + default: + return lhs; + } + case PIC_TALL: + switch(lhs){ + case PIC_MONST: + return PIC_MONST_TALL; + case PIC_MONST_WIDE: + return PIC_MONST_LG; + case PIC_CUSTOM_MONST: + return PIC_CUSTOM_MONST_TALL; + case PIC_CUSTOM_MONST_WIDE: + return PIC_CUSTOM_MONST_LG; + case PIC_PARTY_MONST: + return PIC_PARTY_MONST_TALL; + case PIC_PARTY_MONST_WIDE: + return PIC_PARTY_MONST_LG; + default: + return lhs; + } + case PIC_CUSTOM: + switch(lhs){ + case PIC_TER: + return PIC_CUSTOM_TER; + case PIC_TER_ANIM: + return PIC_CUSTOM_TER_ANIM; + case PIC_MONST: + return PIC_CUSTOM_MONST; + case PIC_DLOG: + return PIC_CUSTOM_DLOG; + case PIC_TALK: + return PIC_CUSTOM_TALK; + case PIC_SCEN: + return PIC_CUSTOM_SCEN; + case PIC_ITEM: + return PIC_CUSTOM_ITEM; + case PIC_FULL: + return PIC_CUSTOM_FULL; + case PIC_MISSILE: + return PIC_CUSTOM_MISSILE; + case PIC_DLOG_LG: + return PIC_CUSTOM_DLOG_LG; + case PIC_TER_MAP: + return PIC_CUSTOM_TER_MAP; + case PIC_MONST_WIDE: + return PIC_CUSTOM_MONST_WIDE; + case PIC_MONST_TALL: + return PIC_CUSTOM_MONST_TALL; + case PIC_MONST_LG: + return PIC_CUSTOM_MONST_LG; + default: + return lhs; + } + case PIC_PARTY: + switch(lhs){ + case PIC_MONST: + return PIC_PARTY_MONST; + case PIC_SCEN: + return PIC_PARTY_SCEN; + case PIC_ITEM: + return PIC_PARTY_ITEM; + case PIC_PC: + return PIC_PARTY_PC; + case PIC_MONST_WIDE: + return PIC_PARTY_MONST_WIDE; + case PIC_MONST_TALL: + return PIC_PARTY_MONST_TALL; + case PIC_MONST_LG: + return PIC_PARTY_MONST_LG; + default: + return lhs; + } + } + return lhs; +} + +ePicType operator- (ePicType lhs, ePicTypeMod rhs){ + switch(rhs){ + case PIC_PRESET: + return lhs; + break; + case PIC_WIDE: + switch(lhs){ + case PIC_MONST_WIDE: + return PIC_MONST; + case PIC_MONST_LG: + return PIC_MONST_TALL; + case PIC_CUSTOM_MONST_WIDE: + return PIC_CUSTOM_MONST; + case PIC_CUSTOM_MONST_LG: + return PIC_CUSTOM_MONST_TALL; + case PIC_PARTY_MONST_WIDE: + return PIC_PARTY_MONST; + case PIC_PARTY_MONST_LG: + return PIC_PARTY_MONST_TALL; + default: + return lhs; + } + case PIC_TALL: + switch(lhs){ + case PIC_MONST_TALL: + return PIC_MONST; + case PIC_MONST_LG: + return PIC_MONST_WIDE; + case PIC_CUSTOM_MONST_TALL: + return PIC_CUSTOM_MONST; + case PIC_CUSTOM_MONST_LG: + return PIC_CUSTOM_MONST_WIDE; + case PIC_PARTY_MONST_TALL: + return PIC_PARTY_MONST; + case PIC_PARTY_MONST_LG: + return PIC_PARTY_MONST_WIDE; + default: + return lhs; + } + case PIC_CUSTOM: + switch(lhs){ + case PIC_CUSTOM_TER: + return PIC_TER; + case PIC_CUSTOM_TER_ANIM: + return PIC_TER_ANIM; + case PIC_CUSTOM_MONST: + return PIC_MONST; + case PIC_CUSTOM_DLOG: + return PIC_DLOG; + case PIC_CUSTOM_TALK: + return PIC_TALK; + case PIC_CUSTOM_SCEN: + return PIC_SCEN; + case PIC_CUSTOM_ITEM: + return PIC_ITEM; + case PIC_CUSTOM_FULL: + return PIC_FULL; + case PIC_CUSTOM_MISSILE: + return PIC_MISSILE; + case PIC_CUSTOM_DLOG_LG: + return PIC_DLOG_LG; + case PIC_CUSTOM_TER_MAP: + return PIC_TER_MAP; + case PIC_CUSTOM_MONST_WIDE: + return PIC_MONST_WIDE; + case PIC_CUSTOM_MONST_TALL: + return PIC_MONST_TALL; + case PIC_CUSTOM_MONST_LG: + return PIC_MONST_LG; + default: + return lhs; + } + case PIC_PARTY: + switch(lhs){ + case PIC_PARTY_MONST: + return PIC_MONST; + case PIC_PARTY_SCEN: + return PIC_SCEN; + case PIC_PARTY_ITEM: + return PIC_ITEM; + case PIC_PARTY_PC: + return PIC_PC; + case PIC_PARTY_MONST_WIDE: + return PIC_MONST_WIDE; + case PIC_PARTY_MONST_TALL: + return PIC_MONST_TALL; + case PIC_PARTY_MONST_LG: + return PIC_MONST_LG; + default: + return lhs; + } + } + return lhs; +} + +ePicType operator+ (ePicTypeMod lhs, ePicType rhs){ + return rhs + lhs; +} + +ePicType operator- (ePicTypeMod lhs, ePicType rhs){ + return rhs + lhs; +} + +ePicType& operator+= (ePicType& lhs, ePicTypeMod rhs){ + return lhs = lhs + rhs; +} + +ePicType& operator-= (ePicType& lhs, ePicTypeMod rhs){ + return lhs = lhs - rhs; +} + +GWorldPtr cPict::teranim = NULL, cPict::dlog = NULL, cPict::talk = NULL, cPict::scen = NULL, cPict::largeScen = NULL; +GWorldPtr cPict::item = NULL, cPict::tinyItem = NULL, cPict::pc = NULL, cPict::field = NULL, cPict::boom = NULL; +GWorldPtr cPict::missile = NULL, cPict::save = NULL, cPict::header = NULL, cPict::map = NULL; +std::vector cPict::ter, cPict::monst, cPict::customSheets; +std::map cPict::largeSheets; +std::map cPict::drawPict; +short cPict::animFrame = 0; + +void cPict::draw(){ + RGBColor store_color; + Rect rect = frame; + + if(!visible){ // Erase it + InsetRect(&rect, -3, -3); + FillCRect(&rect,bg[parent->bg]); + return; + } + if(picNum < 0) { // Just fill with black + GetForeColor(&store_color); + ForeColor(blackColor); + PaintRect(&rect); + RGBForeColor(&store_color); + return; + } + GetBackColor(&store_color); + BackColor(whiteColor); + + drawPict[picType](picNum,(GWorldPtr) parent->win,rect); + if(drawFramed) drawFrame(2,0); +} + +void cPict::drawPresetTer(short num, GWorldPtr to_gw, Rect to_rect){ + printf("Getting terrain icon from sheet %i.\n",num / 50); + GWorldPtr from_gw = ter[num / 50]; + num = num % 50; + Rect from_rect = calc_rect(num % 10, num / 10); + if (to_rect.right - to_rect.left > 28) + InsetRect(&to_rect,4,0); + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 0, 0); +} + +void cPict::drawPresetTerAnim(short num, GWorldPtr to_gw, Rect to_rect){ + Rect from_rect = calc_rect(4 * (num / 5) + animFrame, num % 5); + GWorldPtr from_gw = teranim; + printf("Getting animated terrain graphic %i from sheet 20", num); + if (to_rect.right - to_rect.left > 28) { + InsetRect(&to_rect,4,0); + to_rect.right = to_rect.left + 28; + } + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 0, 0); +} + +static Rect calcDefMonstRect(short i, short animFrame){ + Rect r = calc_rect(2 * (i / 10), i % 10); + switch(animFrame){ // Sequence is right-facing, attack, left-facing, attack + case 1: + OffsetRect(&r,112,0); + break; + case 2: + OffsetRect(&r,28,0); + break; + case 3: + OffsetRect(&r,140,0); + break; + } + return r; +} + +void cPict::drawPresetMonstSm(short num, GWorldPtr to_gw, Rect to_rect){ + short m_start_pic = m_pic_index[num].i; + GWorldPtr from_gw = monst[m_start_pic / 20]; + m_start_pic = m_start_pic % 20; + Rect from_rect = calcDefMonstRect(num, animFrame); + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 36; + PaintRect(&to_rect); + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 1, 0); +} + +void cPict::drawPresetMonstWide(short num, GWorldPtr to_gw, Rect to_rect){ + Rect small_monst_rect = {0,0,18,14}; + to_rect.right = to_rect.left + 28; to_rect.bottom = to_rect.top + 36; + PaintRect(&to_rect); + + short m_start_pic = m_pic_index[num].i; + GWorldPtr from_gw = monst[m_start_pic / 20]; + m_start_pic = m_start_pic % 20; + Rect from_rect = calcDefMonstRect(num, animFrame); + OffsetRect(&small_monst_rect,to_rect.left,to_rect.top + 7); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); + + m_start_pic = m_pic_index[num].i + 1; + from_gw = monst[m_start_pic / 20]; + m_start_pic = m_start_pic % 20; + from_rect = calcDefMonstRect(num, animFrame); + OffsetRect(&small_monst_rect,14,0); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); +} + +void cPict::drawPresetMonstTall(short num, GWorldPtr to_gw, Rect to_rect){ + Rect small_monst_rect = {0,0,18,14}; + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 36; + PaintRect(&to_rect); + + short m_start_pic = m_pic_index[num].i; + GWorldPtr from_gw = monst[m_start_pic / 20]; + m_start_pic = m_start_pic % 20; + Rect from_rect = calcDefMonstRect(num, animFrame); + OffsetRect(&small_monst_rect,to_rect.left + 7,to_rect.top); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); + + m_start_pic = m_pic_index[num].i + 1; + from_gw = monst[m_start_pic / 20]; + m_start_pic = m_start_pic % 20; + from_rect = calcDefMonstRect(num, animFrame); + OffsetRect(&small_monst_rect,0,18); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); +} + +void cPict::drawPresetMonstLg(short num, GWorldPtr to_gw, Rect to_rect){ + Rect small_monst_rect = {0,0,18,14}; + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 36; + PaintRect(&to_rect); + + short m_start_pic = m_pic_index[num].i; + GWorldPtr from_gw = monst[m_start_pic / 20]; + m_start_pic = m_start_pic % 20; + Rect from_rect = calcDefMonstRect(num, animFrame); + OffsetRect(&small_monst_rect,to_rect.left,to_rect.top); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); + + m_start_pic = m_pic_index[num].i + 1; + from_gw = monst[m_start_pic / 20]; + m_start_pic = m_start_pic % 20; + from_rect = calcDefMonstRect(num, animFrame); + OffsetRect(&small_monst_rect,14,0); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); + + m_start_pic = m_pic_index[num].i + 2; + from_gw = monst[m_start_pic / 20]; + m_start_pic = m_start_pic % 20; + from_rect = calcDefMonstRect(num, animFrame); + OffsetRect(&small_monst_rect,-14,18); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); + + m_start_pic = m_pic_index[num].i + 3; + from_gw = monst[m_start_pic / 20]; + m_start_pic = m_start_pic % 20; + from_rect = calcDefMonstRect(num, animFrame); + OffsetRect(&small_monst_rect,14,0); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); +} + +void cPict::drawPresetDlog(short num, GWorldPtr to_gw, Rect to_rect){ + to_rect.right = to_rect.left + 36; + to_rect.bottom = to_rect.top + 36; + GWorldPtr from_gw = dlog; + Rect from_rect = {0,0,36,36}; + OffsetRect(&from_rect,36 * (num % 4),36 * (num / 4)); + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 0, 0); +} + +void cPict::drawPresetDlogLg(short num, GWorldPtr to_gw, Rect to_rect){ + to_rect.right = to_rect.left + 72; + to_rect.bottom = to_rect.top + 72; + GWorldPtr from_gw = dlog; + Rect from_rect = {0,0,72,72}; + OffsetRect(&from_rect,36 * (num % 4),36 * (num / 4)); + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 0, 0); +} + +void cPict::drawPresetTalk(short num, GWorldPtr to_gw, Rect to_rect){ + num--; + to_rect.right = to_rect.left + 32; + to_rect.bottom = to_rect.top + 32; + GWorldPtr from_gw = talk; + Rect from_rect = {0,0,32,32}; + OffsetRect(&from_rect,32 * (num % 10),32 * (num / 10)); + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 0, 0); +} + +void cPict::drawPresetScen(short num, GWorldPtr to_gw, Rect to_rect){ + GWorldPtr from_gw = scen; + Rect from_rect = {0,0,32,32}; + OffsetRect(&from_rect,32 * (num % 5),32 * (num / 5)); + to_rect.right = to_rect.left + 32; + to_rect.bottom = to_rect.top + 32; + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 0, 0); +} + +void cPict::drawPresetScenLg(short num, GWorldPtr to_gw, Rect to_rect){ + GWorldPtr from_gw = largeScen; + to_rect.right = to_rect.left + 64; + to_rect.bottom = to_rect.top + 64; + Rect from_rect = {0,0,64,64}; + OffsetRect(&from_rect, num * 64, 0); + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 0, 0); +} + +void cPict::drawPresetItem(short num, GWorldPtr to_gw, Rect to_rect){ + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 36; + PaintRect(&to_rect); + GWorldPtr from_gw; + Rect from_rect = {0,0,18,18}; + if (num < 45) { + from_gw = item; + from_rect = calc_rect(num % 5, num / 5); + }else{ + from_gw = tinyItem; + InsetRect(&to_rect,5,9); + OffsetRect(&from_rect,18 * (num % 10), 18 * (num / 10)); + } + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 1, 0); +} + +void cPict::drawPresetPc(short num, GWorldPtr to_gw, Rect to_rect){ + GWorldPtr from_gw = pc; + Rect from_rect = calc_rect(2 * (num / 8), num % 8); + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 36; + PaintRect(&to_rect); + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 1, 0); +} + +void cPict::drawPresetField(short num, GWorldPtr to_gw, Rect to_rect){ + GWorldPtr from_gw = field; + Rect from_rect = calc_rect(num % 8, num / 8); + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 36; + PaintRect(&to_rect); + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 0, 0); +} + +void cPict::drawPresetBoom(short num, GWorldPtr to_gw, Rect to_rect){ + GWorldPtr from_gw = boom; + Rect from_rect = calc_rect(num % 8, num / 8); + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 36; + PaintRect(&to_rect); + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 0, 0); +} + +void cPict::drawFullSheet(short num, GWorldPtr to_gw, Rect to_rect){ + Rect from_rect; + GWorldPtr from_gw = largeSheets[num]; + GetPortBounds(from_gw, &from_rect); + to_rect.right = to_rect.left + (from_rect.right - from_rect.left); + to_rect.bottom = to_rect.top + (from_rect.bottom - from_rect.top); + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 0, 0); +} + +void cPict::drawPresetMissile(short num, GWorldPtr to_gw, Rect to_rect){ + Rect from_rect = {0,0,18,18}; + GWorldPtr from_gw = missile; + to_rect.right = to_rect.left + 18; + to_rect.bottom = to_rect.top + 18; + PaintRect(&to_rect); + short i = animFrame == 7 ? 0 : animFrame + 1; + OffsetRect(&from_rect,18 * i, 18 * num); + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 1, 0); +} + +void cPict::drawPresetTerMap(short num, GWorldPtr to_gw, Rect to_rect){ + Rect from_rect = {0,0,12,12}; + GWorldPtr from_gw = map; + to_rect.right = to_rect.left + 24; + to_rect.bottom = to_rect.top + 24; + OffsetRect(&from_rect,12 * (num % 10), 12 * (num / 10)); + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 0, 0); +} + +void cPict::drawCustomTer(short num, GWorldPtr to_gw, Rect to_rect){ + printf("Drawing graphic %i as a custom terrain pic.\n",num); + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 32; + Rect from_rect; + GWorldPtr from_gw = customSheets[get_custom_rect(num,from_rect)]; + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 0, 0); +} + +void cPict::drawCustomTerAnim(short num, GWorldPtr to_gw, Rect to_rect){ + printf("Drawing graphic %i as a custom animated terrain pic.\n",num); + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 32; + num += animFrame; + Rect from_rect; + GWorldPtr from_gw = customSheets[get_custom_rect(num,from_rect)]; + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 0, 0); +} + +void cPict::drawCustomMonstSm(short num, GWorldPtr to_gw, Rect to_rect){ + static const short adj[4] = {0, 2, 1, 3}; + num += adj[animFrame]; + printf("Drawing graphic %i as a custom space pic.\n",num); + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 32; + PaintRect(&to_rect); + + Rect from_rect; + GWorldPtr from_gw = customSheets[get_custom_rect(num,from_rect)]; + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 1, 0); +} + +void cPict::drawCustomMonstWide(short num, GWorldPtr to_gw, Rect to_rect){ + static const short adj[4] = {0, 4, 2, 6}; + num += adj[animFrame]; + Rect small_monst_rect = {0,0,18,14}; + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 36; + PaintRect(&to_rect); + + Rect from_rect; + GWorldPtr from_gw = customSheets[get_custom_rect(num,from_rect)]; + OffsetRect(&small_monst_rect,to_rect.left,to_rect.top + 7); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); + + from_gw = customSheets[get_custom_rect(num + 1,from_rect)]; + OffsetRect(&small_monst_rect,14,0); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); +} + +void cPict::drawCustomMonstTall(short num, GWorldPtr to_gw, Rect to_rect){ + static const short adj[4] = {0, 4, 2, 6}; + num += adj[animFrame]; + Rect small_monst_rect = {0,0,18,14}; + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 36; + PaintRect(&to_rect); + + Rect from_rect; + GWorldPtr from_gw = customSheets[get_custom_rect(num,from_rect)]; + OffsetRect(&small_monst_rect,to_rect.left + 7,to_rect.top); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); + + from_gw = customSheets[get_custom_rect(num + 1,from_rect)]; + OffsetRect(&small_monst_rect,0,18); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); +} + +void cPict::drawCustomMonstLg(short num, GWorldPtr to_gw, Rect to_rect){ + static const short adj[4] = {0, 8, 4, 12}; + num += adj[animFrame]; + Rect small_monst_rect = {0,0,18,14}; + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 36; + PaintRect(&to_rect); + + Rect from_rect; + GWorldPtr from_gw = customSheets[get_custom_rect(num,from_rect)]; + OffsetRect(&small_monst_rect,to_rect.left,to_rect.top); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); + + from_gw = customSheets[get_custom_rect(num+1,from_rect)]; + OffsetRect(&small_monst_rect,14,0); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); + + from_gw = customSheets[get_custom_rect(num+2,from_rect)]; + OffsetRect(&small_monst_rect,-14,18); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); + + from_gw = customSheets[get_custom_rect(num+3,from_rect)]; + OffsetRect(&small_monst_rect,14,0); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); +} + +void cPict::drawCustomDlog(short num, GWorldPtr to_gw, Rect to_rect){ + Rect from_rect; + GWorldPtr from_gw = customSheets[get_custom_rect(num,from_rect)]; + to_rect.right = to_rect.left + 18; + to_rect.bottom = to_rect.top + 36; + from_rect.right = from_rect.left + 18; + from_rect.bottom = from_rect.top + 36; + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 1, 0); + + from_gw = customSheets[get_custom_rect(num,from_rect)]; + OffsetRect(&to_rect,18,0); + from_rect.right = from_rect.left + 18; + from_rect.bottom = from_rect.top + 36; + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 1, 0); +} + +void cPict::drawCustomDlogLg(short num, GWorldPtr to_gw, Rect to_rect){ + drawCustomDlog(num,to_gw,to_rect); + OffsetRect(&to_rect,28,0); + drawCustomDlog(num+2,to_gw,to_rect); + OffsetRect(&to_rect,-28,36); + drawCustomDlog(num+4,to_gw,to_rect); + OffsetRect(&to_rect,28,0); + drawCustomDlog(num+6,to_gw,to_rect); +} + +void cPict::drawCustomTalk(short num, GWorldPtr to_gw, Rect to_rect){ + Rect from_rect; + GWorldPtr from_gw = customSheets[get_custom_rect(num,from_rect)]; + to_rect.right = to_rect.left + 16; + to_rect.bottom = to_rect.top + 32; + from_rect.right = from_rect.left + 16; + from_rect.bottom = from_rect.top + 32; + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 1, 0); + + from_gw = customSheets[get_custom_rect(num+1,from_rect)]; + OffsetRect(&to_rect,16,0); + from_rect.right = from_rect.left + 16; + from_rect.bottom = from_rect.top + 32; + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 1, 0); +} + +void cPict::drawCustomItem(short num, GWorldPtr to_gw, Rect to_rect){ + printf("Drawing graphic %i as a custom space pic.\n",num); + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 32; + Rect from_rect; + GWorldPtr from_gw = customSheets[get_custom_rect(num,from_rect)]; + PaintRect(&to_rect); + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 1, 0); +} + +void cPict::drawCustomMissile(short num, GWorldPtr to_gw, Rect to_rect){ + num += animFrame % 4; + Rect from_rect; + GWorldPtr from_gw = customSheets[get_custom_rect(num,from_rect)]; + from_rect.right = from_rect.left + 18; + from_rect.bottom = from_rect.top + 18; + if(animFrame >= 4) OffsetRect(&from_rect, 0, 18); + PaintRect(&to_rect); + InsetRect(&to_rect,5,9); + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 1, 0); +} + +void cPict::drawCustomTerMap(short num, GWorldPtr to_gw, Rect to_rect){ + Rect from_rect; + GWorldPtr from_gw = customSheets[get_custom_rect(num % 1000,from_rect)]; + from_rect.right = from_rect.left + 12; + from_rect.bottom = from_rect.top + 12; + num /= 1000; num--; + OffsetRect(&from_rect, (num / 3) * 12, (num % 3) * 12); + to_rect.right = to_rect.left + 24; + to_rect.bottom = to_rect.top + 24; + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 0, 0); +} + +void cPict::drawPartyMonstSm(short num, GWorldPtr to_gw, Rect to_rect){ + printf("Drawing graphic %i as a custom space pic.\n",num); + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 32; + GWorldPtr from_gw = save; + Rect from_rect = get_custom_rect(num); + PaintRect(&to_rect); + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 1, 0); +} + +void cPict::drawPartyMonstWide(short num, GWorldPtr to_gw, Rect to_rect){ + Rect small_monst_rect = {0,0,18,14}; + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 36; + PaintRect(&to_rect); + GWorldPtr from_gw = save; + + Rect from_rect = get_custom_rect(num); + OffsetRect(&small_monst_rect,to_rect.left,to_rect.top + 7); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); + + from_rect = get_custom_rect(num+1); + OffsetRect(&small_monst_rect,14,0); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); +} + +void cPict::drawPartyMonstTall(short num, GWorldPtr to_gw, Rect to_rect){ + Rect small_monst_rect = {0,0,18,14}; + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 36; + PaintRect(&to_rect); + GWorldPtr from_gw = save; + + Rect from_rect = get_custom_rect(num); + OffsetRect(&small_monst_rect,to_rect.left + 7,to_rect.top); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); + + OffsetRect(&small_monst_rect,0,18); + from_rect = get_custom_rect(num+1); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); +} + +void cPict::drawPartyMonstLg(short num, GWorldPtr to_gw, Rect to_rect){ + Rect small_monst_rect = {0,0,18,14}; + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 36; + PaintRect(&to_rect); + GWorldPtr from_gw = save; + + Rect from_rect = get_custom_rect(num); + OffsetRect(&small_monst_rect,to_rect.left,to_rect.top); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); + + OffsetRect(&small_monst_rect,14,0); + from_rect = get_custom_rect(num+1); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); + + OffsetRect(&small_monst_rect,-14,18); + from_rect = get_custom_rect(num+2); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); + + OffsetRect(&small_monst_rect,14,0); + from_rect = get_custom_rect(num+3); + rect_draw_some_item(from_gw, from_rect, to_gw, small_monst_rect, 1, 0); +} + +void cPict::drawPartyScen(short num, GWorldPtr to_gw, Rect to_rect){ + GWorldPtr from_gw = header; + Rect from_rect = {0,0,32,32}; + OffsetRect(&from_rect,32 * (num % 5),32 * (num / 5)); + to_rect.right = to_rect.left + 32; + to_rect.bottom = to_rect.top + 32; + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 0, 0); +} + +void cPict::drawPartyItem(short num, GWorldPtr to_gw, Rect to_rect){ + printf("Drawing graphic %i as a custom space pic.\n",num); + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 32; + GWorldPtr from_gw = save; + Rect from_rect = get_custom_rect(num); + PaintRect(&to_rect); + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 1, 0); +} + +void cPict::drawPartyPc(short num, GWorldPtr to_gw, Rect to_rect){ + printf("Drawing graphic %i as a custom space pic.\n",num); + to_rect.right = to_rect.left + 28; + to_rect.bottom = to_rect.top + 32; + GWorldPtr from_gw = save; + Rect from_rect = get_custom_rect(num); + PaintRect(&to_rect); + rect_draw_some_item(from_gw, from_rect, to_gw, to_rect, 1, 0); +} + +cPict::~cPict() {} diff --git a/osx/dialogxml/pict.h b/osx/dialogxml/pict.h new file mode 100644 index 00000000..e72a0c2d --- /dev/null +++ b/osx/dialogxml/pict.h @@ -0,0 +1,160 @@ +/* + * pict.h + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#ifndef PICT_H +#define PICT_H + +#include +#include + +enum ePicType { + PIC_TER = 1, // 28x36 terrain graphic from the preset sheets + PIC_TER_ANIM = 2, // 28x36 terrain graphic from the preset animated terrain sheet + PIC_MONST = 3, // 28x36 monster graphic from the preset sheets + PIC_DLOG = 4, // 36x36 dialog graphic from the preset sheet + PIC_TALK = 5, // 32x32 talking portrait from the preset sheet + PIC_SCEN = 6, // 32x32 scenario graphic from the scenario sheet + PIC_ITEM = 7, // 28x36 item graphic from the large item sheet, or 18x18 item graphic from the small sheet centred in a 28x36 space + PIC_PC = 8, // 28x36 pc graphic from the player sheet + PIC_FIELD = 9, // 28x36 field graphic from the fields sheet + PIC_BOOM = 10, // 28x36 boom graphic from the booms sheet + PIC_FULL = 11, // entire sheet graphic; number is the resource ID + PIC_MISSILE = 12, // 18x18 missile graphic from the missiles sheet + PIC_DLOG_LG = 13, // 72x72 dialog graphic from the dialog sheet + PIC_SCEN_LG = 14, // 64x64 scenario graphic (currently each is on its own sheet) + PIC_TER_MAP = 15, // 12x12 map graphic... or should it be 6x6? + PIC_MONST_WIDE = 23, // 56x36 monster graphic from the preset sheets, resized to fit and centred in a 28x36 space + PIC_MONST_TALL = 43, // 28x72 monster graphic from the preset sheets, resized to fit and centred in a 28x36 space + PIC_MONST_LG = 63, // 56x72 monster graphic from the preset sheets, resized to fit in a 28x36 space + PIC_CUSTOM_TER = 101, // 28x36 custom graphic from the custom sheets + PIC_CUSTOM_TER_ANIM = 102, + PIC_CUSTOM_MONST = 103, + PIC_CUSTOM_DLOG = 104, // 36x36 dialog graphic drawn from two 18x26 halves in the custom sheets + PIC_CUSTOM_TALK = 105, // 32x32 talking portrait drawn from two 16x32 halves in the custom sheets + PIC_CUSTOM_SCEN = 106, // 32x32 scenario portrait loading from scenname.exr/scenario.png + PIC_CUSTOM_ITEM = 107, + PIC_CUSTOM_FULL = 111, // entire sheet graphic, drawn from scenname.exr/sheetxxx.png where xxx is the number + PIC_CUSTOM_MISSILE = 112, // 18x18 missile graphic drawn from the the custom sheets + PIC_CUSTOM_DLOG_LG = 113, // 72x72 dialog graphic from the custom sheet, taken from 8 successive slots + PIC_CUSTOM_TER_MAP = 115, // 12x12 map graphic (should it be 6x6?) taken from the custom sheet + PIC_CUSTOM_MONST_WIDE = 123, // 56x36 monster graphic from the custom sheets, resized to fit and centred in a 28x36 space + PIC_CUSTOM_MONST_TALL = 143, // 28x72 monster graphic from the custom sheets, resized to fit and centred in a 28x36 space + PIC_CUSTOM_MONST_LG = 163, // 56x72 monster graphic from the custom sheets, resized to fit in a 28x36 space + PIC_PARTY_MONST = 203, // 28x36 graphic drawn from the savegame sheet + PIC_PARTY_SCEN = 206, // 32x32 graphic drawn from the scenario headers sheet + PIC_PARTY_ITEM = 207, + PIC_PARTY_PC = 208, + PIC_PARTY_MONST_WIDE = 223, // 56x36 monster graphic from the savegame sheet, resized to fit and centred in a 28x36 space + PIC_PARTY_MONST_TALL = 243, // 28x72 monster graphic from the savegame sheet, resized to fit and centred in a 28x36 space + PIC_PARTY_MONST_LG = 263, // 56x72 monster graphic from the savegame sheet, resized to fit in a 28x36 space +}; + +enum ePicTypeMod { + // Can be added to or subtracted from ePicType enums, returning an ePicType. + PIC_PRESET = 0, // just for good measure + PIC_WIDE = 20, // if applied to any derivative of PIC_MONST, makes the x-dimension 2 instead of 1 + PIC_TALL = 40, // if applied to any derivative of PIC_MONST, makes the y-dimension 2 instead of 1 + PIC_CUSTOM = 100, // if applied to any customizable graphic, makes it custom instead of preset + PIC_PARTY = 200, // similar to above +}; + +enum eSheetType { + SHEET_TER, + SHEET_TER_ANIM, + SHEET_MONST, + SHEET_DLOG, + SHEET_TALK, + SHEET_SCEN, + SHEET_SCEN_LG, + SHEET_ITEM, + SHEET_TINY_ITEM, + SHEET_PC, + SHEET_FIELD, + SHEET_BOOM, + SHEET_MISSILE, + SHEET_PARTY, + SHEET_HEADER, + SHEET_TER_MAP, + SHEET_FULL, + SHEET_CUSTOM, +}; + +class cPict : public cControl { +public: + static void init(); + void attachClickHandler(click_callback_t f) throw(); + void attachFocusHandler(focus_callback_t f) throw(xHandlerNotSupported); + bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods); + void setFormat(eFormat prop, short val) throw(xUnsupportedProp); + short getFormat(eFormat prop) throw(xUnsupportedProp); + static void setSheet(eSheetType type, short n, GWorldPtr sheet); + static bool isSheetSet(eSheetType type, size_t n); + void setPict(short num, ePicType type); + cPict(cDialog* parent); + bool isClickable(); + static void advanceAnim(); + virtual ~cPict(); +protected: + void draw(); +private: + static short animFrame; + short picNum; + ePicType picType; + bool clickable, drawFramed; + friend class cDialog; + static GWorldPtr teranim, dlog, talk, scen, largeScen, item, tinyItem, pc, field, boom, missile, save, header, map; + static std::vector ter, monst, customSheets; + static std::map largeSheets; // map instead of vector because it'll be a sparse array + static void drawPresetTer(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPresetTerAnim(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPresetMonstSm(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPresetMonstWide(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPresetMonstTall(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPresetMonstLg(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPresetDlog(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPresetDlogLg(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPresetTalk(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPresetScen(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPresetScenLg(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPresetItem(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPresetPc(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPresetField(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPresetBoom(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPresetMissile(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPresetTerMap(short num, GWorldPtr to_gw, Rect to_rect); + static void drawFullSheet(short num, GWorldPtr to_gw, Rect to_rect); + static void drawCustomTer(short num, GWorldPtr to_gw, Rect to_rect); + static void drawCustomTerAnim(short num, GWorldPtr to_gw, Rect to_rect); + static void drawCustomMonstSm(short num, GWorldPtr to_gw, Rect to_rect); + static void drawCustomMonstWide(short num, GWorldPtr to_gw, Rect to_rect); + static void drawCustomMonstTall(short num, GWorldPtr to_gw, Rect to_rect); + static void drawCustomMonstLg(short num, GWorldPtr to_gw, Rect to_rect); + static void drawCustomDlog(short num, GWorldPtr to_gw, Rect to_rect); + static void drawCustomDlogLg(short num, GWorldPtr to_gw, Rect to_rect); + static void drawCustomTalk(short num, GWorldPtr to_gw, Rect to_rect); + static void drawCustomItem(short num, GWorldPtr to_gw, Rect to_rect); + static void drawCustomMissile(short num, GWorldPtr to_gw, Rect to_rect); + static void drawCustomTerMap(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPartyMonstSm(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPartyMonstWide(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPartyMonstTall(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPartyMonstLg(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPartyScen(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPartyItem(short num, GWorldPtr to_gw, Rect to_rect); + static void drawPartyPc(short num, GWorldPtr to_gw, Rect to_rect); + static std::map drawPict; + click_callback_t onClick; +}; + +ePicType operator + (ePicType lhs, ePicTypeMod rhs); +ePicType operator - (ePicType lhs, ePicTypeMod rhs); +ePicType operator + (ePicTypeMod lhs, ePicType rhs); +ePicType operator - (ePicTypeMod lhs, ePicType rhs); +ePicType&operator +=(ePicType&lhs, ePicTypeMod rhs); +ePicType&operator -=(ePicType&lhs, ePicTypeMod rhs); +#endif