diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
deleted file mode 100644
index df3fb24e..00000000
--- a/.github/FUNDING.yml
+++ /dev/null
@@ -1 +0,0 @@
-custom: ['https://www.paypal.me/michaelhartlef']
diff --git a/.gitignore b/.gitignore
index 4ff3eea8..cd2f5bda 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,10 @@
!/bin/themes
!/bin/icons
!/bin/templates
+!/bin/data
+!/bin/internal
+!/bin/external
+!/bin/macdeploy*.command
.bmx
diff --git a/README.md b/README.md
index 6701eed8..cf97943a 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,9 @@
## Cerberus X
-[![GitHub release](https://img.shields.io/github/release/KrautApps/cerberus.svg)]()
-[![Github Releases](https://img.shields.io/github/downloads/KrautApps/cerberus/latest/total.svg)]()
-[![Github All Releases](https://img.shields.io/github/downloads/KrautApps/cerberus/total.svg)]()
[![Twitter Follow](https://img.shields.io/twitter/follow/cerberus_x17.svg?style=social)]()
[![GitHub stars](https://img.shields.io/github/stars/KrautApps/cerberus.svg?style=social&label=Star)]()
-![Cerberus X Logo](https://www.cerberus-x.com/community/styles/xenfracture/xenfracture/CBX_Logo_small.png)
+![Cerberus X Logo](https://www.cerberus-x.com/downloads/cx_logo_small.png)
### Cerberus X is a game development language, made for hobbyists, indies and professionals.
@@ -29,7 +26,7 @@ Cerberus X is based on Monkey X programming language created by [Mark Sibly](htt
* https://www.cerberus-x.com/cxDocs/Home.html
* Download pre-built **Cerberus X** for **Windows/Linux/Mac OS**:
- * https://krautapps.itch.io/cerberus-x
+ * https://www.cerberus-x.com/community/resources/categories/cerberus-x.6/
### License
diff --git a/VERSIONS.TXT b/VERSIONS.TXT
index 9d89207e..354b6164 100644
--- a/VERSIONS.TXT
+++ b/VERSIONS.TXT
@@ -1,57 +1,114 @@
+***** v2020-05-09 *****
+
+FIX: [DOCS/brl] Fixed missing entry for the admob, cerberusstore, gamecenter, fielpath, filesystem, url, tween, pool, process and markdown modules. (Author: MikeHart)
+FIX: [DOCS/brl.databuffer] Fixed some typos. (Author: MikeHart)
+FIX: [DOCS/cerberus] Fixed missing entry for the deque module. (Author: MikeHart)
+FIX: [DOCS/cerberus.stack] Fixed some typos. (Author: MikeHart)
+FIX: [DOCS/os] Fixed description of the StripExt statement. (Author: MikeHart)
+FIX: [mojo] Fixed padded usage in Font.Load:Font(url:String, flags:Int=Image.DefaultFlags) (Author: Rich)
+FIX: [mojo2] Fixed padded usage in Font.Load:Font(url:String, flags:Int=Image.Filter ) (Author: Rich)
+FIX: [mojo2] Fixed padded parameter in Image.LoadFrames:Image[]( path:String,cellWidth:Int,cellHeight:Int,padded:Bool=False,xhandle:Float=.5,yhandle:Float=.5,flags:Int=Image.Filter|Image.Mipmap,shader:Shader=Null ). (Author: Rich)
+FIX: [examples] Fixed mak/bbgametest -> missing z parameter in MouseEvent call. (Author: MikeHart)
+FIX: [examples] Fixed mak/dynamicimage -> faulty fullscreen switch. (Author: MikeHart)
+Fix: [TRANSCC] Fixed TRANSCC not being able to install on an Android device when creating a release build on Linux and OSX. (Author: Phil7)
+Fix: [TRANSCC] Fixed TRANSCC not reporting the correct line number in certain cases when preprocessor statements were used.. (Author: dawlane)
+
+MOD: [cerberusstore] updated the underlying code to support the newest Google version. (Author: Rich)
+MOD: [DOCS/interpolate] Fixed and added some images. (Author: Holzchopf)
+MOD: [mojo] Added filter param to Font.Load:Font(url:String, flags:Int=Image.DefaultFlags ) (Author: Rich)
+MOD: [mojo2] Added filter param to Font.Load:Font(url:String, flags:Int=Image.Filter ) (Author: Rich)
+MOD: [mojo/mojo2] Font.Load(url:String, flags:Int=... ) accept now .FNT files and don't add a .TXT anymore. (Author: MikeHart)
+MOD: [TRANSCC] Changed TRANSCC in a way so modules can add Android libs and lift up versions more easily. (Author: Rich)
+MOD: [TRANSCC] Data file filters are not being case sensitive anymore. (Author: MikeHart)
+MOD: [rebuildall.ps1] Reworked the build script for using MS Visual C++ 2017 Community edition. (Author: dawlane)
+MOD: [rebuildall.sh] Reworked the build script. (Author: dawlane)
+MOD: [building.txt] Updated the information. (Author: dawlane)
+
+NEW: [cerberus.interpolate] Added InterpolateCustomLine:Float(dataY:Float[], pX:Float ). (Author: Rich)
+NEW: [cerberus.interpolate] Added InterpolateBackEaseIn:Float(pY0:Float, pY1:Float, pX:Float). (Author: Rich)
+NEW: [cerberus.interpolate] Added InterpolateBackEaseIn:Float(pY0:Float, pY1:Float, pX:Float). (Author: Rich)
+NEW: [cerberus.interpolate] Added InterpolateBackEaseOut:Float(pY0:Float, pY1:Float, pX:Float). (Author: Rich)
+NEW: [cerberus.interpolate] Added InterpolateBackEaseInOut:Float(pY0:Float, pY1:Float, pX:Float). (Author: Rich)
+NEW: [cerberus.interpolate] Added InterpolateElasticEaseIn:Float(pY0:Float, pY1:Float, pX:Float). (Author: Rich)
+NEW: [cerberus.interpolate] Added InterpolateElasticEaseOut:Float(pY0:Float, pY1:Float, pX:Float). (Author: Rich)
+NEW: [cerberus.interpolate] Added InterpolateElasticEaseInOut:Float(pY0:Float, pY1:Float, pX:Float). (Author: Rich)
+NEW: [cerberus.interpolate] Added InterpolateBounceEaseIn:Float(pY0:Float, pY1:Float, pX:Float). (Author: Rich)
+NEW: [cerberus.interpolate] Added InterpolateBounceEaseOut:Float(pY0:Float, pY1:Float, pX:Float). (Author: Rich)
+NEW: [cerberus.interpolate] Added InterpolateBounceEaseInOut:Float(pY0:Float, pY1:Float, pX:Float). (Author: Rich)
+NEW: [brl.tween] Added a module to support easy tweening. (Author: Rich)
+NEW: [TRANSCC] Added app icon creation right into TRANSCC. (Author: Rich)
+NEW: [TRANSCC] Added the Include directive to add files/directories to the build folder (GLFW/STDCPP). (Author: MikeHart)
+NEW: [IOS] Added #IOS_APP_ICON to set icon of the app. (Author: Rich)
+NEW: [ANDROID] Added #ANDROID_APP_ICON to set icon of the app. (Author: Rich)
+NEW: [FLASH] Added #FLASH_APP_ICON to set the favicon of the browser tab. (Author: Rich)
+NEW: [HTML5] Added #HTML5_APP_ICON to set the favicon of the browser tab. (Author: Rich)
+NEW: [HTML5] Added #HTML5_APP_TITLE to be able to set the title of the browser tab. (Author: MikeHart)
+NEW: [HTML5] Added #HTML5_CANVAS_WIDTH and #HTML5_CANVAS_HEIGHT control the size of the html5 canvas. (Author: MikeHart)
+NEW: [HTML5] Added #HTML5_APP_FILENAME to set the output filename. (Author: MikeHart)
+NEW: [HTML5] Added #HTML5_CANVAS_RESIZE_MODE to be able to set the CANVAS resize mode. (Author: MikeHart)
+NEW: [HTML5] Added #HTML5_CONSOLE_SHOW to be able to hide the splitter and console area. (Author: MikeHart)
+NEW: [rebuildall_macos.sh] New script to build CX on OSX right from the github repository. (Author: dawlane)
+
+***** v2019-10-13b *****
+
+MOD: [REQUESTER] Requester dialogs now work on Linux, thanks to tinyfiledialogs (Author: MikeHart)
+FIX: [GLFW] Added missing stb_write_image.h file on Linux (Author: MikeHart)
+FIX: [TED] Was still using the old PrefsDialog on Linux (Author: MikeHart)
+
***** v2019-10-13 *****
-FIX: [ANDROID] change file permission of gradlew in template. (Author: Dawlane)
-MOD: [ANDROID] added 64bit libs to the target, to support Googles changes in August 2019.
-FIX: [TRANS] Fixed CopyFile for Linux to preserve file permissions. (Author: Dawlane)
-FIX: [TED] Fixed symlinks opening a second file when DebugStop is used. (Author: Dawlane)
-MOD: [TED] Another attempt at fixing the capitalization of the API.
-MOD: [TED] Moved Open Project from the BUILD menu to the FILE menu.
-MOD: [TED] Replaced Options dialog with a similar one like from Dawlane's version of TED.
+FIX: [ANDROID] change file permission of gradlew in template. (Author: dawlane)
+MOD: [ANDROID] added 64bit libs to the target, to support Googles changes in August 2019. (Author: MikeHart)
+FIX: [TRANS] Fixed CopyFile for Linux to preserve file permissions. (Author: dawlane)
+FIX: [TED] Fixed symlinks opening a second file when DebugStop is used. (Author: dawlane)
+MOD: [TED] Another attempt at fixing the capitalization of the API. (Author: MikeHart)
+MOD: [TED] Moved Open Project from the BUILD menu to the FILE menu. (Author: MikeHart)
+MOD: [TED] Replaced Options dialog with a similar one like from dawlane's version of TED. (Author: dawlane)
This dialog is much smaller and so can be displayed on small screens two.
-FIX: [TED] CTRL+PgDown and CTRL+PgUP now works on Linux to switch between open code tabs.
-MOD: [TRANS/GLFW] On Windows you can add an app icon (.ico file) now via the new #GLFW_APP_ICON preprocessor setting.
-FIX: [OSX] Recompiled the launcher as a 64bit app, so it is compatible with OSX Catalina (10.15.x).
+FIX: [TED] CTRL+PgDown and CTRL+PgUP now works on Linux to switch between open code tabs. (Author: MikeHart)
+MOD: [TRANS/GLFW] On Windows you can add an app icon (.ico file) now via the new #GLFW_APP_ICON preprocessor setting. (Author: MikeHart)
+FIX: [OSX] Recompiled the launcher as a 64bit app, so it is compatible with OSX Catalina (10.15.x). (Author: MikeHart)
FIX: [MOJO1] Fixed missing usage of frame parameter in DrawImage9P. (Author: Rich)
MOD: [WIN8/WINPHONE8] Depreciated these targets.
If you need them, move them out of the targets/depreciated folder.
-MOD: [TRANS/ANDROID] Reactivated logcat filtering.
+MOD: [TRANS/ANDROID] Reactivated logcat filtering. (Author: MikeHart)
NEW: [Examples/MOJO2] DrawPrimitives2 shows how to use the DrawPrimitives method to draw several images at once.
***** v2019-05-05 *****
-MOD: [ANDROID] Changed MIN_SDK back to 16 like it was before.
-MOD: [DOCS] Added A-Z shortcuts on top of indexes.
-MOD: [Trans/ANDROID] Release builds are installed automatically now.
-FIX: [AGK] Fixed docs creation to be compatible with the latest MakeDocs.
-FIX: [MAKEDOCS] Fixed brl.markdown bug.
-FIX: [TED] Fixed fixed displaying an iframe element in the docs. (Author: Dawlane)
-FIX: [TED] Fixed scaling issues when displaying images.
-NEW: [TED] Added overwrite mode. Just press the insert key to toggle it.
-NEW: [MOJO2] Added Image.LoadFrames:Image[]( path:String,cellWidth:Int,cellHeight:Int,padded:Bool=False,xhandle:Float=.5,yhandle:Float=.5,flags:Int=Image.Filter|Image.Mipmap,shader:Shader=Null ).
-NEW: [MOJO.APP] Added SetDeviceWindowIcon( _path:String ).
-NEW: [MOJO.APP] Added SetDeviceWindowTitle( _title:String ).
-NEW: [MOJO.APP] Added SetDeviceWindowSize( _width:Int, _height:Int ).
-NEW: [MOJO.APP] Added SetDeviceWindowPosition( _x:Int, _y:Int ).
-NEW: [MOJO.APP] Added SetDeviceWindowSizeLimits:Void( _minWidth:Int, _minHeight:Int, _maxWidth:Int, _maxHeight:Int )
-NEW: [MOJO.INPUT] Added SetMousePos:Void( _x:Int, _y:Int ).
-NEW: [MOJO.INPUT] Added SetClipboard:Void( _text:String ).
-NEW: [MOJO.INPUT] Added GetClipboard:String().
-NEW: [CERBERUS.INTERPOLATE] New module.
-NEW: [MOJO.COLOR] New module.
+MOD: [ANDROID] Changed MIN_SDK back to 16 like it was before. (Author: MikeHart)
+MOD: [DOCS] Added A-Z shortcuts on top of indexes. (Author: Holzchopf)
+MOD: [Trans/ANDROID] Release builds are installed automatically now. (Author: MikeHart)
+FIX: [AGK] Fixed docs creation to be compatible with the latest MakeDocs. (Author: MikeHart)
+FIX: [MAKEDOCS] Fixed brl.markdown bug. (Author: Holzchopf)
+FIX: [TED] Fixed fixed displaying an iframe element in the docs. (Author: dawlane)
+FIX: [TED] Fixed scaling issues when displaying images. (Author: MikeHart)
+NEW: [TED] Added overwrite mode. Just press the insert key to toggle it. (Author: MikeHart)
+NEW: [MOJO2] Added Image.LoadFrames:Image[]( path:String,cellWidth:Int,cellHeight:Int,padded:Bool=False,xhandle:Float=.5,yhandle:Float=.5,flags:Int=Image.Filter|Image.Mipmap,shader:Shader=Null ). (Author: MikeHart)
+NEW: [MOJO.APP] Added SetDeviceWindowIcon( _path:String ). (Author: MikeHart)
+NEW: [MOJO.APP] Added SetDeviceWindowTitle( _title:String ). (Author: MikeHart)
+NEW: [MOJO.APP] Added SetDeviceWindowSize( _width:Int, _height:Int ). (Author: MikeHart)
+NEW: [MOJO.APP] Added SetDeviceWindowPosition( _x:Int, _y:Int ). (Author: MikeHart)
+NEW: [MOJO.APP] Added SetDeviceWindowSizeLimits:Void( _minWidth:Int, _minHeight:Int, _maxWidth:Int, _maxHeight:Int ) (Author: MikeHart)
+NEW: [MOJO.INPUT] Added SetMousePos:Void( _x:Int, _y:Int ). (Author: MikeHart)
+NEW: [MOJO.INPUT] Added SetClipboard:Void( _text:String ). (Author: MikeHart)
+NEW: [MOJO.INPUT] Added GetClipboard:String(). (Author: MikeHart)
+NEW: [CERBERUS.INTERPOLATE] New module. (Author: Holzchopf)
+NEW: [MOJO.COLOR] New module. (Author: Holzchopf)
***** v2018-12-30 *****
-FIX: [AGK_IOS] Fixed AGK_IOS target showing up on non OSX platforms.
-FIX: [ANDROID] Fixed MIN_SDK, TARGET and TOOLS version.
-FIX: [brl.requesters] Fixed RequestFile not working with a set path.
-FIX: [TED] Fixed selecting a help topic in the toolbar didn't show up the help file directly.
+FIX: [AGK_IOS] Fixed AGK_IOS target showing up on non OSX platforms. (Author: MikeHart)
+FIX: [ANDROID] Fixed MIN_SDK, TARGET and TOOLS version. (Author: MikeHart)
+FIX: [brl.requesters] Fixed RequestFile not working with a set path. (Author: MikeHart)
+FIX: [TED] Fixed selecting a help topic in the toolbar didn't show up the help file directly. (Author: MikeHart)
MOD: [example] Various changes to sample scripts (Author: Paul59)
-FIX: [TED] Fixed "Open on Desktop" on Linux. (Author: Dawlane)
-MOD: [TED] If text is selected in the editor, it will be pre set in the Find dialog.
-MOD: [DOCS/MAKEDOCS] Numerous changes to the docs and MakeDocs itself.
-FIX: [GLFW/GLFW-ANGLE] Fixed returning MouseZ resets MouseX and MouseY to zero.
-MOD: [TED] Bigger changes so TED uses the QT5 webengine now and needs QT5.9.2 to compile. (Author: Dawlane)
+FIX: [TED] Fixed "Open on Desktop" on Linux. (Author: dawlane)
+MOD: [TED] If text is selected in the editor, it will be pre set in the Find dialog. (Author: MikeHart)
+MOD: [DOCS/MAKEDOCS] Numerous changes to the docs and MakeDocs itself. (Author: Holzchopf)
+FIX: [GLFW/GLFW-ANGLE] Fixed returning MouseZ resets MouseX and MouseY to zero. (Author: MikeHart)
+MOD: [TED] Bigger changes so TED uses the QT5 webengine now and needs QT5.9.2 to compile. (Author: dawlane)
***** v2018-08-10 *****
diff --git a/bin/config.winnt.txt b/bin/config.winnt.txt
index d8779162..1169c661 100644
--- a/bin/config.winnt.txt
+++ b/bin/config.winnt.txt
@@ -4,7 +4,7 @@
'
'Can be overriden via transcc cmd line
'
-MODPATH="${CERBERUSDIR}/modules;${CERBERUSDIR}/modules_ext"
+MODPATH="${CERBERUSDIR}/modules;${CERBERUSDIR}/modules_ext;D:\CerberusX\CerberusModulesx"
'--------------------
'--------------------
@@ -27,7 +27,7 @@ HTML_PLAYER="${CERBERUSDIR}\bin\cserver_winnt.exe"
'***** DO NOT use mingw64-5.1.0 as it has a linker bug *****
'***** 64 bit mingw *****
-MINGW_PATH="D:\Applications\Compilers\TDM-GCC-64"
+MINGW_PATH="D:\TDM-GCC-64"
'--------------------
'--------------------
@@ -37,7 +37,7 @@ MINGW_PATH="D:\Applications\Compilers\TDM-GCC-64"
'
'The Java JDK is currently available here: http://www.oracle.com/technetwork/java/javase/downloads/index.html
'
-JDK_PATH="d:\programme\JavaSDK"
+JDK_PATH="D:\Program Files (x86)\Java\jdk1.8.0_172"
'--------------------
'--------------------
@@ -45,7 +45,7 @@ JDK_PATH="d:\programme\JavaSDK"
'
'Must be set to a valid dir for ANDROID target support
'
-ANDROID_PATH="d:\programme\AndroidSDK"
+ANDROID_PATH="D:\Program Files\Android\Android Studio"
'--------------------
'--------------------
@@ -53,7 +53,7 @@ ANDROID_PATH="d:\programme\AndroidSDK"
'
'Must be set to a valid dir for ANDROID NDK target support
'
-ANDROID_NDK_PATH="d:\devtools\android-ndk-r9"
+'ANDROID_NDK_PATH="D:\Program Files\Android\Android Studio\ndk-bundle"
'--------------------
'--------------------
@@ -63,7 +63,7 @@ ANDROID_NDK_PATH="d:\devtools\android-ndk-r9"
'
'Ant is currently available here: http://ant.apache.org/bindownload.cgi
'
-ANT_PATH="D:\Programme\apache-ant-1.9.7"
+'ANT_PATH="D:\Programme\apache-ant-1.9.7"
'--------------------
'--------------------
@@ -73,7 +73,7 @@ ANT_PATH="D:\Programme\apache-ant-1.9.7"
'
'Either HTML_PLAYER or FLASH_PLAYER must be set for FLASH target support.
'
-FLEX_PATH="d:\devtools\flex-sdk"
+'FLEX_PATH="c:\flex_sdk_4.6"
'for opening .swf files...cerberus will use HTML_PLAYER if this is not set.
'FLASH_PLAYER="...?..."
'--------------------
@@ -83,7 +83,7 @@ FLEX_PATH="d:\devtools\flex-sdk"
'
'PSM_PATH must be set for PSM target support.
'
-PSM_PATH="d:\devtools\PSM_SDK"
+'PSM_PATH="d:\devtools\PSM_SDK"
'--------------------
'--------------------
@@ -91,9 +91,7 @@ PSM_PATH="d:\devtools\PSM_SDK"
'
'Must be set for XNA and GLFW target support.
'
-'MSBUILD_PATH="${PROGRAMFILES}\MSBuild\14.0\Bin\MSBuild.exe"
-'MSBUILD_PATH="${PROGRAMFILES}\MSBuild\12.0\Bin\MSBuild.exe"
-MSBUILD_PATH="${WINDIR}\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe"
+MSBUILD_PATH="${PROGRAMFILES(x86)}\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe"
'--------------------
'--------------------
@@ -101,10 +99,9 @@ MSBUILD_PATH="${WINDIR}\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe"
'
'Must be set for AGK support.
'
-AGK_PATH="C:/Program Files (x86)/The Game Creators/AGK2"
+AGK_PATH="D:\Program Files (x86)\The Game Creators\AGK2"
'
'--------------------
'--->> BEGIN OF JUNGLE IDE GENERATED CONFIG
-MINGW_PATH= "D:\Applications\Compilers\TDM-GCC-64"
'--->> END OF JUNGLE IDE GENERATED CONFIG
diff --git a/bin/data/mojo_font.png b/bin/data/mojo_font.png
new file mode 100644
index 00000000..839650c4
Binary files /dev/null and b/bin/data/mojo_font.png differ
diff --git a/bin/external/dont_delete.txt b/bin/external/dont_delete.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/bin/internal/dont_delete.txt b/bin/internal/dont_delete.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/bin/macdeployqt-5.9.2.command b/bin/macdeployqt-5.9.2.command
new file mode 100755
index 00000000..090b4507
--- /dev/null
+++ b/bin/macdeployqt-5.9.2.command
@@ -0,0 +1,15 @@
+#!/bin/bash
+#
+# Little script to make Ted.app standalone
+#
+cd `dirname $0`
+#cd ../../bin
+#macdeployqt-4.8 Ted.app
+/Users/michaelhartlef/Qt/5.9.2/clang_64/bin/macdeployqt Ted.app -verbose=2 -always-overwrite
+cd Ted.app/Contents/PlugIns
+rm -r -f audio
+rm -r -f bearer
+rm -r -f imageformats
+rm -r -f mediaservice
+rm -r -f printsupport
+rm -r -f sqldrivers
diff --git a/bin/themes/default/images/dock_close.png b/bin/themes/default/images/dock_close.png
new file mode 100644
index 00000000..888c0865
Binary files /dev/null and b/bin/themes/default/images/dock_close.png differ
diff --git a/bin/themes/default/images/dock_close_sel.png b/bin/themes/default/images/dock_close_sel.png
new file mode 100644
index 00000000..e912573c
Binary files /dev/null and b/bin/themes/default/images/dock_close_sel.png differ
diff --git a/docs/cerberusdoc/Credits.cerberusdoc b/docs/cerberusdoc/Credits.cerberusdoc
index ea2e7936..4db4b7f0 100644
--- a/docs/cerberusdoc/Credits.cerberusdoc
+++ b/docs/cerberusdoc/Credits.cerberusdoc
@@ -1,13 +1,15 @@
> Cerberus X credits
-+ Language design and programming - Mark Sibly
++ Work on Cerberus X - dawlane, Holzchopf, muruba, Martin, MikeHart, Paul59, Phil7, PixelPaladin, Rich, Soap.
-+ Documentation - Mark Sibly, James Boyd, Arthur Bikmullin.
++ Cerberus website - Michael Hartlef.
-+ Cerberus website - Martin Leidel and Michael Hartlef.
++ Initial language design and programming of Monkey X - Mark Sibly
+
++ Initial documentation of Monkey X - Mark Sibly, James Boyd, Arthur Bikmullin.
Additional thanks to:
-Muruba, dawlane, Soap, PixelPaladin, Holzchopf, Beaker, Richard Betson, EdzUp[GD], Warpy, MikeHart, msephton, Binary_Moon, Otus 3, CodeGit, skn3[ac], Tibit, Mathieu, Sledge, Difference, CyBeRGoth, _Skully, sknightly, Rhodesy, ziggy, Hujiklo, earok, Robert Cummings, TMK, Playniax.
+adamredwoos, Beaker, Richard Betson, EdzUp[GD], Warpy, msephton, Binary_Moon, Otus 3, CodeGit, skn3[ac], Tibit, Mathieu, Sledge, Difference, CyBeRGoth, _Skully, sknightly, Rhodesy, ziggy, Hujiklo, earok, Robert Cummings, TMK, Playniax, nerobot, Rob Hewitt, En929, AutmnLeaf, TheMrCerebro, wick, Gerry Quinn, magic, Slotman, Ferdi, Coppercicle, JaviCervera.
diff --git a/docs/cerberusdoc/Programming/App config settings.cerberusdoc b/docs/cerberusdoc/Programming/App config settings.cerberusdoc
index 531a2620..0482a228 100644
--- a/docs/cerberusdoc/Programming/App config settings.cerberusdoc
+++ b/docs/cerberusdoc/Programming/App config settings.cerberusdoc
@@ -32,12 +32,20 @@ The following app config settings are currently supported:
'Html5 settings, defaults shown
'
+#HTML5_APP_FILENAME="CerberusGame.html" 'Set the default name for the html outfile.
+#HTML5_APP_ICON="" 'set the name of a ico/png file which will be used as a favicon. If not provided, Trans will use the standard favicon.
+ 'PNG files will be converted to ICO files. Without a filepath, Trans will look in the folder where your .cxs source file is located at.
+#HTML5_APP_TITLE="CerberusGame" 'Set the title inside the browser tab.
+#HTML5_CANVAS_WIDTH=640 'Set the width of the canvas.
+#HTML5_CANVAS_HEIGHT=480 'Set the height of the canvas.
+#HTML5_CANVAS_RESIZE_MODE=1 '0=locked, 1=stretch, 2=resize
+#HTML5_CONSOLE_SHOW=True 'Set it to False to hide the splitter and console DIV in your file.
#HTML5_WEBAUDIO_ENABLED=True 'Set to false to disable webaudio support for mojo audio, and to use older multimedia audio system instead.
'GLFW settings, defaults shown
'
-#GLFW_USE_MINGW=True 'Set to false on Windows to use MSVC instead of MinGW to build glfw apps. Needs VS 2015 installed.
-#GLFW_GCC_MSIZE_WINNT="32" 'When building glfw apps with mingw/gcc, controls whether 32 or 64 bit apps are generated.
+#GLFW_USE_MINGW=True 'Set to false on Windows to use MSVC instead of MinGW to build glfw apps. Needs at least VS 2015 installed.
+#GLFW_GCC_MSIZE_WINNT="64" 'When building glfw apps with mingw/gcc, controls whether 32 or 64 bit apps are generated.
'Set to "64" to force 64 bit builds on Windows (needs mingw64), or "" to use compiler default.
#GLFW_GCC_MSIZE_LINUX="" 'Ditto for Linux.
#GLFW_GCC_CC_OPTS="" 'Pass compiler options to GCC type compilers
@@ -52,10 +60,10 @@ The following app config settings are currently supported:
#GLFW_WINDOW_FULLSCREEN=False
#GLFW_WINDOW_SAMPLES=0 'Set to number of samples for multisampling (glfw3 only).
#GLFW_WINDOW_DECORATED=True 'Set to false to create a broderless window (glfw3 only).
-#GLFW_VERSION=2 'Set to GLFW version, ie: 2 or 3.
-#GLFW_APP_ICON="myIcon.ico" 'On Windows you can set the app and window icon via this setting.
- 'If no path is provided, TRANSCC will assume the source path as its location.
+#GLFW_APP_ICON="" 'Set the name of a ico/png file which will be used as th apps icon. If not provided, Trans will use the standard icon file.
+ 'PNG files will be converted to ICO files. Without a filepath, Trans will look in the folder where your .cxs source file is located at.
+
#GLFW_APP_LABEL="My App" 'Human readable label for app.
'Must be set for cerberus://internal to map to 'per user' app data dir.
'If not set (the default), cerberus://internal is shared by all users of app.
@@ -65,18 +73,35 @@ The following app config settings are currently supported:
#GLFW_APP_PUBLISHER="My Company" 'Optional human readable publisher name for app. Must be filesystem friendly.
'Not defined by default.
+'FLASH settings, defaults shown
+#FLASH_APP_ICON=""
+#FLASH_RENDER_WHILE_SUSPENDED=False
'IOS settings, defaults shown
'
#IOS_RETINA_ENABLED=True
#IOS_ACCELEROMETER_ENABLED=True
-#IOS_DISPLAY_LINK_ENABLED=False
+#IOS_DISPLAY_LINK_ENABLED=True
+#IOS_APP_ICON=""
'Android settings, defaults shown
'
#ANDROID_APP_LABEL="Cerberus X Game"
#ANDROID_APP_PACKAGE="com.Cerberus_X.cxgame"
-#ANDROID_SCREEN_ORIENTATION="portrait" 'one of: user, portrait, landscape
+#ANDROID_APP_ICON=""
+#ANDROID_SCREEN_ORIENTATION="user" '"user", "portrait", "landscape"
+#ANDROID_GAMEPAD_ENABLED=False
+
+#ANDROID_MIN_SDK_VERSION="16"
+#ANDROID_TARGET_SDK_VERSION="28"
+#ANDROID_BUILD_TOOLS_VERSION="28.0.3"
+#ANDROID_GRADLE_VERSION="3.2.1"
+#ANDROID_GRADLE_DISTRIBUTION="gradle-4.6-all.zip"
+#ANDROID_REPOSITORIES=""
+#ANDROID_JAVA_SOURCE_VERSION="VERSION_1_8"
+#ANDROID_JAVA_TARGET_VERSION="VERSION_1_8"
+#ANDROID_APPLICATION_EXTRAS=""
+
#ANDROID_VERSION_CODE="1"
#ANDROID_VERSION_NAME="1.0"
#ANDROID_NATIVE_GL_ENABLED=False 'for use with the opengl modules
@@ -112,6 +137,7 @@ The following app config settings are currently supported:
'Misc
'
#CC_OPTS="" 'additional gcc options for stdcpp target, eg: #CC_OPTS+="-DMyDefine"
+#CC_LIBS="" 'Pass additional libraries to link against for GCC type compilers.
diff --git a/docs/cerberusdoc/Programming/Keywords.cerberusdoc b/docs/cerberusdoc/Programming/Keywords.cerberusdoc
index a3938ea8..2e0ede76 100644
--- a/docs/cerberusdoc/Programming/Keywords.cerberusdoc
+++ b/docs/cerberusdoc/Programming/Keywords.cerberusdoc
@@ -3,7 +3,7 @@
The identifiers below are language keywords and are reserved for use by the Cerberus X language; these keywords are case-insensitive.
>> Module control
-[[Strict]] | [[Import]] | [[Extern]]
+[[Strict]] | [[Import]] | [[Extern]] | [[Include]]
>> Declarations
[[Const]] | [[Local]] | [[Global]] | [[Field]] | [[Alias]] | [[Enumerate]]
diff --git a/docs/cerberusdoc/Programming/Keywords/Import.cerberusdoc b/docs/cerberusdoc/Programming/Keywords/Import.cerberusdoc
index ff8c0add..e4d10a9e 100644
--- a/docs/cerberusdoc/Programming/Keywords/Import.cerberusdoc
+++ b/docs/cerberusdoc/Programming/Keywords/Import.cerberusdoc
@@ -17,7 +17,7 @@ To import another module, the Import keyword must be placed at the top of your s
Cerberus X also supports cyclic imports, whereby modules can import each other, gaining access to each other's declarations.
>> See also
-[[Strict]]~n
+[[Strict]] | [[Include]]~n
[Language reference](Language reference#modules)
>> Example
diff --git a/docs/cerberusdoc/Programming/Keywords/Include.cerberusdoc b/docs/cerberusdoc/Programming/Keywords/Include.cerberusdoc
new file mode 100644
index 00000000..b1ee66eb
--- /dev/null
+++ b/docs/cerberusdoc/Programming/Keywords/Include.cerberusdoc
@@ -0,0 +1,46 @@
+> Directive Include
+
+Module include directive.
+
+>> Syntax
+
+Include "filename"
+
+>> Description
+
+A Cerberus X program can add files into the build folder for further addition during the compile process.
+Contrary to the Import directive, these files are not injected into the translated code and the main.* file.
+Currently only the C++ and Desktop target are supporting this directive.
+
+>> See also
+[[Strict]] | [[Import]]~n
+[Language reference](Language reference#modules)
+
+
+>> Optional parameters (inside the string)
+
+*-out=*
+
+A target directory. Otherwise the content will be copied into the build folder.
+
+*-ext=*
+
+A list of separated file extensions. These will filter the file extensions, that are copied.
+
+*-sub*
+
+If including a directory, this parameter allows to include sub directories.
+
+>> Example
+
+*Add a single file:*
+
+
+Include "native/sokol_app.h -out=targetDir"
+
+
+*Add the content of a directory:*
+
+
+Include "native/ -ext=c;h -out=targetDir -sub"
+
\ No newline at end of file
diff --git a/docs/cerberusdoc/Programming/Language reference.cerberusdoc b/docs/cerberusdoc/Programming/Language reference.cerberusdoc
index f3a6b44d..650a2df4 100644
--- a/docs/cerberusdoc/Programming/Language reference.cerberusdoc
+++ b/docs/cerberusdoc/Programming/Language reference.cerberusdoc
@@ -245,7 +245,7 @@ The following identifiers are [[Keywords|Language keywords]] and are reserved fo
Void Strict Public Private Property Bool Int Float String Array
-Object Mod Continue Exit Import Extern New Self Super Try Catch
+Object Mod Continue Exit Import Include Extern New Self Super Try Catch
Eachin True False Not Extends Abstract Final Select Case Default
Const Enumerate Local Global Field Method Function Class And Or Shl Shr
End If Then Else ElseIf EndIf While Wend Repeat Until Forever
diff --git a/docs/templates/cerberusx/data/cerberusx.png b/docs/templates/cerberusx/data/cerberusx.png
deleted file mode 100644
index 3f8fb04b..00000000
Binary files a/docs/templates/cerberusx/data/cerberusx.png and /dev/null differ
diff --git a/docs/templates/cerberusx/index_template.html b/docs/templates/cerberusx/index_template.html
deleted file mode 100644
index fc67a868..00000000
--- a/docs/templates/cerberusx/index_template.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
- Please note that only documented classes are listed here, there might be undocumented classes that implement this interface.
-${ENDIF}
-${IF CONSTS}
-
-
-${ENDIF}
diff --git a/examples/mojo/mak/bbgametest/bbgametest.cxs b/examples/mojo/mak/bbgametest/bbgametest.cxs
index aade66b9..19857e3e 100644
--- a/examples/mojo/mak/bbgametest/bbgametest.cxs
+++ b/examples/mojo/mak/bbgametest/bbgametest.cxs
@@ -30,8 +30,8 @@ Class GameDelegate Extends BBGameDelegate
Print "KeyEvent: event="+event+", data="+data
End
- Method MouseEvent:Void( event:Int,data:Int,x:Float,y:Float )
- Print "MouseEvent: event="+event+", data="+data+", x="+x+", y="+y
+ Method MouseEvent:Void( event:Int,data:Int,x:Float,y:Float, z:Float )
+ Print "MouseEvent: event="+event+", data="+data+", x="+x+", y="+y+", z="+z
End
Method TouchEvent:Void( event:Int,data:Int,x:Float,y:Float )
diff --git a/examples/mojo/mak/dynamicimage/dynamicimage.cxs b/examples/mojo/mak/dynamicimage/dynamicimage.cxs
index f7fb2364..43209cf4 100644
--- a/examples/mojo/mak/dynamicimage/dynamicimage.cxs
+++ b/examples/mojo/mak/dynamicimage/dynamicimage.cxs
@@ -1,4 +1,3 @@
-
'Ok, looks a bit crap and doesn't make much sense, but it's just a test of offset, pitch, byte order etc...
'
Import mojo
@@ -21,9 +20,9 @@ Class MyApp Extends App
If KeyHit( KEY_SPACE )
fullscreen=Not fullscreen
If fullscreen
- GlfwGame.GetGlfwGame().SetGlfwWindow( 1024,768,8,8,8,0,0,0,True )
+ SetDeviceWindow( 1024, 768, 1 )
Else
- GlfwGame.GetGlfwGame().SetGlfwWindow( 640,480,8,8,8,0,0,0,False )
+ SetDeviceWindow( 640, 480, 4 )
Endif
End
#Endif
diff --git a/examples/mojo2/tween/tween_example.cxs b/examples/mojo2/tween/tween_example.cxs
new file mode 100644
index 00000000..f36e9726
--- /dev/null
+++ b/examples/mojo2/tween/tween_example.cxs
@@ -0,0 +1,169 @@
+Strict
+
+Import mojo2
+Import brl.tween
+
+'*******************************************************************
+' Define the tweenExample that extends the App Class.
+Class tweenExample Extends App
+ Field cnvs:Canvas
+ Field tw:Tween[6]
+ Field selected_tween:Int
+ Field tweens:String[] = ["LINEAR","BEZIER","CUSTOM","CURVE","BOUNCE (EASEOUT)","ELASTIC (EASEINOUT)"]
+ Field loop:Bool,yoyo:Bool
+
+ Method OnCreate:Int()
+ SetUpdateRate(60)
+ cnvs = New Canvas
+
+ ' linear tween
+ tw[0] = New Tween(Tween.LINEAR,2000)
+ tw[0].SetRange(100,540)
+
+ ' cubic bezier tween
+ tw[1] = New Tween(Tween.BEZIER,2000)
+ tw[1].SetBezierPoints(0.2,0.6,0.7,1)
+ tw[1].SetRange(100,540)
+
+ ' custom tween
+ tw[2] = New Tween(Tween.CUSTOM,2000)
+ tw[2].SetCustomData([0,0.1,0.9,0.8,0.4,0.7,1])
+ tw[2].SetRange(100,540)
+
+ ' curve tween
+ tw[3] = New Tween(Tween.CURVE,2000)
+ tw[3].SetCurve(0)
+ tw[3].SetRange(100,540)
+
+ ' bounce tween
+ tw[4] = New Tween(Tween.BOUNCE,2000)
+ tw[4].SetEasing(Tween.EASEOUT)
+ tw[4].SetRange(100,540)
+
+ ' elastic tween
+ tw[5] = New Tween(Tween.ELASTIC,2000)
+ tw[5].SetEasing(Tween.EASEINOUT)
+ tw[5].SetRange(100,540)
+
+ loop = False
+ yoyo = False
+ selected_tween = 0
+ tw[selected_tween].Start()
+ tw[selected_tween].SetLoop(loop)
+ tw[selected_tween].SetYoYo(yoyo)
+
+ Return 0
+ End
+
+ Method OnUpdate:Int()
+ ' start tween again
+ If KeyHit(KEY_SPACE) Then tw[selected_tween].Start()
+
+ ' change tween
+ If KeyHit(KEY_1)
+ selected_tween=(selected_tween+1) Mod tw.Length()
+ tw[selected_tween].Start()
+ tw[selected_tween].SetLoop(loop)
+ tw[selected_tween].SetYoYo(yoyo)
+ End
+
+ ' randdom custom tween
+ If KeyHit(KEY_R)
+ Select selected_tween
+ Case 1
+ tw[1].SetBezierPoints(0.25,Rnd(1),0.75,Rnd(1))
+ Case 2
+ CreateRandomTween()
+ Case 3
+ tw[3].SetCurve(Rnd(1))
+ End
+ tw[selected_tween].Start()
+ tw[selected_tween].SetLoop(loop)
+ tw[selected_tween].SetYoYo(yoyo)
+ End
+
+ ' loop tween
+ If KeyHit(KEY_L)
+ loop = Not loop
+ tw[selected_tween].SetLoop(loop)
+ End
+
+ ' yoyo tween
+ If KeyHit(KEY_Y)
+ yoyo = Not yoyo
+ tw[selected_tween].SetYoYo(yoyo)
+ End
+
+ Return 0
+ End
+
+ Method CreateRandomTween:Void()
+ Local y:Float[Rnd(20)+3]
+ For Local i:Int = 0 Until y.Length()
+ y[i] = Rnd(1)
+ Next
+ tw[2].SetCustomData(y)
+ End
+
+ Method OnRender:Int()
+ ' Clear the canvas with a black color.
+ cnvs.Clear (0,0.5,0)
+
+ cnvs.SetColor 1,1,1
+ cnvs.DrawText "Tween."+tweens[selected_tween],320,80,0.5,0.5
+
+ cnvs.SetColor 0,0.2,0
+ cnvs.DrawRect 100,100,440,20
+
+ ' draw a circle using the Tween Range Value as the x co-ordinate
+ cnvs.SetColor 1,1,1
+ cnvs.DrawOval tw[selected_tween].RangeValue()-10,100,20,20
+
+ DrawTween(220,180,200)
+
+ cnvs.SetColor 1,1,1
+ cnvs.DrawText "1 - Next Tween",10,400
+ cnvs.DrawText "L - Toggle Looping",10,420
+ cnvs.DrawText "Y - Toggle YoYoing",10,440
+ cnvs.DrawText "SPACE - Restart Tween",330,400
+
+ Select selected_tween
+ Case 1,2,3
+ cnvs.DrawText "R - Randomise Tween",330,420
+ End
+
+ cnvs.Flush
+
+ Return 0
+ End
+
+ Method DrawTween:Void(x:Float,y:Float,size:Float)
+ cnvs.SetColor 1,1,1
+ cnvs.DrawText "x",x+size+10,y+size,0.5,0.5
+ cnvs.DrawText "y",x-1,y-10,0.5,0.5
+ cnvs.DrawRect x-1,y,size+1,size+1
+
+ cnvs.SetColor 0,0.2,0
+ cnvs.DrawRect x,y,size,size
+
+ cnvs.SetColor 1,0,0
+ Local tx:Float = x+tw[selected_tween].X()*size
+ Local ty:Float = y+size-tw[selected_tween].TweenValueAtX(tw[selected_tween].X())*size
+ cnvs.DrawLine x,ty,tx,ty
+ cnvs.DrawLine tx,ty,tx,y+size
+
+ cnvs.SetColor 1,1,1
+ Local prey:Float = tw[selected_tween].TweenValueAtX(0)
+ For Local i:Float = 1 Until size
+ cnvs.DrawLine x+i-1,y+size-prey*size,x+i,y+size-tw[selected_tween].TweenValueAtX(i/size)*size
+ prey = tw[selected_tween].TweenValueAtX(i/size)
+ Next
+ cnvs.SetColor 1,0,0
+ cnvs.DrawOval tx-5,ty-5,10,10
+ End
+End
+
+Function Main:Int()
+ New tweenExample
+ Return 0
+End
\ No newline at end of file
diff --git a/license b/license
index 331936ff..7341c363 100644
--- a/license
+++ b/license
@@ -1,7 +1,8 @@
The zlib/libpng License
=======================
-Copyright (c) 2019 Michael Hartlef
+Cerberus X - Copyright (c) 2020 Michael Hartlef
+Monkey X - Copyright (c) 2013 Blitz Research Ltd
This software is provided 'as-is', without any express or implied warranty. In
no event will the authors be held liable for any damages arising from the use of
diff --git a/modules/brl/cerberusdoc/brl.cerberusdoc b/modules/brl/cerberusdoc/brl.cerberusdoc
index 07809def..249f7e4b 100644
--- a/modules/brl/cerberusdoc/brl.cerberusdoc
+++ b/modules/brl/cerberusdoc/brl.cerberusdoc
@@ -1,8 +1,14 @@
# Module brl
+# Import brl.admob
+
+# Import brl.cerberusstore
+
# Import brl.databuffer
+# Import brl.gamecenter
+
# Import brl.stream
# Import brl.datastream
@@ -17,10 +23,29 @@
# Import brl.filestream
+# Import brl.filepath
+
+# Import brl.filesystem
+
# Import brl.httprequest
+# Import brl.url
+
# Import brl.requesters
+# Import brl.tween
+
+# Import brl.pool
+
+# Import brl.process
+
+# Import brl.markdown
+
+# Import brl.json
+
+
+
+
The brl module is a set of utility classes and functions.
To import all modules in brl, simply add "Import brl" at the top of your program.
diff --git a/modules/brl/cerberusdoc/databuffer.cerberusdoc b/modules/brl/cerberusdoc/databuffer.cerberusdoc
index 2094b290..8c531f18 100644
--- a/modules/brl/cerberusdoc/databuffer.cerberusdoc
+++ b/modules/brl/cerberusdoc/databuffer.cerberusdoc
@@ -20,7 +20,7 @@ If @data is Null, the data load failed.
Databuffer objects provide storage for arbitrary data.
-Data may be written to a databufffer using one of the 'poke' methods, and read from a databuffer using one of the 'peek' methods.
+Data may be written to a databuffer using one of the 'poke' methods, and read from a databuffer using one of the 'peek' methods.
Parameters that specify buffer addresses or array indices for data transfers are not currently range checked. In general, you should always ensure that these are always valid, ie: >=0 And <=length of the buffer/array. Any transfer count parameters should always be >=0, but will always be clipped to make sure no overreads or overwrites occur.
diff --git a/modules/brl/cerberusdoc/requesters.cerberusdoc b/modules/brl/cerberusdoc/requesters.cerberusdoc
index 0d3fb039..5f3719e4 100644
--- a/modules/brl/cerberusdoc/requesters.cerberusdoc
+++ b/modules/brl/cerberusdoc/requesters.cerberusdoc
@@ -1,7 +1,7 @@
# Module brl.requesters
-The requesters module allows you to use simple modal requesters with the glfw3 target on Mac and Windows only!
+The requesters module allows you to use simple modal requesters with the glfw3 target.
# Function Notify:Void( title:String,text:String,serious:Bool )
@@ -53,3 +53,7 @@ End
# Function RequestDir:String( title:String,dir:String="" )
RequestDir activates a modal directory requester dialog.
+
+# Function RequestColor:Int( )
+
+RequestColor returns the RGB value of a selected color.
\ No newline at end of file
diff --git a/modules/brl/cerberusdoc/tween.cerberusdoc b/modules/brl/cerberusdoc/tween.cerberusdoc
new file mode 100644
index 00000000..df16fb08
--- /dev/null
+++ b/modules/brl/cerberusdoc/tween.cerberusdoc
@@ -0,0 +1,157 @@
+
+# Module tween
+
+The tween module provides simple support for loops using the built in interpolation functions.
+Some interpolation functions have easing in, easing out and easing in and out abilities.
+
+# Class tween.Tween
+
+The Tween class provides simple support for tweening with timing and loops.
+
+Each Tween will start at p(0,0) and end at p(1,1). A @CUSTOM interpolation is the only one that can overide p(0,y) and p(1,y).
+
+Example:
+
+
+
+# Method New(interpolation:Int, duration:Int)
+
+Setup a new Tween.
+
+* @interpolation can be either @Tween.@LINEAR, @Tween.@CUSTOM, @Tween.@BEZIER, @Tween.@CURVE, @Tween.@ELASTIC, @Tween.@BOUNCE, @Tween.@BACK
+* @duration is the length of the tween in Milli-seconds
+
+For interpolation styles see [[cerberus.interpolate]]
+
+# Method RangeValue:Float()
+
+Get the value in the range of the current Tween.
+
+# Method RangeValueAtX:Float(x:Float)
+
+Get the value in the range of the Tween when x=@x.
+
+# Method RangeValueAtTime:Float(time:Float)
+
+Get the value in the range of the Tween when time=@time.
+
+Links: [[SetRange]]
+
+# Method SetRange:Void(startValue:Float, endValue:Float)
+
+Set the range of the values of the tween. @RangeValue will return values between @startValue and @endValue
+
+Links: [[RangeValue]]
+
+# Method TweenValue:Float()
+
+Return the current tween value. This is usually between 0 and 1.
+
+# Method TweenValueAtX:Float(x:Float)
+
+Returns the tween value when x is @x. @x must be between 0 and 1. This doesnt set the x posiiton of the tween.
+
+# Method TweenValueAtTime:Float(time:Float)
+
+Returns the tween value when time is @time. This doesnt set the time or duration.
+
+# Method Start:Void()
+
+Starts the current tween
+
+# Method Stop:Void()
+
+Stops the current tween
+
+# Method Resume:Void()
+
+Resumes the currently stopped tween
+
+# Method SetLoop:Void(flag:Bool)
+
+Sets looping action.
+
+Links: [[GetLoop]]
+
+# Method SetYoYo:Void(flag:Bool)
+
+Sets YoYo-ing. YoYo-ing will only wotk if looping is set to @True
+
+Links: [[GetYoYo]]
+
+# Method GetLoop:Bool()
+
+Returns @True if looping is set to True
+
+# Method GetYoYo:Bool()
+
+Returns @True if YoYo is set to True
+
+# Method X:Float()
+
+Returns the x value of the current tween. @x is from 0-1
+
+
+# Method SetEasing:Void(easing_mode:Int)
+
+Sets the easing mode for the Tween.
+
+@easing_mode can be @Tween.@EASEIN, @Tween.@EASEOUT, @Tween.@EASEINOUT
+
+Only the following tween modes have easing modes: @BOUNCE, @BACK, @ELASTIC
+
+# Method SetBezierPoints:Void(pXa:Float, pYA:Float, pXb:Float, pYb:Float)
+
+Sets the 2 control points for the Bezier curve.
+
+* Control point 1 = (@pXa, @pYa)
+* Control point 2 = (@pXb, @pYb)
+
+# Method SetCustomData:Void(dataY:Float[])
+
+Sets the y data for the custom interpolation. The Tween will pass through each @dataY point
+
+# Method SetCurve:Void(curveY:Float)
+
+Sets the curve iterpolation point so that the curve passes through p(0.5,@curveY)
+
+# Method SetDuration:Void(duration:Int)
+
+Sets a new duration for the tween. @duration is in Millisecs
\ No newline at end of file
diff --git a/modules/brl/cerberusstore.cxs b/modules/brl/cerberusstore.cxs
index 04714010..92562fb4 100644
--- a/modules/brl/cerberusstore.cxs
+++ b/modules/brl/cerberusstore.cxs
@@ -8,7 +8,7 @@ Import asyncevent
#LIBS+="StoreKit.framework"
Import "native/cerberusstore.ios.cpp"
#Elseif TARGET="android"
-#SRCS+="${CD}/native/android_iab/src/com/android/vending/billing/IInAppBillingService.aidl"
+#SRCS+="${CD}/native/android_iab/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl;"
#ANDROID_MANIFEST_MAIN+=""
Import "native/cerberusstore.android.java"
#Else If TARGET="winrt"
diff --git a/modules/brl/native/android_iab/src/com/android/vending/billing/IInAppBillingService.aidl b/modules/brl/native/android_iab/src/com/android/vending/billing/IInAppBillingService.aidl
deleted file mode 100644
index 2a492f78..00000000
--- a/modules/brl/native/android_iab/src/com/android/vending/billing/IInAppBillingService.aidl
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.vending.billing;
-
-import android.os.Bundle;
-
-/**
- * InAppBillingService is the service that provides in-app billing version 3 and beyond.
- * This service provides the following features:
- * 1. Provides a new API to get details of in-app items published for the app including
- * price, type, title and description.
- * 2. The purchase flow is synchronous and purchase information is available immediately
- * after it completes.
- * 3. Purchase information of in-app purchases is maintained within the Google Play system
- * till the purchase is consumed.
- * 4. An API to consume a purchase of an inapp item. All purchases of one-time
- * in-app items are consumable and thereafter can be purchased again.
- * 5. An API to get current purchases of the user immediately. This will not contain any
- * consumed purchases.
- *
- * All calls will give a response code with the following possible values
- * RESULT_OK = 0 - success
- * RESULT_USER_CANCELED = 1 - user pressed back or canceled a dialog
- * RESULT_BILLING_UNAVAILABLE = 3 - this billing API version is not supported for the type requested
- * RESULT_ITEM_UNAVAILABLE = 4 - requested SKU is not available for purchase
- * RESULT_DEVELOPER_ERROR = 5 - invalid arguments provided to the API
- * RESULT_ERROR = 6 - Fatal error during the API action
- * RESULT_ITEM_ALREADY_OWNED = 7 - Failure to purchase since item is already owned
- * RESULT_ITEM_NOT_OWNED = 8 - Failure to consume since item is not owned
- */
-interface IInAppBillingService {
- /**
- * Checks support for the requested billing API version, package and in-app type.
- * Minimum API version supported by this interface is 3.
- * @param apiVersion the billing version which the app is using
- * @param packageName the package name of the calling app
- * @param type type of the in-app item being purchased "inapp" for one-time purchases
- * and "subs" for subscription.
- * @return RESULT_OK(0) on success, corresponding result code on failures
- */
- int isBillingSupported(int apiVersion, String packageName, String type);
-
- /**
- * Provides details of a list of SKUs
- * Given a list of SKUs of a valid type in the skusBundle, this returns a bundle
- * with a list JSON strings containing the productId, price, title and description.
- * This API can be called with a maximum of 20 SKUs.
- * @param apiVersion billing API version that the Third-party is using
- * @param packageName the package name of the calling app
- * @param skusBundle bundle containing a StringArrayList of SKUs with key "ITEM_ID_LIST"
- * @return Bundle containing the following key-value pairs
- * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
- * failure as listed above.
- * "DETAILS_LIST" with a StringArrayList containing purchase information
- * in JSON format similar to:
- * '{ "productId" : "exampleSku", "type" : "inapp", "price" : "$5.00",
- * "title : "Example Title", "description" : "This is an example description" }'
- */
- Bundle getSkuDetails(int apiVersion, String packageName, String type, in Bundle skusBundle);
-
- /**
- * Returns a pending intent to launch the purchase flow for an in-app item by providing a SKU,
- * the type, a unique purchase token and an optional developer payload.
- * @param apiVersion billing API version that the app is using
- * @param packageName package name of the calling app
- * @param sku the SKU of the in-app item as published in the developer console
- * @param type the type of the in-app item ("inapp" for one-time purchases
- * and "subs" for subscription).
- * @param developerPayload optional argument to be sent back with the purchase information
- * @return Bundle containing the following key-value pairs
- * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
- * failure as listed above.
- * "BUY_INTENT" - PendingIntent to start the purchase flow
- *
- * The Pending intent should be launched with startIntentSenderForResult. When purchase flow
- * has completed, the onActivityResult() will give a resultCode of OK or CANCELED.
- * If the purchase is successful, the result data will contain the following key-value pairs
- * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
- * failure as listed above.
- * "INAPP_PURCHASE_DATA" - String in JSON format similar to
- * '{"orderId":"12999763169054705758.1371079406387615",
- * "packageName":"com.example.app",
- * "productId":"exampleSku",
- * "purchaseTime":1345678900000,
- * "purchaseToken" : "122333444455555",
- * "developerPayload":"example developer payload" }'
- * "INAPP_DATA_SIGNATURE" - String containing the signature of the purchase data that
- * was signed with the private key of the developer
- * TODO: change this to app-specific keys.
- */
- Bundle getBuyIntent(int apiVersion, String packageName, String sku, String type,
- String developerPayload);
-
- /**
- * Returns the current SKUs owned by the user of the type and package name specified along with
- * purchase information and a signature of the data to be validated.
- * This will return all SKUs that have been purchased in V3 and managed items purchased using
- * V1 and V2 that have not been consumed.
- * @param apiVersion billing API version that the app is using
- * @param packageName package name of the calling app
- * @param type the type of the in-app items being requested
- * ("inapp" for one-time purchases and "subs" for subscription).
- * @param continuationToken to be set as null for the first call, if the number of owned
- * skus are too many, a continuationToken is returned in the response bundle.
- * This method can be called again with the continuation token to get the next set of
- * owned skus.
- * @return Bundle containing the following key-value pairs
- * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
- * failure as listed above.
- * "INAPP_PURCHASE_ITEM_LIST" - StringArrayList containing the list of SKUs
- * "INAPP_PURCHASE_DATA_LIST" - StringArrayList containing the purchase information
- * "INAPP_DATA_SIGNATURE_LIST"- StringArrayList containing the signatures
- * of the purchase information
- * "INAPP_CONTINUATION_TOKEN" - String containing a continuation token for the
- * next set of in-app purchases. Only set if the
- * user has more owned skus than the current list.
- */
- Bundle getPurchases(int apiVersion, String packageName, String type, String continuationToken);
-
- /**
- * Consume the last purchase of the given SKU. This will result in this item being removed
- * from all subsequent responses to getPurchases() and allow re-purchase of this item.
- * @param apiVersion billing API version that the app is using
- * @param packageName package name of the calling app
- * @param purchaseToken token in the purchase information JSON that identifies the purchase
- * to be consumed
- * @return 0 if consumption succeeded. Appropriate error values for failures.
- */
- int consumePurchase(int apiVersion, String packageName, String purchaseToken);
-}
diff --git a/targets/android/template/gradletemplate/app/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl b/modules/brl/native/android_iab/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl
similarity index 100%
rename from targets/android/template/gradletemplate/app/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl
rename to modules/brl/native/android_iab/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl
diff --git a/modules/brl/native/requesters.cpp b/modules/brl/native/requesters.cpp
index df6794c0..b0ede69a 100644
--- a/modules/brl/native/requesters.cpp
+++ b/modules/brl/native/requesters.cpp
@@ -380,4 +380,73 @@ String bbRequestDir( String title,String dir ){
return str;
}
+#else
+
+#include
+/*
+String bbRequestFile2( String title,String filter,int save,String path ){
+
+ String ps;
+ if( save ){
+ ps = tinyfd_saveFileDialog (OS_STR(title), OS_STR(path), 0, NULL, NULL);
+ }else{
+ ps = tinyfd_openFileDialog (OS_STR(title), OS_STR(path), 0, NULL, NULL,0);
+ }
+
+ return ps;
+}
+*/
+
+void bbNotify( String title,String text,int serious ){
+
+ tinyfd_messageBox( OS_STR( title ),OS_STR( text ),"ok",serious ? "error" : "info",1 );
+}
+
+int bbConfirm( String title,String text,int serious ){
+
+ return tinyfd_messageBox( OS_STR( title ),OS_STR( text ),"okcancel",serious ? "error" : "info",1 );
+}
+
+int bbProceed( String title,String text,int serious ){
+
+ // Ok, no yesnocancal in tinyfd so we'll use kdialog...
+
+ int result=tinyfd_messageBox( OS_STR( title ),OS_STR( text ),"yesnocancel",serious ? "error" : "info",1 );
+
+ return result==2 ? -1 : result;
+
+}
+
+String bbRequestFile( String title,String exts, int save,String path ){
+ char const * ps;
+ if( path=="" ) path=".";
+
+ if( save ){
+ ps = tinyfd_saveFileDialog( OS_STR( title ),OS_STR( path ),0,0,0 );
+ }else{
+ ps = tinyfd_openFileDialog( OS_STR( title ),OS_STR( path ),0,0,0,0 );
+ }
+ if (! ps) {
+ return "";
+ }else{
+ return ps;
+ }
+
+}
+
+String bbRequestDir( String title,String dir ){
+ char const * ps;
+
+ if( dir=="" ) dir=".";
+
+ ps = tinyfd_selectFolderDialog( OS_STR( title ),OS_STR( dir ) );
+ if (! ps) {
+ return "";
+ }else{
+ return ps;
+ }
+}
+
+
+
#endif
diff --git a/modules/brl/requesters.cxs b/modules/brl/requesters.cxs
index 99becd4e..6addfdd4 100644
--- a/modules/brl/requesters.cxs
+++ b/modules/brl/requesters.cxs
@@ -1,5 +1,6 @@
-#If TARGET<>"glfw" Or (HOST<>"winnt" And HOST<>"macos")
+'#If TARGET<>"glfw" Or (HOST<>"winnt" And HOST<>"macos")
+#If TARGET<>"glfw"
#Error "Requesters module unavailable on this target"
#Endif
@@ -7,11 +8,12 @@ Import "native/requesters.cpp"
Extern
+
Function Notify:Void( title:String,text:String,serious:Bool=False )="bbNotify"
Function Confirm:Bool( title:String,text:String,serious:Bool=False )="bbConfirm"
-Function Proceed:Int( title:String,text:String,serious:Bool=false )="bbProceed"
+Function Proceed:Int( title:String,text:String,serious:Bool=False )="bbProceed"
Function RequestFile:String( title:String,extensions:String="",save:Bool=False,file:String="" )="bbRequestFile"
diff --git a/modules/brl/tween.cxs b/modules/brl/tween.cxs
new file mode 100644
index 00000000..baf2a148
--- /dev/null
+++ b/modules/brl/tween.cxs
@@ -0,0 +1,227 @@
+Strict
+
+Import mojo.app
+Import cerberus.interpolate
+
+Class Tween
+ Public
+ Const LINEAR:=0
+ Const BEZIER:=1
+ Const CUSTOM:=2
+ Const CURVE:=3
+ Const SIN:=4
+ Const FLATS:=5
+ Const ELASTIC:=6
+ Const BOUNCE:=7
+ Const BACK:=8
+
+ Const EASEIN:=0
+ Const EASEOUT:=1
+ Const EASEINOUT:=2
+
+ Private
+ Field range_start:Int
+ Field range_end:Int
+ Field range:Float
+
+ Field interpolation:Int
+ Field easing_mode:Int
+
+ Field duration:Int
+ Field start_time:Int
+ Field old_time:Int
+ Field time:Int
+
+ Field active:Bool
+ Field loop:Bool
+ Field yoyo:Bool
+ Field custom_data:Float[]
+ Field bezier_data:Float[6]
+ Field curve:Float
+ Field x:Float
+ Field value:Float
+
+ Public
+ Method New(interpolation:Int,duration:Int)
+ Init(interpolation,duration)
+ End
+
+ Method RangeValue:Float()
+ Return range_start + range * TweenValue()
+ End
+
+ Method RangeValueAtX:Float(x:Float)
+ Return range_start + range * TweenValue(x)
+ End
+
+ Method RangeValueAtTime:Float(time:Float)
+ Return range_start + range * TweenValue(time)
+ End
+
+ Method SetRange:Void(startValue:Int,endValue:Int)
+ range_start = startValue
+ range_end = endValue
+
+ range = endValue - startValue
+ End
+
+ Method SetEasing:Void(easing:Int)
+ #If CONFIG="debug"
+ If interpolation<6 Then Print "No Easing mode for this interpolation"
+ #End
+ easing_mode = easing
+ End
+
+ Method Start:Void()
+ start_time = Millisecs()
+ active = True
+ End
+
+ Method Stop:Void()
+ old_time = Millisecs()
+ active = False
+ End
+
+ Method Resume:Void()
+ If old_time = -1
+ Start()
+ Else
+ start_time = Millisecs() - (old_time-start_time)
+ active = True
+ End
+ End
+
+ Method SetLoop:Void(flag:Bool)
+ loop = flag
+ End
+
+ Method GetLoop:Bool()
+ Return loop
+ End
+
+ Method SetYoYo:Void(flag:Bool)
+ yoyo = flag
+ End
+
+ Method GetYoYo:Bool()
+ Return yoyo
+ End
+
+ Method X:Float()
+ x = time/Float(duration)
+ Return x
+ End
+
+ Method TweenValue:Float()
+ Update()
+ Return value
+ End
+
+ Method TweenValueAtX:Float(x:Float)
+ Return GetTween(x)
+ End
+
+ Method TweenValueAtTime:Float(time:Float)
+ Return GetTween(time/Float(duration))
+ End
+
+ Method SetCustomData:Void(custom_data:Float[])
+ Self.custom_data = custom_data
+ End
+
+ Method SetBezierPoints:Void(pA:Float, pB:Float, pC:Float, pD:Float, pPrecision:Float = 0.0001)
+ bezier_data = [pA, pB, pC, pD, pPrecision]
+ End
+
+ Method SetCurve:Void(pYA:Float)
+ curve = pYA
+ End
+
+ Method SetDuration:Void(duration:Int)
+ Self.duration = duration
+ End
+
+ Private
+ Method Init:Void(interpolation:Int,duration:Int)
+ Self.duration = duration
+ Self.interpolation = interpolation
+
+ time = 0
+ active = False
+ SetLoop(False)
+ SetYoYo(False)
+
+ SetRange(0,1)
+ End
+
+ Method Update:Void()
+ If active = False Then Return
+ time = Millisecs() - start_time
+
+ If loop=True
+ If yoyo=True
+ time = time Mod (2*duration)
+ If time>duration
+ time = 2*duration - time
+ End
+ Else
+ time = time Mod duration
+ End
+ Else
+ If time>duration Then time=duration
+ End
+
+ x = time/Float(duration)
+ value = GetTween(x)
+ End
+
+ Method GetTween:Float(t:Float)
+ Select interpolation
+ Case LINEAR
+ Return InterpolateLin(0,1,t)
+ Case BEZIER
+ #If CONFIG="debug"
+ If bezier_data.Length()=0 Then Error("Bezier points not set. Use Tween.SetBezierPoints()")
+ #End
+ Return InterpolateCubicBezier(0,1,bezier_data[0],bezier_data[1],bezier_data[2],bezier_data[3],t,bezier_data[4])
+ Case CUSTOM
+ #If CONFIG="debug"
+ If custom_data.Length()=0 Then Error("Custom data not set. Use Tween.SetCustomData()")
+ If custom_data.Length()=1 Then Error("Not enough custom point data. There must be at least 2 points")
+ #End
+ Return InterpolateCustomLine(custom_data,t)
+ Case CURVE
+ Return InterpolateCurve(0,1,curve,t)
+ Case SIN
+ Return InterpolateSin(0,1,t)
+ Case ELASTIC
+ Select easing_mode
+ Case EASEIN
+ Return InterpolateElasticEaseIn(0,1,t)
+ Case EASEOUT
+ Return InterpolateElasticEaseOut(0,1,t)
+ Case EASEINOUT
+ Return InterpolateElasticEaseInOut(0,1,t)
+ End
+ Case BOUNCE
+ Select easing_mode
+ Case EASEIN
+ Return InterpolateBounceEaseIn(0,1,t)
+ Case EASEOUT
+ Return InterpolateBounceEaseOut(0,1,t)
+ Case EASEINOUT
+ Return InterpolateBounceEaseInOut(0,1,t)
+ End
+ Case BACK
+ Select easing_mode
+ Case EASEIN
+ Return InterpolateBackEaseIn(0,1,t)
+ Case EASEOUT
+ Return InterpolateBackEaseOut(0,1,t)
+ Case EASEINOUT
+ Return InterpolateBackEaseInOut(0,1,t)
+ End
+ End
+ Return 0
+ End
+End
\ No newline at end of file
diff --git a/modules/cerberus/cerberusdoc/cerberus.cerberusdoc b/modules/cerberus/cerberusdoc/cerberus.cerberusdoc
index 0f390868..622ae9db 100644
--- a/modules/cerberus/cerberusdoc/cerberus.cerberusdoc
+++ b/modules/cerberus/cerberusdoc/cerberus.cerberusdoc
@@ -3,6 +3,10 @@
# Import cerberus.boxes
+# Import cerberus.deque
+
+# Import cerberus.interpolate
+
# Import cerberus.lang
# Import cerberus.list
@@ -13,8 +17,6 @@
# Import cerberus.random
-# Import cerberus.interpolate
-
# Import cerberus.set
# Import cerberus.stack
diff --git a/modules/cerberus/cerberusdoc/interpolate.cerberusdoc b/modules/cerberus/cerberusdoc/interpolate.cerberusdoc
index dffce294..83cb51b5 100644
--- a/modules/cerberus/cerberusdoc/interpolate.cerberusdoc
+++ b/modules/cerberus/cerberusdoc/interpolate.cerberusdoc
@@ -126,3 +126,155 @@ Parameters:
Returns: Interpolated @y value at @x
Links: [Live demo](./data/cerberus/interpolate/interpolate_applet.build/html5/CerberusGame.html)
+
+# Function InterpolateCustomLine:Float(dataY:Float[], x:Float)
+
+Interpolates on a sawtooth line through all the points in dataY[] spread evenly from `(0,@dataY[0])` to `(1,@dataY[n])` at @x. dataY must contain 2 or more points.
+
+![InterpolateCustomLine diagram](data/cerberus/interpolate/InterpolateCustomLine.png)
+
+Parameters:
+* @dataY[] - an array of @y points
+* @x - point to interpolate, ranging from 0 to 1
+
+Returns: Interpolated @y value at @x
+
+Links: [Live demo](./data/cerberus/interpolate/interpolate_applet.build/html5/CerberusGame.html)
+
+# Function InterpolateElasticEaseIn:Float(y0:Float, y1:Float, x:Float)
+
+Interpolates on an elastic bouncing curve from `(0,@y0)` to `(1,@y1)` at @x. This eases in the bouncing.
+
+![InterpolateElasticEaseIn diagram](data/cerberus/interpolate/InterpolateElasticEaseIn.png)
+
+Parameters:
+* @y0 - value at x=0.0
+* @y1 - value at x=1.0
+* @x - point to interpolate, ranging from 0 to 1
+
+Returns: Interpolated @y value at @x
+
+Links: [Live demo](./data/cerberus/interpolate/interpolate_applet.build/html5/CerberusGame.html)
+
+# Function InterpolateElasticEaseOut:Float(y0:Float, y1:Float, x:Float)
+
+Interpolates on an elastic bouncing curve from `(0,@y0)` to `(1,@y1)` at @x. This eases out the bouncing.
+
+![InterpolateElasticEaseOut diagram](data/cerberus/interpolate/InterpolateElasticEaseOut.png)
+
+Parameters:
+* @y0 - value at x=0.0
+* @y1 - value at x=1.0
+* @x - point to interpolate, ranging from 0 to 1
+
+Returns: Interpolated @y value at @x
+
+Links: [Live demo](./data/cerberus/interpolate/interpolate_applet.build/html5/CerberusGame.html)
+
+# Function InterpolateElasticEaseInOut:Float(y0:Float, y1:Float, x:Float)
+
+Interpolates on an elastic bouncing curve from `(0,@y0)` to `(1,@y1)` at @x. This eases in and out the bouncing.
+
+![InterpolateElasticEaseInOut diagram](data/cerberus/interpolate/InterpolateElasticEaseInOut.png)
+
+Parameters:
+* @y0 - value at x=0.0
+* @y1 - value at x=1.0
+* @x - point to interpolate, ranging from 0 to 1
+
+Returns: Interpolated @y value at @x
+
+Links: [Live demo](./data/cerberus/interpolate/interpolate_applet.build/html5/CerberusGame.html)
+
+# Function InterpolateBackEaseIn:Float(y0:Float, y1:Float, x:Float)
+
+Interpolates on a pull back curve from `(0,@y0)` to `(1,@y1)` at @x. This eases in the pull back mechanism.
+
+![InterpolateBackEaseIn diagram](data/cerberus/interpolate/InterpolateBackEaseIn.png)
+
+Parameters:
+* @y0 - value at x=0.0
+* @y1 - value at x=1.0
+* @x - point to interpolate, ranging from 0 to 1
+
+Returns: Interpolated @y value at @x
+
+Links: [Live demo](./data/cerberus/interpolate/interpolate_applet.build/html5/CerberusGame.html)
+
+
+# Function InterpolateBackEaseOut:Float(y0:Float, y1:Float, x:Float)
+
+Interpolates on a pull back curve from `(0,@y0)` to `(1,@y1)` at @x. This eases out the pull back mechanism.
+
+![InterpolateBackEaseOut diagram](data/cerberus/interpolate/InterpolateBackEaseOut.png)
+
+Parameters:
+* @y0 - value at x=0.0
+* @y1 - value at x=1.0
+* @x - point to interpolate, ranging from 0 to 1
+
+Returns: Interpolated @y value at @x
+
+Links: [Live demo](./data/cerberus/interpolate/interpolate_applet.build/html5/CerberusGame.html)
+
+# Function InterpolateBackEaseInOut:Float(y0:Float, y1:Float, x:Float)
+
+Interpolates on a pull back curve from `(0,@y0)` to `(1,@y1)` at @x. This eases in and out the pull back mechanism.
+
+![InterpolateBackEaseInOut diagram](data/cerberus/interpolate/InterpolateBackEaseInOut.png)
+
+Parameters:
+* @y0 - value at x=0.0
+* @y1 - value at x=1.0
+* @x - point to interpolate, ranging from 0 to 1
+
+Returns: Interpolated @y value at @x
+
+Links: [Live demo](./data/cerberus/interpolate/interpolate_applet.build/html5/CerberusGame.html)
+
+# Function InterpolateBounceEaseIn:Float(y0:Float, y1:Float, x:Float)
+
+Interpolates on a bouncing curve from `(0,@y0)` to `(1,@y1)` at @x. This eases in the bouncing.
+
+![InterpolateBounceEaseIn diagram](data/cerberus/interpolate/InterpolateBounceEaseIn.png)
+
+Parameters:
+* @y0 - value at x=0.0
+* @y1 - value at x=1.0
+* @x - point to interpolate, ranging from 0 to 1
+
+Returns: Interpolated @y value at @x
+
+Links: [Live demo](./data/cerberus/interpolate/interpolate_applet.build/html5/CerberusGame.html)
+
+
+# Function InterpolateBounceEaseOut:Float(y0:Float, y1:Float, x:Float)
+
+Interpolates on a bouncing curve from `(0,@y0)` to `(1,@y1)` at @x. This eases out the bouncing.
+
+![InterpolateBounceEaseOut diagram](data/cerberus/interpolate/InterpolateBounceEaseOut.png)
+
+Parameters:
+* @y0 - value at x=0.0
+* @y1 - value at x=1.0
+* @x - point to interpolate, ranging from 0 to 1
+
+Returns: Interpolated @y value at @x
+
+Links: [Live demo](./data/cerberus/interpolate/interpolate_applet.build/html5/CerberusGame.html)
+
+
+# Function InterpolateBounceEaseInOut:Float(y0:Float, y1:Float, x:Float)
+
+Interpolates on a bouncing curve from `(0,@y0)` to `(1,@y1)` at @x. This eases in and out the bouncing.
+
+![InterpolateBounceEaseIn diagram](data/cerberus/interpolate/InterpolateBounceEaseInOut.png)
+
+Parameters:
+* @y0 - value at x=0.0
+* @y1 - value at x=1.0
+* @x - point to interpolate, ranging from 0 to 1
+
+Returns: Interpolated @y value at @x
+
+Links: [Live demo](./data/cerberus/interpolate/interpolate_applet.build/html5/CerberusGame.html)
diff --git a/modules/cerberus/cerberusdoc/interpolate.data/InterpolateBackEaseIn.png b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateBackEaseIn.png
new file mode 100644
index 00000000..5dd5c13e
Binary files /dev/null and b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateBackEaseIn.png differ
diff --git a/modules/cerberus/cerberusdoc/interpolate.data/InterpolateBackEaseInOut.png b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateBackEaseInOut.png
new file mode 100644
index 00000000..769c428b
Binary files /dev/null and b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateBackEaseInOut.png differ
diff --git a/modules/cerberus/cerberusdoc/interpolate.data/InterpolateBackEaseOut.png b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateBackEaseOut.png
new file mode 100644
index 00000000..0468a33b
Binary files /dev/null and b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateBackEaseOut.png differ
diff --git a/modules/cerberus/cerberusdoc/interpolate.data/InterpolateBounceEaseIn.png b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateBounceEaseIn.png
new file mode 100644
index 00000000..1a6caf87
Binary files /dev/null and b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateBounceEaseIn.png differ
diff --git a/modules/cerberus/cerberusdoc/interpolate.data/InterpolateBounceEaseInOut.png b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateBounceEaseInOut.png
new file mode 100644
index 00000000..1d06462c
Binary files /dev/null and b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateBounceEaseInOut.png differ
diff --git a/modules/cerberus/cerberusdoc/interpolate.data/InterpolateBounceEaseOut.png b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateBounceEaseOut.png
new file mode 100644
index 00000000..d398ea78
Binary files /dev/null and b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateBounceEaseOut.png differ
diff --git a/modules/cerberus/cerberusdoc/interpolate.data/InterpolateCustom.png b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateCustom.png
new file mode 100644
index 00000000..9fadd35b
Binary files /dev/null and b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateCustom.png differ
diff --git a/modules/cerberus/cerberusdoc/interpolate.data/InterpolateElasticEaseIn.png b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateElasticEaseIn.png
new file mode 100644
index 00000000..1c27941e
Binary files /dev/null and b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateElasticEaseIn.png differ
diff --git a/modules/cerberus/cerberusdoc/interpolate.data/InterpolateElasticEaseInOut.png b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateElasticEaseInOut.png
new file mode 100644
index 00000000..ebfade9b
Binary files /dev/null and b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateElasticEaseInOut.png differ
diff --git a/modules/cerberus/cerberusdoc/interpolate.data/InterpolateElasticEaseOut.png b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateElasticEaseOut.png
new file mode 100644
index 00000000..7e424fea
Binary files /dev/null and b/modules/cerberus/cerberusdoc/interpolate.data/InterpolateElasticEaseOut.png differ
diff --git a/modules/cerberus/cerberusdoc/interpolate.data/interpolate_applet.build/html5/main.js b/modules/cerberus/cerberusdoc/interpolate.data/interpolate_applet.build/html5/main.js
index 45959cd8..c10d577e 100644
--- a/modules/cerberus/cerberusdoc/interpolate.data/interpolate_applet.build/html5/main.js
+++ b/modules/cerberus/cerberusdoc/interpolate.data/interpolate_applet.build/html5/main.js
@@ -5,6 +5,7 @@ CFG_BRL_DATABUFFER_IMPLEMENTED="1";
CFG_BRL_GAMETARGET_IMPLEMENTED="1";
CFG_BRL_THREAD_IMPLEMENTED="1";
CFG_CD="";
+CFG_COLOR_USE_NORMALISED_COMPONENTS="1";
CFG_CONFIG="release";
CFG_GLFW_COPY_LIBS="openal32";
CFG_GLFW_GCC_LIB_OPTS="-lopenal32";
@@ -2864,6 +2865,9 @@ c_MyApp.prototype.p_Layout=function(){
bb_interpolate_applet_pointS1.p_SetScale(c_MyApp.m_framesize);
bb_interpolate_applet_pointAB.p_SetScale(c_MyApp.m_framesize);
bb_interpolate_applet_pointCD.p_SetScale(c_MyApp.m_framesize);
+ for(var t_i=0;t_i<6;t_i=t_i+1){
+ bb_interpolate_applet_custom_points[t_i].p_SetScale(c_MyApp.m_framesize);
+ }
c_MyApp.m_demox0=((c_MyApp.m_width/2)|0)+c_MyApp.m_framex0;
c_MyApp.m_demoy0=c_MyApp.m_graphy0+c_MyApp.m_framey0;
}
@@ -2908,6 +2912,13 @@ c_MyApp.prototype.p_OnCreate=function(){
bb_interpolate_applet_pointCD.p_XBounds(0.0,1.0);
bb_interpolate_applet_pointCD.p_YBounds(-0.5,1.5);
bb_interpolate_applet_pointCD.p_Hide();
+ for(var t_i=0;t_i<6;t_i=t_i+1){
+ bb_interpolate_applet_custom_points[t_i]=c_ControlPoint.m_new.call(new c_ControlPoint);
+ bb_interpolate_applet_custom_points[t_i].p_Position(0.14285714285714285*(t_i+1),bb_interpolate_applet_custom_data[t_i+1]);
+ bb_interpolate_applet_custom_points[t_i].p_XBounds(0.14285714285714285*(t_i+1),0.14285714285714285*(t_i+1));
+ bb_interpolate_applet_custom_points[t_i].p_YBounds(-0.5,1.5);
+ bb_interpolate_applet_custom_points[t_i].p_Hide();
+ }
bb_interpolate_applet_curfunc=bb_interpolate_applet_INTERPFUNCS[bb_interpolate_applet_curfuncidx];
bb_interpolate_applet_curfunc.p_Activate();
this.p_Layout();
@@ -2933,6 +2944,9 @@ c_MyApp.prototype.p_OnUpdate=function(){
bb_interpolate_applet_pointYA.p_Update();
bb_interpolate_applet_pointY0.p_Update();
bb_interpolate_applet_pointY1.p_Update();
+ for(var t_i=0;t_i<6;t_i=t_i+1){
+ bb_interpolate_applet_custom_points[t_i].p_Update();
+ }
if((bb_input_KeyHit(32))!=0){
bb_interpolate_applet_curfuncidx=(bb_interpolate_applet_curfuncidx+1) % bb_interpolate_applet_INTERPFUNCS.length;
bb_interpolate_applet_curfunc=bb_interpolate_applet_INTERPFUNCS[bb_interpolate_applet_curfuncidx];
@@ -2941,12 +2955,15 @@ c_MyApp.prototype.p_OnUpdate=function(){
bb_interpolate_applet_pointS0.p_Hide();
bb_interpolate_applet_pointS1.p_Hide();
bb_interpolate_applet_pointYA.p_Hide();
+ for(var t_i2=0;t_i2<6;t_i2=t_i2+1){
+ bb_interpolate_applet_custom_points[t_i2].p_Hide();
+ }
bb_interpolate_applet_curfunc.p_Activate();
bb_interpolate_applet_anypointmoved=1;
}
var t_t=(bb_app_Millisecs() % (c_MyApp.m_DEMO_DURATION_MAX+2000)-1000);
- for(var t_i=0;t_i<3;t_i=t_i+1){
- c_MyApp.m_demot[t_i]=bb_math_Clamp2(t_t/(c_MyApp.m_DEMO_DURATIONS[t_i]),0.0,1.0);
+ for(var t_i3=0;t_i3<3;t_i3=t_i3+1){
+ c_MyApp.m_demot[t_i3]=bb_math_Clamp2(t_t/(c_MyApp.m_DEMO_DURATIONS[t_i3]),0.0,1.0);
}
if((bb_interpolate_applet_anypointmoved)!=0){
var t_ttxt=bb_interpolate_applet_curfunc.p_Label();
@@ -3019,6 +3036,9 @@ c_MyApp.prototype.p_OnRender=function(){
bb_interpolate_applet_pointYA.p_Draw(bb_interpolate_applet_cvMain);
bb_interpolate_applet_pointS0.p_Draw(bb_interpolate_applet_cvMain);
bb_interpolate_applet_pointS1.p_Draw(bb_interpolate_applet_cvMain);
+ for(var t_i=0;t_i<6;t_i=t_i+1){
+ bb_interpolate_applet_custom_points[t_i].p_Draw(bb_interpolate_applet_cvMain);
+ }
var t_x2=.0;
var t_scl=.0;
var t_s20=(c_MyApp.m_framesize)/20.0;
@@ -3026,11 +3046,11 @@ c_MyApp.prototype.p_OnRender=function(){
bb_interpolate_applet_cvMain.p_Translate((c_MyApp.m_demox0),(c_MyApp.m_demoy0));
this.p_DrawFrameBorder();
bb_interpolate_applet_cvMain.p_SetColor3(2587588);
- for(var t_i=0;t_i<3;t_i=t_i+1){
- t_scl=bb_interpolate_applet_curfunc.p_Interpolate(c_MyApp.m_demot[t_i]);
+ for(var t_i2=0;t_i2<3;t_i2=t_i2+1){
+ t_scl=bb_interpolate_applet_curfunc.p_Interpolate(c_MyApp.m_demot[t_i2]);
t_x2=(c_MyApp.m_framesize)*t_scl;
- bb_interpolate_applet_cvMain.p_DrawCircle(t_x2,(4+4*t_i)*t_s20,t_s20,null);
- bb_interpolate_applet_cvMain.p_DrawCircle((5+5*t_i)*t_s20,16.0*t_s20,2.0*t_s20*t_scl,null);
+ bb_interpolate_applet_cvMain.p_DrawCircle(t_x2,(4+4*t_i2)*t_s20,t_s20,null);
+ bb_interpolate_applet_cvMain.p_DrawCircle((5+5*t_i2)*t_s20,16.0*t_s20,2.0*t_s20*t_scl,null);
}
bb_interpolate_applet_cvMain.p_ResetMatrix();
bb_interpolate_applet_cvMain.p_SetColor(0.0,0.0,0.0);
@@ -4183,163 +4203,84 @@ function bb_graphics_SetColor2(t_rgb){
}
function c_Color(){
Object.call(this);
- this.m__red=.0;
- this.m__RgbIsUpToDate=false;
- this.m__HsbIsUpToDate=false;
+ this.m_r=.0;
+ this.m_g=.0;
+ this.m_b=.0;
+ this.m__hue=.0;
this.m__sat=.0;
this.m__bri=.0;
- this.m__grn=.0;
- this.m__blu=.0;
- this.m__hue=.0;
-}
-c_Color.prototype.p_red=function(t_pRed){
- this.m__red=bb_math_Clamp2(t_pRed,0.0,1.0);
- this.m__RgbIsUpToDate=true;
- this.m__HsbIsUpToDate=false;
-}
-c_Color.prototype.p_ToRgb=function(){
- if(this.m__sat==0.0){
- this.m__red=this.m__bri;
- this.m__grn=this.m__bri;
- this.m__blu=this.m__bri;
- }else{
- if(this.m__bri==0.0){
- this.m__red=0.0;
- this.m__grn=0.0;
- this.m__blu=0.0;
- }else{
- var t_hidx=((this.m__hue/60.0)|0);
- var t_hfrac=this.m__hue/60.0-(t_hidx);
- var t_ccj=this.m__bri*(1.0-this.m__sat);
- var t_cck=this.m__bri*(1.0-this.m__sat*t_hfrac);
- var t_ccl=this.m__bri*(1.0-this.m__sat*(1.0-t_hfrac));
- var t_1=t_hidx;
- if(t_1==0){
- this.m__red=this.m__bri;
- this.m__grn=t_ccl;
- this.m__blu=t_ccj;
- }else{
- if(t_1==1){
- this.m__red=t_cck;
- this.m__grn=this.m__bri;
- this.m__blu=t_ccj;
- }else{
- if(t_1==2){
- this.m__red=t_ccj;
- this.m__grn=this.m__bri;
- this.m__blu=t_ccl;
- }else{
- if(t_1==3){
- this.m__red=t_ccj;
- this.m__grn=t_cck;
- this.m__blu=this.m__bri;
- }else{
- if(t_1==4){
- this.m__red=t_ccl;
- this.m__grn=t_ccj;
- this.m__blu=this.m__bri;
- }else{
- if(t_1==5){
- this.m__red=this.m__bri;
- this.m__grn=t_ccj;
- this.m__blu=t_cck;
- }
- }
- }
- }
- }
- }
- }
- }
- this.m__RgbIsUpToDate=true;
-}
-c_Color.prototype.p_red2=function(){
- if(!this.m__RgbIsUpToDate){
- this.p_ToRgb();
- }
- return this.m__red;
+ this.m__HsbSyncRed=.0;
+ this.m__HsbSyncGrn=.0;
+ this.m__HsbSyncBlu=.0;
}
-c_Color.prototype.p_grn=function(t_pGrn){
- this.m__grn=bb_math_Clamp2(t_pGrn,0.0,1.0);
- this.m__RgbIsUpToDate=true;
- this.m__HsbIsUpToDate=false;
+c_Color.prototype.p_Set2=function(t_pHex){
+ this.m_r=(t_pHex>>16&255)/255.0;
+ this.m_g=(t_pHex>>8&255)/255.0;
+ this.m_b=(t_pHex&255)/255.0;
}
-c_Color.prototype.p_grn2=function(){
- if(!this.m__RgbIsUpToDate){
- this.p_ToRgb();
- }
- return this.m__grn;
-}
-c_Color.prototype.p_blu=function(t_pBlu){
- this.m__blu=bb_math_Clamp2(t_pBlu,0.0,1.0);
- this.m__RgbIsUpToDate=true;
- this.m__HsbIsUpToDate=false;
-}
-c_Color.prototype.p_blu2=function(){
- if(!this.m__RgbIsUpToDate){
- this.p_ToRgb();
- }
- return this.m__blu;
-}
-c_Color.prototype.p_Set2=function(t_pRed,t_pGrn,t_pBlu){
- this.m__red=bb_math_Clamp2(t_pRed,0.0,1.0);
- this.m__grn=bb_math_Clamp2(t_pGrn,0.0,1.0);
- this.m__blu=bb_math_Clamp2(t_pBlu,0.0,1.0);
- this.m__RgbIsUpToDate=true;
- this.m__HsbIsUpToDate=false;
-}
-c_Color.prototype.p_Set3=function(t_pHex){
- this.m__red=(t_pHex>>16&255)/255.0;
- this.m__grn=(t_pHex>>8&255)/255.0;
- this.m__blu=(t_pHex&255)/255.0;
- this.m__RgbIsUpToDate=true;
- this.m__HsbIsUpToDate=false;
+c_Color.prototype.p_Set3=function(t_pRed,t_pGrn,t_pBlu){
+ this.m_r=bb_math_Clamp2(t_pRed,0.0,1.0);
+ this.m_g=bb_math_Clamp2(t_pGrn,0.0,1.0);
+ this.m_b=bb_math_Clamp2(t_pBlu,0.0,1.0);
}
c_Color.prototype.p_Set4=function(t_pRgb){
- this.p_Set2(t_pRgb[0],t_pRgb[1],t_pRgb[2]);
+ this.m_r=bb_math_Clamp2(t_pRgb[0],0.0,1.0);
+ this.m_g=bb_math_Clamp2(t_pRgb[1],0.0,1.0);
+ this.m_b=bb_math_Clamp2(t_pRgb[2],0.0,1.0);
}
c_Color.prototype.p_Set5=function(t_pColor){
- this.p_Set3(bb_colornames_NamedHtmlColor(t_pColor));
+ this.m_r=t_pColor.m_r;
+ this.m_g=t_pColor.m_g;
+ this.m_b=t_pColor.m_b;
+ this.m__hue=t_pColor.m__hue;
+ this.m__sat=t_pColor.m__sat;
+ this.m__bri=t_pColor.m__bri;
+ this.m__HsbSyncRed=t_pColor.m__HsbSyncRed;
+ this.m__HsbSyncGrn=t_pColor.m__HsbSyncGrn;
+ this.m__HsbSyncBlu=t_pColor.m__HsbSyncBlu;
+}
+c_Color.m_new=function(t_pRed,t_pGrn,t_pBlu){
+ this.p_Set3(t_pRed,t_pGrn,t_pBlu);
+ return this;
}
-c_Color.m_new=function(){
- this.p_Set3(0);
+c_Color.m_new2=function(t_pRgb){
+ this.p_Set4(t_pRgb);
return this;
}
-c_Color.m_new2=function(t_pHex){
- this.p_Set3(t_pHex);
+c_Color.prototype.p_GetHex=function(){
+ var t__r=((this.m_r*255.0)|0);
+ var t__g=((this.m_g*255.0)|0);
+ var t__b=((this.m_b*255.0)|0);
+ return t__r<<16|t__g<<8|t__b;
+}
+c_Color.prototype.p_ToInt=function(){
+ return this.p_GetHex();
+}
+c_Color.m_new3=function(t_pColor){
+ this.p_Set5(t_pColor);
return this;
}
-c_Color.m_new3=function(t_pRed,t_pGrn,t_pBlu){
- this.p_Set2(t_pRed,t_pGrn,t_pBlu);
+c_Color.m_new4=function(t_pColorName){
+ this.p_Set6(t_pColorName);
return this;
}
-c_Color.m_new4=function(t_pColor){
- this.p_Set5(t_pColor);
+c_Color.m_new5=function(t_pHex){
+ this.p_Set2(t_pHex);
return this;
}
-function bb_math_Clamp(t_n,t_min,t_max){
- if(t_nt_max){
- return t_max;
- }
- return t_n;
+c_Color.prototype.p_Set6=function(t_pColorName){
+ this.p_Set2(bb_colornames_NamedHtmlColor(t_pColorName));
}
-function bb_math_Clamp2(t_n,t_min,t_max){
- if(t_nt_max){
- return t_max;
- }
- return t_n;
+c_Color.m_new6=function(){
+ this.p_Set2(0);
+ return this;
}
function bb_graphics_SetColor3(t_col){
- bb_graphics_context.m_color_r=t_col.p_red2()*255.0;
- bb_graphics_context.m_color_g=t_col.p_grn2()*255.0;
- bb_graphics_context.m_color_b=t_col.p_blu2()*255.0;
+ bb_graphics_context.m_color_r=t_col.m_r;
+ bb_graphics_context.m_color_g=t_col.m_g;
+ bb_graphics_context.m_color_b=t_col.m_b;
bb_graphics_renderDevice.SetColor(bb_graphics_context.m_color_r,bb_graphics_context.m_color_g,bb_graphics_context.m_color_b);
+ bb_graphics_renderDevice.SetAlpha(bb_graphics_context.m_alpha);
return 0;
}
function bb_graphics_SetAlpha(t_alpha){
@@ -4549,10 +4490,10 @@ c_DrawList.prototype.p_Reset=function(){
t_data[t_i].m_material=null;
bb_graphics2_freeOps.p_Push7(t_data[t_i]);
}
- this.m__ops.p_Clear2();
+ this.m__ops.p_Clear4();
this.m__op=bb_graphics2_nullOp;
- this.m__casters.p_Clear2();
- this.m__casterVerts.p_Clear2();
+ this.m__casters.p_Clear4();
+ this.m__casterVerts.p_Clear4();
}
c_DrawList.prototype.p_Flush=function(){
this.p_Render2();
@@ -4610,9 +4551,9 @@ c_DrawList.prototype.p_SetColor3=function(t_hex){
this.m__pmcolor=((this.m__alpha)|0)<<24|((this.m__color[2]*this.m__alpha)|0)<<16|((this.m__color[1]*this.m__alpha)|0)<<8|((this.m__color[0]*this.m__alpha)|0);
}
c_DrawList.prototype.p_SetColor4=function(t_col){
- this.m__color[0]=t_col.p_red2();
- this.m__color[1]=t_col.p_grn2();
- this.m__color[2]=t_col.p_blu2();
+ this.m__color[0]=t_col.m_r;
+ this.m__color[1]=t_col.m_g;
+ this.m__color[2]=t_col.m_b;
this.m__pmcolor=((this.m__alpha)|0)<<24|((this.m__color[2]*this.m__alpha)|0)<<16|((this.m__color[1]*this.m__alpha)|0)<<8|((this.m__color[0]*this.m__alpha)|0);
}
c_DrawList.prototype.p_BeginPrim=function(t_material,t_order){
@@ -5097,6 +5038,15 @@ c_Canvas.prototype.p_Clear=function(t_r,t_g,t_b,t_a){
gl.disable(3089);
}
}
+c_Canvas.prototype.p_Clear2=function(t_col){
+ this.p_Clear(t_col.m_r,t_col.m_g,t_col.m_b,1.0);
+}
+c_Canvas.prototype.p_Clear3=function(t_rgb){
+ var t_r=(t_rgb>>16&255)/255.0;
+ var t_g=(t_rgb>>8&255)/255.0;
+ var t_b=(t_rgb&255)/255.0;
+ this.p_Clear(t_r,t_g,t_b,1.0);
+}
var bb_graphics2_inited=false;
var bb_graphics2_vbosSeq=0;
var bb_graphics2_rs_vbo=0;
@@ -5589,7 +5539,7 @@ c_Map3.prototype.p_InsertFixup3=function(t_node){
this.m_root.m_color=1;
return 0;
}
-c_Map3.prototype.p_Set6=function(t_key,t_value){
+c_Map3.prototype.p_Set7=function(t_key,t_value){
var t_node=this.m_root;
var t_parent=null;
var t_cmp=0;
@@ -5621,7 +5571,7 @@ c_Map3.prototype.p_Set6=function(t_key,t_value){
return true;
}
c_Map3.prototype.p_Insert3=function(t_key,t_value){
- return this.p_Set6(t_key,t_value);
+ return this.p_Set7(t_key,t_value);
}
c_Map3.prototype.p_Keys=function(){
return c_MapKeys.m_new.call(new c_MapKeys,this);
@@ -6464,7 +6414,7 @@ c_Texture.m_Color=function(t_color){
var t_data=c_DataBuffer.m_new.call(new c_DataBuffer,4,false);
t_data.PokeInt(0,t_color);
t_tex=c_Texture.m_new2.call(new c_Texture,1,1,4,12,(t_data));
- c_Texture.m__colors.p_Set7(t_color,t_tex);
+ c_Texture.m__colors.p_Set8(t_color,t_tex);
return t_tex;
}
c_Texture.m_White=function(){
@@ -6543,7 +6493,7 @@ c_Material.prototype.p_SetTexture=function(t_param,t_texture){
}
var t_old=this.m__textures.p_Get2(t_param);
t_texture.p_Retain();
- this.m__textures.p_Set8(t_param,t_texture);
+ this.m__textures.p_Set9(t_param,t_texture);
if((t_old)!=null){
t_old.p_Release();
}
@@ -6647,13 +6597,13 @@ c_Material.prototype.p_SetVector=function(t_param,t_vector){
if(this.m__inited && !this.m__vectors.p_Contains2(t_param)){
return;
}
- this.m__vectors.p_Set10(t_param,t_vector);
+ this.m__vectors.p_Set11(t_param,t_vector);
}
c_Material.prototype.p_SetScalar=function(t_param,t_scalar){
if(this.m__inited && !this.m__scalars.p_Contains2(t_param)){
return;
}
- this.m__scalars.p_Set9(t_param,t_scalar);
+ this.m__scalars.p_Set10(t_param,t_scalar);
}
c_Material.prototype.p_Destroy=function(){
var t_=this.m__textures.p_ObjectEnumerator();
@@ -6773,7 +6723,7 @@ c_Map4.prototype.p_InsertFixup4=function(t_node){
this.m_root.m_color=1;
return 0;
}
-c_Map4.prototype.p_Set7=function(t_key,t_value){
+c_Map4.prototype.p_Set8=function(t_key,t_value){
var t_node=this.m_root;
var t_parent=null;
var t_cmp=0;
@@ -6965,7 +6915,7 @@ c_Map5.prototype.p_InsertFixup5=function(t_node){
this.m_root.m_color=1;
return 0;
}
-c_Map5.prototype.p_Set8=function(t_key,t_value){
+c_Map5.prototype.p_Set9=function(t_key,t_value){
var t_node=this.m_root;
var t_parent=null;
var t_cmp=0;
@@ -7443,7 +7393,7 @@ c_Map7.prototype.p_InsertFixup7=function(t_node){
this.m_root.m_color=1;
return 0;
}
-c_Map7.prototype.p_Set9=function(t_key,t_value){
+c_Map7.prototype.p_Set10=function(t_key,t_value){
var t_node=this.m_root;
var t_parent=null;
var t_cmp=0;
@@ -7618,7 +7568,7 @@ c_Map8.prototype.p_InsertFixup8=function(t_node){
this.m_root.m_color=1;
return 0;
}
-c_Map8.prototype.p_Set10=function(t_key,t_value){
+c_Map8.prototype.p_Set11=function(t_key,t_value){
var t_node=this.m_root;
var t_parent=null;
var t_cmp=0;
@@ -7730,7 +7680,7 @@ c_Stack3.prototype.p_Push8=function(t_values,t_offset,t_count){
c_Stack3.prototype.p_Push9=function(t_values,t_offset){
this.p_Push8(t_values,t_offset,t_values.length-t_offset);
}
-c_Stack3.prototype.p_Clear2=function(){
+c_Stack3.prototype.p_Clear4=function(){
for(var t_i=0;t_it_max){
+ return t_max;
+ }
+ return t_n;
+}
+function bb_math_Clamp2(t_n,t_min,t_max){
+ if(t_nt_max){
+ return t_max;
+ }
+ return t_n;
+}
var bb_interpolate_applet_anypointmoved=0;
function bb_input_KeyHit(t_key){
return bb_input_device.p_KeyHit(t_key);
@@ -8891,6 +9039,158 @@ function bb_interpolate_InterpolateCubicBezier(t_pY0,t_pY1,t_pA,t_pB,t_pC,t_pD,t
}while(!(t_runs==20));
return t_pY0+(3.0*t_pB-3.0*t_pY0)*t_t+(3.0*t_pY0-6.0*t_pB+3.0*t_pD)*t_t*t_t+(t_pY1+3.0*t_pB-3.0*t_pD-t_pY0)*t_t*t_t*t_t;
}
+function bb_interpolate_InterpolateCustomLine(t_dataY,t_pX){
+ var t_steps=t_dataY.length-1;
+ if(t_steps<1){
+ return 1.0;
+ }
+ var t_segment=((bb_math_Min2(t_pX*(t_steps),(t_steps)-1.0))|0);
+ var t_ratio=(t_pX-1.0/(t_steps)*(t_segment))/(1.0/(t_steps));
+ return t_dataY[t_segment]+(t_dataY[t_segment+1]-t_dataY[t_segment])*t_ratio;
+}
+function bb_interpolate_InterpolateBackEaseIn(t_pY0,t_pY1,t_pX){
+ var t_s=1.70158;
+ return t_pY0+t_pX*t_pX*((t_s+1.0)*t_pX-t_s)*(t_pY1-t_pY0);
+}
+function bb_interpolate_InterpolateBackEaseOut(t_pY0,t_pY1,t_pX){
+ var t_s=1.70158;
+ t_pX=t_pX-1.0;
+ return t_pY0+(t_pX*t_pX*((t_s+1.0)*t_pX+t_s)+1.0)*(t_pY1-t_pY0);
+}
+function bb_interpolate_InterpolateBackEaseInOut(t_pY0,t_pY1,t_pX){
+ var t_s=1.70158;
+ var t_s2=.0;
+ t_s2=t_s;
+ t_pX=t_pX*2.0;
+ t_s2*=1.525;
+ if(t_pX<1.0){
+ return t_pY0+0.5*(t_pX*t_pX*((t_s2+1.0)*t_pX-t_s2))*(t_pY1-t_pY0);
+ }
+ t_pX=t_pX-2.0;
+ return t_pY0+0.5*(t_pX*t_pX*((t_s2+1.0)*t_pX+t_s2)+2.0)*(t_pY1-t_pY0);
+}
+function bb_interpolate_InterpolateBounceEaseIn(t_pY0,t_pY1,t_pX){
+ t_pX=1.0-t_pX;
+ if(t_pX<0.3636363){
+ return t_pY0+(1.0-7.5625*t_pX*t_pX)*(t_pY1-t_pY0);
+ }else{
+ if(t_pX<0.7272727){
+ t_pX-=0.5454545;
+ return t_pY0+(1.0-(7.5625*t_pX*t_pX+0.75))*(t_pY1-t_pY0);
+ }else{
+ if(t_pX<0.9090909){
+ t_pX-=0.8181818;
+ return t_pY0+(1.0-(7.5625*t_pX*t_pX+0.9375))*(t_pY1-t_pY0);
+ }else{
+ t_pX-=0.9636363;
+ return t_pY0+(1.0-(7.5625*t_pX*t_pX+0.984375))*(t_pY1-t_pY0);
+ }
+ }
+ }
+}
+function bb_interpolate_InterpolateBounceEaseOut(t_pY0,t_pY1,t_pX){
+ if(t_pX<0.3636363){
+ return t_pY0+7.5625*t_pX*t_pX*(t_pY1-t_pY0);
+ }else{
+ if(t_pX<0.7272727){
+ t_pX-=0.5454545;
+ return t_pY0+(7.5625*t_pX*t_pX+0.75)*(t_pY1-t_pY0);
+ }else{
+ if(t_pX<0.9090909){
+ t_pX-=0.8181818;
+ return t_pY0+(7.5625*t_pX*t_pX+0.9375)*(t_pY1-t_pY0);
+ }else{
+ t_pX-=0.9636363;
+ return t_pY0+(7.5625*t_pX*t_pX+0.984375)*(t_pY1-t_pY0);
+ }
+ }
+ }
+}
+function bb_interpolate_InterpolateBounceEaseInOut(t_pY0,t_pY1,t_pX){
+ if(t_pX<0.5){
+ t_pX=1.0-t_pX*2.0;
+ if(t_pX<0.3636363){
+ return t_pY0+(1.0-7.5625*t_pX*t_pX)*0.5*(t_pY1-t_pY0);
+ }else{
+ if(t_pX<0.7272727){
+ t_pX-=0.5454545;
+ return t_pY0+(1.0-(7.5625*t_pX*t_pX+0.75))*0.5*(t_pY1-t_pY0);
+ }else{
+ if(t_pX<0.9090909){
+ t_pX-=0.8181818;
+ return t_pY0+(1.0-(7.5625*t_pX*t_pX+0.9375))*0.5*(t_pY1-t_pY0);
+ }else{
+ t_pX-=0.9636363;
+ return t_pY0+(1.0-(7.5625*t_pX*t_pX+0.984375))*0.5*(t_pY1-t_pY0);
+ }
+ }
+ }
+ }else{
+ t_pX=t_pX*2.0-1.0;
+ if(t_pX<0.3636363){
+ return t_pY0+(7.5625*t_pX*t_pX*0.5+0.5)*(t_pY1-t_pY0);
+ }else{
+ if(t_pX<0.7272727){
+ t_pX-=0.5454545;
+ return t_pY0+((7.5625*t_pX*t_pX+0.75)*0.5+0.5)*(t_pY1-t_pY0);
+ }else{
+ if(t_pX<0.9090909){
+ t_pX-=0.8181818;
+ return t_pY0+((7.5625*t_pX*t_pX+0.9375)*0.5+0.5)*(t_pY1-t_pY0);
+ }else{
+ t_pX-=0.9636363;
+ return t_pY0+((7.5625*t_pX*t_pX+0.984375)*0.5+0.5)*(t_pY1-t_pY0);
+ }
+ }
+ }
+ }
+}
+function bb_interpolate_InterpolateElasticEaseIn(t_pY0,t_pY1,t_pX){
+ var t_p=.0;
+ var t_s=.0;
+ if(t_pX==0.0){
+ return t_pY0;
+ }
+ if(t_pX==1.0){
+ return t_pY1;
+ }
+ t_p=0.3;
+ t_s=t_p/4.0;
+ t_pX=t_pX-1.0;
+ return t_pY0-Math.pow(2.0,10.0*t_pX)*Math.sin(((t_pX-t_s)*6.2831853000000004/t_p*57.2957795)*D2R)*(t_pY1-t_pY0);
+}
+function bb_interpolate_InterpolateElasticEaseOut(t_pY0,t_pY1,t_pX){
+ var t_p=.0;
+ var t_s=.0;
+ if(t_pX==0.0){
+ return t_pY0;
+ }
+ if(t_pX==1.0){
+ return t_pY1;
+ }
+ t_p=0.3;
+ t_s=t_p/4.0;
+ return t_pY0+(Math.pow(2.0,-10.0*t_pX)*Math.sin(((t_pX-t_s)*6.2831853000000004/t_p*57.2957795)*D2R)+1.0)*(t_pY1-t_pY0);
+}
+function bb_interpolate_InterpolateElasticEaseInOut(t_pY0,t_pY1,t_pX){
+ var t_p=.0;
+ var t_s=.0;
+ if(t_pX==0.0){
+ return t_pY0;
+ }
+ t_pX=t_pX*2.0;
+ if(t_pX==2.0){
+ return t_pY1;
+ }
+ t_p=0.44999999999999996;
+ t_s=t_p/4.0;
+ if(t_pX<1.0){
+ t_pX=t_pX-1.0;
+ return t_pY0+-0.5*(Math.pow(2.0,10.0*t_pX)*Math.sin(((t_pX-t_s)*6.2831853000000004/t_p*57.2957795)*D2R))*(t_pY1-t_pY0);
+ }
+ t_pX=t_pX-1.0;
+ return t_pY0+(Math.pow(2.0,-10.0*t_pX)*Math.sin(((t_pX-t_s)*6.2831853000000004/t_p*57.2957795)*D2R)*0.5+1.0)*(t_pY1-t_pY0);
+}
function bbInit(){
bb_app__app=null;
bb_app__delegate=null;
@@ -8955,7 +9255,9 @@ function bbInit(){
bb_interpolate_applet_pointS1=c_ControlPoint.m_new.call(new c_ControlPoint);
bb_interpolate_applet_pointAB=c_ControlPoint.m_new.call(new c_ControlPoint);
bb_interpolate_applet_pointCD=c_ControlPoint.m_new.call(new c_ControlPoint);
- bb_interpolate_applet_INTERPFUNCS=[(c_InterpFuncLin.m_new.call(new c_InterpFuncLin)),(c_InterpFuncCurve.m_new.call(new c_InterpFuncCurve)),(c_InterpFuncSin.m_new.call(new c_InterpFuncSin)),(c_InterpFuncFit.m_new.call(new c_InterpFuncFit)),(c_InterpFuncFlats.m_new.call(new c_InterpFuncFlats)),(c_InterpFuncCubicBezier.m_new.call(new c_InterpFuncCubicBezier))];
+ bb_interpolate_applet_custom_points=new_object_array(6);
+ bb_interpolate_applet_custom_data=[0.0,0.6,1.0,1.0,0.0,0.5,0.9,1.0];
+ bb_interpolate_applet_INTERPFUNCS=[(c_InterpFuncLin.m_new.call(new c_InterpFuncLin)),(c_InterpFuncCurve.m_new.call(new c_InterpFuncCurve)),(c_InterpFuncSin.m_new.call(new c_InterpFuncSin)),(c_InterpFuncFit.m_new.call(new c_InterpFuncFit)),(c_InterpFuncFlats.m_new.call(new c_InterpFuncFlats)),(c_InterpFuncCubicBezier.m_new.call(new c_InterpFuncCubicBezier)),(c_InterpFuncCustomLine.m_new.call(new c_InterpFuncCustomLine)),(c_InterpFuncBackEaseIn.m_new.call(new c_InterpFuncBackEaseIn)),(c_InterpFuncBackEaseOut.m_new.call(new c_InterpFuncBackEaseOut)),(c_InterpFuncBackEaseInOut.m_new.call(new c_InterpFuncBackEaseInOut)),(c_InterpFuncBounceEaseIn.m_new.call(new c_InterpFuncBounceEaseIn)),(c_InterpFuncBounceEaseOut.m_new.call(new c_InterpFuncBounceEaseOut)),(c_InterpFuncBounceEaseInOut.m_new.call(new c_InterpFuncBounceEaseInOut)),(c_InterpFuncElasticEaseIn.m_new.call(new c_InterpFuncElasticEaseIn)),(c_InterpFuncElasticEaseOut.m_new.call(new c_InterpFuncElasticEaseOut)),(c_InterpFuncElasticEaseInOut.m_new.call(new c_InterpFuncElasticEaseInOut))];
bb_interpolate_applet_curfuncidx=0;
bb_interpolate_applet_curfunc=null;
c_MyApp.m_width=0;
diff --git a/modules/cerberus/cerberusdoc/interpolate.data/interpolate_applet.cxs b/modules/cerberus/cerberusdoc/interpolate.data/interpolate_applet.cxs
index e7f2f25f..dad618be 100644
--- a/modules/cerberus/cerberusdoc/interpolate.data/interpolate_applet.cxs
+++ b/modules/cerberus/cerberusdoc/interpolate.data/interpolate_applet.cxs
@@ -31,7 +31,17 @@ Global INTERPFUNCS:InterpFunc[] = [ InterpFunc(New InterpFuncLin),
InterpFunc(New InterpFuncSin),
InterpFunc(New InterpFuncFit),
InterpFunc(New InterpFuncFlats),
- InterpFunc(New InterpFuncCubicBezier)]
+ InterpFunc(New InterpFuncCubicBezier),
+ InterpFunc(New InterpFuncCustomLine),
+ InterpFunc(New InterpFuncBackEaseIn),
+ InterpFunc(New InterpFuncBackEaseOut),
+ InterpFunc(New InterpFuncBackEaseInOut),
+ InterpFunc(New InterpFuncBounceEaseIn),
+ InterpFunc(New InterpFuncBounceEaseOut),
+ InterpFunc(New InterpFuncBounceEaseInOut),
+ InterpFunc(New InterpFuncElasticEaseIn),
+ InterpFunc(New InterpFuncElasticEaseOut),
+ InterpFunc(New InterpFuncElasticEaseInOut)]
Global curfuncidx:Int = 0
Global curfunc:InterpFunc
@@ -46,10 +56,14 @@ Global pointS1 := New ControlPoint()
' cubic bezier points
Global pointAB := New ControlPoint()
Global pointCD := New ControlPoint()
+' custom data
+Global custom_data:Float[] = [0,0.6,1,1,0,0.5,0.9,1]
+Global custom_points:ControlPoint[6]
Global cvMain:Canvas
' track if any of the points moved
Global anypointmoved:Int = True
+
' main function
@@ -71,7 +85,7 @@ Class MyApp Extends App
Global demot:Float[3]
Global DEMO_DURATIONS:Int[] = [500, 1000, 2000]
Global DEMO_DURATION_MAX:Int
-
+
Method OnCreate:Int()
cvMain = New Canvas
SetUpdateRate(60)
@@ -113,10 +127,17 @@ Class MyApp Extends App
pointCD.XBounds(0,1)
pointCD.YBounds(-0.5,1.5)
pointCD.Hide()
+ ' init custom data
+ For Local i:Int = 0 Until 6
+ custom_points[i] = New ControlPoint()
+ custom_points[i].Position((1/7.0)*(i+1),custom_data[i+1])
+ custom_points[i].XBounds((1/7.0)*(i+1),(1/7.0)*(i+1))
+ custom_points[i].YBounds(-0.5,1.5)
+ custom_points[i].Hide()
+ Next
'--- init tweening function attachments ---
curfunc = INTERPFUNCS[ curfuncidx ]
curfunc.Activate()
-
Layout()
Return 0
End
@@ -146,6 +167,9 @@ Class MyApp Extends App
pointS1.SetScale( framesize )
pointAB.SetScale( framesize )
pointCD.SetScale( framesize )
+ For Local i:Int = 0 Until 6
+ custom_points[i].SetScale( framesize )
+ Next
' demo stuff
demox0 = width / 2 + framex0
demoy0 = graphy0 + framey0
@@ -169,6 +193,9 @@ Class MyApp Extends App
pointYA.Update()
pointY0.Update()
pointY1.Update()
+ For Local i:Int = 0 Until 6
+ custom_points[i].Update()
+ Next
' update function to use
If KeyHit( KEY_SPACE ) Then
curfuncidx = (curfuncidx + 1) Mod INTERPFUNCS.Length
@@ -178,6 +205,9 @@ Class MyApp Extends App
pointS0.Hide()
pointS1.Hide()
pointYA.Hide()
+ For Local i:Int = 0 Until 6
+ custom_points[i].Hide()
+ Next
curfunc.Activate()
anypointmoved = True
End
@@ -245,6 +275,9 @@ Class MyApp Extends App
pointYA.Draw(cvMain)
pointS0.Draw(cvMain)
pointS1.Draw(cvMain)
+ For Local i:Int = 0 Until 6
+ custom_points[i].Draw(cvMain)
+ Next
' draw demo
Local x:Float
Local scl:Float
@@ -320,6 +353,38 @@ Class InterpFuncLin Extends InterpFunc
Method Activate:Void()
End
End
+' InterpolateLin
+Class InterpFuncCustomLine Extends InterpFunc
+ Method Interpolate:Float(pX:Float)
+ For Local i:Int = 1 Until 7
+ custom_data[i] = custom_points[i-1].y
+ Next
+ custom_data[0] = pointY0.y
+ custom_data[7] = pointY1.y
+
+ Return InterpolateCustomLine( custom_data, pX )
+ End
+ Method Label:String()
+ Return "InterpolateCustomLine( ["+CustomDataString()+"], t )"
+ End
+ Method Activate:Void()
+ For Local i:Int = 0 Until 6
+ custom_points[i].Show()
+ Next
+ End
+ Method CustomDataString:String()
+ Local data:String
+
+ Local i:Int=0
+ While i=0 and 1 then t=1
- If t < 0 then t=0
+ If t > 1 Then t=1
+ If t < 0 Then t=0
EndIf
oldx = x
' abort after 20 runs to prevent infinite loops when AB/CD where badly set
@@ -141,4 +141,144 @@ Function InterpolateCubicBezier:Float(pY0:Float, pY1:Float, pA:Float, pB:Float,
Until runs=20
' calculate y of cubic bezier spline and return
Return pY0 + (3*pB - 3*pY0) * t + (3*pY0 - 6*pB + 3*pD) * t*t + (pY1 + 3*pB - 3*pD - pY0) * t*t*t
-End
\ No newline at end of file
+End
+
+' interpolates across a custom range of points
+Function InterpolateCustomLine:Float(dataY:Float[], pX:Float )
+ Local steps:Int = dataY.Length()-1
+ If steps <1 Then Return 1
+
+ Local segment:Int = Min(pX*steps,steps-1.0)
+ ' between segment and segment+1
+ Local ratio:Float = (pX - 1.0/steps*segment) / (1.0/steps)
+ Return dataY[segment] + (dataY[segment+1]-dataY[segment])*ratio
+End
+
+Function InterpolateBackEaseIn:Float(pY0:Float, pY1:Float, pX:Float)
+ Local s := 1.70158
+ Return pY0 + (pX * pX * ((s + 1) * pX - s)) * (pY1-pY0)
+End
+
+Function InterpolateBackEaseOut:Float(pY0:Float, pY1:Float, pX:Float)
+ Local s := 1.70158
+ pX-=1
+ Return pY0 + ((pX * pX * ((s + 1) * pX + s) + 1)) * (pY1-pY0)
+End
+
+Function InterpolateBackEaseInOut:Float(pY0:Float, pY1:Float, pX:Float)
+ Local s:Float= 1.70158
+ Local s2:Float
+ s2 = s
+ pX *= 2
+ s2 *= 1.525
+ If pX < 1
+ Return pY0 + (0.5 * (pX * pX *((s2+1) * pX - s2))) * (pY1-pY0)
+ Endif
+ pX -= 2
+ Return pY0 + (0.5 * (pX * pX * ((s2 + 1) * pX + s2) + 2)) * (pY1-pY0)
+End
+
+
+Function InterpolateElasticEaseIn:Float(pY0:Float, pY1:Float, pX:Float)
+ Local p:Float, s:Float
+ If pX = 0 Return pY0
+ If pX = 1 Return pY1
+ p = 0.3
+ s = p / 4
+ pX -= 1
+ Return pY0 - ((Pow(2,10 * (pX)) * Sin(((pX - s) * (2 * PI) / p) * 57.2957795))) * (pY1-pY0)
+End
+
+Function InterpolateElasticEaseOut:Float(pY0:Float, pY1:Float, pX:Float)
+ Local p:Float
+ Local s:Float
+
+ If pX = 0 Return pY0
+ If pX = 1 Return pY1
+ p = 0.3
+ s = p / 4
+ Return pY0 + ((Pow(2,-10 * pX) * Sin(((pX - s) * (2 * PI) / p) * 57.2957795) + 1)) * (pY1-pY0)
+End
+
+Function InterpolateElasticEaseInOut:Float(pY0:Float, pY1:Float, pX:Float)
+ Local p:Float
+ Local s:Float
+
+ If pX = 0 Return pY0
+ pX*=2
+ If pX = 2 Return pY1
+ p = (0.3 * 1.5)
+ s = p / 4
+ If pX < 1
+ pX -= 1
+ Return pY0 + (-0.5 * (Pow(2,10 * pX) * Sin(((pX - s) * (2 * PI) / p) * 57.2957795))) * (pY1-pY0)
+ End
+ pX -= 1
+ Return pY0 + (Pow(2,-10 * pX) * Sin(((pX - s) * (2 * PI) / p) * 57.2957795) * 0.5 + 1) * (pY1-pY0)
+End
+
+
+
+Function InterpolateBounceEaseIn:Float(pY0:Float, pY1:Float, pX:Float)
+ pX = 1 - pX
+ If pX < 0.3636363
+ Return pY0 + (1 - (7.5625 * pX * pX))*(pY1-pY0)
+ Else If pX < 0.7272727
+ pX -= 0.5454545
+ Return pY0 + (1 - (7.5625 * pX * pX + 0.75))*(pY1-pY0)
+ Else If pX < 0.9090909
+ pX -= 0.8181818
+ Return pY0 + (1 - (7.5625 * pX * pX + 0.9375))*(pY1-pY0)
+ Else
+ pX -= 0.9636363
+ Return pY0 + (1 - (7.5625 * pX * pX + 0.984375))*(pY1-pY0)
+ Endif
+End
+
+Function InterpolateBounceEaseOut:Float(pY0:Float, pY1:Float, pX:Float)
+ If pX < 0.3636363
+ Return pY0 + ((7.5625 * pX * pX) )*(pY1-pY0)
+ Else If pX < 0.7272727
+ pX -= 0.5454545
+ Return pY0 + ((7.5625 * pX * pX + 0.75))*(pY1-pY0)
+ Else If pX < 0.9090909
+ pX -= 0.8181818
+ Return pY0 + ((7.5625 * pX * pX + 0.9375))*(pY1-pY0)
+ Else
+ pX -= 0.9636363
+ Return pY0 + ((7.5625 * pX * pX + 0.984375))*(pY1-pY0)
+ Endif
+End
+
+Function InterpolateBounceEaseInOut:Float(pY0:Float, pY1:Float, pX:Float)
+ If pX < 0.5
+ pX = (1 - pX * 2)
+ If pX < 0.3636363
+ Return pY0 + ((1 - (7.5625 * pX * pX)) * 0.5)*(pY1-pY0)
+ Else If pX < 0.7272727
+ pX -= 0.5454545
+ Return pY0 + ((1 - (7.5625 * pX * pX + 0.75)) * 0.5)*(pY1-pY0)
+ Else If pX < 0.9090909
+ pX -= 0.8181818
+ Return pY0 + ((1 - (7.5625 * pX * pX + 0.9375)) * 0.5)*(pY1-pY0)
+ Else
+ pX -= 0.9636363
+ Return pY0 + ((1 - (7.5625 * pX * pX + 0.984375)) * 0.5)*(pY1-pY0)
+ Endif
+ Else
+ pX = (pX * 2 - 1)
+ If pX < 0.3636363
+ Return pY0 + ((7.5625 * pX * pX) * 0.5 + 0.5)*(pY1-pY0)
+ Else If pX < 0.7272727
+ pX -= 0.5454545
+ Return pY0 + ((7.5625 * pX * pX + 0.75) * 0.5 + 0.5)*(pY1-pY0)
+ Else If pX < 0.9090909
+ pX -= 0.8181818
+ Return pY0 + ((7.5625 * pX * pX + 0.9375) * 0.5 + 0.5)*(pY1-pY0)
+ Else
+ pX -= 0.9636363
+ Return pY0 + ((7.5625 * pX * pX + 0.984375) * 0.5 + 0.5)*(pY1-pY0)
+ Endif
+ Endif
+End
+
diff --git a/modules/mojo/cerberusdoc/graphics.cerberusdoc b/modules/mojo/cerberusdoc/graphics.cerberusdoc
index 2b11a357..4ffe7212 100644
--- a/modules/mojo/cerberusdoc/graphics.cerberusdoc
+++ b/modules/mojo/cerberusdoc/graphics.cerberusdoc
@@ -487,12 +487,14 @@ Load a fixed width font from @path.
@firstChar represents the ASCII code of the first char.
-# Function Load:Font(path:String)
+# Function Load:Font(path:String, flags:Int=Image.DefaultFlags)
Loads a bitmap font file created in tools like GlyphDesigner and alike.
@path represents the filename of the texfile that defines the font and its individual glyphs.
+@flags represents the Image filter that is applied at loading the image sheet.
+
# Class mojo.graphics.Image
diff --git a/modules/mojo/graphics.cxs b/modules/mojo/graphics.cxs
index 51bf582b..74ce873e 100644
--- a/modules/mojo/graphics.cxs
+++ b/modules/mojo/graphics.cxs
@@ -183,7 +183,7 @@ Class Font
End
'------------------------------------------
- Function Load:Font(url:String)
+ Function Load:Font(url:String, flags:Int=Image.DefaultFlags)
Local iniText:String
Local pageNum:Int = 0
Local idnum:Int = 0
@@ -207,12 +207,16 @@ Class Font
path = path + pl[pi]+"/"
Next
Endif
- Local ts:String = url.ToLower()
- If (ts.Find(".txt") > 0) Then
+ 'Local ts:String = url.ToLower()
+ 'If (ts.Find(".txt") > 0) Then
+ If (url.Find(".txt") > 0) Or (url.Find(".fnt") > 0) Then
iniText = app.LoadString(url)
- Else
- iniText = app.LoadString(url+".txt")
+ 'Else
+ ' iniText = app.LoadString(url+".txt")
Endif
+#If CONFIG="debug"
+ If iniText.Length = 0 Then Error("~n~nError in file graphics.cxs, Method Font.Load:Font(url:String, flags:Int=Image.DefaultFlags)~n~nCan not load font: "+url)
+#End
lines = iniText.Split(String.FromChar(13)+String.FromChar(10))
If lines.Length() < 2 then
@@ -256,9 +260,9 @@ Class Font
Endif
filename = path+filename.Trim()
- _pages[pageNum] = LoadImage(filename)
+ _pages[pageNum] = LoadImage(filename, 1, flags)
#If CONFIG="debug"
- If _pages[pageNum] = Null Then Error("~n~nError in file graphics.cxs, Method Font.Load:Font(url:String)~n~nCan not load page image: "+filename)
+ If _pages[pageNum] = Null Then Error("~n~nError in file graphics.cxs, Method Font.Load:Font(url:String, flags:Int=Image.DefaultFlags)~n~nCan not load page image: "+filename)
#End
pageNum = pageNum + 1
Endif
diff --git a/modules/mojo2/cerberusdoc/graphics.cerberusdoc b/modules/mojo2/cerberusdoc/graphics.cerberusdoc
index d51630ea..2b72cd67 100644
--- a/modules/mojo2/cerberusdoc/graphics.cerberusdoc
+++ b/modules/mojo2/cerberusdoc/graphics.cerberusdoc
@@ -307,12 +307,14 @@ Load a fixed width font from @path.
@firstChar represents the ASCII code of the first char.
-# Function Load:Font(path:String)
+# Function Load:Font(path:String, flags:Int=Image.Filter)
Loads a bitmap font file created in tools like GlyphDesigner and alike.
@path represents the filename of the texfile that defines the font and its individual glyphs.
+@flags represents the Image filter that is applied at loading the image sheet.
+
# Class ShadowCaster
diff --git a/modules/mojo2/cerberusdoc/mojo2.cerberusdoc b/modules/mojo2/cerberusdoc/mojo2.cerberusdoc
index f03da057..39a9b63b 100644
--- a/modules/mojo2/cerberusdoc/mojo2.cerberusdoc
+++ b/modules/mojo2/cerberusdoc/mojo2.cerberusdoc
@@ -1,10 +1,16 @@
# Module mojo2
+# Import mojo.app
+
+# Import mojo.audio
+
# Import mojo.color
# Import mojo2.graphics
+# Import mojo.input
+
# Import mojo2.renderer
The mojo2 module is a new 2d rendering module for Cerberus.
diff --git a/modules/mojo2/graphics.cxs b/modules/mojo2/graphics.cxs
index e1e569c2..f68146b4 100644
--- a/modules/mojo2/graphics.cxs
+++ b/modules/mojo2/graphics.cxs
@@ -1234,7 +1234,11 @@ Class Image
'Local cellWidth:=material.Width/numFrames,cellHeight:=material.Height
Local x:=0,width:=cellWidth
- If padded x+=1;width-=2
+ Local y:=0,height:=cellHeight
+ If padded
+ x+=1;width-=2
+ y+=1;height-=2
+ Endif
Local tx:Int = material.Width/cellWidth
Local ty:Int = material.Height/cellHeight
@@ -1242,7 +1246,7 @@ Class Image
Local i:Int = 0
For Local yi:Int = 0 To ty-1
For Local xi:Int = 0 To tx-1
- frames[i]=New Image( material,xi*cellWidth+x,yi*cellHeight,width,cellHeight,xhandle,yhandle )
+ frames[i]=New Image( material,xi*cellWidth+x,yi*cellHeight+y,width,cellHeight,xhandle,yhandle )
i += 1
Next
Next
@@ -1377,7 +1381,7 @@ Class Font
End
'------------------------------------------
- Function Load:Font(url:String)
+ Function Load:Font(url:String, flags:Int=Image.Filter )
Local iniText:String
Local pageNum:Int = 0
Local idnum:Int = 0
@@ -1401,13 +1405,16 @@ Class Font
path = path + pl[pi]+"/"
Next
Endif
- Local ts:String = url.ToLower()
- If (ts.Find(".txt") > 0) Then
+ 'Local ts:String = url.ToLower()
+ 'If (ts.Find(".txt") > 0) Then
+ If (url.ToLower().Find(".txt") > 0) Or (url.ToLower().Find(".fnt") > 0) Then
iniText = app.LoadString(url)
- Else
- iniText = app.LoadString(url+".txt")
+ 'Else
+ ' iniText = app.LoadString(url+".txt")
Endif
-
+#If CONFIG="debug"
+ If iniText.Length() = 0 Then Error("~n~nError in file graphics.cxs, Method Font.Load:Font(url:String, flags:Int=Image.Filter)~n~nCan not load font: "+url)
+#End
lines = iniText.Split(String.FromChar(13)+String.FromChar(10))
If lines.Length() < 2 then
lines = iniText.Split(String.FromChar(10))
@@ -1450,9 +1457,9 @@ Class Font
Endif
filename = path+filename.Trim()
- _pages[pageNum] = Image.Load(filename)
+ _pages[pageNum] = Image.Load(filename,0.5,0.5,flags)
#If CONFIG="debug"
- If _pages[pageNum] = Null Then Error("~n~nError in file graphics.cxs, Method Font.Load:Font(url:String)~n~nCan not load page image: "+filename)
+ If _pages[pageNum] = Null Then Error("~n~nError in file graphics.cxs, Method Font.Load:Font(url:String, flags:Int=Image.Filter)~n~nCan not load page image: "+filename)
#End
pageNum = pageNum + 1
Endif
diff --git a/modules/os/os.cerberusdoc b/modules/os/os.cerberusdoc
index 2ec7dcb9..5b14e8b6 100644
--- a/modules/os/os.cerberusdoc
+++ b/modules/os/os.cerberusdoc
@@ -277,7 +277,7 @@ path - a file system path.
# Function StripExt:String(path:String)
-Extracts and returns the file extension of a file system path.
+Removes the file type extension from a file system path.
Parameters:
diff --git a/modules/reflection/reflector.cxs b/modules/reflection/reflector.cxs
index 850b65d2..ab5fbce2 100644
--- a/modules/reflection/reflector.cxs
+++ b/modules/reflection/reflector.cxs
@@ -628,7 +628,7 @@ Class Reflector
Emit " End"
Emit "End"
- Local source:=output.Join( "~n" )
+ Local source:=output.Join( "~n" )+"~n" ' Append a new line character to avoid EOF issues.
Local attrs:=DECL_REFLECTOR
diff --git a/modules/trans/blktrace.cxs b/modules/trans/blktrace.cxs
new file mode 100644
index 00000000..11a556ce
--- /dev/null
+++ b/modules/trans/blktrace.cxs
@@ -0,0 +1,246 @@
+' Module trans.blktrace
+'
+' Placed into the public domain 27/04/2020.
+' No warranty implied; use at your own risk.
+
+'#########################################################################
+' Classes to keep track of code block starts for use in tracing errors
+' FILE VERSION 0.1
+' TODO: Modify the file preprocessor.cxs to make use of these classes
+Import trans
+
+'#########################################################################
+' Class definintion to contain the token and it's associated line number.
+Class TraceRecord
+ Field _toke
+ Field _line
+
+ Method New( toke,line )
+ _toke=toke
+ _line=line
+ End
+
+ Method Toke()
+ Return _toke
+ End
+
+ Method Line()
+ Return _line
+ End
+
+End
+
+'#############################################################################
+' Self contained class definition to keep track of the stgart of code blocks.
+Class BlockTrace
+
+ Global _Blocks:=New BlockTrace
+
+ ' Identifier code for each type of code block
+ Const BLK_UNKNOWN:=0
+ Const BLK_FOR:=1
+ Const BLK_FUNCTION:=2
+ Const BLK_METHOD:=3
+ Const BLK_IF:=4
+ Const BLK_REPEAT:=5
+ Const BLK_WHILE:=6
+ Const BLK_TRY:=6
+ Const BLK_CLASS:=7
+ Const BLK_INTERFACE:=8
+ Const BLK_SELECT:=9
+
+ Field _record:=New List ' Work list to keep track of the current blocks.
+ Field _map:=New IntMap ' Map to keep a permanent track of all block type entry points.
+
+ ' Internal method for adding a record to both the work list and permanent map.
+ Method AddRecord( record:TraceRecord )
+
+ Local token:=record.Toke
+
+ If Not _map.Contains( token )
+ Local newlist:=New IntList
+ newlist.AddLast( record.Line )
+ _map.Add( token, newlist )
+ Else
+ _map.Get( token ).AddLast( record.Line )
+ Endif
+
+ _record.AddLast( record )
+ End
+
+ ' Internal method to remove and return the last item on the work list.
+ Method RemoveRecord:TraceRecord()
+ If _record.IsEmpty Return Null ' Safe check. Return a Null if there is no item.
+ Return _record.RemoveLast
+ End
+
+ ' Internal method to return the last item on the work list.
+ Method LastBlockItem:TraceRecord()
+ If _record.IsEmpty Return Null ' Safe check. Return a Null if there is no item.
+ Return _record.Last
+ End
+
+ ' Internal method to build a list of line number for known block starts in the permanent map
+ ' to be sent back to the trace log function.
+ Method BlockLineList:IntList( token )
+ Local blklines:=New IntList
+ Local lastblkline:Int
+
+ ' Only add the last item line if there is one.
+ If LastBlockItem()<>Null lastblkline=LastBlockItem.Line()
+
+ ' If the token passed is known, then only build a list for that token block.
+ If token>BLK_UNKNOWN
+ Local tokelines:=_map.Get( token )
+
+ ' Always add the last work list item if it exists.
+ If lastblkline>0 blklines.AddLast( lastblkline )
+ For Local i:=Eachin tokelines
+ If i>lastblkline blklines.AddLast( i )
+ Next
+
+ ' If the token is not known, then construct a full
+ Else
+ ' Always add the last work list item if it exists.
+ If lastblkline>0 blklines.AddLast( lastblkline )
+
+ ' Read each key in the permanent map and iterate the list stored
+ ' to add to the list that will be used for the trace log.
+ For Local i:=Eachin _map.Keys
+ For Local j:=Eachin _map.Get( i )
+ If j>lastblkline blklines.AddLast( j )
+ Next
+ Next
+
+ blklines.Sort
+ Endif
+
+ Return blklines
+ End
+
+ ' Internal method to print out a trace log.
+ Method Unwind( token )
+ 'Local rows:=New StringStack
+
+ Local blklines:=_Blocks.BlockLineList( token ).ToArray
+ Local path:=_errInfo[.. _errInfo.FindLast( "<" )]
+
+ Print "~n~t------------ BLOCK TRACE ------------"
+ Print "FILE: "+path
+ Local i:=0
+
+ ' All lines should be output as rows of ten to cut down on the length of the console output.
+ While i=blklines.Length Exit
+ str+=blklines[i]+", "
+ i+=1
+ col+=1
+ Wend
+ Print "Statement Blocks at lines: "+str[..str.Length()-2]
+ Wend
+
+ Print ""
+
+ ' Return either the first line if there is one or zero.
+ If blklines.Length>0 Return blklines[0] Else Return 0
+ End
+
+ ' External function to get the last item stored on the work list.
+ Function LastRecordItem:TraceRecord()
+ Return _Blocks.LastBlockItem()
+ End
+
+ ' External function to output a trace log by passing the block identifier code
+ ' that is of interest.
+ Function TraceLog( token=BLK_UNKNOWN )
+ Return _Blocks.Unwind( token )
+ End
+
+ ' External function to output a trace log by passing the block identifier string
+ ' that is of interest.
+ Function TraceLog( token$="" )
+ Return _Blocks.Unwind( Str2Code( token ) )
+ End
+
+ ' External function to return a block string identifier from a block code identifier.
+ Function Code2Str$( code )
+ Select code
+ Case BLK_FOR
+ Return "For"
+ Case BLK_FUNCTION
+ Return "Function"
+ Case BLK_METHOD
+ Return "Method"
+ Case BLK_IF
+ Return "If"
+ Case BLK_REPEAT
+ Return "Repeat"
+ Case BLK_WHILE
+ Return "While"
+ Case BLK_TRY
+ Return "Try"
+ Case BLK_CLASS
+ Return "Class"
+ Case BLK_INTERFACE
+ Return "Try"
+ Case BLK_SELECT
+ Return "Select"
+ Default
+ Return ""
+ End
+ End
+
+ ' External function to return a block code identifier from a block string identifier.
+ Function Str2Code( toke$ )
+ Select toke.ToLower()
+ Case "for"
+ Return BLK_FOR
+ Case "function"
+ Return BLK_FUNCTION
+ Case "method"
+ Return BLK_METHOD
+ Case "if"
+ Return BLK_IF
+ Case "repeat"
+ Return BLK_REPEAT
+ Case "while"
+ Return BLK_WHILE
+ Case "try"
+ Return BLK_TRY
+ Case "class"
+ Return BLK_CLASS
+ Case "interface"
+ Return BLK_INTERFACE
+ Case "select"
+ Return BLK_SELECT
+ Default
+ Return BLK_UNKNOWN
+ End
+ End
+
+ ' Reset both the work list and permanent map
+ Function Clear()
+ _Blocks._map.Clear
+ _Blocks._record.Clear
+ End
+
+ ' External function to store both a block start token and it's line number by passing
+ ' the token's identifier code.
+ Function Push( toke, line )
+ _Blocks.AddRecord( New TraceRecord( toke,line ) )
+ End
+
+ ' External function to store both a block start token and it's line number by passing
+ ' the token's identifier string.
+ Function Push( toke$, line )
+ _Blocks.AddRecord( New TraceRecord( Str2Code( toke ),line ) )
+ End
+
+ ' External function to remove and return the last item on the work list.
+ Function Pop:TraceRecord()
+ Return _Blocks.RemoveRecord
+ End
+
+End
\ No newline at end of file
diff --git a/modules/trans/decl.cxs b/modules/trans/decl.cxs
index b3727211..91239ad9 100644
--- a/modules/trans/decl.cxs
+++ b/modules/trans/decl.cxs
@@ -1471,6 +1471,7 @@ Class AppDecl Extends ScopeDecl
Field allSemantedDecls:=New List 'top-level decls including externs
Field fileImports:=New StringList
+ Field fileIncludes:=New StringList
Method InsertModule( mdecl:ModuleDecl )
mdecl.scope=Self
diff --git a/modules/trans/parser.cxs b/modules/trans/parser.cxs
index 52244368..7a5d7956 100644
--- a/modules/trans/parser.cxs
+++ b/modules/trans/parser.cxs
@@ -3,7 +3,16 @@
' Placed into the public domain 24/02/2011.
' No warranty implied; use at your own risk.
+'######################################################################################################
+' This file scans the source file for syntax and builds a statement block ready for semantic analysis.
+'######################################################################################################
+' NOTE: All comments should be viewed as a work-in-progress and my not be an accurate description of
+' the internal workings of this file.
+
+' TODO: Commplete and check comments for accuracy.
+
Import trans
+Import blktrace
Global FILE_EXT_OLD$=".monkey"
Global FILE_EXT$=".cxs"
@@ -356,8 +365,9 @@ Class Parser
Field _module:ModuleDecl
Field _defattrs
- Method SetErr()
- If _toker.Path _errInfo=_toker.Path+"<"+_toker.Line+">"
+ Method SetErr( line=-1 )
+ If line=-1 line=_toker.Line
+ If _toker.Path _errInfo=_toker.Path+"<"+line+">"
End
Method PushErr()
@@ -368,6 +378,38 @@ Class Parser
_errInfo=_errStack.RemoveLast()
End
+ ' Check that the optional terminators are valid.
+ Method ParseBlockEnd( toke$, msg$="", log=False )
+ SetErr
+ If Not CParse( toke ) And AtEos2=False And _tokeType<>TOKE_LINECOMMENT
+ If msg<>""
+ If log BlockTrace.TraceLog( toke )
+ Err msg
+ Endif
+ Return True
+ Endif
+ Return False
+ End
+
+ ' End of file error reporting.
+ Method AtEOF( tokeID, msg$ )
+ SetErr( BlockTrace.TraceLog( tokeID ) )
+ Err "End-Of-File Reached. "+msg+" block not terminated correctly."
+ End
+
+ ' End of file error reporting. String token version.
+ Method AtEOF( tokeID$, msg$ )
+ SetErr( BlockTrace.TraceLog( tokeID ) )
+ Err "End-Of-File Reached. "+msg+" block not terminated correctly."
+ End
+
+ Method BackTrace:TraceRecord( tokeID )
+ Local blk:=BlockTrace.TraceLog( tokeID )
+ Local record:=BlockTrace.Pop
+ If record<>Null SetErr( record.Line )
+ Return record
+ End
+
Method PushBlock( block:BlockDecl )
_blockStack.AddLast _block
_errStack.AddLast _errInfo
@@ -401,7 +443,7 @@ Class Parser
Case TOKE_SYMBOL
If _toke[0]=91 And _toke[_toke.Length-1]=93
' If _toke[0]=Asc("[") And _toke[_toke.Length-1]=Asc("]")
- _toke="[]"
+ _toke="[]" ' Set toke for empty array parsing.
Endif
End
@@ -420,7 +462,7 @@ Class Parser
Method Parse( toke$ )
If Not CParse( toke )
- Err "Syntax error - expecting '"+toke+"'."
+ Err "Syntax error - Expecting '"+toke+"'."
Endif
End
@@ -428,6 +470,10 @@ Class Parser
Return _toke="" Or _toke=";" Or _toke="~n" Or _toke="else"
End
+ Method AtEos2()
+ Return _toke="" Or _toke=";" Or _toke="~n"
+ End
+
Method SkipEols()
While CParse( "~n" )
Wend
@@ -448,7 +494,7 @@ Class Parser
Case "object","throwable"
'
Default
- If _tokeType<>TOKE_IDENT Err "Syntax error - expecting identifier."
+ If _tokeType<>TOKE_IDENT Err "Syntax error - Expecting identifier."
End
Local id$=_toke
NextToke
@@ -701,14 +747,27 @@ Class Parser
Case TOKE_INTLIT
expr=New ConstExpr( Type.intType,_toke )
NextToke
+
Case TOKE_FLOATLIT
expr=New ConstExpr( Type.floatType,_toke )
NextToke
+
Case TOKE_STRINGLIT
expr=New ConstExpr( Type.stringType,Dequote( _toke,"cerberus" ) )
NextToke
+
+ ' In the case the parser should reach the end of the file and there is no known
+ ' open blocks. Provide a trace log and highlight the last known block that is still
+ ' on the record list.
+ Case TOKE_EOF
+ Local record:=BackTrace( BlockTrace.BLK_UNKNOWN )
+ Err "End-Of-File. "+
+ BlockTrace.Code2Str( record.Toke )+" block incorrectly terminated."
+
Default
- Err "Syntax error - unexpected token '"+_toke+"'"
+ Local record:=BackTrace( BlockTrace.BLK_UNKNOWN )
+ If record<>Null SetErr( _toker.Line ) Else SetErr
+ Err "Syntax error - Unexpected token '"+_toke+"'."
End Select
End Select
@@ -882,9 +941,9 @@ Class Parser
End
Method ParseIfStmt( term$ )
-
+ Local lineStart=_toker.Line, tokeID=BlockTrace.BLK_IF
CParse "if"
-
+
Local expr:Expr=ParseExpr()
CParse "then"
@@ -898,12 +957,18 @@ Class Parser
eatTerm=True
Endif
+ BlockTrace.Push( tokeID, lineStart )
PushBlock thenBlock
While _toke<>term
+
+ ' If the EOF is reached, then the last block item is made as the error, giving a trace of all open blocks.
+ If _tokeType=TOKE_EOF AtEOF( tokeID, "Conditional" )
+
Select _toke
Case "endif"
If term="end" Exit
- Err "Syntax error - expecting 'End'."
+ SetErr( BlockTrace.TraceLog( tokeID ) )
+ Err "Syntax error - Expecting conditional blocks to terminate with 'End', 'End If' or 'Endif'."
Case "else","elseif"
Local elif=_toke="elseif"
NextToke
@@ -920,10 +985,15 @@ Class Parser
End
Wend
PopBlock
+ Local blkTrace:=BlockTrace.Pop
If eatTerm
NextToke
- If term="end" CParse "if"
+ If term="end"
+ ' If the next token is not an 'If' statement, or one of the known Eos terminators. Then trhow an error.
+ ParseBlockEnd( "if",
+ "Syntax error - Expecting conditional blocks to terminate with 'End', 'Endif' Or 'End If'.", True )
+ Endif
Endif
Local stmt:IfStmt=New IfStmt( expr,thenBlock,elseBlock )
@@ -932,39 +1002,65 @@ Class Parser
End
Method ParseWhileStmt()
-
+ Local lineStart:=_toker.Line, tokeID:=BlockTrace.BLK_WHILE
+
+ SetErr
+ Local errLine:=_errInfo
Parse "while"
Local expr:Expr=ParseExpr()
Local block:BlockDecl=New BlockDecl( _block )
+ BlockTrace.Push( tokeID,lineStart )
PushBlock block
- While Not CParse( "wend" )
- If CParse( "end" )
- CParse "while"
+
+ While True
+ ' Deal with the end of the file before touching the trace data.
+ If _tokeType=TOKE_EOF AtEOF( tokeID,"While/Wend/End While iterator" )
+
+ ' If the block terminator isn't 'Wend', then test for 'End'
+ ' If 'end' is found, then test to see if the following is 'While'. If not, then throw an error.
+ If Not CParse( "wend" )
+ If CParse( "end" )
+ If Not ParseBlockEnd( "while", "Syntax error - Expecting 'while' block to terminate with 'End' or 'End While'." ) Exit
+ Exit
+ Endif
+ Else
+ If Not AtEos2; SetErr; Err "Syntax error - Wend does not except a variable or expression."
Exit
Endif
ParseStmt
Wend
PopBlock
+ Local blkTrace:=BlockTrace.Pop
+
Local stmt:WhileStmt=New WhileStmt( expr,block )
_block.AddStmt stmt
End
Method ParseRepeatStmt()
-
+ Local lineStart:=_toker.Line, tokeID:=BlockTrace.BLK_REPEAT
Parse "repeat"
Local block:BlockDecl=New BlockDecl( _block )
+ ' Store the trace and declaration blocks before iterate through the following tokens
+ ' until one of the iterator's exit tokes are met.
+ BlockTrace.Push( tokeID,lineStart )
PushBlock block
- While _toke<>"until" And _toke<>"forever"
+ While _toke<>"until" And _toke<>"forever" And _tokeType<>TOKE_EOF
ParseStmt
Wend
PopBlock
+ ' Deal with the end of the file before touching the trace data.
+ If _tokeType=TOKE_EOF AtEOF( tokeID, "Repeat/Until/Forever" )
+
+ Local blkTrace:=BlockTrace.Pop
+
+ ' Depending on the block terminator, either parse the expression, or create a new forever expression.
Local expr:Expr
If CParse( "until" )
PushErr
@@ -978,14 +1074,16 @@ Class Parser
Local stmt:RepeatStmt=New RepeatStmt( block,expr )
_block.AddStmt stmt
+
End
Method ParseForStmt()
-
+ Local lineStart=_toker.Line, tokeID=BlockTrace.BLK_FOR
+
Parse "for"
Local varid$,varty:Type,varlocal
-
+
If CParse( "local" )
varlocal=True
varid=ParseIdent()
@@ -1003,16 +1101,54 @@ Class Parser
Local expr:Expr=ParseExpr()
Local block:BlockDecl=New BlockDecl( _block )
+ BlockTrace.Push( tokeID, lineStart )
PushBlock block
- While Not CParse( "next" )
- If CParse( "end" )
- CParse "for"
+ While True
+
+ ' If the EOF is reached, then the last block item is made as the error, giving a trace of all open blocks.
+ If _tokeType=TOKE_EOF AtEOF( tokeID,"For/Next/End For" )
+
+ ' Check for block ends. As these blocks can have variables as part of their temination code, these are checked for.
+ If CParse( "next" )
+ If _tokeType=TOKE_IDENT And ParseIdent()<>varid Err "Syntax error - Next variable name does not match For variable name"
+
+ ' If the token is not and end of line character, then throw an error on which 'For' iterators are allowed.
+ If Not AtEos2() BlockTrace.TraceLog( tokeID ); Err "Syntax error - Expecting 'For' iterator to terminate with 'Next', 'End' or 'End For'."
+ Exit
+
+ ' Not 'Next', so test for 'End'
+ Else If CParse( "end" )
+
+ ' If the current token isn't 'For', then assume that it's the iteration variable.
+ If _toke<>"for"
+
+ ' Check for the iteration variable, if it's not, then throw an error.
+ If _tokeType=TOKE_IDENT And ParseIdent()<>varid
+ Err "Syntax error - Next variable name does not match For variable name"
+ Endif
+
+ ' If the token is not and end of line character, then throw an error on which 'For' iterators are allowed.
+ If Not AtEos2() BlockTrace.TraceLog( tokeID ); Err "Syntax error - Expecting 'For' iterator to terminate with 'Next', 'End' or 'End For'."
+
+ ' It is 'For', advance one token and assume that the next token will be the iteration variable
+ Else
+ NextToke
+
+ ' Check for the iteration variable, if it's not, then throw an error.
+ If _tokeType=TOKE_IDENT And ParseIdent()<>varid
+ Err "Syntax error - Next variable name does not match For variable name"
+ Endif
+
+ ' If the token is not and end of line character, then throw an error on which 'For' iterators are allowed.
+ If Not AtEos2() BlockTrace.TraceLog( tokeID ); Err "Syntax error - Expecting 'For' iterator to terminate with 'Next', 'End' or 'End For'."
+ Endif
Exit
Endif
+
ParseStmt
- Wend
- If _tokeType=TOKE_IDENT And ParseIdent()<>varid Err "Next variable name does not match For variable name"
+ Wend
PopBlock
+ Local blkTrace:=BlockTrace.Pop()
Local stmt:ForEachinStmt=New ForEachinStmt( varid,varty,varlocal,expr,block )
@@ -1055,16 +1191,55 @@ Class Parser
Local block:BlockDecl=New BlockDecl( _block )
+ BlockTrace.Push( tokeID, lineStart )
PushBlock block
- While Not CParse( "next" )
- If CParse( "end" )
- CParse "for"
+
+ While True
+ ' If the EOF is reached, then the last block item is made as the error, giving a trace of all open blocks.
+ If _tokeType=TOKE_EOF AtEOF( tokeID,"For/Next/End For" )
+
+ ' Check for block ends. As these blocks can have variables as part of their temination code, these are checked for.
+ If CParse( "next" )
+ If _tokeType=TOKE_IDENT And ParseIdent()<>varid Err "Syntax error - Next variable name does not match For variable name"
+
+ ' If the token is not and end of line character, then throw an error on which 'For' iterators are allowed.
+ If Not AtEos2() BlockTrace.TraceLog( tokeID ); Err "Syntax error - Expecting 'For' iterator to terminate with 'Next', 'End' or 'End For'."
+ Exit
+
+ ' Not 'Next', so test for 'End'
+ Else If CParse( "end" )
+
+ ' If the current token isn't 'For', then assume that it's the iteration variable.
+ If _toke<>"for"
+
+ ' Check for the iteration variable, if it's not, then throw an error.
+ If _tokeType=TOKE_IDENT And ParseIdent()<>varid
+ Err "Syntax error - Next variable name does not match For variable name"
+ Endif
+
+ ' If the token is not and end of line character, then throw an error on which 'For' iterators are allowed.
+ If Not AtEos2() BlockTrace.TraceLog( tokeID ); Err "Syntax error - Expecting 'For' iterator to terminate with 'Next', 'End' or 'End For'."
+
+ ' It is 'For', advance one token and assume that the next token will be the iteration variable
+ Else
+ NextToke
+
+ ' Check for the iteration variable, if it's not, then throw an error.
+ If _tokeType=TOKE_IDENT And ParseIdent()<>varid
+ Err "Syntax error - Next variable name does not match For variable name"
+ Endif
+
+ ' If the token is not and end of line character, then throw an error on which 'For' iterators are allowed.
+ If Not AtEos2() BlockTrace.TraceLog( tokeID ); Err "Syntax error - Expecting 'For' iterator to terminate with 'Next', 'End' or 'End For'."
+ Endif
Exit
Endif
+
ParseStmt
Wend
- If _tokeType=TOKE_IDENT And ParseIdent()<>varid Err "Next variable name does not match For variable name"
+
PopBlock
+ Local blkTrace:=BlockTrace.Pop()
Local stmt:ForStmt=New ForStmt( init,expr,incr,block )
@@ -1089,13 +1264,20 @@ Class Parser
End
Method ParseTryStmt()
+ Local lineStart=_toker.Line, tokeID=BlockTrace.BLK_TRY
Parse "try"
Local block:=New BlockDecl( _block )
Local catches:=New Stack
+ BlockTrace.Push( tokeID,lineStart )
PushBlock block
While _toke<>"end"
+
+ ' If the EOF is reached, then the last block item is made as the error, giving a trace of all open blocks.
+ If _tokeType=TOKE_EOF AtEOF( tokeID,"Try/End Try" )
+
+ ' Process the catch block if found.
If CParse( "catch" )
Local id:=ParseIdent()
Parse ":"
@@ -1105,15 +1287,19 @@ Class Parser
catches.Push New CatchStmt( init,block )
PopBlock
PushBlock block
- Else
+
+ Else
ParseStmt
Endif
Wend
+
If Not catches.Length Err "Try block must have at least one catch block"
PopBlock
+ Local record:=BlockTrace.Pop
+
NextToke
- CParse "try"
-
+ ParseBlockEnd( "try","Expecting 'Try' block must terminate with 'End' or 'End Try'." )
+
_block.AddStmt New TryStmt( block,catches.ToArray() )
End
@@ -1125,11 +1311,13 @@ Class Parser
Method ParseSelectStmt()
Parse "select"
-
+ Local lineStart=_toker.Line, tokeID=BlockTrace.BLK_SELECT
Local expr:=ParseExpr()
Local block:BlockDecl=_block
-
+
+ BlockTrace.Push( tokeID,lineStart )
+
_selTmpId+=1
Local tmpId:=String( _selTmpId ) '1,2,3...
block.AddStmt New DeclStmt( tmpId,Null,expr )
@@ -1141,6 +1329,8 @@ Class Parser
While _toke<>"end" And _toke<>"default"
SetErr
+ If _tokeType=TOKE_EOF Exit
+
Select _toke
Case "~n"
NextToke
@@ -1176,7 +1366,7 @@ Class Parser
block=elseBlock
Default
- Err "Syntax error - expecting 'Case', 'Default' or 'End'."
+ Err "Syntax error - Expecting 'Case', 'Default' or 'End'."
End Select
Wend
@@ -1184,6 +1374,8 @@ Class Parser
NextToke
PushBlock block
While _toke<>"end"
+ If _tokeType=TOKE_EOF Exit
+
SetErr
Select _toke
Case "case"
@@ -1196,9 +1388,14 @@ Class Parser
PopBlock
Endif
+ ' If the EOF is reached, then the last block item is made as the error, giving a trace of all open blocks.
+ If _tokeType=TOKE_EOF AtEOF( tokeID, "Selec/Case" )
+
SetErr
Parse "end"
- CParse "select"
+ ParseBlockEnd( "select", "Syntax error -"+
+ "Expecting 'Select' block to terminate with 'End' or 'End Select'." )
+ BlockTrace.Pop
End
Method ParseStmt()
@@ -1254,7 +1451,7 @@ Class Parser
expr=New FuncCallExpr( expr,ParseArgs( True ) )
Else If FuncCallExpr( expr) Or InvokeSuperExpr( expr ) Or NewObjectExpr( expr )
-
+
Else
Err "Expression cannot be used as a statement."
Endif
@@ -1266,27 +1463,34 @@ Class Parser
Method ParseDecl:Decl( toke$,attrs )
SetErr
- Local id$=ParseIdent()
- Local ty:Type
- Local init:Expr
+
+ Local id$=ParseIdent() ' If the token is of the TOKE_IDENT, then this will return the string identifier and advance to the next token.
+ Local ty:Type ' Holds any type evaluated.
+ Local init:Expr ' Holds any expression evaluated.
+
If attrs & DECL_EXTERN
ty=ParseDeclType()
+
Else If CParse( ":=" )
init=ParseExpr()
+
Else
ty=ParseDeclType()
If CParse( "=" )
init=ParseExpr()
+
Else If CParse( "[" )
Local len:=ParseExpr()
Parse "]"
- While CParse( "[]" )
+ While CParse( "[]" ) ' This is a token that the method Parser.NextToke applies for empty arrays.
ty=ty.ArrayOf()
Wend
init=New NewArrayExpr( ty,len )
ty=ty.ArrayOf()
+
Else If toke<>"const"
init=New ConstExpr( ty,"" )
+
Else
Err "Constants must be initialized."
Endif
@@ -1344,7 +1548,7 @@ Class Parser
init=New ConstExpr(Type.intType, i)
Else
init=New BinaryMathExpr( "+",lastInit.Copy(),New ConstExpr(Type.intType, i) )
- End
+ Endif
decl=New ConstDecl( id,attrs,Type.intType,init )
Else
Parse "="
@@ -1358,7 +1562,7 @@ Class Parser
declList.AddLast(decl)
Else
_block.AddStmt New DeclStmt( decl )
- End
+ Endif
Until Not CParse(",")
Return declList
End
@@ -1373,11 +1577,12 @@ Class Parser
End
Method ParseFuncDecl:FuncDecl( attrs )
-
+ Local lineStart=_toker.Line, tokeID=BlockTrace.BLK_FUNCTION
SetErr
If CParse( "method" )
attrs|=FUNC_METHOD
+ tokeID=BlockTrace.BLK_METHOD
Else If Not CParse( "function" )
InternalErr
Endif
@@ -1451,37 +1656,55 @@ Class Parser
Endif
Endif
- If funcDecl.IsExtern() Or funcDecl.IsAbstract() Return funcDecl
+ If funcDecl.IsExtern() Or funcDecl.IsAbstract()
+ Return funcDecl
+ Endif
+ BlockTrace.Push( tokeID, lineStart )
PushBlock funcDecl
While _toke<>"end"
ParseStmt
Wend
PopBlock
-
- NextToke
-
- If attrs & (FUNC_CTOR|FUNC_METHOD)
- CParse "method"
+ Local blkTrace:=BlockTrace.Pop()
+
+ ' If the last token parsed was 'end', then check to see in the next token is one of the
+ ' allowed keywords.
+ If _toke="end"
+ NextToke
+
+ Local blkend:="function"
+ Local msg:="Syntax error - Expecting Function block to terminate with 'End' or 'End Function'."
+
+ If attrs & (FUNC_CTOR|FUNC_METHOD)
+ blkend="method"
+ msg="Syntax error - Expecting Method block to terminate with 'End' Or 'End Method'."
+ Endif
+
+ SetErr
+ ParseBlockEnd( blkend, msg )
Else
- CParse "function"
+ NextToke
Endif
-
+
Return funcDecl
End
Method ParseClassDecl:ClassDecl( attrs )
-
SetErr
- Local toke:=_toke
+
+ Local toke:=_toke, lineStart=_toker.Line, tokeID=BlockTrace.BLK_CLASS
If CParse( "interface" )
If attrs & DECL_EXTERN Err "Interfaces cannot be extern."
attrs|=CLASS_INTERFACE|DECL_ABSTRACT
+ tokeID=BlockTrace.BLK_INTERFACE
Else If Not CParse( "class" )
InternalErr
Endif
+ BlockTrace.Push( tokeID,lineStart )
+
Local id$=ParseIdent()
Local args:=New StringStack
Local superTy:IdentType=Type.objectType
@@ -1575,11 +1798,29 @@ Class Parser
If (attrs & CLASS_INTERFACE) Err "Interfaces can only contain constants and methods."
classDecl.InsertDecl ParseFuncDecl( decl_attrs|func_attrs )
Default
- Err "Syntax error - expecting class member declaration."
+ ' In the case the parser should reach the end of the file and there is no known
+ ' open blocks. Provide a trace log and highlight the last known block that is still
+ ' on the record list.
+ If _tokeType=TOKE_EOF AtEOF( BlockTrace.BLK_UNKNOWN, "Code" )
+ Err "Syntax error - Expecting class member declaration."
End Select
Forever
- If toke CParse toke
+ If toke
+ ' Line end checks for class or interface
+ Local msg:=""
+ If toke="class"
+ msg="Syntax error - Expecting 'Class' to terminate with 'End' or 'End Class'."
+ Else If toke="interface"
+ msg="Syntax error - Expecting 'Interface' to terminate with 'End' or 'End Interface'."
+ Endif
+
+ If msg<>""
+ SetErr
+ ParseBlockEnd( toke, msg, True )
+ End
+ Endif
+ Local recor:=BlockTrace.Pop
Return classDecl
End
@@ -1630,9 +1871,12 @@ Class Parser
Local attrs
+ BlockTrace.Clear
+
'Parse header - imports etc.
While _toke
SetErr
+
Select _toke
Case "~n"
NextToke
@@ -1651,6 +1895,16 @@ Class Parser
Else
ImportModule ParseModPath(),attrs
Endif
+ Case "include"
+ NextToke
+ Local filepath:String = ParseStringLit()
+ Local iOpt:= filepath.Find(" ")
+ If iOpt > 1
+ filepath = RealPath(filepath[..iOpt])+filepath[iOpt..]
+ Else
+ filepath = RealPath(filepath)
+ Endif
+ _app.fileIncludes.AddLast(filepath )
Case "friend"
NextToke
Local modpath:=ParseModPath()
@@ -1733,7 +1987,7 @@ Class Parser
Case "function"
_module.InsertDecl ParseFuncDecl( attrs )
Default
- Err "Syntax error - expecting declaration."
+ Err "Syntax error - Expecting declaration."
End Select
Wend
diff --git a/modules/trans/preprocessor.cxs b/modules/trans/preprocessor.cxs
index 42f53e86..af2495ff 100644
--- a/modules/trans/preprocessor.cxs
+++ b/modules/trans/preprocessor.cxs
@@ -1,6 +1,15 @@
-
Import parser
+'###################################################################
+' This file scans the source file for module and preprocessor data.
+'###################################################################
+' NOTE: All comments should be viewed as a work-in-progress and my not be an accurate description of
+' the internal workings of this file.
+
+' TODO: Change the block tracking method to use the one in the file 'blktrace.cxs'.
+' TODO: Check comments for accuracy.
+' The next three functions are used to evaluate tokens that are expressions.
+' Evaluate the token an expression
Function EvalExpr:Expr( toker:Toker )
Local buf:=New StringStack
@@ -8,6 +17,7 @@ Function EvalExpr:Expr( toker:Toker )
buf.Push toker.Toke
toker.NextToke
Wend
+
Local source:=buf.Join( "" )
toker=New Toker( "",source )
@@ -17,13 +27,17 @@ Function EvalExpr:Expr( toker:Toker )
Return expr
End
+' Evaluate the token as boolean
Function EvalBool:Bool( toker:Toker )
+ If toker.Remarks() Return False ' If the remark flag is set then return false.
+
Local expr:=EvalExpr( toker )
If Not BoolType( expr.exprType ) expr=expr.Cast( Type.boolType,CAST_EXPLICIT )
If expr.Eval() Return True
Return False
End
+' Evaluate the token an string/text
Function EvalText:String( toker:Toker )
Local expr:=EvalExpr( toker )
@@ -41,198 +55,311 @@ Function EvalText:String( toker:Toker )
Return val
End
+'############################################################################################################################################
+' Description: The function scans the source file to process and preprocessor directives, modules and other types of configuration variables.
+' FUNCTION PreProcess( path:String, mdecl:ModuleDecl=Null)
+' path: The source file on disk to process
+' mdec: A module declaration (see file modules/trans/decl.cxs)
Function PreProcess$( path$,mdecl:ModuleDecl=Null )
- Local cnest,ifnest,line,source:=New StringStack
+ ' Set up internal variables for the function
+ ' The cnest variable has two jobs:
+ ' The first being the total nexting level depth.
+ ' The second is to keep skip blocks within conditionals by setting by 17.
+ ' This means that nesting level depths are only permitted upto 65535. Any thing past this will be unpredictable.
+ Local cnest,ifnest,line,source:=New StringStack, tracknesting:=New IntStack(), trace:=New IntStack()
- PushEnv GetConfigScope()
+ PushEnv GetConfigScope() ' Preserver the current configuration scope.
+ ' Get the current directory and module path configuration variables.
Local p_cd:=GetConfigVar( "CD" )
Local p_modpath:=GetConfigVar( "MODPATH" )
- SetConfigVar "CD",ExtractDir( RealPath( path ) )
- If mdecl SetConfigVar "MODPATH",mdecl.rmodpath Else SetConfigVar "MODPATH",""
+ SetConfigVar "CD",ExtractDir( RealPath( path ) ) ' Set the CD configuration variable will the real file path.
- Local toker:=New Toker( path,LoadString( path ) )
+ If mdecl SetConfigVar "MODPATH",mdecl.rmodpath Else SetConfigVar "MODPATH","" ' If there is a valid module declaration, then set the module path configuration variable, else start with an empty one.
+
+ Local toker:=New Toker( path,LoadString( path ) ) ' Load in the source file from disk and point to the first item to tokenize
toker.NextToke
- Local attrs:=0
-' If mdecl mdecl.ImportModule "monkey",0
+ Local attrs:=0 ' The attrs variable will determine if the imported module will be public (value of zero) or private value of DECL_PRIVATE.
+ '##############################################################################################################################
+ ' SCANNER/LEXER
+ ' Description: Get the tokens from the source file to parse and build another set of tokes for the parser to construct the AST
Repeat
-
+
+ '#######################
+ ' SCAN FOR VALID TOKENS
+ ' Description: TODO
If line
source.Push "~n"
While toker.Toke And toker.Toke<>"~n" And toker.TokeType<>TOKE_LINECOMMENT
toker.NextToke
Wend
+
If Not toker.Toke Exit
toker.NextToke
Endif
line+=1
- _errInfo=toker.Path+"<"+toker.Line+">"
+ _errInfo=toker.Path+"<"+toker.Line+">" ' Store the file path and the current line number for use when there is an error.
If toker.TokeType=TOKE_SPACE toker.NextToke
+ '#######################################
+ ' READ IN NON PREPROCESS DIRECTIVE CODE
+ ' If the token is not the hash symbol, then import any modules and pass through any non preprocessor directives statements.
If toker.Toke<>"#"
- If cnest=ifnest
+
+ ' If both cnest and ifnest are equal. Proceed to process any module imports and code that is not a preprocessor directive.
+ If cnest=ifnest
+
Local line:=""
- While toker.Toke And toker.Toke<>"~n" And toker.TokeType<>TOKE_LINECOMMENT
- Local toke:=toker.Toke
+ ' Loop through the tokens as long as the token is not a newline escape, or a line comment.
+ While toker.Toke And toker.Toke<>"~n" And toker.TokeType<>TOKE_LINECOMMENT
+
+ Local toke:=toker.Toke ' Get the current token string and advance to the next token
toker.NextToke
+ ' If there is a valid module object, aka a source file etc.
+ ' Then set the public/private flag or add a module to import to the list.
If mdecl
Select toke.ToLower()
- Case "public"
- attrs=0
- Case "private"
- attrs=DECL_PRIVATE
- Case "import"
- While toker.TokeType=TOKE_SPACE
- toke+=toker.Toke
- toker.NextToke
- Wend
- If toker.TokeType=TOKE_IDENT
- Local modpath:=toker.Toke
- While toker.NextToke="."
- modpath+="."
+ Case "public"
+ attrs=0
+ Case "private"
+ attrs=DECL_PRIVATE
+ Case "import"
+ While toker.TokeType=TOKE_SPACE
+ toke+=toker.Toke
toker.NextToke
- If toker.TokeType<>TOKE_IDENT Exit
- modpath+=toker.Toke
Wend
- toke+=modpath
-' Print "Import found: "+toke
- mdecl.ImportModule modpath,attrs
- Endif
- End
+
+ ' If the last token is a IDENT, then this is the start of a module scope
+ If toker.TokeType=TOKE_IDENT
+
+ Local modpath:=toker.Toke ' Add the initial token as part of the module path.
+
+ ' Loop through untill the token in not an IDENT or the scope operator.
+ While toker.NextToke="."
+ modpath+="."
+ toker.NextToke
+ If toker.TokeType<>TOKE_IDENT Exit
+ modpath+=toker.Toke
+ Wend
+ toke+=modpath
+
+ mdecl.ImportModule modpath,attrs ' Call the import module with the path and public/private flag.
+ Endif
+ End
Endif
- line+=toke
+ line+=toke ' Add the token to the line that will be pushed onto the internal source data.
Wend
+
If line source.Push line
+
Endif
Continue
Endif
+ '#################################
+ ' PROCESS PREPROCESSOR DIRECTIVES
+ ' Description: The last token will be a hash `#`, so the token is advanced by one to get the next one.
+ ' This token is then checked to see if it's one of the following preprocessor directives,
+ ' `rem`, `if`, `else`, `elseif`, `endif`, `end`, `print` and `error`. Any non predefined will be treated as
+ ' an environment variable. An error is throw if any attempt to change any of the following
+ ' predefined environment variables `HOST`, `LANG`, `CONFIG`, `TARGET` and `SAFEMODE`.
+ '
+ ' Nesting of conditional preprocessor directives and remark blocks are tracked by cnest and ifnest.
+ ' Bit 17 of cnest is used it set cnest to a higher value. When both cnest and ifnest are the same value
+ ' and when a `else` or `elseif` statement is encountered. Bit 17 of cnest is set, this will force the scanner to ignore parsing statements
+ ' until either an `if`, `elseif`, `endif`, `end` is encountered, with `if` and `elseif` re-evaluating the parity of cnest and ifnest based on the outcome if the condition test.
+ '
+ ' Each time a `rem`, `if` is encountered, then the current line is stored to the string stack `tracknesting` and removed when a `end`, or `endif` is encountered.
+ ' This and the string stack `trace`, which holds `else` and `elseif` preprocessors is used to generate an error if the current token is of the type End-Of-File
+ ' and there was no correct termination of a conditional or remark block.
+ ' This makes for a primative preprocess nesting trace to highlight all block rem/if/else/elseif starts.
Local toke:=toker.NextToke
+
If toker.TokeType=TOKE_SPACE toke=toker.NextToke
Local stm:=toke.ToLower()
Local ty:=toker.TokeType()
toker.NextToke
-
+
+ ' Make adjustments to the current statment if it is an `end` or `else` statment and the following is an `if` statment.
If stm="end" Or stm="else"
If toker.TokeType=TOKE_SPACE toker.NextToke
- If toker.Toke.ToLower()="if"
+
+ If toker.Toke.ToLower()="if"
toker.NextToke
stm+="if"
Endif
+
Endif
+ ' Process the statement
Select stm
- Case "rem"
-
- ifnest+=1
-
- Case "if"
-
- ifnest+=1
-
- If cnest=ifnest-1
- If EvalBool( toker ) cnest=ifnest
- Endif
-
- Case "else"
-
- If Not ifnest Err "#Else without #If"
-
- If cnest=ifnest
- cnest|=$10000
- Else If cnest=ifnest-1
- cnest=ifnest
- Endif
-
- Case "elseif"
-
- If Not ifnest Err "#ElseIf without #If"
-
- If cnest=ifnest
- cnest|=$10000
- Else If cnest=ifnest-1
- If EvalBool( toker ) cnest=ifnest
- Endif
-
- Case "end","endif"
-
- If Not ifnest Err "#End without #If or #Rem"
-
- ifnest-=1
-
- If ifnest<(cnest & $ffff) cnest=ifnest
-
- Case "print"
-
- If cnest=ifnest
- Print EvalText( toker )
- Endif
-
- Case "error"
-
- If cnest=ifnest
- Err EvalText( toker )
- Endif
+ Case "rem"
+
+ If Not Toker.Remarks()
+ Toker.RemarksOn()
+ ifnest+=1
+ tracknesting.Push line ' Keep trace of the error line when a nesting value has been increased
+ trace.Push line ' Keep track of elseif statements for tracing if there is an open nesting block at the end of the file.
+ Endif
+
+ Case "if"
+
+ ifnest+=1
+
+ If cnest=ifnest-1
+ If EvalBool( toker ) cnest=ifnest
+ Endif
+
+ tracknesting.Push line ' Keep trace of the error line when a nesting value has been increased
+ trace.Push line ' Keep track of elseif statements for tracing if there is an open nesting block at the end of the file.
+
+ Case "else"
+
+ If Not ifnest Err "#Else without #If"
+
+ If cnest=ifnest
+ cnest|=$10000
+ Else If cnest=ifnest-1
+ cnest=ifnest
+ Endif
+
+ trace.Push line ' Keep track of elseif statements for tracing if there is an open nesting block at the end of the file.
- Default
-
- If cnest=ifnest
- If ty=TOKE_IDENT
+ Case "elseif"
- If toker.TokeType=TOKE_SPACE toker.NextToke
- Local op:=toker.Toke()
-
- Select op
- Case "=","+="
-
- Select toke
- Case "HOST","LANG","CONFIG","TARGET","SAFEMODE"
- Err "App config var '"+toke+"' cannot be modified"
- End
+ If Not ifnest Err "#ElseIf without #If"
+
+ If cnest=ifnest
+ cnest|=$10000
+ Else If cnest=ifnest-1
+ If EvalBool( toker ) cnest=ifnest
+ Endif
+
+ trace.Push line ' Keep track of elseif statements for tracing if there is an open nesting block at the end of the file.
+
+ Case "end","endif"
+
+ If Not ifnest Err "#End without #If or #Rem"
+
+ ifnest-=1
+
+ ' Trap the lower 16 bits (0-15) of the cnest value. This removes bit 17 and gives a nesting level range of 0-65535.
+ ' If the cnest value is still higher than the ifnest value, then the cnest value is set to the value in ifnest.
+ ' Any other preprocessor directve such as #else, #elseif, #endif or #end will throw an error on the next loop.
+ If ifnest<(cnest & $ffff)
+ cnest=ifnest
+ Endif
+
+ If Not tracknesting.IsEmpty() tracknesting.Pop ' Keep trace of the error line when a nesting value has been decreased.
+ If Toker.Remarks() Toker.RemarksOff() ' Clear the remarks block flag.
+
+ Case "print"
+
+ If cnest=ifnest
+ Print EvalText( toker )
+ Endif
+
+ Case "error"
+
+ If cnest=ifnest
+ Err EvalText( toker )
+ Endif
+
+ Default
+
+ ' No predefined processor directives used, so check the token is of type IDENT to assign or adjust a user configuration variable.
+ If cnest=ifnest
+
+ If ty=TOKE_IDENT
- toker.NextToke
+ If toker.TokeType=TOKE_SPACE toker.NextToke
- Select op
- Case "="
- Local expr:=EvalExpr( toker )
- Local val:=expr.Eval()
- If Not GetConfigVars().Contains( toke )
- If StringType( expr.exprType ) val=EvalConfigTags( val )
- SetConfigVar toke,val,expr.exprType
- Endif
- Case "+="
- Local val:=EvalText( toker )
- Local var:=GetConfigVar( toke )
- If BoolType( GetConfigVarType( toke ) )
- If var="1" var="True" Else var="False"
- Endif
- If var And Not val.StartsWith( ";" ) val=";"+val
- SetConfigVar toke,var+val
- End
+ Local op:=toker.Toke()
- Default
- Err "Expecting assignment operator."
- End
- Else
- Err "Unrecognized preprocessor directive '"+toke+"'"
- Endif
+ Select op
+ Case "=","+="
- Endif
- End
+ Select toke
+ Case "HOST","LANG","CONFIG","TARGET","SAFEMODE"
+ Err "App config var '"+toke+"' cannot be modified"
+ End
+
+ toker.NextToke
+
+ Select op
+ Case "="
+ Local expr:=EvalExpr( toker )
+ Local val:=expr.Eval()
+
+ If Not GetConfigVars().Contains( toke )
+ If StringType( expr.exprType ) val=EvalConfigTags( val )
+ SetConfigVar toke,val,expr.exprType
+ Endif
+
+ Case "+="
+ Local val:=EvalText( toker )
+ Local var:=GetConfigVar( toke )
+
+ If BoolType( GetConfigVarType( toke ) )
+ If var="1" var="True" Else var="False"
+ Endif
+
+ If var And Not val.StartsWith( ";" ) val=";"+val
+ SetConfigVar toke,var+val
+ End
+
+ Default
+ Err "Expecting assignment operator."
+ End
+ Else
+ Err "Unrecognized preprocessor directive '"+toke+"'"
+ Endif
+
+ Endif
+ End
+
Forever
+
+ ' Final check for the end of file
+ If toker.TokeType=TOKE_EOF
+
+ ' If the tracknesting string stack is empty, then check to see if there were any rem/elseif/else statement pushed to the second trace stack.
+ ' And if there was, list them out.
+ If Not tracknesting.IsEmpty()
+
+ ' List out any trace information
+ If Not trace.IsEmpty()
+ Print "~t~t-------------- Preprocessor Trace Log --------------"
+ Local s:=" : Starts here....."
+ For Local i:=0 Until trace.Length-1
+ If i>0 s=""
+ Print _errInfo[.. _errInfo.FindLast("<")+1]+trace.Get(i)+">"+s
+ End
+ Print ""
+ Endif
+
+ ' Safey check, if there is noting in the trace stack, then pop the last item off the tracknesting string stack, else use the trace string stack
+ If trace.IsEmpty() _errInfo=_errInfo[.. _errInfo.FindLast("<")]+"<"+tracknesting.Pop+">" Else _errInfo=_errInfo[.. _errInfo.FindLast("<")]+"<"+trace.Pop+">"
+ Err "End of file reached. Preprocessor Conditional or Remark block preprocess not closed."
+ Endif
+
+ trace.Clear
+ tracknesting.Clear
+ Endif
+ ' Set the configuration variables.
SetConfigVar "MODPATH",p_modpath
SetConfigVar "CD",p_cd
diff --git a/modules/trans/toker.cxs b/modules/trans/toker.cxs
index 3ddb080e..89791f2c 100644
--- a/modules/trans/toker.cxs
+++ b/modules/trans/toker.cxs
@@ -4,6 +4,14 @@
' Placed into the public domain 24/02/2011.
' No warranty implied; use at your own risk.
+'##################################################################################
+' This file scans the source file strings that are to be turned into parser tokens
+'##################################################################################
+' NOTE: All comments should be viewed as a work-in-progress and my not be an accurate description of
+' the internal workings of this file.
+
+' TODO: Check comments for accuracy.
+
Import trans
'toke_type
@@ -19,11 +27,15 @@ Const TOKE_SYMBOL=8
Const TOKE_LINECOMMENT=9
Const TOKE_INTLITEX=10
+Const REMARK_BLOCK=$01
+Const CONBLOCK=$02
+
'***** Tokenizer *****
Class Toker
Global _symbols:StringSet
Global _keywords:StringSet
+ Global _tokenFlags
Field _path$
Field _line
@@ -33,7 +45,9 @@ Class Toker
Field _tokeType
Field _tokePos
+ ' Initialisation method to define the keywords and symbols to treat as command tokens
Method _init()
+
If _keywords Return
Const keywords:="void strict "+
@@ -64,6 +78,7 @@ Class Toker
_symbols.Insert "~~="
End
+ ' Two constructors. One requiring a path and a source file. The other just needs a valid token object.
Method New( path$,source$ )
_init
_path=path
@@ -74,7 +89,7 @@ Class Toker
_tokeType=TOKE_EOF
_tokePos=0
End
-
+
Method New( toker:Toker )
_init
_path=toker._path
@@ -86,6 +101,7 @@ Class Toker
_tokePos=toker._tokePos
End
+ ' Retrieve the file path or line that the tonkenizer is currently working with.
Method Path$()
Return _path
End
@@ -94,44 +110,86 @@ Class Toker
Return _line
End
+ ' Process an character to determine what the toke will be.
Method NextToke$()
_toke=""
+ ' Check for end of source file and add a End-Of-File token
If _tokePos=_length
+
_tokeType=TOKE_EOF
Return _toke
+
Endif
+ ' Preload chr and str with the current character code and is string representation.
Local chr:=TCHR()
Local str:=TSTR()
+
+ ' Preserve the current character position before advancing by one.
+ ' This will be the start of a token that is to be parsed.
Local start:=_tokePos
_tokePos+=1
+ ' If the current character is a new line or empty string, then set the token type to a SYMBOL skip a line.
If str="~n"
+
_tokeType=TOKE_SYMBOL
_line+=1
+
+ ' If the character is a white space character, then set the token type to SPACE and advance the token character count.
Else If IsSpace( chr )
+
_tokeType=TOKE_SPACE
+
While _tokePos<_length And IsSpace( TCHR() ) And TSTR()<>"~n"
_tokePos+=1
Wend
+
+ ' If the character is the start of a line comment then process until the next new line character and set the token type to LINECOMMENT.
+ Else If str="'"
+
+ _tokeType=TOKE_LINECOMMENT
+
+ While _tokePos<_length And TSTR()<>"~n"
+ _tokePos+=1
+ Wend
+
+ ' If not at the end of the file, increase the line count and advance to the next character for the next token when the method is called again.
+ If _tokePos<_length
+ _tokePos+=1
+ _line+=1
+ Endif
+
+ ' If the character is an underscore or an alpha-beta, then the next token will be either an IDENT or KEYWORD token type.
Else If str="_" Or IsAlpha( chr )
_tokeType=TOKE_IDENT
+
While _tokePos<_length
Local chr=_source[_tokePos]
If chr<>95 And Not IsAlpha( chr ) And Not IsDigit( chr ) Exit
-' If chr<>Asc("_") And Not IsAlpha( chr ) And Not IsDigit( chr ) Exit
_tokePos+=1
Wend
+
_toke=_source[start.._tokePos]
+
+ ' If the result is one of the predefined keywords, then set the type accordingly.
If _keywords.Contains( _toke.ToLower() ) _tokeType=TOKE_KEYWORD
+
+ ' If the next character is a digit or period, then the token will be integer or a floating point number.
Else If IsDigit( chr ) Or str="." And IsDigit( TCHR() )
+
_tokeType=TOKE_INTLIT
If str="." _tokeType=TOKE_FLOATLIT
+
+ ' Loop through to the first non digit character
While IsDigit( TCHR() )
_tokePos+=1
Wend
+
+ ' The token type is an INTLIT, then test to see if the character at the end is a peroid and the one after is another digit.
+ ' If they are, then set the token type to a FLOATLIT and loop the next characters until another non digit character is encountered.
If _tokeType=TOKE_INTLIT And TSTR()="." And IsDigit( TCHR(1) )
_tokeType=TOKE_FLOATLIT
_tokePos+=2
@@ -139,89 +197,176 @@ Class Toker
_tokePos+=1
Wend
Endif
+
+ ' If the end character is the exponent of a number, then set the token type to FLOATLIT process any exponent symbols before looping to the end.
If TSTR().ToLower()="e"
+
_tokeType=TOKE_FLOATLIT
_tokePos+=1
+
If TSTR()="+" Or TSTR()="-" _tokePos+=1
+
While IsDigit( TCHR() )
_tokePos+=1
Wend
+
Endif
+
+ ' If the next character is the binary digit character, then set the token type to INTLIT and loop through until a non binary digit is encountered.
Else If str="%" And IsBinDigit( TCHR() )
+
_tokeType=TOKE_INTLIT
_tokePos+=1
+
While IsBinDigit( TCHR() )
_tokePos+=1
Wend
+
+ ' If the next character is the hexadecimal digit character, then set the token type to INTLIT and loop through until a non hexadecimal digit is encountered.
Else If str="$" And IsHexDigit( TCHR() )
+
_tokeType=TOKE_INTLIT
_tokePos+=1
+
While IsHexDigit( TCHR() )
_tokePos+=1
Wend
+
+ ' If the next character is the quotation character, then set the token type to STRINGLIT and loop through until the closing quote or newline character is encountered.
+ ' If the remarks flag is set, then the token type should be set to LINECOMMENT
Else If str="~q"
+
_tokeType=TOKE_STRINGLIT
- While _tokePos<_length And TSTR()<>"~q"
+
+ ' Loop through until either a closing quote is encountered. Or if the comments flag is set in the token flags,
+ ' then look for a newline escape sequence and the set token type to TOKE_LINECOMMENT.
+ While _tokePos<_length
+
+ If Remarks()
+ _tokeType=TOKE_LINECOMMENT
+
+ If TSTR="~n"
+ _line+=1
+ Exit
+ Endif
+
+ Else
+
+ If TSTR="~q" Exit
+ Endif
+
_tokePos+=1
Wend
- If _tokePos<_length _tokePos+=1 Else _tokeType=TOKE_STRINGLITEX
+
+ If _tokePos<_length
+ _tokePos+=1
+ Else
+ If Not Remarks() _tokeType=TOKE_STRINGLITEX
+ Endif
+
+ ' If the next character is the grave accent character, then set the token type to STRINGLIT and loop through until the closing quote or newline character is encountered.
+ ' If the remarks flag is set, then the token type should be set to LINECOMMENT
Else If str="`"
+
_tokeType=TOKE_INTLIT
- While _tokePos<_length And TSTR()<>"`"
- _tokePos+=1
- Wend
- If _tokePos<_length _tokePos+=1 Else _tokeType=TOKE_INTLITEX
- Else If str="'"
- _tokeType=TOKE_LINECOMMENT
- While _tokePos<_length And TSTR()<>"~n"
+
+ ' Loop through until either a closing grave accent is encountered. Or if the comments flag is set in the token flags,
+ ' then look for a newline escape sequence and the set token type to TOKE_LINECOMMENT.
+ While _tokePos<_length
+
+ If Remarks()
+ _tokeType=TOKE_LINECOMMENT
+ If TSTR="~n"
+ _line+=1
+ Exit
+ Endif
+ Else
+ If TSTR="`" Exit
+ Endif
_tokePos+=1
Wend
+
If _tokePos<_length
_tokePos+=1
- _line+=1
+ Else
+ If Not Remarks() _tokeType=TOKE_INTLITEX
Endif
+
+ ' If the character is on opening square bracket, then set the token type to SYMBOL and loop through the next set of characters until the closing square bracket.
Else If str="["
+
_tokeType=TOKE_SYMBOL
+
Local i
+
While _tokePos+i<_length
+
If TSTR(i)="]"
_tokePos+=i+1
Exit
Endif
+
If TSTR(i)="~n" Or Not IsSpace( TCHR(i) ) Exit
+
i+=1
Wend
+
+
+ ' Treat anything left as a token type of SYMBOL
Else
+
_tokeType=TOKE_SYMBOL
If _symbols.Contains( _source[_tokePos-1.._tokePos+1] ) _tokePos+=1
Endif
+ ' If no token was process in the nested conditional above, then set the token to whatever was left.
+ ' The token type should not have been set, so it will be a zero value, meaning that it will be a token type of EOF.
If Not _toke _toke=_source[start.._tokePos]
-
+
Return _toke
End
+ ' Return the actual token string
Method Toke$()
Return _toke
End
+ ' Return the token type
Method TokeType()
Return _tokeType
End
+ ' Iterate over any whitespace character
Method SkipSpace()
While _tokeType=TOKE_SPACE
NextToke
Wend
End
+ ' Exposed external functions to set the various flags.
+ ' Use these to set and unset the remark block flag.
+ Function RemarksOn()
+ _tokenFlags|=REMARK_BLOCK
+ End
+
+ Function RemarksOff()
+ _tokenFlags&= ~REMARK_BLOCK
+ End
+
+ ' Check to see the status of the REMARK BLOCK FLAG.
+ Function Remarks:Bool()
+ Return Bool(_tokenFlags & REMARK_BLOCK)
+ End
+
Private
+ ' Returns the character code at the current token position with offset if required.
Method TCHR( i=0 )
i+=_tokePos
If i<_length Return _source[i]
End
+ ' Returns the character string at the current token position with offset if required.
Method TSTR$( i=0 )
i+=_tokePos
If i<_length Return _source[i..i+1]
diff --git a/modules_ext/.gitignore b/modules_ext/.gitignore
deleted file mode 100644
index f935021a..00000000
--- a/modules_ext/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-!.gitignore
diff --git a/src/BUILDING.txt b/src/BUILDING.txt
index 649cd455..0a535f7b 100644
--- a/src/BUILDING.txt
+++ b/src/BUILDING.txt
@@ -1,71 +1,117 @@
Building instructions
+Before you beging. You should check out one of the desktop sub forums for any issues and work arounds, or to ask questions.
+https://www.cerberus-x.com/community/categories/desktop-targets.70/
+
+NOTE: The CerberusX IDE requires that Qt 5.9.x be installed to your system.
+The IDE does not work correctly with any version later than 5.9.9. And versions below 5.9 are not officially supported.
+
======= LINUX =======
You should find all the developer packages in your distributions online repository.
-E.G. for Ubuntu/Linux Mint
-sudo apt-get -y install g++ libglu1-mesa-dev libopenal-dev libxi-dev libxrandr-dev
-libxinerama-dev libxcursor-dev libxxf86vm-dev libx11-dev libgl1-mesa-dev
+Unbuntu 18.04/Ubuntu 19.04 (packages should be the same for Linux Mint 18/19)
+Cerberus standard development files for making applications
+sudo apt-get install g++ libxcursor-dev libxrandr-dev libxinerama-dev libxi-dev libopenal-dev libglu1-mesa-dev
+
+Cerberus IDE development files for Ubuntu 18.04/Linux Mint 18 Only (Uses Qt 5.9.5)
+sudo apt-get install qtmultimedia5-dev qt5-default qtwebengine5-dev
+
+OpenSUSE 15
+Cerberus standard development files for making applications
+sudo zypper in gcc-c++ Mesa-libGL-devel openal-soft-devel libXcursor-devel libXrandr-devel libXinerama-devel libXi-devel
+
+Cerberus IDE development files for OpenSUSE 15 Only (Uses Qt 5.9.4)
+sudo zypper in libqt5-qtwebengine-devel libqt5-qtmultimedia-devel
+
+Fedora 29
+Cerberus standard development files for making applications
+sudo dnf install gcc-c++ mesa-libGLU-devel libXi-devel libXcursor-devel libXrandr-devel libXinerama-devel openal-soft-devel
+
+Cerberus IDE development files for Fedora 29 Only (Uses Qt 5.11.2) and only listed here for reference or at some stage Ted is made to work with later versions of Qt.
+sudo dnf install qt5-qtwebengine-devel qt5-qtmultimedia-devel
+You should download the Qt SDK and install version 5.9.2. And follow Manual Install of Ted.
+
+Raspbery Pi:
+Open Terminal window:
+sudo raspi-config
+
+Navigate to:
+7 - Advanced options >> A7 - GL Driver >> G1 - GL (Full KMS) OpenGL desktop driver with full KMS
-Qt4
-sudo apt-get install libqt4-dev libqtwebkit-dev qt4-default
+sudo apt-get -y install g++ libglu1-mesa-dev libopenal-dev libxi-dev libxrandr-dev libxinerama-dev libxcursor-dev libxxf86vm-dev libx11-dev libgl1-mesa-dev
+sudo apt-get -y install libqt5webkit5-dev libqt5sensors5-dev qtlocation5-dev libxslt1-dev libsqlite3-dev libgstreamer-plugins-base0.10-dev qt5-default libicu-dev
-Qt5
-sudo apt-get -y install libqt5webkit5-dev qtlocation5-dev qtsensors5-dev libxslt-dev
-libsqlite3-dev libgstreamer-plugins-base0.10-dev qt5-default libicu-dev
-Special not for 64 bit users of Debian/Ubuntu and their derivatives:
-Please be aware that you will of course need the g++-multilib package installed to do the following.
-It is posible to cross compile and test for 32 bit builds by linking the required development libraries like so
+You will find a bash script called rebuildall.sh.
+If you have installed the Qt SDK directly from https://www.qt.io/
+And you have installed them to your home directory as a directory called Qt, or created a symbolic link to the Qt SDK in your home directory.
+Then the script will automatically use those files, with the default being 5.9.2 if installed.
+You can pass the Qt version to use from the command line.
-Debian
-sudo ln -s /usr/lib/i386-linux-gnu/libGL.so.1 /usr/lib32/libGL.so
+If you have installed the distributions Qt pacakage, then you may have to edit the script to the
+name that the distribution is using for executing Qt 5's qmake. Each distribution commonly uses their own naming scheme.
-Ubuntu
-sudo ln -s /usr/lib/i386-linux-gnu/mesa/libGL.so.1 /usr/lib32/libGL.so
-All
-sudo ln -s /usr/lib/i386-linux-gnu/libopenal.so.1 /usr/lib32/libopenal.so
-sudo ln -s /usr/lib/i386-linux-gnu/libX11.so.6 /usr/lib32/libX11.so
-sudo ln -s /usr/lib/i386-linux-gnu/libXxf86vm.so.1 /usr/lib32/libXxf86vm.so
-sudo ln -s /usr/lib/i386-linux-gnu/libXi.so.6 /usr/lib32/libXi.so
-sudo ln -s /usr/lib/i386-linux-gnu/libXrandr.so.2 /usr/lib32/libXrandr.so
-sudo ln -s /usr/lib/i386-linux-gnu/libXinerama.so.1 /usr/lib32/libXinerama.so
-sudo ln -s /usr/lib/i386-linux-gnu/libXcursor.so.1 /usr/lib32/libXcursor.so
+Open a bash shell and change directory to where this script is located.
+Then type:
+.\rebuildall.sh QTVER
+NOTE: The parameter QTVER is the version of Qt to use if you have got the Qt SDK from https://www.qt.io/
+The default is to use Qt 5.9.2.
-======= WINDOWS VISTA/WIN&/8/X =======
-You will require the Window version of GCC, either MinGW (http://www.mingw.org/) or TDM (http://tdm-gcc.tdragon.net/)
-You will need Visual Studio 2013 and the corresponding Qt 5.5.1 SDK for Visual Studio 2013 to build Ted
+IMPORTANT NOTE:
+The GCC compiler that comes with later versions of Linux is setup to produce Position-Independent Executable's, also known as PIE.
+The file browser/manager in most distributions currently will not launch these files directly and may never will. And launching a file via the file manager may be removed entirely in future releases.
+
+To run Cerberus you will have to open a bash shell and change directory to the Cerberus root directory and type:
+./Cerberus
+
+For a much easier solution, see IMPORTANT NOTE at
+https://www.cerberus-x.com/community/threads/install-requirements-for-linux-includes-raspbery-pi.741/#post-5728
+
+======= WINDOWS 8 and 10 =======
+You will require the Window version of GCC, but please note that newer versions will have issues.
+It is recommended that you use the 64 bit version of TDM GCC 4.7/5.1.0.
+
+To build the IDE for Cerberus, you will need to have Visual Studio 2017 installed.
You will find a power-shell script called rebuildall.ps1 that should work on Win7+.
-To use it open a power shell (not the noraml command shell) and type
-.\rebuildall.ps1 -mingw "path_to_mingw_root_directory" -qtsdk "path_to_qtsdk_root_directory" -qtspec "qtspec_directory_for_compiler"
-NOTE: This script requires that the execution policy for the current user be set to unrestricted.
-to do this open a power shell as administrator and use:
+NOTE: Before using this script make sure that the execution policy for the current user be set to unrestricted.
+To do this open a power shell as administrator and use:
get-executionpolicy -list
set-executionpolicy -scope currentuser unrestricted
If the file is still blocked use:
unblock-file -path "full_path_to_this_script"
-You should reset the execution policy back to it's original state e.g.:
+You should reset the execution policy back to it's original state after using this script e.g.:
set-executionpolicy -scope currentuser undefined
-ALSO NOTE:
+To use the script, open a power shell (not the noraml command shell) and change directory to where this script is located.
+Then type:
+.\rebuildall.ps1 -mingw "path_to_mingw_root_directory" -qtsdk "path_to_qtsdk_root_directory"
+
+NOTE:
The parameters -mingw and -qtsdk are optional if you already have both paths set correctly in your system paths.
The defaults are shown
'path_to_mingw_root_directory' would be for example:
C:\MinGW
'path_to_qtsdk_root_directory' would be for example:
-C:\Qt5\5.5\msvc2013_64
-
-If you are using a different compiler, you need to tell qmake which pre-built binaries you wish to use.
-These are located in the Qt SDK under the mkspecs directory
-'qtspec_directory_for_compiler' would be for example
-win32-msvc2013 for Visual Studio 2013
-
-To build a debug version of Ted add -qtdbg 1
-
-======= MAC OSX =======
-TO DO
-
+C:\Qt5\5.9.2\msvc2017_64
+
+======= Mac OS X =======
+You will require XCode at least 8.2, the xcode command line tools and the Qt SDK versions (5.9.x).
+As Apple do change their tools often, you should check out the latest documentation.
+But in general, once you have XCode installed. You can usually find the place to download the tools in general/download/components.
+You just have to go looking for them. Or you can install the command line tools by opening a terminal, found in Applications->Utilities.
+And typing xcode-select --install.
+
+You will find a bash script called rebuildall_macos.sh.
+If you have installed the Qt SDK directly from https://www.qt.io/
+And you have installed them to your home directory as a directory called Qt, or created a symbolic link to the Qt SDK in your home directory.
+Then the script will automatically use those files, with the default being 5.9.2 if installed.
+You can pass the Qt version to use from the command line.
+
+Then type:
+.\rebuildall_macos.sh QTVER
+NOTE: The parameter QTVER is the version of Qt to use if you have got the Qt SDK from https://www.qt.io/
+The default is to use Qt 5.9.2.
\ No newline at end of file
diff --git a/src/cserver/cserver.cxs b/src/cserver/cserver.cxs
index 41874b8e..3f3d7b3c 100644
--- a/src/cserver/cserver.cxs
+++ b/src/cserver/cserver.cxs
@@ -1,5 +1,5 @@
Strict
-#GLFW_USE_MINGW=false
+
#Rem
================================================================================
Cerberus X MiniServer, used for local testing of HTML5 games
diff --git a/src/launcher/xcode/Cerberus.xcodeproj/project.pbxproj b/src/launcher/xcode/Cerberus.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..629b5838
--- /dev/null
+++ b/src/launcher/xcode/Cerberus.xcodeproj/project.pbxproj
@@ -0,0 +1,287 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 96693B3520C2ACD00061DD43 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 96693B3420C2ACD00061DD43 /* main.m */; };
+ D5928CF02465A655005D9702 /* cerberus.icns in Resources */ = {isa = PBXBuildFile; fileRef = D5928CEE2465A4D6005D9702 /* cerberus.icns */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 96693B2D20C2ACD00061DD43 /* Cerberus.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Cerberus.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 96693B3420C2ACD00061DD43 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
+ 96693B3B20C2ACD00061DD43 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ D5928CEE2465A4D6005D9702 /* cerberus.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = cerberus.icns; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 96693B2A20C2ACD00061DD43 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 96693B2420C2ACD00061DD43 = {
+ isa = PBXGroup;
+ children = (
+ D5928CEE2465A4D6005D9702 /* cerberus.icns */,
+ 96693B2F20C2ACD00061DD43 /* Cerberus */,
+ 96693B2E20C2ACD00061DD43 /* Products */,
+ );
+ sourceTree = "";
+ };
+ 96693B2E20C2ACD00061DD43 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 96693B2D20C2ACD00061DD43 /* Cerberus.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 96693B2F20C2ACD00061DD43 /* Cerberus */ = {
+ isa = PBXGroup;
+ children = (
+ 96693B3420C2ACD00061DD43 /* main.m */,
+ 96693B3B20C2ACD00061DD43 /* Info.plist */,
+ );
+ name = Cerberus;
+ path = "cerberus-launcher";
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 96693B2C20C2ACD00061DD43 /* Cerberus */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 96693B3E20C2ACD00061DD43 /* Build configuration list for PBXNativeTarget "Cerberus" */;
+ buildPhases = (
+ 96693B2920C2ACD00061DD43 /* Sources */,
+ 96693B2A20C2ACD00061DD43 /* Frameworks */,
+ D5928CEF2465A648005D9702 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Cerberus;
+ productName = "cerberus-launcher";
+ productReference = 96693B2D20C2ACD00061DD43 /* Cerberus.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 96693B2520C2ACD00061DD43 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 1140;
+ ORGANIZATIONNAME = Krautapps;
+ TargetAttributes = {
+ 96693B2C20C2ACD00061DD43 = {
+ CreatedOnToolsVersion = 7.3;
+ };
+ };
+ };
+ buildConfigurationList = 96693B2820C2ACD00061DD43 /* Build configuration list for PBXProject "Cerberus" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 96693B2420C2ACD00061DD43;
+ productRefGroup = 96693B2E20C2ACD00061DD43 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 96693B2C20C2ACD00061DD43 /* Cerberus */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ D5928CEF2465A648005D9702 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D5928CF02465A655005D9702 /* cerberus.icns in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 96693B2920C2ACD00061DD43 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 96693B3520C2ACD00061DD43 /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 96693B3C20C2ACD00061DD43 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ };
+ name = Debug;
+ };
+ 96693B3D20C2ACD00061DD43 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = macosx;
+ };
+ name = Release;
+ };
+ 96693B3F20C2ACD00061DD43 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "-";
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = "cerberus-launcher/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = 10.9;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.krautapps.cerberus-launcher";
+ PRODUCT_NAME = Cerberus;
+ };
+ name = Debug;
+ };
+ 96693B4020C2ACD00061DD43 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "-";
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = "cerberus-launcher/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = 10.9;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.krautapps.cerberus-launcher";
+ PRODUCT_NAME = Cerberus;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 96693B2820C2ACD00061DD43 /* Build configuration list for PBXProject "Cerberus" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 96693B3C20C2ACD00061DD43 /* Debug */,
+ 96693B3D20C2ACD00061DD43 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 96693B3E20C2ACD00061DD43 /* Build configuration list for PBXNativeTarget "Cerberus" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 96693B3F20C2ACD00061DD43 /* Debug */,
+ 96693B4020C2ACD00061DD43 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 96693B2520C2ACD00061DD43 /* Project object */;
+}
diff --git a/src/launcher/xcode/Cerberus.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/src/launcher/xcode/Cerberus.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 00000000..919434a6
--- /dev/null
+++ b/src/launcher/xcode/Cerberus.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/src/launcher/xcode/Cerberus.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/src/launcher/xcode/Cerberus.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 00000000..18d98100
--- /dev/null
+++ b/src/launcher/xcode/Cerberus.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/src/launcher/xcode/Cerberus.xcodeproj/project.xcworkspace/xcuserdata/dawlane.xcuserdatad/UserInterfaceState.xcuserstate b/src/launcher/xcode/Cerberus.xcodeproj/project.xcworkspace/xcuserdata/dawlane.xcuserdatad/UserInterfaceState.xcuserstate
new file mode 100644
index 00000000..c067e8c7
Binary files /dev/null and b/src/launcher/xcode/Cerberus.xcodeproj/project.xcworkspace/xcuserdata/dawlane.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/src/launcher/xcode/Cerberus.xcodeproj/project.xcworkspace/xcuserdata/dawlane.xcuserdatad/WorkspaceSettings.xcsettings b/src/launcher/xcode/Cerberus.xcodeproj/project.xcworkspace/xcuserdata/dawlane.xcuserdatad/WorkspaceSettings.xcsettings
new file mode 100644
index 00000000..070be288
--- /dev/null
+++ b/src/launcher/xcode/Cerberus.xcodeproj/project.xcworkspace/xcuserdata/dawlane.xcuserdatad/WorkspaceSettings.xcsettings
@@ -0,0 +1,22 @@
+
+
+
+
+ BuildLocationStyle
+ CustomLocation
+ CustomBuildIntermediatesPath
+ Build/Intermediates
+ CustomBuildLocationType
+ RelativeToWorkspace
+ CustomBuildProductsPath
+ Build/Products
+ DerivedDataCustomLocation
+ xcode
+ DerivedDataLocationStyle
+ WorkspaceRelativePath
+ IssueFilterStyle
+ ShowActiveSchemeOnly
+ LiveSourceIssuesEnabled
+
+
+
diff --git a/src/launcher/xcode/Cerberus.xcodeproj/project.xcworkspace/xcuserdata/michaelhartlef.xcuserdatad/UserInterfaceState.xcuserstate b/src/launcher/xcode/Cerberus.xcodeproj/project.xcworkspace/xcuserdata/michaelhartlef.xcuserdatad/UserInterfaceState.xcuserstate
new file mode 100644
index 00000000..3180aedd
Binary files /dev/null and b/src/launcher/xcode/Cerberus.xcodeproj/project.xcworkspace/xcuserdata/michaelhartlef.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/src/launcher/xcode/Cerberus.xcodeproj/xcshareddata/xcschemes/Cerberus.xcscheme b/src/launcher/xcode/Cerberus.xcodeproj/xcshareddata/xcschemes/Cerberus.xcscheme
new file mode 100644
index 00000000..b8e506da
--- /dev/null
+++ b/src/launcher/xcode/Cerberus.xcodeproj/xcshareddata/xcschemes/Cerberus.xcscheme
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/launcher/xcode/Cerberus.xcodeproj/xcuserdata/dawlane.xcuserdatad/xcschemes/Cerberus.xcscheme b/src/launcher/xcode/Cerberus.xcodeproj/xcuserdata/dawlane.xcuserdatad/xcschemes/Cerberus.xcscheme
new file mode 100644
index 00000000..d8497ae6
--- /dev/null
+++ b/src/launcher/xcode/Cerberus.xcodeproj/xcuserdata/dawlane.xcuserdatad/xcschemes/Cerberus.xcscheme
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/launcher/xcode/Cerberus.xcodeproj/xcuserdata/dawlane.xcuserdatad/xcschemes/xcschememanagement.plist b/src/launcher/xcode/Cerberus.xcodeproj/xcuserdata/dawlane.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644
index 00000000..6ba0c578
--- /dev/null
+++ b/src/launcher/xcode/Cerberus.xcodeproj/xcuserdata/dawlane.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -0,0 +1,22 @@
+
+
+
+
+ SchemeUserState
+
+ Cerberus.xcscheme
+
+ orderHint
+ 0
+
+
+ SuppressBuildableAutocreation
+
+ 96693B2C20C2ACD00061DD43
+
+ primary
+
+
+
+
+
diff --git a/src/launcher/xcode/Cerberus.xcodeproj/xcuserdata/michaelhartlef.xcuserdatad/xcschemes/xcschememanagement.plist b/src/launcher/xcode/Cerberus.xcodeproj/xcuserdata/michaelhartlef.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644
index 00000000..8d4304b3
--- /dev/null
+++ b/src/launcher/xcode/Cerberus.xcodeproj/xcuserdata/michaelhartlef.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -0,0 +1,22 @@
+
+
+
+
+ SchemeUserState
+
+ Cerberus.xcscheme_^#shared#^_
+
+ orderHint
+ 0
+
+
+ SuppressBuildableAutocreation
+
+ 96693B2C20C2ACD00061DD43
+
+ primary
+
+
+
+
+
diff --git a/src/launcher/xcode/cerberus-launcher/Info.plist b/src/launcher/xcode/cerberus-launcher/Info.plist
new file mode 100644
index 00000000..5358fcb5
--- /dev/null
+++ b/src/launcher/xcode/cerberus-launcher/Info.plist
@@ -0,0 +1,32 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIconFile
+ cerberus.icns
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+ LSApplicationCategoryType
+ public.app-category.developer-tools
+ LSMinimumSystemVersion
+ $(MACOSX_DEPLOYMENT_TARGET)
+ NSPrincipalClass
+ NSApplication
+
+
diff --git a/src/launcher/xcode/cerberus-launcher/main.m b/src/launcher/xcode/cerberus-launcher/main.m
new file mode 100644
index 00000000..b932c795
--- /dev/null
+++ b/src/launcher/xcode/cerberus-launcher/main.m
@@ -0,0 +1,51 @@
+//
+// Mac OSX Cerberus Launcher v0.1
+//
+
+#include
+#include
+#include
+
+//#define APP_BUNDLE_ID "com.krautapps.Ted"
+
+// Output error data
+void outlist(NSMutableArray *array){
+ for(int i = 1;i
-#include
-
-// C++ Cerberus runtime.
-//
-// Placed into the public domain 24/02/2011.
-// No warranty implied; use at your own risk.
-
-//***** Cerberus Types *****
-
-typedef wchar_t Char;
-template class Array;
-class String;
-class Object;
-
-#if CFG_CPP_DOUBLE_PRECISION_FLOATS
-typedef double Float;
-#define FLOAT(X) X
-#else
-typedef float Float;
-#define FLOAT(X) X##f
-#endif
-
-void dbg_error( const char *p );
-
-#if !_MSC_VER
-#define sprintf_s sprintf
-#define sscanf_s sscanf
-#endif
-
-//***** GC Config *****
-
-#if CFG_CPP_GC_DEBUG
-#define DEBUG_GC 1
-#else
-#define DEBUG_GC 0
-#endif
-
-// GC mode:
-//
-// 0 = disabled
-// 1 = Incremental GC every OnWhatever
-// 2 = Incremental GC every allocation
-//
-#ifndef CFG_CPP_GC_MODE
-#define CFG_CPP_GC_MODE 1
-#endif
-
-//How many bytes alloced to trigger GC
-//
-#ifndef CFG_CPP_GC_TRIGGER
-#define CFG_CPP_GC_TRIGGER 8*1024*1024
-#endif
-
-//GC_MODE 2 needs to track locals on a stack - this may need to be bumped if your app uses a LOT of locals, eg: is heavily recursive...
-//
-#ifndef CFG_CPP_GC_MAX_LOCALS
-#define CFG_CPP_GC_MAX_LOCALS 8192
-#endif
-
-// ***** GC *****
-
-#if _WIN32
-
-int gc_micros(){
- static int f;
- static LARGE_INTEGER pcf;
- if( !f ){
- if( QueryPerformanceFrequency( &pcf ) && pcf.QuadPart>=1000000L ){
- pcf.QuadPart/=1000000L;
- f=1;
- }else{
- f=-1;
- }
- }
- if( f>0 ){
- LARGE_INTEGER pc;
- if( QueryPerformanceCounter( &pc ) ) return pc.QuadPart/pcf.QuadPart;
- f=-1;
- }
- return 0;// timeGetTime()*1000;
-}
-
-#elif __APPLE__
-
-#include
-
-int gc_micros(){
- static int f;
- static mach_timebase_info_data_t timeInfo;
- if( !f ){
- mach_timebase_info( &timeInfo );
- timeInfo.denom*=1000L;
- f=1;
- }
- return mach_absolute_time()*timeInfo.numer/timeInfo.denom;
-}
-
-#else
-
-int gc_micros(){
- return 0;
-}
-
-#endif
-
-#define gc_mark_roots gc_mark
-
-void gc_mark_roots();
-
-struct gc_object;
-
-gc_object *gc_object_alloc( int size );
-void gc_object_free( gc_object *p );
-
-struct gc_object{
- gc_object *succ;
- gc_object *pred;
- int flags;
-
- virtual ~gc_object(){
- }
-
- virtual void mark(){
- }
-
- void *operator new( size_t size ){
- return gc_object_alloc( size );
- }
-
- void operator delete( void *p ){
- gc_object_free( (gc_object*)p );
- }
-};
-
-gc_object gc_free_list;
-gc_object gc_marked_list;
-gc_object gc_unmarked_list;
-gc_object gc_queued_list; //doesn't really need to be doubly linked...
-
-int gc_free_bytes;
-int gc_marked_bytes;
-int gc_alloced_bytes;
-int gc_max_alloced_bytes;
-int gc_new_bytes;
-int gc_markbit=1;
-
-gc_object *gc_cache[8];
-
-void gc_collect_all();
-void gc_mark_queued( int n );
-
-#define GC_CLEAR_LIST( LIST ) ((LIST).succ=(LIST).pred=&(LIST))
-
-#define GC_LIST_IS_EMPTY( LIST ) ((LIST).succ==&(LIST))
-
-#define GC_REMOVE_NODE( NODE ){\
-(NODE)->pred->succ=(NODE)->succ;\
-(NODE)->succ->pred=(NODE)->pred;}
-
-#define GC_INSERT_NODE( NODE,SUCC ){\
-(NODE)->pred=(SUCC)->pred;\
-(NODE)->succ=(SUCC);\
-(SUCC)->pred->succ=(NODE);\
-(SUCC)->pred=(NODE);}
-
-void gc_init1(){
- GC_CLEAR_LIST( gc_free_list );
- GC_CLEAR_LIST( gc_marked_list );
- GC_CLEAR_LIST( gc_unmarked_list);
- GC_CLEAR_LIST( gc_queued_list );
-}
-
-void gc_init2(){
- gc_mark_roots();
-}
-
-#if CFG_CPP_GC_MODE==2
-
-int gc_ctor_nest;
-gc_object *gc_locals[CFG_CPP_GC_MAX_LOCALS],**gc_locals_sp=gc_locals;
-
-struct gc_ctor{
- gc_ctor(){ ++gc_ctor_nest; }
- ~gc_ctor(){ --gc_ctor_nest; }
-};
-
-struct gc_enter{
- gc_object **sp;
- gc_enter():sp(gc_locals_sp){
- }
- ~gc_enter(){
-#if DEBUG_GC
- static int max_locals;
- int n=gc_locals_sp-gc_locals;
- if( n>max_locals ){
- max_locals=n;
- printf( "max_locals=%i\n",n );
- }
-#endif
- gc_locals_sp=sp;
- }
-};
-
-#define GC_CTOR gc_ctor _c;
-#define GC_ENTER gc_enter _e;
-
-#else
-
-struct gc_ctor{
-};
-struct gc_enter{
-};
-
-#define GC_CTOR
-#define GC_ENTER
-
-#endif
-
-//Can be modified off thread!
-static volatile int gc_ext_new_bytes;
-
-#if _MSC_VER
-#define atomic_add(P,V) InterlockedExchangeAdd((volatile unsigned int*)P,V) //(*(P)+=(V))
-#define atomic_sub(P,V) InterlockedExchangeSubtract((volatile unsigned int*)P,V) //(*(P)-=(V))
-#else
-#define atomic_add(P,V) __sync_fetch_and_add(P,V)
-#define atomic_sub(P,V) __sync_fetch_and_sub(P,V)
-#endif
-
-//Careful! May be called off thread!
-//
-void gc_ext_malloced( int size ){
- atomic_add( &gc_ext_new_bytes,size );
-}
-
-void gc_object_free( gc_object *p ){
-
- int size=p->flags & ~7;
- gc_free_bytes-=size;
-
- if( size<64 ){
- p->succ=gc_cache[size>>3];
- gc_cache[size>>3]=p;
- }else{
- free( p );
- }
-}
-
-void gc_flush_free( int size ){
-
- int t=gc_free_bytes-size;
- if( t<0 ) t=0;
-
- //ignore bytes freed by released strings
- int new_bytes=gc_new_bytes;
-
- while( gc_free_bytes>t ){
-
- gc_object *p=gc_free_list.succ;
-
- GC_REMOVE_NODE( p );
-
-#if DEBUG_GC
-// printf( "deleting @%p\n",p );fflush( stdout );
-// p->flags|=4;
-// continue;
-#endif
- delete p;
- }
-
- gc_new_bytes=new_bytes;
-}
-
-gc_object *gc_object_alloc( int size ){
-
- size=(size+7)&~7;
-
- gc_new_bytes+=size;
-
-#if CFG_CPP_GC_MODE==2
-
- if( !gc_ctor_nest ){
-
-#if DEBUG_GC
- int ms=gc_micros();
-#endif
- if( gc_new_bytes+gc_ext_new_bytes>(CFG_CPP_GC_TRIGGER) ){
- atomic_sub( &gc_ext_new_bytes,gc_ext_new_bytes );
- gc_collect_all();
- gc_new_bytes=0;
- }else{
- gc_mark_queued( (long long)(gc_new_bytes)*(gc_alloced_bytes-gc_new_bytes)/(CFG_CPP_GC_TRIGGER)+gc_new_bytes );
- }
-
-#if DEBUG_GC
- ms=gc_micros()-ms;
- if( ms>=100 ) {printf( "gc time:%i\n",ms );fflush( stdout );}
-#endif
- }
-
-#endif
-
- gc_flush_free( size );
-
- gc_object *p;
- if( size<64 && (p=gc_cache[size>>3]) ){
- gc_cache[size>>3]=p->succ;
- }else{
- p=(gc_object*)malloc( size );
- }
-
- p->flags=size|gc_markbit;
- GC_INSERT_NODE( p,&gc_unmarked_list );
-
- gc_alloced_bytes+=size;
- if( gc_alloced_bytes>gc_max_alloced_bytes ) gc_max_alloced_bytes=gc_alloced_bytes;
-
-#if CFG_CPP_GC_MODE==2
- *gc_locals_sp++=p;
-#endif
-
- return p;
-}
-
-#if DEBUG_GC
-
-template gc_object *to_gc_object( T *t ){
- gc_object *p=dynamic_cast(t);
- if( p && (p->flags & 4) ){
- printf( "gc error : object already deleted @%p\n",p );fflush( stdout );
- exit(-1);
- }
- return p;
-}
-
-#else
-
-#define to_gc_object(t) dynamic_cast(t)
-
-#endif
-
-template T *gc_retain( T *t ){
-#if CFG_CPP_GC_MODE==2
- *gc_locals_sp++=to_gc_object( t );
-#endif
- return t;
-}
-
-template void gc_mark( T *t ){
-
- gc_object *p=to_gc_object( t );
-
- if( p && (p->flags & 3)==gc_markbit ){
- p->flags^=1;
- GC_REMOVE_NODE( p );
- GC_INSERT_NODE( p,&gc_marked_list );
- gc_marked_bytes+=(p->flags & ~7);
- p->mark();
- }
-}
-
-template void gc_mark_q( T *t ){
-
- gc_object *p=to_gc_object( t );
-
- if( p && (p->flags & 3)==gc_markbit ){
- p->flags^=1;
- GC_REMOVE_NODE( p );
- GC_INSERT_NODE( p,&gc_queued_list );
- }
-}
-
-template void gc_assign( T *&lhs,V *rhs ){
-
- gc_object *p=to_gc_object( rhs );
-
- if( p && (p->flags & 3)==gc_markbit ){
- p->flags^=1;
- GC_REMOVE_NODE( p );
- GC_INSERT_NODE( p,&gc_queued_list );
- }
- lhs=rhs;
-}
-
-void gc_mark_locals(){
-
-#if CFG_CPP_GC_MODE==2
- for( gc_object **pp=gc_locals;pp!=gc_locals_sp;++pp ){
- gc_object *p=*pp;
- if( p && (p->flags & 3)==gc_markbit ){
- p->flags^=1;
- GC_REMOVE_NODE( p );
- GC_INSERT_NODE( p,&gc_marked_list );
- gc_marked_bytes+=(p->flags & ~7);
- p->mark();
- }
- }
-#endif
-}
-
-void gc_mark_queued( int n ){
- while( gc_marked_bytesflags & ~7);
- p->mark();
- }
-}
-
-void gc_validate_list( gc_object &list,const char *msg ){
- gc_object *node=list.succ;
- while( node ){
- if( node==&list ) return;
- if( !node->pred ) break;
- if( node->pred->succ!=node ) break;
- node=node->succ;
- }
- if( msg ){
- puts( msg );fflush( stdout );
- }
- puts( "LIST ERROR!" );
- exit(-1);
-}
-
-//returns reclaimed bytes
-void gc_sweep(){
-
- int reclaimed_bytes=gc_alloced_bytes-gc_marked_bytes;
-
- if( reclaimed_bytes ){
-
- //append unmarked list to end of free list
- gc_object *head=gc_unmarked_list.succ;
- gc_object *tail=gc_unmarked_list.pred;
- gc_object *succ=&gc_free_list;
- gc_object *pred=succ->pred;
-
- head->pred=pred;
- tail->succ=succ;
- pred->succ=head;
- succ->pred=tail;
-
- gc_free_bytes+=reclaimed_bytes;
- }
-
- //move marked to unmarked.
- if( GC_LIST_IS_EMPTY( gc_marked_list ) ){
- GC_CLEAR_LIST( gc_unmarked_list );
- }else{
- gc_unmarked_list.succ=gc_marked_list.succ;
- gc_unmarked_list.pred=gc_marked_list.pred;
- gc_unmarked_list.succ->pred=gc_unmarked_list.pred->succ=&gc_unmarked_list;
- GC_CLEAR_LIST( gc_marked_list );
- }
-
- //adjust sizes
- gc_alloced_bytes=gc_marked_bytes;
- gc_marked_bytes=0;
- gc_markbit^=1;
-}
-
-void gc_collect_all(){
-
-// puts( "Mark locals" );
- gc_mark_locals();
-
-// puts( "Marked queued" );
- gc_mark_queued( 0x7fffffff );
-
-// puts( "Sweep" );
- gc_sweep();
-
-// puts( "Mark roots" );
- gc_mark_roots();
-
-#if DEBUG_GC
- gc_validate_list( gc_marked_list,"Validating gc_marked_list" );
- gc_validate_list( gc_unmarked_list,"Validating gc_unmarked_list" );
- gc_validate_list( gc_free_list,"Validating gc_free_list" );
-#endif
-
-}
-
-void gc_collect(){
-
-#if CFG_CPP_GC_MODE==1
-
-#if DEBUG_GC
- int ms=gc_micros();
-#endif
-
- if( gc_new_bytes+gc_ext_new_bytes>(CFG_CPP_GC_TRIGGER) ){
- atomic_sub( &gc_ext_new_bytes,gc_ext_new_bytes );
- gc_collect_all();
- gc_new_bytes=0;
- }else{
- gc_mark_queued( (long long)(gc_new_bytes)*(gc_alloced_bytes-gc_new_bytes)/(CFG_CPP_GC_TRIGGER)+gc_new_bytes );
- }
-
-#if DEBUG_GC
- ms=gc_micros()-ms;
-// if( ms>=100 ) {printf( "gc time:%i\n",ms );fflush( stdout );}
- if( ms>10 ) {printf( "gc time:%i\n",ms );fflush( stdout );}
-#endif
-
-#endif
-}
-
-// ***** Array *****
-
-template T *t_memcpy( T *dst,const T *src,int n ){
- memcpy( dst,src,n*sizeof(T) );
- return dst+n;
-}
-
-template T *t_memset( T *dst,int val,int n ){
- memset( dst,val,n*sizeof(T) );
- return dst+n;
-}
-
-template int t_memcmp( const T *x,const T *y,int n ){
- return memcmp( x,y,n*sizeof(T) );
-}
-
-template int t_strlen( const T *p ){
- const T *q=p++;
- while( *q++ ){}
- return q-p;
-}
-
-template T *t_create( int n,T *p ){
- t_memset( p,0,n );
- return p+n;
-}
-
-template T *t_create( int n,T *p,const T *q ){
- t_memcpy( p,q,n );
- return p+n;
-}
-
-template void t_destroy( int n,T *p ){
-}
-
-template void gc_mark_elements( int n,T *p ){
-}
-
-template void gc_mark_elements( int n,T **p ){
- for( int i=0;i class Array{
-public:
- Array():rep( &nullRep ){
- }
-
- //Uses default...
-// Array( const Array &t )...
-
- Array( int length ):rep( Rep::alloc( length ) ){
- t_create( rep->length,rep->data );
- }
-
- Array( const T *p,int length ):rep( Rep::alloc(length) ){
- t_create( rep->length,rep->data,p );
- }
-
- ~Array(){
- }
-
- //Uses default...
-// Array &operator=( const Array &t )...
-
- int Length()const{
- return rep->length;
- }
-
- T &At( int index ){
- if( index<0 || index>=rep->length ) dbg_error( "Array index out of range" );
- return rep->data[index];
- }
-
- const T &At( int index )const{
- if( index<0 || index>=rep->length ) dbg_error( "Array index out of range" );
- return rep->data[index];
- }
-
- T &operator[]( int index ){
- return rep->data[index];
- }
-
- const T &operator[]( int index )const{
- return rep->data[index];
- }
-
- Array Slice( int from,int term )const{
- int len=rep->length;
- if( from<0 ){
- from+=len;
- if( from<0 ) from=0;
- }else if( from>len ){
- from=len;
- }
- if( term<0 ){
- term+=len;
- }else if( term>len ){
- term=len;
- }
- if( term<=from ) return Array();
- return Array( rep->data+from,term-from );
- }
-
- Array Slice( int from )const{
- return Slice( from,rep->length );
- }
-
- Array Resize( int newlen )const{
- if( newlen<=0 ) return Array();
- int n=rep->length;
- if( newlendata;
- q=t_create( n,q,rep->data );
- q=t_create( (newlen-n),q );
- return Array( p );
- }
-
-private:
- struct Rep : public gc_object{
- int length;
- T data[0];
-
- Rep():length(0){
- flags=3;
- }
-
- Rep( int length ):length(length){
- }
-
- ~Rep(){
- t_destroy( length,data );
- }
-
- void mark(){
- gc_mark_elements( length,data );
- }
-
- static Rep *alloc( int length ){
- if( !length ) return &nullRep;
- void *p=gc_object_alloc( sizeof(Rep)+length*sizeof(T) );
- return ::new(p) Rep( length );
- }
-
- };
- Rep *rep;
-
- static Rep nullRep;
-
- template friend void gc_mark( Array t );
- template friend void gc_mark_q( Array t );
- template friend Array gc_retain( Array t );
- template friend void gc_assign( Array &lhs,Array rhs );
- template friend void gc_mark_elements( int n,Array *p );
-
- Array( Rep *rep ):rep(rep){
- }
-};
-
-template typename Array::Rep Array::nullRep;
-
-template Array *t_create( int n,Array *p ){
- for( int i=0;i();
- return p;
-}
-
-template Array *t_create( int n,Array *p,const Array *q ){
- for( int i=0;i void gc_mark( Array t ){
- gc_mark( t.rep );
-}
-
-template void gc_mark_q( Array t ){
- gc_mark_q( t.rep );
-}
-
-template Array gc_retain( Array t ){
-#if CFG_CPP_GC_MODE==2
- gc_retain( t.rep );
-#endif
- return t;
-}
-
-template void gc_assign( Array &lhs,Array rhs ){
- gc_mark( rhs.rep );
- lhs=rhs;
-}
-
-template void gc_mark_elements( int n,Array *p ){
- for( int i=0;iretain();
- }
-
- String( int n ){
- char buf[256];
- sprintf_s( buf,"%i",n );
- rep=Rep::alloc( t_strlen(buf) );
- for( int i=0;ilength;++i ) rep->data[i]=buf[i];
- }
-
- String( Float n ){
- char buf[256];
-
- //would rather use snprintf, but it's doing weird things in MingW.
- //
- sprintf_s( buf,"%.17lg",n );
- //
- char *p;
- for( p=buf;*p;++p ){
- if( *p=='.' || *p=='e' ) break;
- }
- if( !*p ){
- *p++='.';
- *p++='0';
- *p=0;
- }
-
- rep=Rep::alloc( t_strlen(buf) );
- for( int i=0;ilength;++i ) rep->data[i]=buf[i];
- }
-
- String( Char ch,int length ):rep( Rep::alloc(length) ){
- for( int i=0;idata[i]=ch;
- }
-
- String( const Char *p ):rep( Rep::alloc(t_strlen(p)) ){
- t_memcpy( rep->data,p,rep->length );
- }
-
- String( const Char *p,int length ):rep( Rep::alloc(length) ){
- t_memcpy( rep->data,p,rep->length );
- }
-
-#if __OBJC__
- String( NSString *nsstr ):rep( Rep::alloc([nsstr length]) ){
- unichar *buf=(unichar*)malloc( rep->length * sizeof(unichar) );
- [nsstr getCharacters:buf range:NSMakeRange(0,rep->length)];
- for( int i=0;ilength;++i ) rep->data[i]=buf[i];
- free( buf );
- }
-#endif
-
-#if __cplusplus_winrt
- String( Platform::String ^str ):rep( Rep::alloc(str->Length()) ){
- for( int i=0;ilength;++i ) rep->data[i]=str->Data()[i];
- }
-#endif
-
- ~String(){
- rep->release();
- }
-
- template String( const C *p ):rep( Rep::alloc(t_strlen(p)) ){
- for( int i=0;ilength;++i ) rep->data[i]=p[i];
- }
-
- template String( const C *p,int length ):rep( Rep::alloc(length) ){
- for( int i=0;ilength;++i ) rep->data[i]=p[i];
- }
-
- String Copy()const{
- Rep *crep=Rep::alloc( rep->length );
- t_memcpy( crep->data,rep->data,rep->length );
- return String( crep );
- }
-
- int Length()const{
- return rep->length;
- }
-
- const Char *Data()const{
- return rep->data;
- }
-
- Char At( int index )const{
- if( index<0 || index>=rep->length ) dbg_error( "Character index out of range" );
- return rep->data[index];
- }
-
- Char operator[]( int index )const{
- return rep->data[index];
- }
-
- String &operator=( const String &t ){
- t.rep->retain();
- rep->release();
- rep=t.rep;
- return *this;
- }
-
- String &operator+=( const String &t ){
- return operator=( *this+t );
- }
-
- int Compare( const String &t )const{
- int n=rep->lengthlength ? rep->length : t.rep->length;
- for( int i=0;idata[i])-(int)(t.rep->data[i]) ) return q;
- }
- return rep->length-t.rep->length;
- }
-
- bool operator==( const String &t )const{
- return rep->length==t.rep->length && t_memcmp( rep->data,t.rep->data,rep->length )==0;
- }
-
- bool operator!=( const String &t )const{
- return rep->length!=t.rep->length || t_memcmp( rep->data,t.rep->data,rep->length )!=0;
- }
-
- bool operator<( const String &t )const{
- return Compare( t )<0;
- }
-
- bool operator<=( const String &t )const{
- return Compare( t )<=0;
- }
-
- bool operator>( const String &t )const{
- return Compare( t )>0;
- }
-
- bool operator>=( const String &t )const{
- return Compare( t )>=0;
- }
-
- String operator+( const String &t )const{
- if( !rep->length ) return t;
- if( !t.rep->length ) return *this;
- Rep *p=Rep::alloc( rep->length+t.rep->length );
- Char *q=p->data;
- q=t_memcpy( q,rep->data,rep->length );
- q=t_memcpy( q,t.rep->data,t.rep->length );
- return String( p );
- }
-
- int Find( String find,int start=0 )const{
- if( start<0 ) start=0;
- while( start+find.rep->length<=rep->length ){
- if( !t_memcmp( rep->data+start,find.rep->data,find.rep->length ) ) return start;
- ++start;
- }
- return -1;
- }
-
- int FindLast( String find )const{
- int start=rep->length-find.rep->length;
- while( start>=0 ){
- if( !t_memcmp( rep->data+start,find.rep->data,find.rep->length ) ) return start;
- --start;
- }
- return -1;
- }
-
- int FindLast( String find,int start )const{
- if( start>rep->length-find.rep->length ) start=rep->length-find.rep->length;
- while( start>=0 ){
- if( !t_memcmp( rep->data+start,find.rep->data,find.rep->length ) ) return start;
- --start;
- }
- return -1;
- }
-
- String Trim()const{
- int i=0,i2=rep->length;
- while( idata[i]<=32 ) ++i;
- while( i2>i && rep->data[i2-1]<=32 ) --i2;
- if( i==0 && i2==rep->length ) return *this;
- return String( rep->data+i,i2-i );
- }
-
- Array Split( String sep )const{
-
- if( !sep.rep->length ){
- Array bits( rep->length );
- for( int i=0;ilength;++i ){
- bits[i]=String( (Char)(*this)[i],1 );
- }
- return bits;
- }
-
- int i=0,i2,n=1;
- while( (i2=Find( sep,i ))!=-1 ){
- ++n;
- i=i2+sep.rep->length;
- }
- Array bits( n );
- if( n==1 ){
- bits[0]=*this;
- return bits;
- }
- i=0;n=0;
- while( (i2=Find( sep,i ))!=-1 ){
- bits[n++]=Slice( i,i2 );
- i=i2+sep.rep->length;
- }
- bits[n]=Slice( i );
- return bits;
- }
-
- String Join( Array bits )const{
- if( bits.Length()==0 ) return String();
- if( bits.Length()==1 ) return bits[0];
- int newlen=rep->length * (bits.Length()-1);
- for( int i=0;ilength;
- }
- Rep *p=Rep::alloc( newlen );
- Char *q=p->data;
- q=t_memcpy( q,bits[0].rep->data,bits[0].rep->length );
- for( int i=1;idata,rep->length );
- q=t_memcpy( q,bits[i].rep->data,bits[i].rep->length );
- }
- return String( p );
- }
-
- String Replace( String find,String repl )const{
- int i=0,i2,newlen=0;
- while( (i2=Find( find,i ))!=-1 ){
- newlen+=(i2-i)+repl.rep->length;
- i=i2+find.rep->length;
- }
- if( !i ) return *this;
- newlen+=rep->length-i;
- Rep *p=Rep::alloc( newlen );
- Char *q=p->data;
- i=0;
- while( (i2=Find( find,i ))!=-1 ){
- q=t_memcpy( q,rep->data+i,i2-i );
- q=t_memcpy( q,repl.rep->data,repl.rep->length );
- i=i2+find.rep->length;
- }
- q=t_memcpy( q,rep->data+i,rep->length-i );
- return String( p );
- }
-
- String ToLower()const{
- for( int i=0;ilength;++i ){
- Char t=towlower( rep->data[i] );
- if( t==rep->data[i] ) continue;
- Rep *p=Rep::alloc( rep->length );
- Char *q=p->data;
- t_memcpy( q,rep->data,i );
- for( q[i++]=t;ilength;++i ){
- q[i]=towlower( rep->data[i] );
- }
- return String( p );
- }
- return *this;
- }
-
- String ToUpper()const{
- for( int i=0;ilength;++i ){
- Char t=towupper( rep->data[i] );
- if( t==rep->data[i] ) continue;
- Rep *p=Rep::alloc( rep->length );
- Char *q=p->data;
- t_memcpy( q,rep->data,i );
- for( q[i++]=t;ilength;++i ){
- q[i]=towupper( rep->data[i] );
- }
- return String( p );
- }
- return *this;
- }
-
- bool Contains( String sub )const{
- return Find( sub )!=-1;
- }
-
- bool StartsWith( String sub )const{
- return sub.rep->length<=rep->length && !t_memcmp( rep->data,sub.rep->data,sub.rep->length );
- }
-
- bool EndsWith( String sub )const{
- return sub.rep->length<=rep->length && !t_memcmp( rep->data+rep->length-sub.rep->length,sub.rep->data,sub.rep->length );
- }
-
- String Slice( int from,int term )const{
- int len=rep->length;
- if( from<0 ){
- from+=len;
- if( from<0 ) from=0;
- }else if( from>len ){
- from=len;
- }
- if( term<0 ){
- term+=len;
- }else if( term>len ){
- term=len;
- }
- if( termdata+from,term-from );
- }
-
- String Slice( int from )const{
- return Slice( from,rep->length );
- }
-
- Array ToChars()const{
- Array chars( rep->length );
- for( int i=0;ilength;++i ) chars[i]=rep->data[i];
- return chars;
- }
-
- int ToInt()const{
- char buf[64];
- return atoi( ToCString( buf,sizeof(buf) ) );
- }
-
- Float ToFloat()const{
- char buf[256];
- return atof( ToCString( buf,sizeof(buf) ) );
- }
-
- template class CString{
- struct Rep{
- int refs;
- C data[1];
- };
- Rep *_rep;
- static Rep _nul;
- public:
- template CString( const T *data,int length ){
- _rep=(Rep*)malloc( length*sizeof(C)+sizeof(Rep) );
- _rep->refs=1;
- _rep->data[length]=0;
- for( int i=0;idata[i]=(C)data[i];
- }
- }
- CString():_rep( new Rep ){
- _rep->refs=1;
- }
- CString( const CString &c ):_rep(c._rep){
- ++_rep->refs;
- }
- ~CString(){
- if( !--_rep->refs ) free( _rep );
- }
- CString &operator=( const CString &c ){
- ++c._rep->refs;
- if( !--_rep->refs ) free( _rep );
- _rep=c._rep;
- return *this;
- }
- operator const C*()const{
- return _rep->data;
- }
- };
-
- template CString ToCString()const{
- return CString( rep->data,rep->length );
- }
-
- template C *ToCString( C *p,int length )const{
- if( --length>rep->length ) length=rep->length;
- for( int i=0;idata[i];
- p[length]=0;
- return p;
- }
-
-#if __OBJC__
- NSString *ToNSString()const{
- return [NSString stringWithCharacters:ToCString() length:rep->length];
- }
-#endif
-
-#if __cplusplus_winrt
- Platform::String ^ToWinRTString()const{
- return ref new Platform::String( rep->data,rep->length );
- }
-#endif
- CString ToUtf8()const{
- std::vector buf;
- Save( buf );
- return CString( &buf[0],buf.size() );
- }
-
- bool Save( FILE *fp )const{
- std::vector buf;
- Save( buf );
- return buf.size() ? fwrite( &buf[0],1,buf.size(),fp )==buf.size() : true;
- }
-
- void Save( std::vector &buf )const{
-
- Char *p=rep->data;
- Char *e=p+rep->length;
-
- while( p>6) );
- buf.push_back( 0x80 | (c & 0x3f) );
- }else{
- buf.push_back( 0xe0 | (c>>12) );
- buf.push_back( 0x80 | ((c>>6) & 0x3f) );
- buf.push_back( 0x80 | (c & 0x3f) );
- }
- }
- }
-
- static String FromChars( Array chars ){
- int n=chars.Length();
- Rep *p=Rep::alloc( n );
- for( int i=0;idata[i]=chars[i];
- }
- return String( p );
- }
-
- static String Load( FILE *fp ){
- unsigned char tmp[4096];
- std::vector buf;
- for(;;){
- int n=fread( tmp,1,4096,fp );
- if( n>0 ) buf.insert( buf.end(),tmp,tmp+n );
- if( n!=4096 ) break;
- }
- return buf.size() ? String::Load( &buf[0],buf.size() ) : String();
- }
-
- static String Load( unsigned char *p,int n ){
-
- _str_load_err=0;
-
- unsigned char *e=p+n;
- std::vector chars;
-
- int t0=n>0 ? p[0] : -1;
- int t1=n>1 ? p[1] : -1;
-
- if( t0==0xfe && t1==0xff ){
- p+=2;
- while( p2 ? p[2] : -1;
- if( t0==0xef && t1==0xbb && t2==0xbf ) p+=3;
- unsigned char *q=p;
- bool fail=false;
- while( p=e || (p[0] & 0xc0)!=0x80 ){
- fail=true;
- break;
- }
- c=((c & 0x1f)<<6) | (p[0] & 0x3f);
- p+=1;
- }else if( (c & 0xf0)==0xe0 ){
- if( p+1>=e || (p[0] & 0xc0)!=0x80 || (p[1] & 0xc0)!=0x80 ){
- fail=true;
- break;
- }
- c=((c & 0x0f)<<12) | ((p[0] & 0x3f)<<6) | (p[1] & 0x3f);
- p+=2;
- }else{
- fail=true;
- break;
- }
- }
- chars.push_back( c );
- }
- if( fail ){
- _str_load_err="Invalid UTF-8";
- return String( q,n );
- }
- }
- return chars.size() ? String( &chars[0],chars.size() ) : String();
- }
-
-private:
-
- struct Rep{
- int refs;
- int length;
- Char data[0];
-
- Rep():refs(1),length(0){
- }
-
- Rep( int length ):refs(1),length(length){
- }
-
- void retain(){
- ++refs;
- }
-
- void release(){
- if( --refs || this==&nullRep ) return;
- gc_new_bytes-=sizeof(Rep)+length*sizeof(Char);
- free( this );
- }
-
- static Rep *alloc( int length ){
- if( !length ) return &nullRep;
- void *p=malloc( sizeof(Rep)+length*sizeof(Char) );
- gc_new_bytes+=sizeof(Rep)+length*sizeof(Char);
- return new(p) Rep( length );
- }
- };
- Rep *rep;
-
- static Rep nullRep;
-
- String( Rep *rep ):rep(rep){
- }
-};
-
-String::Rep String::nullRep;
-
-String *t_create( int n,String *p ){
- for( int i=0;i String dbg_type( T **p ){
- return "Object";
-}
-
-template String dbg_type( Array *p ){
- return dbg_type( &(*p)[0] )+"[]";
-}
-
-String dbg_value( bool *p ){
- return *p ? "True" : "False";
-}
-
-String dbg_value( int *p ){
- return String( *p );
-}
-
-String dbg_value( Float *p ){
- return String( *p );
-}
-
-String dbg_value( String *p ){
- String t=*p;
- if( t.Length()>100 ) t=t.Slice( 0,100 )+"...";
- t=t.Replace( "\"","~q" );
- t=t.Replace( "\t","~t" );
- t=t.Replace( "\n","~n" );
- t=t.Replace( "\r","~r" );
- return String("\"")+t+"\"";
-}
-
-template String dbg_value( T **t ){
- Object *p=dynamic_cast