├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── appveyor.yml ├── assets └── unihx-logo.png ├── build-tool ├── build.hxml ├── res │ └── Template.hxproj └── src │ └── Cli.hx ├── extraParams.hxml ├── haxe ├── Log.hx └── Timer.hx ├── lib ├── Unity.CecilTools.dll ├── Unity.DataContract.dll ├── Unity.IvyParser.dll ├── Unity.Locator.dll ├── Unity.SerializationLogic.dll ├── UnityEditor.Graphs.dll ├── UnityEditor.dll └── UnityEngine.dll ├── run.n ├── tests ├── build-unity.hxml ├── build.hxml ├── project │ ├── .gitignore │ ├── Assets │ │ ├── TestEntryPoint.cs │ │ ├── TestEntryPoint.cs.meta │ │ ├── TestScene.unity │ │ ├── TestScene.unity.meta │ │ ├── bin-Debug.dll │ │ └── bin-Debug.dll.meta │ └── ProjectSettings │ │ ├── AudioManager.asset │ │ ├── DynamicsManager.asset │ │ ├── EditorBuildSettings.asset │ │ ├── EditorSettings.asset │ │ ├── GraphicsSettings.asset │ │ ├── InputManager.asset │ │ ├── NavMeshLayers.asset │ │ ├── NetworkManager.asset │ │ ├── Physics2DSettings.asset │ │ ├── ProjectSettings.asset │ │ ├── QualitySettings.asset │ │ ├── TagManager.asset │ │ └── TimeManager.asset └── src │ ├── CmdTests.hx │ ├── UnityTests.hx │ └── tests │ └── YieldTests.hx ├── unihx ├── _internal │ ├── Compiler.hx │ ├── PrivateAccessMacro.hx │ ├── PrivateTypeAccess.hx │ ├── StructHelper.hx │ ├── Yield.hx │ ├── YieldBase.hx │ ├── YieldGenerator.hx │ └── editor │ │ ├── AllowDragDrop.hx │ │ ├── AssetProcessor.hx │ │ ├── HaxeCompiler.hx │ │ └── HaxeProperties.hx └── inspector │ ├── AnimationCurve.hx │ ├── Button.hx │ ├── Color.hx │ ├── ConstLabel.hx │ ├── Fold.hx │ ├── InspectorBuild.hx │ ├── IntField.hx │ ├── Label.hx │ ├── Layer.hx │ ├── Macro.hx │ ├── ObjectField.hx │ ├── Password.hx │ ├── Range.hx │ ├── Rect.hx │ ├── Select.hx │ ├── Slider.hx │ ├── Space.hx │ ├── Tag.hx │ ├── TextArea.hx │ ├── Vector2.hx │ ├── Vector3.hx │ └── Vector4.hx └── unityengine ├── Bounds.hx ├── BoundsData.hx ├── Color.hx ├── Color32.hx ├── Color32Data.hx ├── ColorData.hx ├── HaxeBehaviour.hx ├── Matrix4x4.hx ├── Matrix4x4Data.hx ├── Quaternion.hx ├── QuaternionData.hx ├── Rect.hx ├── RectData.hx ├── Vector2.hx ├── Vector2Data.hx ├── Vector3.hx ├── Vector3Data.hx ├── Vector4.hx └── Vector4Data.hx /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.swo 3 | bin 4 | 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # example travis.yml haxe configuration 2 | language: objective-c # change this to c to test on a linux machine 3 | env: 4 | global: 5 | - OS=mac # add this too to let the script know that the OS is a mac 6 | # - ARCH=i686 # add this to run in 32-bit mode. See availability at README 7 | matrix: 8 | - TARGET=cs 9 | 10 | matrix: 11 | fast_finish: true 12 | 13 | before_install: # clone travis-hx repo 14 | - travis_retry git clone --depth=50 --branch=master git://github.com/waneck/travis-hx.git ~/travis-hx 15 | 16 | install: # setup the target 17 | - ~/travis-hx/setup.sh 18 | - haxelib install utest 19 | - haxelib dev unihx "$TRAVIS_BUILD_DIR" 20 | - cd ~ 21 | - curl -L "https://docs.google.com/uc?export=download&id=0B8FjDKR0nfqoQmpOYW44S2c3SU0" -o mac.tar.gz 22 | - tar -zxf mac.tar.gz 23 | - chmod +x test.app/Contents/MacOS/test 24 | 25 | script: 26 | - cd $TRAVIS_BUILD_DIR/tests 27 | # build the target. This will call haxe with the HXFLAGS and HXFLAGS_EXTRA environment variables 28 | - haxe build.hxml 29 | - mono --debug bin/bin/CmdTests-Debug.exe 30 | - haxe build-unity.hxml 31 | - cp bin/bin/bin-Debug.dll ~/test.app/Contents/Data/Managed 32 | - cd ~ 33 | - ./test.app/Contents/MacOS/test 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Cauê Waneck 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # unihx 2 | Unity-Haxe tools. Compile to Unity3D from Haxe. 3 | 4 | ## Goal 5 | Make Haxe be a first-class Unity development language, and make it easier to work with Haxe on Unity than the natively supported Unity languages 6 | 7 | ## Getting started 8 | Use `haxelib git unihx https://github.com/waneck/unihx.git` to install it. 9 | 10 | On an existing Unity project, run `haxelib run unihx init path/to/unity/proj`. Beware that you currently need a Haxe nightly build to be able to compile and use this library correctly. 11 | 12 | ## What works 13 | You can see a demonstration of some of its features at http://waneck.github.io/wwx-unity3d-haxe/ . The following are working already: 14 | * When Unity gets back to focus, it compiles the changed .hx scripts 15 | * You can click & drag .hx scripts into the inspector, like you can do with pure C#/UnityScript scripts 16 | * The resulting C# files are compiled in a directory relative to the .hx script file - so you can create Editor scripts, etc more easily 17 | * You can access other C# scripts from within Haxe, and vice-versa - even those that are compiled within the same compilation unit! 18 | * Access to any .NET library through `-net-lib` 19 | * Extend MonoBehaviour and code like you would with other Unity languages. Be sure to check the wwx presentation to get an idea of the types equivalence (e.g. C#'s array are cs.NativeArray in Haxe) 20 | * Use the `@:nativeGen` metadata to generate very clean code 21 | * Error positions always shown in the .hx code 22 | * Operator overloading on core structures like Vector2, Vector3, Matrix4x4, Quaternion, etc. See more about it at [Core Structures](https://github.com/waneck/unihx/wiki/Core-Structures) 23 | 24 | ## What still needs work 25 | * The HaxeBehaviour class is available, but some of its features demonstrated were proof-of-concept and are currently only accessible through the development branch. 26 | 27 | ## Help wanted 28 | Any kind of contribution will be much appreciated - from feature requests, testing it and adding bug reports, tutorials and documentation, to actual code and features! 29 | Pull requests are very welcome, and if you are excited as we are to bring an awesome Haxe support to Unity, let us know and join the team! 30 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | clone_folder: c:\projects\unihx 2 | 3 | environment: 4 | matrix: 5 | - TARGET: cs 6 | 7 | install: # clone travis-hx repo and setup the target 8 | - echo starting 9 | - git clone --depth=50 --branch=master git://github.com/waneck/travis-hx.git C:\travis-hx 10 | - C:\travis-hx\extra\appveyor\AppVeyor.exe setup 11 | - SET PATH=c:\HaxeToolkit\haxe;C:\HaxeToolkit\neko;C:\Program Files\7-Zip\;%PATH% 12 | - haxelib install utest 13 | - haxelib dev unihx C:\projects\unihx 14 | - cinst wget -x86 15 | - cd \projects\unihx\tests 16 | - wget "https://docs.google.com/uc?export=download&id=0B8FjDKR0nfqoTmZDWDNBTWtIYjA" -O win32.tar.gz --no-check-certificate 17 | - 7z x win32.tar.gz 18 | - 7z x win32.tar 19 | 20 | build_script: 21 | - cd \projects\unihx\tests 22 | - haxe build.hxml 23 | - bin\bin\CmdTests-Debug.exe 24 | - copy bin\bin\bin-Debug.dll test_Data\Managed 25 | - test.exe 26 | -------------------------------------------------------------------------------- /assets/unihx-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/assets/unihx-logo.png -------------------------------------------------------------------------------- /build-tool/build.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -neko ../run.n 3 | -main Cli 4 | -lib mcli 5 | -resource res/Template.hxproj@hxproj 6 | -------------------------------------------------------------------------------- /build-tool/res/Template.hxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | haxe --cwd "$(ProjectDir)/Assets" classpaths.hxml params.hxml --macro unihx._internal.Compiler.compile\(\) 43 | 44 | 45 | 46 | 47 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /build-tool/src/Cli.hx: -------------------------------------------------------------------------------- 1 | import mcli.*; 2 | import sys.FileSystem.*; 3 | import haxe.io.Path; 4 | import haxe.Resource; 5 | 6 | using StringTools; 7 | 8 | class Cli extends CommandLine 9 | { 10 | /** 11 | Show this message. 12 | **/ 13 | public function help() 14 | { 15 | Sys.println(this.showUsage()); 16 | Sys.exit(0); 17 | } 18 | 19 | private function err(msg:String) 20 | { 21 | Sys.stderr().writeString(msg + "\n"); 22 | Sys.exit(1); 23 | } 24 | 25 | private function haxe(args:Array) 26 | { 27 | print( 'haxe ' + [for (arg in args) arg.split('"').join('\\\"') ].join(" ") ); 28 | var ret = Sys.command('haxe ' + [for (arg in args) arg.split('"').join('\\\"') ].join(" ")); 29 | if (ret != 0) 30 | Sys.exit(ret); 31 | } 32 | 33 | /** 34 | Force always to yes 35 | **/ 36 | public var force:Bool = false; 37 | 38 | public var verbose:Bool = false; 39 | 40 | private function print(msg:String) 41 | { 42 | if (verbose) Sys.println(msg); 43 | } 44 | 45 | private function ask(msg:String, ?preSelect:Bool):Bool 46 | { 47 | if (force) return true; 48 | Sys.println(msg); 49 | var stdin = Sys.stdin(); 50 | var str = "(" + (preSelect == true ? "Y" : "y") + "/" + (preSelect == false ? "N" : "n") + ") "; 51 | while (true) 52 | { 53 | Sys.print(str); 54 | var ln = stdin.readLine().trim().toLowerCase(); 55 | if (ln == "" && preSelect != null) 56 | return preSelect; 57 | else if (ln == "y") 58 | return true; 59 | else if (ln == "n") 60 | return false; 61 | } 62 | } 63 | 64 | public static function main() 65 | { 66 | var args = Sys.args(); 67 | if (Sys.getEnv('HAXELIB_RUN') == "1") 68 | { 69 | var curpath = args.pop(); 70 | Sys.setCwd(curpath); 71 | } 72 | new mcli.Dispatch(args).dispatch(new Helper()); 73 | } 74 | } 75 | 76 | /** 77 | unihx helper tool 78 | **/ 79 | class Helper extends CommandLine 80 | { 81 | /** 82 | Initializes the target Unity project to use unihx 83 | **/ 84 | public function init(d:Dispatch) 85 | { 86 | d.dispatch(new InitCmd()); 87 | } 88 | } 89 | 90 | /** 91 | unihx init [target-dir] : initializes the target Unity project to use unihx. 92 | **/ 93 | class InitCmd extends Cli 94 | { 95 | public function runDefault(targetDir=".") 96 | { 97 | if (!exists(targetDir)) 98 | { 99 | err('"$targetDir" does not exist'); 100 | } 101 | 102 | if (targetDir == "") 103 | targetDir = "."; 104 | // look for 'Assets' folder 105 | var assets = getAssets(targetDir); 106 | if (assets == null) 107 | { 108 | err('Cannot find the Assets folder at "$targetDir"'); 109 | } 110 | if (assets == "") 111 | assets = "."; 112 | 113 | if (!exists(assets + "/classpaths.hxml")) 114 | { 115 | sys.io.File.saveContent(assets + '/classpaths.hxml', '#this file is automatically generated. any change made here may be lost\n-cp .\n-cp Scripts'); 116 | } 117 | 118 | if (!exists(assets + "/build.hxml")) 119 | { 120 | sys.io.File.saveContent(assets + '/build.hxml', 'params.hxml\n# Add your own compiler parameters here\n'); 121 | } 122 | 123 | if (!exists(assets + '/params.hxml') || ask('$targetDir/params.hxml already exists. Replace?',true)) 124 | { 125 | sys.io.File.saveContent(assets + '/params.hxml', 'classpaths.hxml\n-lib unihx\n-cs hx-compiled\n-D unity_std_target=Standard Assets'); 126 | var old = Sys.getCwd(); 127 | Sys.setCwd(assets); 128 | if (Sys.systemName() == "Windows") 129 | haxe(['params.hxml',"--macro","include(\"unihx._internal.editor\")"]); 130 | else 131 | haxe(['params.hxml',"--macro","include\\(\"unihx._internal.editor\"\\)"]); 132 | Sys.setCwd(old); 133 | } 134 | 135 | var proj = assets + "/../" + Path.withoutDirectory( fullPath(assets + "/..") ) + '.hxproj'; 136 | if (!exists(proj)) 137 | { 138 | sys.io.File.saveContent(proj, Resource.getString("hxproj")); 139 | } 140 | 141 | for (f in ['smcs','gmcs']) 142 | { 143 | if (!exists(assets + '/$f.rsp')) 144 | { 145 | sys.io.File.saveContent(assets+'/$f.rsp', "-nowarn:0109,0114,0219,0429,0168,0162"); 146 | } 147 | } 148 | 149 | } 150 | 151 | private function getAssets(dir:String):Null 152 | { 153 | var full = fullPath(dir).split('\\').join('/').split('/'); 154 | while (full[full.length-1] == "") 155 | full.pop(); 156 | 157 | var buf = new StringBuf(); 158 | buf.add("."); 159 | while (full.length > 1) 160 | { 161 | var dir = full.join('/'); 162 | for (file in readDirectory(dir)) 163 | { 164 | if (file == "Assets") 165 | return buf + '/Assets'; 166 | } 167 | buf.add('/..'); 168 | full.pop(); 169 | } 170 | return null; 171 | } 172 | 173 | } 174 | -------------------------------------------------------------------------------- /extraParams.hxml: -------------------------------------------------------------------------------- 1 | -net-lib lib/UnityEngine.dll 2 | -net-lib lib/UnityEditor.dll 3 | -D use_rtti_doc 4 | -------------------------------------------------------------------------------- /haxe/Log.hx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C)2005-2012 Haxe Foundation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | package haxe; 23 | 24 | /** 25 | Log primarily provides the trace() method, which is invoked upon a call to 26 | trace() in haxe code. 27 | **/ 28 | class Log { 29 | 30 | /** 31 | Outputs `v` in a platform-dependent way. 32 | 33 | The second parameter `infos` is injected by the compiler and contains 34 | information about the position where the trace() call was made. 35 | 36 | This method can be rebound to a custom function: 37 | var oldTrace = haxe.Log.trace; // store old function 38 | haxe.Log.trace = function(v,infos) { // handle trace } 39 | ... 40 | haxe.Log.trace = oldTrace; 41 | 42 | If it is bound to null, subsequent calls to trace() will cause an 43 | exception. 44 | **/ 45 | public static dynamic function trace( v : Dynamic, ?infos : PosInfos ) : Void { 46 | #if flash 47 | #if (fdb || native_trace) 48 | var pstr = infos == null ? "(null)" : infos.fileName + ":" + infos.lineNumber; 49 | var str = flash.Boot.__string_rec(v, ""); 50 | if( infos != null && infos.customParams != null ) for( v in infos.customParams ) str += "," + flash.Boot.__string_rec(v, ""); 51 | untyped #if flash9 __global__["trace"] #else __trace__ #end(pstr+": "+str); 52 | #else 53 | untyped flash.Boot.__trace(v,infos); 54 | #end 55 | #elseif neko 56 | untyped { 57 | $print(infos.fileName + ":" + infos.lineNumber + ": ", v); 58 | if( infos.customParams != null ) for( v in infos.customParams ) $print(",", v); 59 | $print("\n"); 60 | } 61 | #elseif js 62 | untyped js.Boot.__trace(v,infos); 63 | #elseif php 64 | if (infos!=null && infos.customParams!=null) { 65 | var extra:String = ""; 66 | for( v in infos.customParams ) 67 | extra += "," + v; 68 | untyped __call__('_hx_trace', v + extra, infos); 69 | } 70 | else 71 | untyped __call__('_hx_trace', v, infos); 72 | #elseif cpp 73 | if (infos!=null && infos.customParams!=null) { 74 | var extra:String = ""; 75 | for( v in infos.customParams ) 76 | extra += "," + v; 77 | untyped __trace(v + extra,infos); 78 | } 79 | else 80 | untyped __trace(v,infos); 81 | #elseif (cs || java) 82 | var str:String = null; 83 | if (infos != null) { 84 | str = infos.fileName + ":" + infos.lineNumber + ": " + v; 85 | if (infos.customParams != null) 86 | { 87 | str += "," + infos.customParams.join(","); 88 | } 89 | } else { 90 | str = v; 91 | } 92 | #if cs 93 | // cs.system.Console.WriteLine(str); 94 | unityengine.Debug.Log(str); 95 | #elseif java 96 | untyped __java__("java.lang.System.out.println(str)"); 97 | #end 98 | #end 99 | } 100 | 101 | #if (flash || js) 102 | /** 103 | Clears the trace output. 104 | **/ 105 | public static dynamic function clear() : Void { 106 | #if flash 107 | untyped flash.Boot.__clear_trace(); 108 | #elseif js 109 | untyped js.Boot.__clear_trace(); 110 | #end 111 | } 112 | #end 113 | 114 | #if flash 115 | /** 116 | Sets the color of the trace output to `rgb`. 117 | **/ 118 | public static dynamic function setColor( rgb : Int ) { 119 | untyped flash.Boot.__set_trace_color(rgb); 120 | } 121 | #end 122 | 123 | } 124 | -------------------------------------------------------------------------------- /haxe/Timer.hx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005, The haXe Project Contributors 3 | * All rights reserved. 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * - Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY 14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR 17 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 23 | * DAMAGE. 24 | */ 25 | package haxe; 26 | #if cs 27 | import cs.system.DateTime; 28 | import cs.system.Object; 29 | import cs.system.timers.ElapsedEventArgs; 30 | import cs.system.timers.ElapsedEventHandler; 31 | import cs.system.TimeSpan; 32 | #end 33 | /** 34 | The Timer class allows you to create asynchronous timers on platforms that support events. 35 | **/ 36 | class Timer { 37 | 38 | #if (neko || php || cpp) 39 | #else 40 | #if cs 41 | private var t:cs.system.timers.Timer; 42 | private var id : Null; 43 | private function runRun():Void run(); 44 | #end 45 | /** 46 | Create a new timer that will run every [time_ms] (in milliseconds). 47 | **/ 48 | public function new( time_ms : Int ) { 49 | #if cs 50 | id = 1; 51 | var f = runRun; 52 | var tt = t = new cs.system.timers.Timer(time_ms); 53 | t.Enabled = true; 54 | untyped __cs__("tt.Elapsed+=delegate(System.Object o, System.Timers.ElapsedEventArgs e){f.__hx_invoke0_o();}"); 55 | #elseif flash9 56 | var me = this; 57 | id = untyped __global__["flash.utils.setInterval"](function() { me.run(); },time_ms); 58 | #elseif flash 59 | var me = this; 60 | id = untyped _global["setInterval"](function() { me.run(); },time_ms); 61 | #elseif js 62 | var me = this; 63 | id = untyped window.setInterval(function() me.run(),time_ms); 64 | #end 65 | } 66 | 67 | /** 68 | Stop the timer definitely. 69 | **/ 70 | public function stop() { 71 | if( id == null ) 72 | return; 73 | #if cs 74 | t.Stop(); 75 | t.Enabled = false; 76 | t = null; 77 | #elseif flash9 78 | untyped __global__["flash.utils.clearInterval"](id); 79 | #elseif flash 80 | untyped _global["clearInterval"](id); 81 | #elseif js 82 | untyped window.clearInterval(id); 83 | #end 84 | id = null; 85 | } 86 | 87 | /** 88 | This is the [run()] method that is called when the Timer executes. It can be either overriden in subclasses or directly rebinded with another function-value. 89 | **/ 90 | public dynamic function run() { 91 | trace("run"); 92 | } 93 | 94 | /** 95 | This will delay the call to [f] for the given time. [f] will only be called once. 96 | **/ 97 | public static function delay( f : Void -> Void, time_ms : Int ) { 98 | var t = new haxe.Timer(time_ms); 99 | t.run = function() { 100 | t.stop(); 101 | f(); 102 | }; 103 | return t; 104 | } 105 | 106 | #end 107 | 108 | /** 109 | Measure the time it takes to execute the function [f] and trace it. Returns the value returned by [f]. 110 | **/ 111 | public static function measure( f : Void -> T, ?pos : PosInfos ) : T { 112 | var t0 = stamp(); 113 | var r = f(); 114 | Log.trace((stamp() - t0) + "s", pos); 115 | return r; 116 | } 117 | 118 | /** 119 | Returns the most precise timestamp, in seconds. The value itself might differ depending on platforms, only differences between two values make sense. 120 | **/ 121 | public static function stamp() : Float { 122 | #if cs 123 | var ts:TimeSpan = null; 124 | ts = untyped __cs__('System.DateTime.UtcNow - new System.DateTime(1970, 1, 1)'); 125 | return ts.TotalMilliseconds; 126 | #elseif flash 127 | return flash.Lib.getTimer() / 1000; 128 | #elseif (neko || php) 129 | return Sys.time(); 130 | #elseif js 131 | return Date.now().getTime() / 1000; 132 | #elseif cpp 133 | return untyped __global__.__time_stamp(); 134 | #else 135 | return 0; 136 | #end 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /lib/Unity.CecilTools.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/lib/Unity.CecilTools.dll -------------------------------------------------------------------------------- /lib/Unity.DataContract.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/lib/Unity.DataContract.dll -------------------------------------------------------------------------------- /lib/Unity.IvyParser.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/lib/Unity.IvyParser.dll -------------------------------------------------------------------------------- /lib/Unity.Locator.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/lib/Unity.Locator.dll -------------------------------------------------------------------------------- /lib/Unity.SerializationLogic.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/lib/Unity.SerializationLogic.dll -------------------------------------------------------------------------------- /lib/UnityEditor.Graphs.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/lib/UnityEditor.Graphs.dll -------------------------------------------------------------------------------- /lib/UnityEditor.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/lib/UnityEditor.dll -------------------------------------------------------------------------------- /lib/UnityEngine.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/lib/UnityEngine.dll -------------------------------------------------------------------------------- /run.n: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/run.n -------------------------------------------------------------------------------- /tests/build-unity.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -lib unihx 3 | -lib utest 4 | -debug 5 | -cs bin 6 | -D dll 7 | UnityTests 8 | -------------------------------------------------------------------------------- /tests/build.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -main CmdTests 3 | -lib unihx 4 | -lib utest 5 | -debug 6 | -cs bin 7 | -------------------------------------------------------------------------------- /tests/project/.gitignore: -------------------------------------------------------------------------------- 1 | # =============== # 2 | # Unity generated # 3 | # =============== # 4 | Temp/ 5 | Obj/ 6 | UnityGenerated/ 7 | Library/ 8 | 9 | # ===================================== # 10 | # Visual Studio / MonoDevelop generated # 11 | # ===================================== # 12 | ExportedObj/ 13 | *.svd 14 | *.userprefs 15 | *.csproj 16 | *.pidb 17 | *.suo 18 | *.sln 19 | *.user 20 | *.unityproj 21 | *.booproj 22 | 23 | # ============ # 24 | # OS generated # 25 | # ============ # 26 | .DS_Store 27 | .DS_Store? 28 | ._* 29 | .Spotlight-V100 30 | .Trashes 31 | Icon? 32 | ehthumbs.db 33 | Thumbs.db 34 | -------------------------------------------------------------------------------- /tests/project/Assets/TestEntryPoint.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class TestEntryPoint : MonoBehaviour { 5 | 6 | // Use this for initialization 7 | void Start () { 8 | UnityTests.runTests(delegate(bool passed) { 9 | Debug.Log(passed); 10 | }); 11 | } 12 | 13 | // Update is called once per frame 14 | void Update () { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/project/Assets/TestEntryPoint.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 635e032aec4370446a139dea98aa90c2 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /tests/project/Assets/TestScene.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/tests/project/Assets/TestScene.unity -------------------------------------------------------------------------------- /tests/project/Assets/TestScene.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d856d7b17ab19f543aa870627c0cfaf6 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /tests/project/Assets/bin-Debug.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/tests/project/Assets/bin-Debug.dll -------------------------------------------------------------------------------- /tests/project/Assets/bin-Debug.dll.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: feaad69e28992a84dbacb73b95c5b475 3 | MonoAssemblyImporter: 4 | serializedVersion: 1 5 | iconMap: {} 6 | executionOrder: {} 7 | userData: 8 | -------------------------------------------------------------------------------- /tests/project/ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/tests/project/ProjectSettings/AudioManager.asset -------------------------------------------------------------------------------- /tests/project/ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/tests/project/ProjectSettings/DynamicsManager.asset -------------------------------------------------------------------------------- /tests/project/ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/tests/project/ProjectSettings/EditorBuildSettings.asset -------------------------------------------------------------------------------- /tests/project/ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/tests/project/ProjectSettings/EditorSettings.asset -------------------------------------------------------------------------------- /tests/project/ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/tests/project/ProjectSettings/GraphicsSettings.asset -------------------------------------------------------------------------------- /tests/project/ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/tests/project/ProjectSettings/InputManager.asset -------------------------------------------------------------------------------- /tests/project/ProjectSettings/NavMeshLayers.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/tests/project/ProjectSettings/NavMeshLayers.asset -------------------------------------------------------------------------------- /tests/project/ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/tests/project/ProjectSettings/NetworkManager.asset -------------------------------------------------------------------------------- /tests/project/ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/tests/project/ProjectSettings/Physics2DSettings.asset -------------------------------------------------------------------------------- /tests/project/ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/tests/project/ProjectSettings/ProjectSettings.asset -------------------------------------------------------------------------------- /tests/project/ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/tests/project/ProjectSettings/QualitySettings.asset -------------------------------------------------------------------------------- /tests/project/ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/tests/project/ProjectSettings/TagManager.asset -------------------------------------------------------------------------------- /tests/project/ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waneck/unihx/b2e19c69926ea072de07f7de7c59ee4f86464502/tests/project/ProjectSettings/TimeManager.asset -------------------------------------------------------------------------------- /tests/src/CmdTests.hx: -------------------------------------------------------------------------------- 1 | import utest.Runner; 2 | import utest.ui.Report; 3 | 4 | class CmdTests 5 | { 6 | static function main() 7 | { 8 | // var ret = sys.io.File.write('test.txt'); 9 | haxe.Log.trace = function(v:Dynamic, ?infos:haxe.PosInfos) { 10 | var str:String = null; 11 | if (infos != null) { 12 | str = infos.fileName + ":" + infos.lineNumber + ": " + v; 13 | if (infos.customParams != null) 14 | { 15 | str += "," + infos.customParams.join(","); 16 | } 17 | } else { 18 | str = v; 19 | } 20 | // ret.writeString(str); 21 | // ret.writeString('\n'); 22 | cs.system.Console.WriteLine(str); 23 | }; 24 | var runner = new Runner(); 25 | 26 | runner.addCase(new tests.YieldTests()); 27 | 28 | var report = new utest.ui.text.PrintReport(runner); 29 | runner.run(); 30 | 31 | // ret.close(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/src/UnityTests.hx: -------------------------------------------------------------------------------- 1 | import utest.Runner; 2 | import utest.ui.Report; 3 | 4 | class UnityTests 5 | { 6 | static function runTests(onEnd:cs.system.Action_1) 7 | { 8 | // var ret = sys.io.File.write('test.txt'); 9 | haxe.Log.trace = function(v:Dynamic, ?infos:haxe.PosInfos) { 10 | var str:String = null; 11 | if (infos != null) { 12 | str = infos.fileName + ":" + infos.lineNumber + ": " + v; 13 | if (infos.customParams != null) 14 | { 15 | str += "," + infos.customParams.join(","); 16 | } 17 | } else { 18 | str = v; 19 | } 20 | // ret.writeString(str); 21 | // ret.writeString('\n'); 22 | cs.system.Console.WriteLine(str); 23 | }; 24 | var runner = new Runner(); 25 | 26 | runner.addCase(new tests.YieldTests()); 27 | 28 | var report = new utest.ui.text.PrintReport(runner); 29 | runner.run(); 30 | 31 | // ret.close(); 32 | unityengine.Application.Quit(); 33 | onEnd.Invoke(true); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/src/tests/YieldTests.hx: -------------------------------------------------------------------------------- 1 | package tests; 2 | import utest.Assert; 3 | import unihx._internal.YieldBase; 4 | 5 | using Lambda; 6 | 7 | class YieldTests 8 | { 9 | public function new() 10 | { 11 | this.someTest = "someTest"; 12 | } 13 | 14 | private var someTest:String; 15 | 16 | macro private static function test(expr:haxe.macro.Expr):haxe.macro.Expr.ExprOf 17 | { 18 | var ret = unihx._internal.YieldGenerator.make('tests.unihx',expr); 19 | return macro ($ret : unihx._internal.YieldBase); 20 | } 21 | 22 | macro private static function fails(e:haxe.macro.Expr) 23 | { 24 | try 25 | { 26 | haxe.macro.Context.typeof(e); 27 | return macro false; 28 | } 29 | catch(e:Dynamic) { 30 | return macro true; 31 | } 32 | } 33 | 34 | #if !macro 35 | public function test_basic() 36 | { 37 | var t1 = test({ 38 | var a:Array = []; 39 | { 40 | a.push(1); 41 | { 42 | @yield {retn:"A",arr:a}; 43 | a.push(1.1); 44 | } 45 | { 46 | a.push(1.2); 47 | @yield {retn:"B",arr:a}; 48 | a.push(1.3); 49 | a = []; 50 | } 51 | a.push(2); 52 | @yield {retn:"b",arr:a}; 53 | a.push(3); 54 | } 55 | @yield {retn:"c",arr:a}; 56 | a.push(4); 57 | }); 58 | Assert.isTrue(t1.hasNext()); 59 | Assert.same({retn:"A",arr:[1]}, t1.next()); 60 | Assert.isTrue(t1.hasNext()); 61 | Assert.same({retn:"B",arr:[1,1.1,1.2]}, t1.next()); 62 | Assert.isTrue(t1.hasNext()); 63 | Assert.same({retn:"b",arr:[2]}, t1.next()); 64 | Assert.isTrue(t1.hasNext()); 65 | var last = t1.next(); 66 | Assert.same({retn:"c",arr:[2,3]}, last); 67 | Assert.isFalse(t1.hasNext()); 68 | Assert.same([2,3,4],last.arr); 69 | } 70 | 71 | public function test_if() 72 | { 73 | var t = true, f = false; 74 | var t1 = test({ 75 | var a:Array = []; 76 | if (t) 77 | { 78 | a.push(1); 79 | if (true) 80 | { 81 | @yield {retn:"A",arr:a}; 82 | a.push(1.1); 83 | } 84 | if (f) 85 | { 86 | a.push(-2); 87 | @yield {retn:"-a",arr:a}; 88 | a.push(-3); 89 | } else { 90 | a.push(1.2); 91 | @yield {retn:"B",arr:a}; 92 | a.push(1.3); 93 | } 94 | a = []; 95 | a.push(2); 96 | @yield {retn:"b",arr:a}; 97 | a.push(3); 98 | } 99 | @yield {retn:"c",arr:a}; 100 | a.push(4); 101 | }); 102 | 103 | Assert.isTrue(t1.hasNext()); 104 | f = true; //it shouldn't change the behavior here - as vars aren't captured, they are copied 105 | Assert.same({retn:"A",arr:[1]}, t1.next()); 106 | Assert.isTrue(t1.hasNext()); 107 | Assert.same({retn:"B",arr:[1,1.1,1.2]}, t1.next()); 108 | Assert.isTrue(t1.hasNext()); 109 | Assert.same({retn:"b",arr:[2]}, t1.next()); 110 | Assert.isTrue(t1.hasNext()); 111 | var last = t1.next(); 112 | Assert.same({retn:"c",arr:[2,3]}, last); 113 | Assert.isFalse(t1.hasNext()); 114 | Assert.same([2,3,4],last.arr); 115 | 116 | //check for deep nesting 117 | var t = true, f = false; 118 | var t1 = test({ 119 | var a:Array = []; 120 | if (t) 121 | { 122 | a.push(1); 123 | if (true) 124 | { 125 | @yield {retn:"A",arr:a}; 126 | a.push(1.1); 127 | } 128 | if (f) 129 | { 130 | a.push(-2); 131 | @yield {retn:"-a",arr:a}; 132 | a.push(-3); 133 | if (f) 134 | { 135 | a.push(-4); 136 | @yield null; 137 | a.push(-5); 138 | } else if (false) { 139 | a.push(-6); 140 | @yield null; 141 | if (true) 142 | { 143 | a.push(-6.1); 144 | @yield null; 145 | a.push(-6.2); 146 | } 147 | a.push(-7); 148 | @yield null; 149 | a.push(-8); 150 | } else { 151 | a.push(-9); 152 | @yield null; 153 | a.push(-10); 154 | } 155 | } else { 156 | if (t) 157 | { 158 | a.push(1.11); 159 | @yield {retn:"A1",arr:a}; 160 | a.push(1.12); 161 | } else { 162 | a.push(-11); 163 | @yield null; 164 | a.push(-12); 165 | } 166 | a.push(1.2); 167 | @yield {retn:"B",arr:a}; 168 | a.push(1.3); 169 | } 170 | a = []; 171 | //test now first true, then false 172 | if (t) 173 | { 174 | a.push(1.4); 175 | @yield {retn:"B1",arr:a}; 176 | a.push(1.5); 177 | @yield {retn:"B2",arr:a}; 178 | } else if (f) { 179 | a.push(-4); 180 | @yield null; 181 | a.push(-5); 182 | } else { 183 | a.push(-6); 184 | @yield null; 185 | if (true) 186 | { 187 | a.push(-6.1); 188 | @yield null; 189 | a.push(-6.2); 190 | } 191 | a.push(-7); 192 | @yield null; 193 | a.push(-8); 194 | } 195 | a = []; 196 | a.push(2); 197 | @yield {retn:"b",arr:a}; 198 | a.push(3); 199 | } 200 | @yield {retn:"c",arr:a}; 201 | a.push(4); 202 | }); 203 | 204 | Assert.isTrue(t1.hasNext()); 205 | Assert.same({retn:"A",arr:[1]}, t1.next()); 206 | Assert.isTrue(t1.hasNext()); 207 | Assert.same({retn:"A1",arr:[1,1.1,1.11]}, t1.next()); 208 | Assert.isTrue(t1.hasNext()); 209 | Assert.same({retn:"B",arr:[1,1.1,1.11,1.12,1.2]}, t1.next()); 210 | Assert.isTrue(t1.hasNext()); 211 | Assert.same({retn:"B1",arr:[1.4]}, t1.next()); 212 | Assert.isTrue(t1.hasNext()); 213 | Assert.same({retn:"B2",arr:[1.4,1.5]}, t1.next()); 214 | Assert.isTrue(t1.hasNext()); 215 | Assert.same({retn:"b",arr:[2]}, t1.next()); 216 | Assert.isTrue(t1.hasNext()); 217 | var last = t1.next(); 218 | Assert.same({retn:"c",arr:[2,3]}, last); 219 | Assert.isFalse(t1.hasNext()); 220 | Assert.same([2,3,4],last.arr); 221 | } 222 | 223 | public function test_fibonacci() 224 | { 225 | //returns the 10 first fibonacci numbers 226 | var fib = test({ 227 | var an2 = 0, an1 = 1; 228 | @yield 0; @yield 1; 229 | for (i in 0...8) 230 | { 231 | var c = an1 + an2; 232 | an2 = an1; an1 = c; 233 | @yield c; 234 | } 235 | }); 236 | 237 | Assert.same([0,1, 1, 2, 3, 5, 8, 13, 21, 34], [for(v in fib) v]); 238 | 239 | //infinite version 240 | var fib = test({ 241 | var an2 = 0, an1 = 1; 242 | @yield 0; @yield 1; 243 | while(true) 244 | { 245 | var c = an1 + an2; 246 | an2 = an1; an1 = c; 247 | @yield c; 248 | } 249 | }); 250 | 251 | for (i in [0,1, 1, 2, 3, 5, 8, 13, 21, 34]) 252 | { 253 | Assert.isTrue(fib.hasNext()); 254 | Assert.equals(i,fib.next()); 255 | } 256 | Assert.isTrue(fib.hasNext()); 257 | } 258 | 259 | public function test_fact() 260 | { 261 | //first 10 factorial numbers 262 | var fact = test({ 263 | var acc = 1; 264 | @yield 1; 265 | for (i in 1...10) 266 | { 267 | @yield (acc *= i); 268 | } 269 | }); 270 | 271 | Assert.same([1,1,2,6,24,120,720,5040,40320,362880], [for(v in fact) v]); 272 | 273 | //infinite version 274 | var fact = test({ 275 | var acc = 1, i = 1; 276 | @yield 1; 277 | while(true) 278 | { 279 | @yield (acc *= i++); 280 | } 281 | }); 282 | 283 | for (i in [1,1,2,6,24,120,720,5040,40320,362880]) 284 | { 285 | Assert.isTrue(fact.hasNext()); 286 | Assert.equals(i,fact.next()); 287 | } 288 | Assert.isTrue(fact.hasNext()); 289 | } 290 | 291 | public function test_array_for() 292 | { 293 | var t = test({ 294 | var arr = [1,2,3,4,5,6,7], lastValue = -1; 295 | for (a in arr) 296 | { 297 | var myval = a + lastValue; 298 | lastValue = a; 299 | @yield myval; 300 | } 301 | }); 302 | for (i in [0, 3, 5, 7, 9, 11, 13]) 303 | { 304 | Assert.isTrue(t.hasNext()); 305 | Assert.equals(i, t.next()); 306 | } 307 | 308 | //calling iterator() directly 309 | var t = test({ 310 | var arr = [1,2,3,4,5,6,7], lastValue = -1; 311 | for (a in arr.iterator()) 312 | { 313 | var myval = a + lastValue; 314 | lastValue = a; 315 | @yield myval; 316 | } 317 | }); 318 | for (i in [0, 3, 5, 7, 9, 11, 13]) 319 | { 320 | Assert.isTrue(t.hasNext()); 321 | Assert.equals(i, t.next()); 322 | } 323 | } 324 | 325 | public function test_list_for() 326 | { 327 | var t = test({ 328 | var arr = [1,2,3,4,5,6,7].list(), lastValue = -1; 329 | for (a in arr) 330 | { 331 | var myval = a + lastValue; 332 | @yield myval; 333 | lastValue = a; 334 | } 335 | }); 336 | for (i in [0, 3, 5, 7, 9, 11, 13]) 337 | { 338 | Assert.isTrue(t.hasNext()); 339 | Assert.equals(i, t.next()); 340 | } 341 | var t = test({ 342 | var arr = [1,2,3,4,5,6,7].list(), lastValue = -1; 343 | for (a in arr.iterator()) 344 | { 345 | var myval = a + lastValue; 346 | lastValue = a; 347 | @yield myval; 348 | } 349 | }); 350 | for (i in [0, 3, 5, 7, 9, 11, 13]) 351 | { 352 | Assert.isTrue(t.hasNext()); 353 | Assert.equals(i, t.next()); 354 | } 355 | 356 | } 357 | 358 | public function test_while() 359 | { 360 | for (rand in [true,false]) 361 | { 362 | var t = true, f = false; 363 | var t = test({ 364 | var i = 10, a = [1.]; 365 | while(++i < 15) 366 | { 367 | a.push(i / 10); 368 | if(t) 369 | { 370 | a.push(2); 371 | if (true) 372 | { 373 | @yield {retn:1, arr:a}; 374 | if(rand) 375 | a.push(2.05); 376 | } 377 | if (f) 378 | { 379 | a.push(-2); 380 | @yield {retn:-1,arr:a}; 381 | a.push(-3); 382 | if (f) 383 | { 384 | a.push(-4); 385 | @yield null; 386 | a.push(-5); 387 | } else if (false) { 388 | a.push(-6); 389 | for(i in 0...10) 390 | @yield null; 391 | if (true) 392 | { 393 | a.push(-6.1); 394 | do 395 | { 396 | @yield null; 397 | } while(--i > 0); 398 | a.push(-6.2); 399 | } 400 | a.push(-7); 401 | @yield null; 402 | a.push(-8); 403 | } else { 404 | a.push(-9); 405 | @yield null; 406 | a.push(-10); 407 | } 408 | } else { 409 | if (t) 410 | { 411 | a.push(2.10); 412 | @yield {retn:2, arr:a}; 413 | if (rand) 414 | a.push(2.15); 415 | } else { 416 | a.push(-11); 417 | @yield null; 418 | a.push(-12); 419 | } 420 | a.push(2.2); 421 | @yield {retn:3, arr:a}; 422 | var j = 3; 423 | do 424 | { 425 | a.push(2 + j / 10); 426 | @yield {retn:j+1, arr:a}; 427 | if (rand) 428 | a.push(2 + j / 10 + .05); 429 | } while(++j < 6); 430 | a.push(2.6); 431 | } 432 | a = []; 433 | if(t) 434 | { 435 | a.push(3); 436 | @yield {retn:7, arr:a}; 437 | var j = 0; 438 | while(++j < 3) 439 | { 440 | a.push(3 + j / 10); 441 | @yield {retn:7 + j, arr:a}; 442 | } 443 | } else if (f) { 444 | a.push(-4); 445 | @yield null; 446 | a.push(-5); 447 | } else { 448 | a.push(-6); 449 | @yield null; 450 | if (true) 451 | { 452 | a.push(-7); 453 | @yield null; 454 | a.push(-8); 455 | } 456 | a.push(-9); 457 | @yield null; 458 | a.push(-10); 459 | } 460 | a = []; 461 | a.push(4); 462 | var j = 0; 463 | do 464 | { 465 | @yield {retn:10 + j, arr:a}; 466 | a.push(4 + j / 10); 467 | if (rand) 468 | a.push(4 + j / 10 + .05); 469 | } while(++j < 4); 470 | } 471 | @yield {retn:14, arr:a}; 472 | a.push(5); 473 | } 474 | }); 475 | 476 | // var answers = 477 | var i = 10, 478 | a = [1.]; 479 | inline function getValue() return t.hasNext() ? t.next() : null; 480 | 481 | for (i in 11...15) 482 | { 483 | a.push(i / 10); 484 | a.push(2); 485 | Assert.same({ retn:1, arr: a }, getValue()); 486 | if (rand) a.push(2.05); 487 | a.push(2.10); 488 | Assert.same({ retn:2, arr: a }, getValue()); 489 | if (rand) a.push(2.15); 490 | a.push(2.2); 491 | Assert.same({ retn:3, arr : a}, getValue()); 492 | a.push(2.3); 493 | Assert.same({ retn:4, arr : a}, getValue()); 494 | if (rand) a.push(2.35); 495 | a.push(2.4); 496 | Assert.same({ retn:5, arr : a}, getValue()); 497 | if (rand) a.push(2.45); 498 | a.push(2.5); 499 | Assert.same({ retn:6, arr : a}, getValue()); 500 | a.push(2.6); 501 | a = [3]; 502 | Assert.same({ retn:7, arr : a}, getValue()); 503 | a.push(3.1); 504 | Assert.same({ retn:8, arr : a}, getValue()); 505 | a.push(3.2); 506 | Assert.same({ retn:9, arr : a}, getValue()); 507 | a = [4]; 508 | Assert.same({ retn:10, arr : a}, getValue()); 509 | for (i in 0...4) 510 | { 511 | a.push(4 + i / 10); 512 | if (rand) a.push(4 + i / 10 + .05); 513 | Assert.same({ retn:11 + i, arr : a}, getValue()); 514 | } 515 | a.push(5); 516 | // Assert.same({ retn: 12, arr : a}, getValue()); 517 | } 518 | // for (v in t) 519 | // trace(v); 520 | } 521 | } 522 | 523 | public function test_pat_match() 524 | { 525 | var expr = macro 10 + 20 + 60 - 10; 526 | var t = test({ 527 | var acc = 0; 528 | while(true) 529 | { 530 | switch(expr.expr) 531 | { 532 | case EBinop(op,{ expr:EConst(CInt(x)) },{ expr:EConst(CInt(y)) }): 533 | acc += Std.parseInt(x); 534 | acc += Std.parseInt(y); 535 | @yield { op:op + "", acc:acc, v:2 }; 536 | break; 537 | case EBinop(op,e1,{ expr:EConst(CInt(x)) }): 538 | acc += Std.parseInt(x); 539 | @yield { op:op + "", acc:acc, v:1 }; 540 | expr = e1; 541 | case _: 542 | throw "argh: " + expr; 543 | } 544 | } 545 | }); 546 | inline function getValue() return t.hasNext() ? t.next() : null; 547 | 548 | Assert.same({ op:"OpSub", acc:10, v:1 }, getValue()); 549 | Assert.same({ op:"OpAdd", acc:70, v:1 }, getValue()); 550 | Assert.same({ op:"OpAdd", acc:100, v:2 }, getValue()); 551 | Assert.isFalse(t.hasNext()); 552 | 553 | expr = macro @:someMeta 50 + 5 - 10 + 20 + 60 - 10; 554 | t = test({ 555 | var acc = 0; 556 | while(true) 557 | { 558 | switch(expr.expr) 559 | { 560 | case EBinop(op,{ expr:EConst(CInt(x)) },{ expr:EConst(CInt(y)) }): 561 | acc += Std.parseInt(x); 562 | acc += Std.parseInt(y); 563 | @yield { op:op + "", acc:acc, v:2 }; 564 | break; 565 | case EBinop(op,e1 = { expr:EBinop(_,_,_) },{ expr:EConst(CInt(x)) }): 566 | acc += Std.parseInt(x); 567 | @yield { op:op + "", acc:acc, v:1 }; 568 | expr = e1; 569 | case EBinop(op,e1,e2): 570 | acc += 5; 571 | @yield { op:"no const", acc:acc, v:0 }; 572 | switch(e1) 573 | { 574 | case macro notHere: 575 | acc -= 10; 576 | case macro @:someMeta $v: 577 | switch(v.expr) { 578 | case EConst(CInt(x)): 579 | @yield { acc:acc, v:3 }; 580 | acc += Std.parseInt(x); 581 | @yield { acc:acc, v:4 }; 582 | case _: 583 | acc -= 100; 584 | @yield acc; 585 | acc -= 90; 586 | @yield acc; 587 | } 588 | case _: 589 | acc = 4; 590 | @yield false; 591 | trace(acc); 592 | @yield acc; 593 | acc -= 10; 594 | } 595 | acc += 5; 596 | @yield { op:"finished", acc:acc, v:5 }; 597 | switch (e2) { 598 | case { expr: EConst(CInt(x)) }: 599 | @yield { acc:acc, v:6 }; 600 | acc += Std.parseInt(x); 601 | @yield { acc:acc, v:7 }; 602 | acc = Std.parseInt(x); 603 | case _: 604 | acc = 0; 605 | @yield false; 606 | trace(acc); 607 | @yield acc; 608 | acc -= 10; 609 | } 610 | @yield { op:op + "", acc:acc, v:8 }; 611 | break; 612 | @yield { op:op + "", acc:acc, v:9 }; 613 | case _: 614 | throw "shouldnt be here: " + expr; 615 | } 616 | } 617 | }); 618 | inline function getValue() return t.hasNext() ? t.next() : null; 619 | 620 | Assert.same({ op:"OpSub", acc:10, v:1 }, getValue()); 621 | Assert.same({ op:"OpAdd", acc:70, v:1 }, getValue()); 622 | Assert.same({ op:"OpAdd", acc:90, v:1 }, getValue()); 623 | Assert.same({ op:"OpSub", acc:100, v:1 }, getValue()); 624 | Assert.same({ op:"no const", acc:105, v:0 }, getValue()); 625 | Assert.same({ acc:105, v:3 }, getValue()); 626 | Assert.same({ acc:155, v:4 }, getValue()); 627 | Assert.same({ op:"finished", acc:160, v:5 }, getValue()); 628 | Assert.same({ acc:160, v:6 }, getValue()); 629 | Assert.same({ acc:165, v:7 }, getValue()); 630 | Assert.same({ op:"OpAdd", acc:5, v:8 }, getValue()); 631 | Assert.isFalse(t.hasNext()); 632 | } 633 | 634 | public function test_try() 635 | { 636 | var throwobj:Dynamic = null, 637 | i = 0; 638 | function mayThrow() 639 | { 640 | if (throwobj != null) 641 | { 642 | var t = throwobj; 643 | throwobj = null; 644 | throw t; 645 | } 646 | return i++; 647 | } 648 | 649 | var t = test({ 650 | while(true) 651 | { 652 | var acc = 100; 653 | try 654 | { 655 | acc+= 10; 656 | @yield { v:0, retn:"A", acc:acc }; 657 | try 658 | { 659 | acc += 2; 660 | if (mayThrow() == 0) 661 | { 662 | acc -= 4; 663 | @yield { v:mayThrow(), retn:"B", acc:acc }; 664 | acc += 6; 665 | @yield { v:mayThrow(), retn:"-", acc:acc }; 666 | acc -= 100; 667 | } else { 668 | acc += 300; 669 | @yield { v:mayThrow(), retn:"AB", acc:acc }; 670 | @yield { v:mayThrow(), retn:"-", acc:acc }; 671 | acc -= 500; 672 | } 673 | } 674 | catch(e:String) 675 | { 676 | @yield { v:mayThrow(), retn:"String " + e, acc:++acc }; 677 | acc = 5; 678 | @yield { v:mayThrow(), retn:"String", acc:++acc }; 679 | acc += 4; 680 | try 681 | { 682 | @yield { v:mayThrow(), retn:"String", acc:++acc }; 683 | acc += 15; 684 | @yield { v:mayThrow(), retn:"StringT2", acc:acc }; 685 | acc += 5; 686 | @yield { v:mayThrow(), retn:"-", acc:acc }; 687 | } 688 | catch(e:Dynamic) 689 | { 690 | @yield true; 691 | try 692 | { 693 | @yield { v:mayThrow(), retn:"StringT3", acc:acc }; 694 | acc += 20; 695 | @yield { v:mayThrow(), retn:"-", acc:acc }; 696 | } 697 | catch(str:String) 698 | { 699 | @yield { v:mayThrow(), retn:"-", acc:acc }; 700 | } 701 | } 702 | } 703 | catch(e:haxe.io.Eof) 704 | { 705 | @yield { v:mayThrow(), retn:"-", acc:acc }; 706 | } 707 | } 708 | catch(e:haxe.io.Eof) 709 | { 710 | @yield { v:mayThrow(), retn:"eof", acc:acc }; 711 | } 712 | } 713 | }); 714 | 715 | inline function getValue() return t.hasNext() ? t.next() : null; 716 | Assert.same({ v:0, retn:"A", acc:110 }, getValue()); 717 | Assert.same({ v:1, retn:"B", acc:108 }, getValue()); 718 | 719 | throwobj = "SomeString"; 720 | Assert.same({ v:2, retn:"String SomeString", acc:115 }, getValue()); 721 | Assert.same({ v:3, retn:"String", acc:6 }, getValue()); 722 | Assert.same({ v:4, retn:"String", acc:11 }, getValue()); 723 | Assert.same({ v:5, retn:"StringT2", acc:26 }, getValue()); 724 | 725 | throwobj = new haxe.io.Eof(); 726 | Assert.equals(true,getValue()); 727 | Assert.same({ v:6, retn:"StringT3", acc:31 }, getValue()); 728 | throwobj = new haxe.io.Eof(); 729 | Assert.same({ v:7, retn:"eof", acc:51 }, getValue()); 730 | 731 | Assert.same({ v:0, retn:"A", acc:110 }, getValue()); 732 | Assert.same({ v:9, retn:"AB", acc:412 }, getValue()); 733 | throwobj = "OtherString"; 734 | Assert.same({ v:10, retn:"String OtherString", acc:413 }, getValue()); 735 | throwobj = "AnotherString"; 736 | var hadExc = false; 737 | try { 738 | getValue(); 739 | } catch(e:String) { 740 | hadExc = true; 741 | Assert.equals("AnotherString",e); 742 | } 743 | Assert.isTrue(hadExc); 744 | Assert.isFalse(t.hasNext()); 745 | } 746 | 747 | //test private access 748 | //test 'this' 749 | private function test_pvt_access() 750 | { 751 | var t = test({ 752 | //this value get 753 | var theValue = someTest; 754 | @yield { v:1, val:theValue }; 755 | Assert.equals('someTest', theValue); 756 | //this function call 757 | @yield { v:2, val:pvtFunc() }; 758 | @yield { v:3, val:theValue != someTest }; 759 | @yield { v:4, val:someTest }; 760 | }); 761 | 762 | inline function getValue() return t.hasNext() ? t.next() : null; 763 | Assert.same({ v:1, val:'someTest'}, getValue()); 764 | Assert.same({ v:2, val:true}, getValue()); 765 | Assert.same({ v:3, val:true}, getValue()); 766 | Assert.same({ v:4, val:'didCall'}, getValue()); 767 | Assert.isFalse(t.hasNext()); 768 | } 769 | 770 | private function pvtFunc() 771 | { 772 | this.someTest = "didCall"; 773 | return true; 774 | } 775 | 776 | 777 | //test type parameter 778 | private function localTypeParam(v:T, y:T) 779 | { 780 | return test({ 781 | @yield v; 782 | @yield y; 783 | @yield v == y; 784 | }); 785 | } 786 | 787 | public function test_tparam() 788 | { 789 | inline function getVal(t:Iterator) return t.hasNext() ? t.next() : null; 790 | var t1 = localTypeParam(10,20); 791 | Assert.equals(10,getVal(t1)); 792 | Assert.equals(20,getVal(t1)); 793 | Assert.equals(false,getVal(t1)); 794 | Assert.isFalse(t1.hasNext()); 795 | 796 | t1 = localTypeParam('a','a'); 797 | Assert.equals('a',getVal(t1)); 798 | Assert.equals('a',getVal(t1)); 799 | Assert.equals(true,getVal(t1)); 800 | Assert.isFalse(t1.hasNext()); 801 | 802 | function fnTypeParam(a:Array) 803 | { 804 | return test({ 805 | var last = null; 806 | for (v in a) 807 | { 808 | @yield v; 809 | @yield v == last; 810 | last = v; 811 | } 812 | }); 813 | } 814 | t1 = fnTypeParam([1,2,1,1]); 815 | Assert.equals(1,getVal(t1)); 816 | Assert.equals(false,getVal(t1)); 817 | Assert.equals(2,getVal(t1)); 818 | Assert.equals(false,getVal(t1)); 819 | Assert.equals(1,getVal(t1)); 820 | Assert.equals(false,getVal(t1)); 821 | Assert.equals(1,getVal(t1)); 822 | Assert.equals(true,getVal(t1)); 823 | Assert.isFalse(t1.hasNext()); 824 | } 825 | 826 | //better naming for defined classes 827 | public function test_naming() 828 | { 829 | var x = test({ 830 | @yield 1; 831 | @yield 2; 832 | @yield 3; 833 | }); 834 | 835 | Assert.isTrue(Type.getClassName(Type.getClass(x)).indexOf('test_naming') >= 0); 836 | } 837 | 838 | //TODO test v_captured fail - v_captured is only added later; see how to implement 839 | // public function test_captured() 840 | // { 841 | // var x = 10; 842 | // function testC() 843 | // { 844 | // return fails(test({ 845 | // @yield x; 846 | // x = 20; 847 | // @yield x; 848 | // })); 849 | // } 850 | // Assert.isTrue(testC()); 851 | // } 852 | #end 853 | } 854 | -------------------------------------------------------------------------------- /unihx/_internal/Compiler.hx: -------------------------------------------------------------------------------- 1 | package unihx._internal; 2 | import haxe.macro.*; 3 | import sys.FileSystem.*; 4 | using StringTools; 5 | 6 | class Compiler 7 | { 8 | public static function compile():Void 9 | { 10 | var cwd = normalize(Sys.getCwd()); 11 | var asm = '../Library/ScriptAssemblies'; 12 | if (exists(asm)) 13 | { 14 | for (file in readDirectory(asm)) 15 | { 16 | if (file.endsWith('.dll')) 17 | haxe.macro.Compiler.addNativeLib('$asm/$file'); 18 | } 19 | } 20 | // var files = []; 21 | var paths = [ for (p in Context.getClassPath()) if (normalize(p) != null) normalize(p) ]; 22 | for (i in 0...paths.length) 23 | { 24 | var cp = paths[i]; 25 | if (cp.startsWith(cwd)) 26 | { 27 | collect(paths,i); 28 | } 29 | } 30 | haxe.macro.Compiler.include('unihx._internal.editor'); 31 | } 32 | 33 | private static function normalize(path:String) 34 | { 35 | if (path == "") 36 | path = "."; 37 | if (!exists(path)) 38 | return null; 39 | try 40 | { 41 | var ret = fullPath(haxe.io.Path.removeTrailingSlashes(path)); 42 | switch (Sys.systemName()) 43 | { 44 | case "Windows" | "Mac": 45 | ret = ret.toLowerCase(); 46 | case _: 47 | } 48 | return ret; 49 | } 50 | catch(e:Dynamic) 51 | { 52 | return null; 53 | } 54 | } 55 | 56 | private static function collect(cps:Array, index:Int, ?pack) 57 | { 58 | var cp = cps[index]; 59 | var slash = "/", 60 | dot = '.'; 61 | if (pack == null) 62 | { 63 | slash = ""; 64 | pack = []; 65 | dot = ''; 66 | } 67 | var path = cp + slash + pack.join('/'); 68 | for (file in readDirectory(path)) 69 | { 70 | var path = path + "/" + file; 71 | if (isDirectory(path)) 72 | { 73 | var p = normalize(path), 74 | found = false; 75 | for (j in 0...cps.length) 76 | { 77 | if (j != index && cps[j] == p) 78 | { 79 | found = true; 80 | break; 81 | } 82 | } 83 | if (!found) 84 | { 85 | pack.push(file); 86 | collect(cps,index,pack); 87 | pack.pop(); 88 | } 89 | } else if (file.endsWith('.hx')) { 90 | Context.getModule(pack.join('.') + dot + file.substr(0,-3)); 91 | } 92 | } 93 | } 94 | 95 | private static function getStdDir() 96 | { 97 | for (cp in Context.getClassPath()) 98 | { 99 | var cp = haxe.io.Path.removeTrailingSlashes(cp); 100 | if (exists(cp) && !cp.endsWith('_std') && cp.endsWith('std')) 101 | { 102 | return cp; 103 | } 104 | } 105 | return null; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /unihx/_internal/PrivateAccessMacro.hx: -------------------------------------------------------------------------------- 1 | package unihx._internal; 2 | import haxe.macro.Expr; 3 | import haxe.macro.Context.*; 4 | import haxe.macro.Context; 5 | import haxe.macro.Type; 6 | 7 | using haxe.macro.ExprTools; 8 | using haxe.macro.TypeTools; 9 | using haxe.macro.TypedExprTools; 10 | using Lambda; 11 | using StringTools; 12 | 13 | class PrivateAccessMacro 14 | { 15 | #if macro 16 | public static function build():Type 17 | { 18 | switch (Context.getLocalType()) { 19 | case TInst(_, params): 20 | var module = getConst(params.shift(),1), 21 | typeName = getConst(params.shift(),2); 22 | 23 | var mod = getModule(module); 24 | for (m in mod) { 25 | switch(m) { 26 | case TInst(c,_): 27 | if (c.get().name == typeName) 28 | return TInst(c,params); 29 | case TEnum(c,_): 30 | if (c.get().name == typeName) 31 | return TEnum(c,params); 32 | case TType(c,_): 33 | if (c.get().name == typeName) 34 | return TType(c,params); 35 | case TAbstract(c,_): 36 | if (c.get().name == typeName) 37 | return TAbstract(c,params); 38 | case _: 39 | } 40 | } 41 | throw new Error('Private type "${typeName}" cannot be found on "$module"',currentPos()); 42 | case _: 43 | throw "assert"; 44 | } 45 | } 46 | 47 | private static function getConst(t:Type, n:Int):String 48 | { 49 | switch (t) { 50 | case TInst(x,_): 51 | var name = x.get().name; 52 | if (!name.startsWith('S')) 53 | throw new Error('PrivateTypeAccess must have the parameter number $n as a String', currentPos()); 54 | return name.substr(1); 55 | case _: 56 | throw new Error('PrivateTypeAccess must have the parameter number $n as a String', currentPos()); 57 | } 58 | } 59 | #end 60 | } 61 | -------------------------------------------------------------------------------- /unihx/_internal/PrivateTypeAccess.hx: -------------------------------------------------------------------------------- 1 | package unihx._internal; 2 | 3 | @:genericBuild(unihx._internal.PrivateAccessMacro.build()) 4 | class PrivateTypeAccess {} 5 | -------------------------------------------------------------------------------- /unihx/_internal/StructHelper.hx: -------------------------------------------------------------------------------- 1 | package unihx._internal; 2 | import haxe.macro.Expr; 3 | 4 | class StructHelper 5 | { 6 | public static function with(fields:Array, clsName:ComplexType, ethis:Expr, expr:Expr):Expr 7 | { 8 | switch (expr.expr) 9 | { 10 | case EObjectDecl(declFieldsArr): 11 | var declFields = new Map(); 12 | { 13 | for (f in declFieldsArr) 14 | { 15 | if (declFields.exists(f.field)) 16 | throw new Error('Duplicate field definition: ${f.field}', f.expr.pos); 17 | else if (fields.indexOf(f.field) == -1) 18 | throw new Error('Extra field constructor: ${f.field}', f.expr.pos); 19 | declFields[f.field] = f.expr; 20 | } 21 | } 22 | var ctorArgs = fields.map(function(f) { 23 | if (declFields.exists(f)) 24 | { 25 | return declFields[f]; 26 | } else { 27 | return macro @:pos(expr.pos) $ethis.$f; 28 | } 29 | }); 30 | var type = switch (clsName) 31 | { 32 | case TPath(p): 33 | p; 34 | case _: 35 | throw 'assert'; 36 | } 37 | 38 | return { expr:ENew(type, ctorArgs), pos:expr.pos }; 39 | case _: 40 | throw new Error("The `with' macro expects an anonymous object declaration as its argument", expr.pos); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /unihx/_internal/Yield.hx: -------------------------------------------------------------------------------- 1 | package unihx._internal; 2 | 3 | class Yield 4 | { 5 | macro public static function getIterator(e:haxe.macro.Expr):haxe.macro.Expr 6 | { 7 | return YieldGenerator.getIterator(e); 8 | } 9 | 10 | // only typing helper 11 | private static function __yield__(t:T):T 12 | { 13 | return t; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /unihx/_internal/YieldBase.hx: -------------------------------------------------------------------------------- 1 | package unihx._internal; 2 | 3 | class YieldBase #if !macro implements cs.system.collections.IEnumerator #end 4 | { 5 | @:property public var Current(get,never):Dynamic; 6 | private var eip:Int = 0; 7 | private var value:Dynamic; 8 | private var exc:Dynamic; 9 | 10 | public function MoveNext():Bool 11 | { 12 | return false; 13 | } 14 | 15 | inline public function get_Current():Dynamic 16 | { 17 | return value; 18 | } 19 | 20 | inline public function hasNext():Bool 21 | { 22 | return MoveNext(); 23 | } 24 | 25 | inline public function next():Dynamic 26 | { 27 | return value; 28 | } 29 | 30 | /** 31 | This function will be called internally by the handler to see if an exception 32 | can be handled. It will work like a MoveNext() call. 33 | 34 | If the handler returns false, the enumerator will be in a 'errored' state and will not return any more values 35 | **/ 36 | public function handleError(exc:Dynamic):Bool 37 | { 38 | this.eip = -1; //error state 39 | return false; 40 | } 41 | 42 | public function Reset():Void 43 | { 44 | this.eip = 0; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /unihx/_internal/YieldGenerator.hx: -------------------------------------------------------------------------------- 1 | package unihx._internal; 2 | import haxe.macro.Expr; 3 | import haxe.macro.Context.*; 4 | import haxe.macro.Context; 5 | import haxe.macro.Type; 6 | 7 | using haxe.macro.ExprTools; 8 | using haxe.macro.TypeTools; 9 | using haxe.macro.TypedExprTools; 10 | using haxe.macro.ComplexTypeTools; 11 | using Lambda; 12 | using StringTools; 13 | 14 | class YieldGenerator 15 | { 16 | static var packs = new Map(); 17 | var expr:TypedExpr; 18 | var usedVars:Map>; 19 | 20 | // control flow graph 21 | var id = -1; 22 | var cfgs:Array; 23 | var current:FlowGraph; 24 | 25 | var tbool:Type; 26 | var tint:Type; 27 | var tdynamic:Type; 28 | 29 | var goto:TypedExpr; 30 | var gotoEnd:TypedExpr; 31 | var exc:TypedExpr; 32 | var pos:Position; 33 | 34 | var pack:String; 35 | var condGraph:Null; 36 | 37 | var onBreak:TypedExpr; 38 | var onContinue:TypedExpr; 39 | var catchStack:Array>; 40 | var bakedCatchStack:Array<{ t:Type, gotoHandler:TypedExpr }>; 41 | 42 | var rethrow:Expr; 43 | 44 | var thisUsed:Bool = false; 45 | var infos:haxe.PosInfos; 46 | 47 | public function new(pack:String, e:Expr) 48 | { 49 | var expr = typeExpr(macro { var __yield__:Dynamic = null; ${prepare(e)}; }); 50 | switch(expr.expr) 51 | { 52 | case TBlock(bl): 53 | this.expr = bl[1]; 54 | default: throw "assert"; 55 | } 56 | 57 | this.catchStack = []; 58 | this.usedVars = new Map(); 59 | this.cfgs = []; 60 | newFlow(); 61 | this.current = cfgs[0]; 62 | 63 | this.tbool = getType("Bool"); 64 | this.tint = getType("Int"); 65 | this.tdynamic = getType("Dynamic"); 66 | 67 | this.goto = typeExpr( macro untyped __goto__ ); 68 | this.gotoEnd = typeExpr( macro untyped __goto_end__ ); 69 | this.exc = typeExpr( macro untyped __exc__ ); 70 | this.pos = currentPos(); 71 | 72 | this.pack = pack; 73 | this.rethrow = if (defined('cs')) 74 | macro cs.Lib.rethrow(exc); 75 | else if (defined('neko')) 76 | macro neko.Lib.rethrow(exc); 77 | else if (defined('cpp')) 78 | macro cpp.Lib.rethrow(exc); 79 | else if (defined('php')) 80 | macro php.Lib.rethrow(exc); 81 | else 82 | macro throw exc; 83 | 84 | this.infos = getHere(e.pos); 85 | // trace(infos); 86 | } 87 | 88 | static function extractYield(e:Expr):Null 89 | { 90 | var hasYield = false; 91 | function map(e:Expr) 92 | { 93 | return switch(e.expr) { 94 | case EBinop(op,e1,e2): 95 | { expr:EBinop(op, map(e1), e2), pos:e.pos }; 96 | case EUnop(op,post,e1): 97 | { expr:EUnop(op,post,map(e1)), pos:e.pos }; 98 | case EMeta({ name:'yield' }, e): 99 | hasYield = true; 100 | e; 101 | case _: 102 | e; 103 | } 104 | } 105 | var ret = map(e); 106 | if (hasYield) 107 | return ret; 108 | else 109 | return null; 110 | } 111 | 112 | static function prepare(e:Expr):Expr 113 | { 114 | return switch(e) { 115 | case macro __yield__: 116 | throw new Error("Reserved variable name: __yield__", e.pos); 117 | case macro @yield $something: 118 | return macro __yield__(${prepare(something)}); 119 | case { expr:EBinop(op,e1,e2) }: 120 | var ret = extractYield(e); 121 | if (ret == null) 122 | e.map(prepare); 123 | else 124 | macro __yield__(${prepare( prepare(ret) )}); 125 | case _: 126 | return e.map(prepare); 127 | } 128 | } 129 | 130 | public static function make(pack,e:Expr):Expr 131 | { 132 | return new YieldGenerator(pack,e).change(); 133 | } 134 | 135 | public static function getIterator(e:Expr):Expr 136 | { 137 | var t = typeof(e); 138 | switch (t.follow()) 139 | { 140 | case TAnonymous(a): 141 | if (a.get().fields.exists(function(cf) return cf.name == "hasNext" || cf.name == "next")) 142 | return e; 143 | else 144 | return macro $e.iterator(); 145 | case TInst(t,_): 146 | if (t.get().findField('iterator') != null) 147 | return macro $e.iterator(); 148 | else 149 | return e; 150 | case _: 151 | throw new Error('This expression has type $t, but an Iterable or Iterator was expected', e.pos); 152 | } 153 | } 154 | 155 | private function bakeCatches() 156 | { 157 | var i = catchStack.length, 158 | stack = catchStack; 159 | var baked = this.bakedCatchStack = []; 160 | while (i --> 0) 161 | { 162 | var cur = stack[i]; 163 | for (cur in cur) 164 | { 165 | var t = cur.t; 166 | var add = true; 167 | for (v in baked) 168 | { 169 | if (t.unify(v.t)) 170 | { 171 | add = false; 172 | break; 173 | } 174 | } 175 | if (add) 176 | baked.push(cur); 177 | } 178 | } 179 | } 180 | 181 | inline function newFlow() 182 | { 183 | var ret = { block:[], tryctx:bakedCatchStack, id: ++id, next: null }; 184 | cfgs.push(ret); 185 | current = ret; 186 | } 187 | 188 | inline function setUsed(id:Int) 189 | { 190 | var ret =usedVars[id]; 191 | if (ret == null) 192 | { 193 | usedVars[id] = ret = new Map(); 194 | } 195 | ret[current] = current; 196 | } 197 | 198 | function ensureNoYield(e:TypedExpr) 199 | { 200 | switch (e.expr) 201 | { 202 | case TCall( { expr:TLocal({ name:"__yield__" }) }, [e]): 203 | throw new Error('@yield cannot be used here', e.pos); 204 | case TLocal(v) | TVar(v,_): 205 | setUsed(v.id); 206 | e.iter(ensureNoYield); 207 | case TReturn(_): 208 | throw new Error("Cannot return inside a 'yield' context", e.pos); 209 | case _: 210 | e.iter(ensureNoYield); 211 | } 212 | } 213 | 214 | function hasYield(e:TypedExpr) 215 | { 216 | var has = false; 217 | function iter(e:TypedExpr) 218 | { 219 | switch (e.expr) 220 | { 221 | case TCall( { expr:TLocal({ name:"__yield__" }) }, [e]): 222 | has = true; 223 | case _: 224 | if (!has) e.iter(iter); 225 | } 226 | } 227 | iter(e); 228 | return has; 229 | } 230 | 231 | inline function mkGetExc(t:Type):TypedExpr 232 | { 233 | return { expr:TCast(exc, null), t:t, pos:pos }; 234 | } 235 | 236 | function mkGoto(id:Int,final:Bool):TypedExpr 237 | { 238 | return { expr: TCall(goto, [{ expr:TConst(TInt(id)), t:tint, pos:pos }, { expr:TConst(TBool(final)), t:tbool, pos:pos }]), t:tdynamic, pos:pos }; 239 | } 240 | 241 | function mkGotoEnd(id:Int,final:Bool):TypedExpr 242 | { 243 | return { expr: TCall(gotoEnd, [{ expr:TConst(TInt(id)), t:tint, pos:pos }, { expr:TConst(TBool(final)), t:tbool, pos:pos }]), t:tdynamic, pos:pos }; 244 | } 245 | 246 | function mkNothing():TypedExpr 247 | { 248 | return { expr: TBlock([]), t:tdynamic, pos:pos }; 249 | } 250 | 251 | static function replace(from:TypedExpr, to:TypedExpr):Void 252 | { 253 | from.expr = to.expr; 254 | from.t = to.t; 255 | from.pos = to.pos; 256 | } 257 | 258 | function iter(e:TypedExpr) 259 | { 260 | switch(e.expr) 261 | { 262 | case TVar(v,_) | TLocal(v): 263 | setUsed(v.id); 264 | current.block.push(e); 265 | case TFunction(f): 266 | ensureNoYield(e); 267 | current.block.push(e); 268 | case TBlock(el): 269 | for (e in el) 270 | iter(e); 271 | case TIf(econd,eif,eelse): 272 | ensureNoYield(econd); 273 | var yieldIf = hasYield(eif), 274 | yieldElse = eelse != null && hasYield(eelse); 275 | if (yieldIf || yieldElse) 276 | { 277 | // invert if and else - if necessary 278 | if (yieldIf && !yieldElse && eelse != null) 279 | { 280 | econd = mk_not(econd); 281 | var tmp = eelse; 282 | eelse = eif; 283 | eif = tmp; 284 | 285 | yieldIf = false; 286 | yieldElse = true; 287 | } 288 | // if (!cond) goto else; 289 | var gotoElse = mkNothing(); 290 | current.block.push({ expr: TIf(mk_not(econd),gotoElse,null), t: tdynamic, pos: econd.pos }); 291 | 292 | // otherwise continue on eif 293 | iter(eif); 294 | var endIfBlock = current; 295 | // starting else 296 | newFlow(); 297 | replace(gotoElse, mkGoto(current.id, true)); 298 | 299 | // make else block 300 | if (eelse != null) 301 | { 302 | iter(eelse); 303 | } 304 | newFlow(); 305 | 306 | endIfBlock.next = current.id; 307 | } else { 308 | ensureNoYield(eif); 309 | if (eelse != null) 310 | ensureNoYield(eelse); 311 | current.block.push(e); 312 | } 313 | 314 | case TWhile(econd, block, normalWhile) if(hasYield(block)): 315 | ensureNoYield(econd); 316 | 317 | var prelude = null; 318 | if (!normalWhile) 319 | { 320 | newFlow(); 321 | prelude = current; 322 | } 323 | newFlow(); 324 | var lastOnBreak = onBreak, 325 | lastOnContinue = onContinue; 326 | onBreak = mkNothing(); 327 | onContinue = mkNothing(); 328 | 329 | // while condition 330 | var condCfg = current; 331 | var changedCond = { expr: TIf( mk_not(econd), onBreak, null ), t: tdynamic, pos:econd.pos }; 332 | iter(changedCond); 333 | 334 | //body 335 | newFlow(); 336 | var bodyCfg = current; 337 | if (prelude != null) 338 | prelude.next = bodyCfg.id; 339 | iter(block); 340 | current.next = condCfg.id; 341 | newFlow(); 342 | 343 | //returning last loop 344 | replace(onBreak,mkGoto(current.id,true)); 345 | replace(onContinue,mkGoto(condCfg.id,true)); 346 | this.onBreak = lastOnBreak; 347 | this.onContinue = lastOnContinue; 348 | 349 | case TBreak: 350 | if (this.onBreak == null) throw new Error("Break outside loop",e.pos); 351 | current.block.push(onBreak); 352 | case TContinue: 353 | if (this.onContinue == null) throw new Error("Continue outside loop",e.pos); 354 | current.block.push(onContinue); 355 | 356 | case TSwitch(econd,ecases,edef): 357 | var cur = current, 358 | curBlock = cur.block, 359 | curNext = cur.next; 360 | ensureNoYield(econd); 361 | var currents = [cur]; 362 | for (c in ecases) 363 | { 364 | current = cur; 365 | var bl = cur.block = []; 366 | cur.next = id + 1; 367 | for (v in c.values) ensureNoYield(v); 368 | iter(c.expr); 369 | c.expr = mk_block(bl); 370 | currents.push(current); 371 | } 372 | if (edef != null) 373 | { 374 | current = cur; 375 | var defs = cur.block = []; 376 | cur.next = id + 1; 377 | iter(edef); 378 | edef = mk_block(defs); 379 | currents.push(current); 380 | } 381 | current = cfgs[cfgs.length-1]; 382 | 383 | cur.next = curNext; 384 | cur.block = curBlock; 385 | curBlock.push({ expr:TSwitch(econd, ecases, edef), t:e.t, pos:e.pos }); 386 | if (cur != current) 387 | { 388 | newFlow(); 389 | for (c in currents) 390 | c.next = current.id; 391 | } 392 | case TTry(etry, ecatches): 393 | var cur = current, 394 | curNext = cur.next, 395 | curBlock = cur.block; 396 | var currents = []; 397 | 398 | if (hasYield(etry)) 399 | { 400 | var handlers = [ for (c in ecatches) { t:c.v.t, gotoHandler: mkNothing() } ]; 401 | this.catchStack.push(handlers); 402 | var old = this.bakedCatchStack; 403 | bakeCatches(); 404 | newFlow(); //we need a new flow since we'll change the handlers mask 405 | 406 | iter(etry); 407 | currents.push(current); 408 | this.catchStack.pop(); 409 | this.bakedCatchStack = old; 410 | for (i in 0...ecatches.length) 411 | { 412 | var c = ecatches[i], 413 | handler = handlers[i]; 414 | newFlow(); 415 | replace(handler.gotoHandler, mkGoto(current.id, true)); 416 | iter({ expr: TVar(c.v, mkGetExc(c.v.t)), t:tdynamic, pos:c.expr.pos }); 417 | iter(c.expr); 418 | currents.push(current); 419 | } 420 | } else { 421 | var tryblock = cur.block = []; 422 | iter(etry); 423 | var newc = []; 424 | for (c in ecatches) 425 | { 426 | current = cur; 427 | cur.next = id + 1; 428 | var bl = cur.block = []; 429 | var newVar = alloc_var(c.v.name, c.v.t); 430 | iter({ expr: TVar(c.v, { expr: TLocal(newVar), t:newVar.t, pos:c.expr.pos }), t:tdynamic, pos:c.expr.pos }); 431 | iter(c.expr); 432 | newc.push({ v: newVar, expr:mk_block(bl) }); 433 | currents.push(current); 434 | } 435 | cur.block = curBlock; 436 | curBlock.push({ expr:TTry(mk_block(tryblock), newc), t: e.t, pos:e.pos }); 437 | cur.next = curNext; 438 | } 439 | if (cur != current) 440 | { 441 | newFlow(); 442 | for (c in currents) 443 | c.next = current.id; 444 | } 445 | 446 | case TMeta(meta,e1): 447 | iter(e1); 448 | 449 | case TFor(v,eit,eblock): 450 | if (hasYield(eblock)) 451 | { 452 | switch (typeExpr( macro var _iterator_ ).expr) { 453 | case TVar(v2,_): 454 | v2.t = eit.t; 455 | iter({ expr:TVar(v2,eit), t:tdynamic, pos:eit.pos }); 456 | var local = { expr:TLocal(v2), t:eit.t, pos:eit.pos }; 457 | 458 | var wexpr = { 459 | expr:TWhile( 460 | { expr:TCall( mk_field(local, 'hasNext', tdynamic), []), t:tbool, pos:eit.pos }, 461 | { expr:TBlock([{ expr:TVar(v, { expr:TCall( mk_field(local, 'next', tdynamic), []), t:v.t, pos:eit.pos }), t:tdynamic, pos:eit.pos }, eblock]), t:tdynamic, pos:eblock.pos }, 462 | true), 463 | t: tdynamic, 464 | pos: e.pos }; 465 | iter(wexpr); 466 | case _: throw 'assert'; 467 | } 468 | } else { 469 | ensureNoYield(e); 470 | current.block.push(e); 471 | } 472 | 473 | case TCall( { expr:TLocal({ name:"__yield__" }) }, [ev]): 474 | // return value 475 | ensureNoYield(ev); 476 | current.block.push( { expr:TMeta({name:"yield", params:[], pos:ev.pos}, ev), t: ev.t, pos:ev.pos } ); 477 | // current.block.push( mk_assign( mk_this('value', ev.t, e.pos), ev, e.pos) ); 478 | if (current.next != null) 479 | current.block.push( mkGoto( current.next, false ) ); 480 | else 481 | current.block.push( mkGotoEnd( current.id, false ) ); 482 | // set to next 483 | current.block.push( { expr: TReturn( { expr:TConst(TBool(true)), t:tbool, pos:e.pos } ), t:tbool, pos:e.pos } ); 484 | // break flow 485 | newFlow(); 486 | case TReturn(_): 487 | throw new Error("Cannot return inside a 'yield' context", e.pos); 488 | 489 | case _: 490 | ensureNoYield(e); 491 | current.block.push(e); 492 | } 493 | } 494 | 495 | public function change():Expr 496 | { 497 | // create the control flow graph 498 | iter(expr); 499 | var used = new Map(); 500 | { 501 | // get used vars - canonically 502 | for (k in usedVars.keys()) 503 | { 504 | var cur = new Map(); 505 | used[k] = cur; 506 | for (cfg in usedVars[k]) 507 | { 508 | var cfg = cfg; 509 | cur[cfg.id] = true; 510 | } 511 | } 512 | } 513 | // get the variables that need to be changed 514 | var changed = new Map(), 515 | used = [ for (k in used.keys()) k => this.usedVars.get(k).count() ]; 516 | var external = [ for (ext in getLocalTVars()) ext.id => ext ]; 517 | for (ext in external) 518 | used[ext.id] = 2; //mark as used 519 | // trace(changed,used); 520 | // create cases function 521 | var ecases = [], 522 | acc = []; 523 | for (cfg in cfgs) 524 | { 525 | acc.push({ expr:EConst(CInt(cfg.id + "")), pos:pos }); 526 | if (cfg.block.length == 0 && cfg.next == null) 527 | continue; 528 | //TODO tryctx 529 | var expr = getExprFromCg(cfg, used, changed); 530 | ecases.push({ values:acc, expr: expr }); 531 | acc = []; 532 | } 533 | var eswitch = { expr:ESwitch(macro this.eip, ecases, macro return false), pos:pos }; 534 | 535 | eswitch = macro try { @:privateAccess $eswitch; } catch(exc:Dynamic) { if (!this.handleError(exc)) {$rethrow; return false;} }; 536 | // see if C# 537 | if (!false) 538 | { 539 | eswitch = macro while(true) $eswitch; 540 | } 541 | // trace(eswitch.toString()); 542 | 543 | var extChanged = [ for (ext in external) if (changed.exists(ext.id)) ext ]; 544 | if (thisUsed) 545 | { 546 | var ethis = { id:-1, name:'this', t: typeof(macro this), capture:false, extra:null }; 547 | extChanged.push(ethis); 548 | changed[ethis.id] = ethis; 549 | } 550 | 551 | var tparams = new Map(); 552 | for (c in extChanged) 553 | collectTParams(c.t, tparams); 554 | 555 | //create new() function 556 | var nf = { 557 | name: "new", 558 | kind: FFun({ 559 | args: [ for (arg in extChanged) { name: getVarName(arg), type: null } ], 560 | ret: null, 561 | expr: { expr:EBlock([ for (arg in extChanged) { var name = getVarName(arg); macro this.$name = $i{name}; } ]), pos:pos } 562 | }), 563 | pos: pos 564 | }; 565 | 566 | //create all changed fields 567 | var clsnum = packs.get(pack); 568 | if (clsnum == null) 569 | { 570 | clsnum = 0; 571 | } 572 | packs[pack] = clsnum + 1; 573 | var pack = pack.split('.'), 574 | name = "yield_" + (infos != null ? infos.className.split('.').pop() + "_" + infos.methodName + "_" + infos.lineNumber + "_": "" + clsnum); 575 | 576 | var cls = macro class extends unihx._internal.YieldBase { 577 | override public function MoveNext():Bool 578 | $eswitch; 579 | }; 580 | cls.fields.push(nf); 581 | var excHandler = getExcHandler(); 582 | if (excHandler != null) 583 | cls.fields.push(excHandler); 584 | var pvtAcc = macro : unihx._internal.PrivateTypeAccess; 585 | for (changed in changed) 586 | { 587 | var t2 = toComplexType(changed.t); 588 | // trace(changed.name, changed.t.toString(), t2.toString()); 589 | cls.fields.push({ 590 | name:getVarName(changed), 591 | kind: FVar(t2,null), 592 | pos: pos 593 | }); 594 | } 595 | cls.params = [ for (k in tparams.keys()) { name:k } ]; 596 | cls.name = name; 597 | cls.pack = pack; 598 | defineType(cls); 599 | return { expr:ENew({ pack:pack, name: name }, [ for (arg in extChanged) macro $i{arg.name} ]), pos:pos }; 600 | } 601 | 602 | function getExcHandler() 603 | { 604 | var all = new Map(); 605 | var found = false; 606 | for (i in 0...cfgs.length) 607 | { 608 | var cfg = cfgs[i]; 609 | if (cfg.tryctx != null) 610 | { 611 | found =true; 612 | var g = all[cfg.tryctx]; 613 | if (g == null) 614 | { 615 | all[cfg.tryctx] = g = { ctx:cfg.tryctx, ids:[] }; 616 | } 617 | g.ids.push(cfg.id); 618 | } 619 | } 620 | 621 | if (!found) 622 | return null; 623 | var used = new Map(), 624 | changed = new Map(); 625 | var cases = []; 626 | for (ctx in all) 627 | { 628 | var ids = ctx.ids, 629 | ctx = ctx.ctx; 630 | var exprs = []; 631 | for (c in ctx) 632 | { 633 | var module = switch(c.t) { 634 | case TInst(c,_): 635 | exprModule(TClassDecl(c),pos); 636 | case TEnum(e,_): 637 | exprModule(TEnumDecl(e),pos); 638 | case TAbstract(a,_): 639 | exprModule(ModuleType.TAbstract(a),pos); 640 | case TType(t,_): 641 | exprModule(TTypeDecl(t),pos); 642 | case TDynamic(_): 643 | macro Dynamic; 644 | case _: throw 'assert: ' + c.t; 645 | }; 646 | var gotoHandler = switch (c.gotoHandler.expr) { 647 | case TCall({ expr:TLocal({ name: "__goto__" }) }, [{ expr:TConst(TInt(i)) }, _]): 648 | macro { this.eip = $v{i}; return true; } 649 | case _: 650 | throw 'assert'; 651 | }; 652 | exprs.push(macro if(std.Std.is(exc,$module)) $gotoHandler); 653 | } 654 | 655 | cases.push({ values: [ for (v in ids) macro $v{v} ], expr: { expr:EBlock(exprs), pos:pos } }); 656 | } 657 | var eswitch = { expr: ESwitch(macro this.eip, cases, null), pos:pos }; 658 | var field = (macro class { 659 | override public function handleError(exc:Dynamic):Bool { 660 | this.exc = exc; 661 | $eswitch; 662 | this.eip = -1; 663 | this.exc = null; 664 | return false; 665 | } 666 | }).fields[0]; 667 | return field; 668 | } 669 | 670 | function getExprFromCg(cfg:FlowGraph, used:Map, changed:Map):Expr 671 | { 672 | var exprs = [ for (e in cfg.block) texprToExpr(e,used,changed) ]; 673 | if (exprs.length == 0) 674 | { 675 | exprs = [texprToExpr(mkGotoEnd(cfg.id,true),used,changed)]; 676 | } else switch (exprs[exprs.length-1]) { 677 | case macro return $_: 678 | case macro this.eip = $_: 679 | case macro continue: 680 | case _: 681 | exprs.push(texprToExpr(mkGotoEnd(cfg.id, true),used,changed)); 682 | } 683 | return { expr: EBlock(exprs), pos: pos }; 684 | } 685 | 686 | function mk_assign(e1:TypedExpr, e2:TypedExpr, pos:Position):TypedExpr 687 | { 688 | return { expr: TBinop(OpAssign, e1, e2), t: e1.t, pos:pos }; 689 | } 690 | 691 | function mk_field(e:TypedExpr, field:String, type:Type):TypedExpr 692 | { 693 | return { expr: TField(e, FDynamic(field)), t:type, pos:e.pos }; 694 | } 695 | 696 | function mk_this(name:String, t:Type, pos:Position):TypedExpr 697 | { 698 | return { expr: TField({ expr:TConst(TThis), t:tdynamic, pos:pos }, FDynamic(name)), t: t, pos:pos }; 699 | } 700 | 701 | static function mk_paren(e:TypedExpr):TypedExpr 702 | { 703 | return { expr: TParenthesis(e), t: e.t, pos: e.pos }; 704 | } 705 | 706 | function mk_not(e:TypedExpr):TypedExpr 707 | { 708 | return switch(e.expr) { 709 | case TUnop(OpNot, false, e): 710 | e; 711 | case _: 712 | { expr: TUnop(OpNot, false, mk_paren(e)), t: tbool, pos: e.pos }; 713 | } 714 | } 715 | 716 | function mk_block(el:Array):TypedExpr 717 | { 718 | return { expr: TBlock(el), t: tdynamic, pos: el.length > 0 ? el[0].pos : pos }; 719 | } 720 | 721 | static function getHere(pos:Position) 722 | { 723 | var expr = typeExpr(macro @:pos(pos) { 724 | inline function here(?infos:haxe.PosInfos) return infos; 725 | here(); 726 | }); 727 | var ret:haxe.PosInfos = null; 728 | function getConst(e:TypedExpr):Dynamic { 729 | return switch(e.expr) { 730 | case TConst(TInt(i)): i; 731 | case TConst(TString(s)): s; 732 | case _: null; 733 | } 734 | } 735 | function iter(e:TypedExpr) 736 | { 737 | switch(e.expr) { 738 | case TObjectDecl(d): 739 | ret = cast {}; 740 | for (arg in d) 741 | { 742 | Reflect.setField(ret,arg.name, getConst(arg.expr)); 743 | } 744 | case _: 745 | e.iter(iter); 746 | } 747 | } 748 | iter(expr); 749 | return ret; 750 | } 751 | 752 | function alloc_var(name:String, t:Type):TVar 753 | { 754 | switch (typeExpr(macro var _).expr) { 755 | case TVar(v,_): 756 | v.name = name; 757 | v.t = t; 758 | return v; 759 | case _: throw 'assert'; 760 | } 761 | } 762 | 763 | var inswitch = false; 764 | private function texprToExpr(e:TypedExpr, used:Map, changed:Map):Expr 765 | { 766 | function map(e:TypedExpr):Expr 767 | { 768 | return switch(e.expr) { 769 | case TConst(TThis): 770 | thisUsed = true; 771 | return macro this.parent; 772 | case TMeta({name:"yield"}, v): 773 | return macro this.value = ${ map(v) }; 774 | case TLocal({ name:"__exc__" }): 775 | return macro this.exc; 776 | case TLocal(v) if (v.capture): 777 | throw new Error('Cannot bind to captured variable ${v.name}',e.pos); 778 | case TLocal(v) if (used.get(v.id) > 1): 779 | changed[v.id] = v; 780 | var name = getVarName(v); 781 | macro @:pos(e.pos) this.$name; 782 | case TVar(v,eset) if (used.get(v.id) > 1): 783 | changed[v.id] = v; 784 | var name = getVarName(v); 785 | if (eset == null) 786 | macro @:pos(e.pos) this.$name = null; 787 | else 788 | macro @:pos(e.pos) this.$name = ${map(eset)}; 789 | case TNew(c, params, el): 790 | var complex = switch(toComplexType( TInst(c,params) )) { 791 | case TPath(p): 792 | p; 793 | case _: 794 | throw 'assert'; 795 | }; 796 | { expr: ENew( complex, [ for (e in el) map(e) ]), pos: e.pos }; 797 | case TTypeExpr(m): 798 | return exprModule(m, e.pos); 799 | 800 | case TCall({ expr:TLocal({ name: "__goto__" }) }, [{expr:TConst(TInt(i))}, final]): 801 | var i = followId(i); 802 | switch (final.expr) 803 | { 804 | case TConst(TBool(true)) if (!inswitch && defined('cs')): 805 | var str = 'goto case $i'; 806 | if (i > getMaxId()) 807 | str = 'goto default'; 808 | macro @:pos(e.pos) untyped __cs__($v{str}); 809 | case TConst(TBool(true)): 810 | macro @:pos(e.pos) { this.eip = $v{i}; continue; }; 811 | 812 | case TConst(TBool(false)): 813 | macro @:pos(e.pos) this.eip = $v{i}; 814 | case _: throw new Error("Invalid goto expr", e.pos); 815 | } 816 | case TCall({ expr:TLocal({ name: "__goto_end__" }) }, [i, final]): 817 | var block = switch (i.expr) { 818 | case TConst(TInt(i)): 819 | cfgs[i]; 820 | case _: throw "assert"; 821 | }; 822 | var i = if (block.next == null) block.id + 1; else block.next; 823 | i = followId(i); 824 | switch(final.expr) 825 | { 826 | case TConst(TBool(true)) if (!inswitch && defined('cs')): 827 | var str = 'goto case $i'; 828 | if (i > getMaxId()) 829 | str = 'goto default'; 830 | macro @:pos(e.pos) untyped __cs__($v{str}); 831 | case TConst(TBool(true)): 832 | macro @:pos(e.pos) { this.eip = $v{i}; continue; }; 833 | 834 | case TConst(TBool(false)): 835 | macro @:pos(e.pos) this.eip = $v{i}; 836 | case _: throw new Error("Invalid goto expr", e.pos); 837 | } 838 | 839 | // conversion boilerplate 840 | case TConst(_): 841 | getTypedExpr(e); 842 | case TMeta({ name:":ast", params: [p] }, _): 843 | p; 844 | case TEnumParameter(e1,ef,idx): 845 | var params = switch(ef.type.follow()) { 846 | case TFun(args,_):args; 847 | case _: throw 'assert'; 848 | }; 849 | var ecase = macro $i{ef.name}, 850 | c2 = { expr: ECall(ecase,[ for (i in 0...params.length) if (i == idx) macro val; else macro _ ]), pos:e.pos }; 851 | @:pos(e.pos) macro switch (${map(e1)}) { case $c2: val; default: throw 'assert'; }; 852 | // these are considered complex, so the AST is handled in TMeta(Meta.Ast) 853 | // throw new Error('assert', e.pos); 854 | case TLocal(v): 855 | macro @:pos(e.pos) $i{v.name}; 856 | case TBreak: 857 | macro @:pos(e.pos) break; 858 | case TContinue: 859 | macro @:pos(e.pos) continue; 860 | case TArray(e1,e2): 861 | macro @:pos(e.pos) ${map(e1)}[${map(e2)}]; 862 | case TBinop(op,e1,e2): 863 | { expr: EBinop(op, map(e1), map(e2)), pos: e.pos }; 864 | case TField(e1, fa): 865 | switch (fa) { 866 | case FInstance(_,cf) | FStatic(_,cf) | FAnon(cf) | FClosure(_,cf): 867 | var cf = cf.get(); 868 | var field = { expr: EField(map(e1), cf.name), pos:e.pos }; 869 | if (!cf.isPublic) 870 | macro @:pos(e.pos) $field; 871 | else 872 | field; 873 | case FDynamic(s): 874 | { expr: EField(map(e1), s), pos:e.pos }; 875 | case FEnum(_,ef): 876 | { expr: EField(map(e1), ef.name), pos:e.pos }; 877 | } 878 | case TParenthesis(e1): 879 | { expr: EParenthesis(map(e1)), pos: e.pos }; 880 | case TObjectDecl(fields): 881 | { expr: EObjectDecl([ for (f in fields) { field:f.name, expr:map(f.expr) } ]), pos: e.pos }; 882 | case TArrayDecl(el): 883 | { expr: EArrayDecl([ for (e in el) map(e) ]), pos: e.pos }; 884 | case TCall(e1, el): 885 | { expr: ECall( map(e1), [ for ( e in el ) map(e) ] ), pos: e.pos }; 886 | case TUnop(op,postFix,e1): 887 | { expr: EUnop(op, postFix, map(e1)), pos:e.pos }; 888 | case TFunction(tf): 889 | { expr: EFunction(null, { args:[for (arg in tf.args) { name: arg.v.name, type:toComplexType(arg.v.t) }], ret:toComplexType(tf.t), expr:tf.expr == null ? null : map(tf.expr) }), pos:e.pos }; 890 | case TVar(v, e1): 891 | { expr: EVars([{ name: v.name, type: toComplexType(v.t), expr: e1 == null ? null : map(e1) }]), pos: e.pos }; 892 | case TBlock(el): 893 | { expr: EBlock([ for (e in el) map(e) ]), pos:e.pos }; 894 | case TIf(econd,eif,eelse): 895 | { expr: EIf(map(econd), map(eif), eelse == null ? null : map(eelse)), pos: e.pos }; 896 | case TReturn(e1): 897 | { expr: EReturn(map(e1)), pos: e.pos }; 898 | case TThrow(e1): 899 | { expr: EThrow(map(e1)), pos: e.pos }; 900 | case TMeta(m, e1): 901 | { expr: EMeta(m, map(e1)), pos: e.pos }; 902 | case TWhile(econd,eblock,normal): 903 | { expr:EWhile(map(econd),map(eblock),normal), pos:e.pos }; 904 | case TCast(e1,_): 905 | var t = toComplexType(e.t); 906 | var e1 = map(e1); 907 | macro @:pos(e.pos) ( (cast $e1) : $t ); 908 | case TFor(v,e1,e2): 909 | var e1 = map(e1); 910 | var e2 = map(e2); 911 | { expr: EFor(macro $i{v.name} in $e1, e2), pos:e.pos }; 912 | case TSwitch(econd, cases, edef): 913 | var last = inswitch; 914 | inswitch = true; 915 | var ret = { expr: ESwitch( map(econd), [ for (c in cases) { values: [ for (e in c.values) map(e) ], expr: map(c.expr) } ], edef == null ? null : map(edef) ), pos:e.pos }; 916 | inswitch = last; 917 | ret; 918 | case TTry(etry, catches): 919 | { expr: ETry(map(etry), [ for (c in catches) { name: c.v.name, type: toComplexType(c.v.t), expr: map(c.expr) } ]), pos: e.pos }; 920 | } 921 | } 922 | return map(e); 923 | } 924 | 925 | private function exprModule(m:ModuleType,pos:Position):Expr 926 | { 927 | var base:BaseType = switch(m) { 928 | case TClassDecl(c): 929 | c.get(); 930 | case TEnumDecl(e): 931 | e.get(); 932 | case TTypeDecl(t): 933 | t.get(); 934 | case TAbstract(a): 935 | a.get(); 936 | }; 937 | if (base.isPrivate) 938 | { 939 | // create a helper typedef 940 | var clsnum = packs.get(pack); 941 | if (clsnum == null) 942 | clsnum = 0; 943 | packs[pack] = clsnum + 1; 944 | var pack = pack.split('.'), 945 | name = base.name + "_Access_" + clsnum; 946 | var tparams = [for(p in base.params) tdynamic]; 947 | var type = switch (m) { 948 | case TClassDecl(c): 949 | TInst(c,tparams); 950 | case TEnumDecl(e): 951 | TEnum(e,tparams); 952 | case TTypeDecl(t): 953 | TType(t,tparams); 954 | case TAbstract(a): 955 | TAbstract(a,tparams); 956 | }; 957 | 958 | defineType({ pack:pack, name:name, pos:pos, kind: TDAlias( toComplexType(type) ), fields:[] }); 959 | if (pack.length == 0) 960 | return macro @:pos(pos) $i{name}; 961 | var expr = macro @:pos(pos) $i{pack[0]}; 962 | for (i in 1...pack.length) 963 | { 964 | var p = pack[i]; 965 | expr = macro @:pos(pos) $expr.$p; 966 | } 967 | expr = macro @:pos(pos) $expr.$name; 968 | return expr; 969 | } else { 970 | return getTypedExpr({ expr: TTypeExpr(m), t:tdynamic, pos:pos }); 971 | } 972 | } 973 | 974 | private static function toComplexType(t:Type):ComplexType 975 | { 976 | // we need this function because there are some types that aren't compatible with toComplexType 977 | // for example, TMonos and private types 978 | // For TMonos, we'll transform them into Dynamic; For private types, we'll use unihx._internal.PrivateTypeAccess 979 | var params = null; 980 | var base:BaseType = switch (t.follow()) { 981 | case TInst(c,p): 982 | params = p; 983 | c.get(); 984 | case TEnum(c,p): 985 | params = p; 986 | c.get(); 987 | case TAbstract(c,p): 988 | params = p; 989 | c.get(); 990 | case TMono(_): 991 | return macro : Dynamic; 992 | case _: 993 | null; 994 | } 995 | return if (base != null && base.isPrivate) 996 | { 997 | // use PrivateTypeAccess 998 | var t = base.module, 999 | name = base.name; 1000 | var pvtAcc = macro : unihx._internal.PrivateTypeAccess; 1001 | switch (pvtAcc) { 1002 | case TPath(p): 1003 | p.params = [TPExpr( macro $v{t} ), TPExpr( macro $v{name} )]; 1004 | for (param in params) 1005 | { 1006 | p.params.push(TPType( toComplexType(param) )); 1007 | } 1008 | case _: throw "assert"; 1009 | } 1010 | pvtAcc; 1011 | } else { 1012 | t.toComplexType(); 1013 | } 1014 | } 1015 | 1016 | private static function getVarName(v:TVar) 1017 | { 1018 | if (v.id == -1 && v.name == "this") return "parent"; 1019 | var name = if (v.name.startsWith('`')) 'tmp' else v.name; 1020 | return name + '__' + v.id; 1021 | } 1022 | 1023 | private static function collectTParams(type:Type, collected:Map) 1024 | { 1025 | while(true) 1026 | { 1027 | switch(type) { 1028 | case TMono(t): 1029 | var t = t.get(); 1030 | if (t != null) 1031 | { 1032 | type = t; 1033 | continue; 1034 | } 1035 | case TEnum(_,params): 1036 | for (p in params) collectTParams(p,collected); 1037 | case TType(_,params): 1038 | for (p in params) collectTParams(p,collected); 1039 | case TFun(args,ret): 1040 | for (arg in args) collectTParams(arg.t,collected); 1041 | collectTParams(ret, collected); 1042 | case TAnonymous(a): 1043 | for (f in a.get().fields) 1044 | collectTParams(f.type,collected); 1045 | case TDynamic(t): 1046 | if (t != null) 1047 | { 1048 | type = t; 1049 | continue; 1050 | } 1051 | case TLazy(f): 1052 | type = f(); 1053 | case TAbstract(_,params): 1054 | for (p in params) collectTParams(p,collected); 1055 | case TInst(_.get() => cl, params): 1056 | switch(cl.kind) { 1057 | case KTypeParameter(_): 1058 | collected[cl.name] = type; 1059 | return; 1060 | case _: 1061 | } 1062 | for (p in params) collectTParams(p,collected); 1063 | } 1064 | break; 1065 | } 1066 | } 1067 | 1068 | private function getMaxId() 1069 | { 1070 | var max = 0; 1071 | var len = cfgs.length; 1072 | while (len --> 0) 1073 | { 1074 | var c = cfgs[len]; 1075 | max = c.id; 1076 | if (c.block.length != 0 || c.next != null) 1077 | { 1078 | break; 1079 | } 1080 | } 1081 | return max; 1082 | } 1083 | 1084 | private function followId(i:Int) 1085 | { 1086 | var cfg = cfgs[i]; 1087 | while (cfg != null && cfg.block.length == 0 && cfg.next != null) 1088 | { 1089 | cfg = cfgs[cfg.next]; 1090 | i = cfg.id; 1091 | } 1092 | return i; 1093 | } 1094 | } 1095 | 1096 | typedef FlowGraph = { block:Array, tryctx:Array<{ t:Type, gotoHandler:TypedExpr }>, next:Null, id:Int }; 1097 | -------------------------------------------------------------------------------- /unihx/_internal/editor/AllowDragDrop.hx: -------------------------------------------------------------------------------- 1 | package unihx._internal.editor; 2 | import unityengine.*; 3 | import unityeditor.*; 4 | import haxe.ds.Vector; 5 | using StringTools; 6 | 7 | @:meta(UnityEditor.CustomEditor(typeof(UnityEngine.Transform))) 8 | @:meta(UnityEditor.CanEditMultipleObjects) 9 | @:nativeGen 10 | @:native('AllowDragDrop') 11 | class AllowDragDrop extends Editor 12 | { 13 | private var _target(get,never):Transform; 14 | 15 | private function OnEnable() 16 | { 17 | Repaint(); 18 | } 19 | 20 | inline private function get__target():Transform 21 | { 22 | return cast this.target; 23 | } 24 | 25 | @:overload override public function OnInspectorGUI() 26 | { 27 | var obj = DragAndDrop.objectReferences; 28 | if (obj == null || obj.Length == 0) 29 | return; 30 | switch(Event.current.type) 31 | { 32 | case DragUpdated | DragExited if (AssetDatabase.GetAssetPath(DragAndDrop.objectReferences[0]).endsWith('.hx')): 33 | DragAndDrop.visualMode = Link; 34 | Event.current.Use(); 35 | case DragPerform if (AssetDatabase.GetAssetPath(DragAndDrop.objectReferences[0]).endsWith('.hx')): 36 | DragAndDrop.visualMode = Link; 37 | DragAndDrop.AcceptDrag(); 38 | Event.current.Use(); 39 | var ret = _target.gameObject.AddComponent(DragAndDrop.objectReferences[0].name); 40 | if (ret == null) 41 | EditorUtility.DisplayDialog('Can\'t add script','Can\'t add script behaviour "${DragAndDrop.objectReferences[0].name}"',"OK"); 42 | case _: 43 | super.OnInspectorGUI(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /unihx/_internal/editor/AssetProcessor.hx: -------------------------------------------------------------------------------- 1 | package unihx._internal.editor; 2 | import haxe.ds.Vector; 3 | import sys.FileSystem.*; 4 | import haxe.io.Path; 5 | import unityengine.*; 6 | import Std.*; 7 | import cs.system.reflection.BindingFlags; 8 | 9 | using StringTools; 10 | 11 | @:nativeGen @:keep class AssetProcessor extends unityeditor.AssetPostprocessor 12 | { 13 | static function OnPostprocessAllAssets( 14 | importedAssets:Vector, 15 | deletedAssets:Vector, 16 | movedAssets:Vector, 17 | movedFromAssetPaths:Vector) 18 | { 19 | var sources = [], 20 | deleted = [], 21 | refresh = false; 22 | for (str in importedAssets) 23 | { 24 | if (str.endsWith(".hx")) 25 | sources.push(str); 26 | } 27 | for (str in movedAssets) 28 | { 29 | if (str.endsWith(".hx")) 30 | sources.push(str); 31 | } 32 | 33 | for (d in movedFromAssetPaths) 34 | { 35 | if (d.endsWith(".hx")) 36 | { 37 | deleted.push(d); 38 | } 39 | } 40 | for (d in deletedAssets) 41 | { 42 | if (d.endsWith(".hx")) 43 | { 44 | deleted.push(d); 45 | } 46 | } 47 | 48 | for (d in deleted) 49 | { 50 | //delete also .cs file 51 | var path = Path.directory(d) + '/hx-compiled/' + Path.withoutDirectory(d).substr(0,-2) + "cs"; 52 | if (exists( path )) 53 | { 54 | deleteFile(path); 55 | if (exists( path + '.meta' )) 56 | deleteFile( path + '.meta' ); 57 | if (readDirectory( Path.directory(d) + '/hx-compiled' ).length == 0) 58 | deleteDirectory( Path.directory(d) + '/hx-compiled' ); 59 | refresh = true; 60 | } 61 | } 62 | if (sources.length > 0) 63 | { 64 | refresh = true; 65 | var comp = HaxeProperties.props(); 66 | var success = comp.compile(['--cwd','./Assets','build.hxml','--macro','unihx._internal.Compiler.compile()']); 67 | } 68 | if (refresh) 69 | { 70 | unityeditor.AssetDatabase.Refresh(); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /unihx/_internal/editor/HaxeCompiler.hx: -------------------------------------------------------------------------------- 1 | package unihx._internal.editor; 2 | import unihx._internal.editor.HaxeProperties; 3 | import sys.io.Process; 4 | import unityengine.*; 5 | import Std.*; 6 | 7 | using StringTools; 8 | 9 | class HaxeCompiler 10 | { 11 | public var props(default,null):Comp; 12 | var process:Process; 13 | 14 | public function new(prop:Comp) 15 | { 16 | this.props = prop; 17 | switch(prop) 18 | { 19 | case CompilationServer(port): 20 | newProcess(port); 21 | case _: 22 | } 23 | } 24 | 25 | function newProcess(port:Int) 26 | { 27 | if (process != null) 28 | { 29 | try 30 | { 31 | process.kill(); 32 | process.close(); 33 | } 34 | catch(e:Dynamic) {} 35 | } 36 | process = null; 37 | process = new Process('haxe',['--wait',port + ""]); 38 | } 39 | 40 | public function compile(args:Array, verbose=false):Bool 41 | { 42 | var cmd = switch(props) 43 | { 44 | case DontCompile: 45 | return true; 46 | case Compile: 47 | trace('compile',args); 48 | new Process("haxe",args); 49 | case CompilationServer(port): 50 | if (process == null || ( untyped process.native : cs.system.diagnostics.Process ).HasExited ) 51 | newProcess(port); 52 | args = args.copy(); 53 | args.push('--connect'); args.push(port+""); 54 | trace('compile',args); 55 | new Process('haxe',args); 56 | } 57 | 58 | var ret = true; 59 | if (cmd != null) 60 | { 61 | var sw = new cs.system.diagnostics.Stopwatch(); 62 | sw.Start(); 63 | if (cmd.exitCode() != 0) 64 | { 65 | ret = false; 66 | Debug.LogError("Haxe compilation failed."); 67 | } 68 | sw.Stop(); 69 | if (verbose) 70 | Debug.Log('Compilation ended (' + sw.Elapsed + ")" ); 71 | for (ln in cmd.stdout.readAll().toString().trim().split('\n')) 72 | { 73 | var ln = ln.trim(); 74 | if (ln != "") 75 | Debug.Log(ln); 76 | } 77 | for (ln in cmd.stderr.readAll().toString().trim().split('\n')) 78 | { 79 | var ln = ln.trim(); 80 | 81 | if (ln == "") continue; 82 | if (ln.startsWith('Warning')) 83 | Debug.LogWarning(ln); 84 | else 85 | reportError(ln); 86 | } 87 | } 88 | return ret; 89 | } 90 | 91 | public function close() 92 | { 93 | if (process != null) 94 | { 95 | process.kill(); 96 | process.close(); 97 | process = null; 98 | } 99 | } 100 | 101 | public static function reportError(line:String) 102 | { 103 | var ln = line.split(':'); 104 | ln.reverse(); 105 | var file = ln.pop(), 106 | lineno = parseInt(ln.pop()), 107 | other = ln.pop(), 108 | rest = ln.join(":"); 109 | 110 | var fullp = cs.system.io.Path.GetFullPath(cs.system.io.Path.Combine("Assets",file)); 111 | var debug = cs.Lib.toNativeType(Debug); 112 | try 113 | { 114 | Debug.LogException(new HaxeError(line,fullp,lineno)); 115 | } 116 | catch(e:Dynamic) 117 | { 118 | Debug.LogError(line); 119 | } 120 | } 121 | } 122 | 123 | @:nativeGen class HaxeError extends cs.system.Exception 124 | { 125 | var file:String; 126 | var line:Int; 127 | var msg:String; 128 | public function new(msg:String,file:String,line:Int) 129 | { 130 | super(msg); 131 | this.msg = msg; 132 | this.file = file; 133 | this.line = line; 134 | } 135 | 136 | @:overload override private function get_Message():String 137 | { 138 | return msg; 139 | } 140 | 141 | @:overload override private function get_StackTrace():String 142 | { 143 | return "(at " + file + ":" + line + ")"; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /unihx/_internal/editor/HaxeProperties.hx: -------------------------------------------------------------------------------- 1 | package unihx._internal.editor; 2 | import unityengine.*; 3 | import unityeditor.*; 4 | import unihx.inspector.*; 5 | import cs.system.net.sockets.*; 6 | import cs.system.net.*; 7 | import sys.FileSystem.*; 8 | 9 | using StringTools; 10 | 11 | @:nativeGen 12 | @:native('HaxeProperties') 13 | class HaxeProperties extends EditorWindow 14 | { 15 | public var scroll:Vector2; 16 | @:meta(UnityEditor.MenuItem("Window/Haxe Properties")) 17 | public static function showWindow() 18 | { 19 | EditorWindow.GetWindow(cs.Lib.toNativeType(HaxeProperties)); 20 | } 21 | 22 | @:meta(UnityEditor.MenuItem("Assets/Create/Haxe Script")) 23 | public static function createHaxeClass() 24 | { 25 | var path = AssetDatabase.GetAssetPath (Selection.activeObject); 26 | if (path == "") 27 | { 28 | path = "Assets"; 29 | } 30 | 31 | if (exists('$path/NewHaxeBehaviour.hx')) 32 | { 33 | var n = 0; 34 | while (exists('$path/NewHaxeBehaviour${++n}.hx')) {} 35 | path = '$path/NewHaxeBehaviour$n.hx'; 36 | } else { 37 | path = '$path/NewHaxeBehaviour.hx'; 38 | } 39 | sys.io.File.saveContent(path, 'import unityengine.*;\nclass NewHaxeBehaviour extends HaxeBehaviour\n{\n\tfunction Update()\n\t{\n\t}\n}'); 40 | 41 | unityeditor.AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); 42 | EditorUtility.FocusProjectWindow(); 43 | } 44 | 45 | function OnEnable() 46 | { 47 | props(); 48 | } 49 | 50 | function OnDisable() 51 | { 52 | props().close(); 53 | } 54 | 55 | function OnGUI() 56 | { 57 | var arr = new cs.NativeArray(1); 58 | arr[0] = GUILayout.MaxHeight(300); 59 | // arr[1] = GUILayout.MaxWidth(300); 60 | GUILayout.BeginVertical(arr); 61 | scroll = GUILayout.BeginScrollView(scroll, new cs.NativeArray(0)); 62 | props().OnGUI(); 63 | GUILayout.EndScrollView(); 64 | if (GUILayout.Button("Save",null)) 65 | { 66 | props().save(); 67 | } 68 | if (GUILayout.Button("Reload",null)) 69 | { 70 | props().reload(); 71 | } 72 | if (GUILayout.Button("Force recompile",null)) 73 | { 74 | props().compile(['--cwd','./Assets','params.hxml','--macro','unihx._internal.Compiler.compile()']); 75 | unityeditor.AssetDatabase.Refresh(); 76 | } 77 | GUILayout.EndVertical(); 78 | } 79 | 80 | public static function props():HaxePropertiesData 81 | { 82 | return HaxePropertiesData.get(); 83 | } 84 | } 85 | 86 | class HaxePropertiesData implements InspectorBuild 87 | { 88 | /** 89 | Choose how will Haxe classes be compiled 90 | **/ 91 | public var compilation:Comp; 92 | 93 | public var _:Space; 94 | 95 | public var verbose:Bool; 96 | 97 | /** 98 | Extra Haxe parameters from build.hxml 99 | @label Extra parameters 100 | **/ 101 | public var _:ConstLabel; 102 | 103 | /** 104 | Extra Haxe parameters from build.hxml 105 | @min-height 200 106 | **/ 107 | public var extraParams:TextArea; 108 | 109 | private var compiler:HaxeCompiler; 110 | 111 | private static var current:HaxePropertiesData; 112 | 113 | public static function get() 114 | { 115 | if (current == null) 116 | return current = new HaxePropertiesData().reload(); 117 | return current; 118 | } 119 | 120 | public function reload():HaxePropertiesData 121 | { 122 | if (exists('Assets/build.hxml')) 123 | { 124 | reloadFrom( sys.io.File.read('Assets/build.hxml') ); 125 | } else { //create 126 | save(); 127 | } 128 | return this; 129 | } 130 | 131 | public function compile(args) 132 | { 133 | if (compiler == null) 134 | reload(); 135 | if (compiler == null) 136 | compiler = new HaxeCompiler(compilation); 137 | 138 | return compiler.compile(args); 139 | } 140 | 141 | public function close() 142 | { 143 | current = null; 144 | if (compiler != null) 145 | compiler.close(); 146 | compiler = null; 147 | } 148 | 149 | private function getSaveContents() 150 | { 151 | var b = new StringBuf(); 152 | if (extraParams == null || extraParams == "") 153 | b.add("# Add your own compiler parameters here\n\n"); 154 | switch(compilation) 155 | { 156 | case CompilationServer(p): 157 | if (p < 1024) 158 | p = availablePort(); 159 | b.add('params.hxml\n#--connect $p\n'); 160 | case Compile: 161 | b.add('params.hxml\n'); 162 | case DontCompile: 163 | } 164 | if (verbose) 165 | b.add('#verbose\n'); 166 | b.add('\n'); 167 | if (extraParams != null) 168 | b.add(extraParams); 169 | return b.toString(); 170 | } 171 | 172 | public function save() 173 | { 174 | var w = sys.io.File.write('Assets/build.hxml'); 175 | w.writeString(getSaveContents()); 176 | w.close(); 177 | 178 | if (this.compiler == null || !Type.enumEq(this.compiler.props, this.compilation)) 179 | { 180 | if (this.compiler != null) 181 | this.compiler.close(); 182 | this.compiler = new HaxeCompiler(this.compilation); 183 | } 184 | } 185 | 186 | private function reloadFrom(i:haxe.io.Input) 187 | { 188 | var comp = DontCompile, 189 | buf = new StringBuf(); 190 | verbose = false; 191 | try 192 | { 193 | var regex = ~/[ \t]+/g; 194 | while(true) 195 | { 196 | var ln = i.readLine().trim(); 197 | var cmd = regex.split(ln); 198 | switch (cmd[0]) 199 | { 200 | case '--connect' | '#--connect': 201 | var portCmd = cmd[1].split(":"); 202 | var port = if (portCmd.length == 1) 203 | Std.parseInt(portCmd[0]); 204 | else 205 | Std.parseInt(portCmd[1]); 206 | comp = CompilationServer(port); 207 | case '#verbose': 208 | verbose = true; 209 | case 'params.hxml': 210 | if (comp == DontCompile) 211 | comp = Compile; 212 | default: 213 | buf.add(ln); 214 | buf.add("\n"); 215 | } 216 | } 217 | } 218 | catch(e:haxe.io.Eof) {} 219 | if (this.compilation == null || !Type.enumEq(this.compilation,comp)) 220 | { 221 | if (this.compiler != null) 222 | this.compiler.close(); 223 | this.compiler = new HaxeCompiler(comp); 224 | } 225 | 226 | this.compilation = comp; 227 | this.extraParams = buf.toString().trim(); 228 | } 229 | 230 | function new() 231 | { 232 | } 233 | 234 | private static function availablePort() 235 | { 236 | var l = new TcpListener(IPAddress.Loopback,0); 237 | l.Start(); 238 | var port = cast(l.LocalEndpoint, IPEndPoint).Port; 239 | l.Stop(); 240 | return port; 241 | } 242 | } 243 | 244 | enum Comp 245 | { 246 | /** 247 | @label Don't compile 248 | **/ 249 | DontCompile; 250 | /** 251 | @label Use standard Haxe compiler 252 | **/ 253 | Compile; 254 | /** 255 | @label Use compilation server 256 | **/ 257 | CompilationServer(port:Int); 258 | } 259 | -------------------------------------------------------------------------------- /unihx/inspector/AnimationCurve.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | 3 | /** 4 | A field for editing an AnimationCurve. 5 | Options: 6 | - range (left,top,width,height) : optional rectangle that the curve is restrained within 7 | - color #RRGGBBAA : color 8 | **/ 9 | typedef AnimationCurve = unityengine.AnimationCurve; 10 | -------------------------------------------------------------------------------- /unihx/inspector/Button.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | 3 | typedef Button = Bool; 4 | -------------------------------------------------------------------------------- /unihx/inspector/Color.hx: -------------------------------------------------------------------------------- 1 | package unihx.inpector; 2 | 3 | typedef Color = unityengine.Color; 4 | -------------------------------------------------------------------------------- /unihx/inspector/ConstLabel.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | 3 | //@selectable = SelectableLabel 4 | typedef ConstLabel = Void; 5 | -------------------------------------------------------------------------------- /unihx/inspector/Fold.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | 3 | typedef Fold = T; 4 | -------------------------------------------------------------------------------- /unihx/inspector/InspectorBuild.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | 3 | @:autoBuild(unihx.inspector.Macro.build("OnGUI")) 4 | interface InspectorBuild 5 | { 6 | function OnGUI():Void; 7 | } 8 | -------------------------------------------------------------------------------- /unihx/inspector/IntField.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | 3 | typedef IntField = Int; 4 | -------------------------------------------------------------------------------- /unihx/inspector/Label.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | 3 | //@selectable = SelectableLabel 4 | typedef Label = String; 5 | -------------------------------------------------------------------------------- /unihx/inspector/Layer.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | 3 | abstract Layer(Int) from Int to Int 4 | { 5 | @:extern inline public function toInt():Int 6 | { 7 | return this; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /unihx/inspector/Macro.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | #if macro 3 | import haxe.macro.Expr; 4 | import haxe.macro.Type; 5 | import haxe.macro.Context.*; 6 | import sys.FileSystem.*; 7 | 8 | using haxe.macro.Tools; 9 | using StringTools; 10 | using Lambda; 11 | #end 12 | 13 | class Macro 14 | { 15 | macro public static function prop(ethis:Expr, efield:Expr) 16 | { 17 | var field = switch efield.expr { 18 | case EConst(CIdent(s)) | EConst(CString(s)): 19 | s; 20 | case _: 21 | throw new Error("This argument must either be a constant string or a constant identifier", efield.pos); 22 | }; 23 | 24 | var cf = switch typeof(ethis).follow() { 25 | case TInst(_.get() => c,_): 26 | function loop(c:ClassType) 27 | { 28 | var f = c.fields.get().find(function (cf) return cf.name == field); 29 | if (f == null) 30 | { 31 | if (c.superClass == null) 32 | return null; 33 | return loop( c.superClass.t.get() ); 34 | } else { 35 | return f; 36 | } 37 | } 38 | loop(c); 39 | case TAnonymous(_.get() => a): 40 | a.fields.find(function (cf) return cf.name == field); 41 | case t: 42 | throw new Error('Only class instances or anonymous types can be used, but the type was ' + t.toString(), ethis.pos); 43 | }; 44 | 45 | if (cf == null) 46 | throw new Error('Field $field was not found at ${typeof(ethis).toString()}',currentPos()); 47 | var ret = exprFromType(ethis,cf); 48 | if (ret == null) 49 | return macro null; 50 | else 51 | return ret; 52 | } 53 | 54 | #if macro 55 | public static function build(fieldName:Null):Array 56 | { 57 | if (defined('display')) 58 | return null; 59 | var fields = getBuildFields(), 60 | pos = currentPos(); 61 | var addedFields = []; 62 | var ctorAdded = [], 63 | ctor = null; 64 | 65 | for (f in fields) 66 | { 67 | if (f.name == "new") ctor = f; 68 | if (f.access.has(AStatic)) 69 | continue; 70 | switch f.kind { 71 | case FVar(t,e): 72 | if (!f.meta.exists(function(v) return v.name == ":skip") && f.access.has(APublic)) 73 | addedFields.push(f); 74 | if (e == null) 75 | { 76 | switch t { 77 | case TAnonymous(fields): 78 | var objDecl = []; 79 | for (f in fields) 80 | { 81 | switch f.kind { 82 | case FVar(_,null): 83 | objDecl.push({ field:f.name, expr: macro @:pos(f.pos) cast null }); 84 | case FVar(t,e): 85 | objDecl.push({ field:f.name, expr: e }); 86 | f.kind = FVar(t,null); 87 | case _: 88 | } 89 | } 90 | e = { expr:EObjectDecl(objDecl), pos:f.pos }; 91 | case null | _: 92 | } 93 | } 94 | 95 | if (e != null) 96 | { 97 | var ethis = { expr: EField(macro this, f.name), pos:f.pos }; 98 | ctorAdded.push(macro $ethis = $e); 99 | f.kind = FVar(t,null); 100 | } 101 | case FProp(get,set,t,e): 102 | if (!f.meta.exists(function(v) return v.name == ":skip") && f.access.has(APublic)) 103 | addedFields.push(f); 104 | if (e != null) 105 | { 106 | var ethis = { expr: EField(macro this, f.name), pos:f.pos }; 107 | ctorAdded.push(macro $ethis = $e); 108 | f.kind = FProp(get,set,t,null); 109 | } 110 | case _: 111 | } 112 | } 113 | 114 | function filter(f:Field) 115 | { 116 | switch (f.kind) 117 | { 118 | case FVar(t,_) | FProp(_,_,t,_): 119 | var t = t.toType(); 120 | if (t != null) switch (t.follow()) 121 | { 122 | case TAbstract(_.get() => { pack:[], name:"Void" },_): 123 | return false; 124 | case _: 125 | return true; 126 | } 127 | case _: 128 | } 129 | return true; 130 | } 131 | 132 | var f2 = fields.filter(filter); 133 | var i = 0; 134 | for (f in addedFields) 135 | if (f.name == "_") 136 | f.name = "_" + i++; 137 | 138 | if (fields.exists(function (cf) return cf.name == fieldName)) 139 | { 140 | if (ctorAdded.length == 0 && f2.length == fields.length) 141 | return null; 142 | } else { 143 | switch ComplexType.TAnonymous(addedFields).toType() { 144 | case TAnonymous(_.get() => f): 145 | var complex = getLocalType().toComplexType(); 146 | var allfields = [], 147 | ethis = if (fieldName == null) 148 | macro ( (cast this.target) : $complex); 149 | else 150 | macro this; 151 | var fs = [ for (f in f.fields) f.name => f ]; 152 | for (cf in addedFields) 153 | { 154 | var ethis = { expr:EField(ethis, cf.name), pos:pos }; 155 | var expr = exprFromType(ethis, fs[cf.name]); 156 | if (expr == null) 157 | continue; 158 | 159 | changePos(expr,cf.pos); 160 | allfields.push(expr); 161 | } 162 | var block = { expr:EBlock(allfields), pos:pos }; 163 | var td = macro class extends unityeditor.Editor { @:overload public function OnGUI() $block; }; 164 | 165 | if (fieldName == null) 166 | { 167 | var cl = getLocalClass().get(); 168 | allfields.push(macro unityeditor.EditorUtility.SetDirty(this.target)); 169 | // trace(block.toString()); 170 | switch macro @:meta(UnityEditor.CustomEditor(typeof($i{cl.name}))) "" { 171 | case { expr:EMeta(m,_) }: 172 | td.meta = [m]; 173 | case _: throw "assert"; 174 | } 175 | 176 | if (cl.meta.has(':editMulti')) 177 | { 178 | switch macro @:meta(UnityEditor.CanEditMultipleObjects) "" { 179 | case { expr:EMeta(m,_) }: 180 | td.meta.push(m); 181 | case _: throw "assert"; 182 | } 183 | } 184 | 185 | //define type 186 | td.name = cl.name + '_Helper__'; 187 | td.pack = cl.pack.copy(); 188 | td.pack.push('editor'); 189 | td.fields[0].access.push(AOverride); 190 | td.fields[0].name = "OnInspectorGUI"; 191 | f2 = f2.filter(function(f) { 192 | if (f.meta.exists(function(m) return m.name == ":editor")) 193 | { 194 | switch (f.kind) { 195 | case FFun(fun) if (fun.expr != null): 196 | function map(e:Expr) 197 | { 198 | switch(e.expr) 199 | { 200 | case EConst(CIdent("this")): 201 | return ethis; 202 | case EConst(CIdent(id)): 203 | return try getTypedExpr( typeExpr(e) ) catch(exc:Dynamic) e; 204 | case _: 205 | return e.map(map); 206 | } 207 | } 208 | fun.expr = map(fun.expr); 209 | case _: 210 | } 211 | td.fields.push(f); 212 | return false; 213 | } else { 214 | return true; 215 | } 216 | }); 217 | if (cl.pack.length != 0) 218 | { 219 | cl.meta.add(':native', [macro $v{cl.name}], cl.pos); 220 | } 221 | try { 222 | defineType(td); 223 | } catch(e:Dynamic) { trace(e); } 224 | } else { 225 | td.fields[0].name = fieldName; 226 | f2.push(td.fields[0]); 227 | } 228 | case _: throw "assert"; 229 | } 230 | } 231 | 232 | if (ctorAdded.length > 0) 233 | { 234 | if (ctor == null) 235 | { 236 | var sup = getSuper(getLocalClass()), 237 | block = [], 238 | expr = { expr:EBlock(block), pos:pos }; 239 | var kind = sup == null || sup.length == 0 ? FFun({ args:[], ret:null, expr:expr}) : FFun({ args:[ for (s in sup) { name:s.name, opt:s.opt, type:null } ], ret:null, expr:expr }); 240 | if (sup != null) 241 | { 242 | block.push({ expr:ECall(macro super, [ for (s in sup) macro $i{s.name} ]), pos:pos }); 243 | } 244 | 245 | ctor = { name: "new", access: [APublic], pos:pos, kind:kind }; 246 | f2.push(ctor); 247 | } 248 | switch ctor.kind { 249 | case FFun(fn): 250 | var arr = null; 251 | switch fn.expr { 252 | case { expr: EBlock(bl) }: 253 | arr = bl; 254 | case _: 255 | fn.expr = { expr: EBlock( arr = [fn.expr] ), pos: pos }; 256 | } 257 | for (added in ctorAdded) 258 | arr.push(added); 259 | case _: throw "assert"; 260 | } 261 | } 262 | return f2; 263 | } 264 | 265 | private static function getSuper(cls:Ref) 266 | { 267 | var sup = cls.get().superClass; 268 | if (sup == null) 269 | return null; 270 | 271 | var ctor = sup.t.get().constructor; 272 | if (ctor == null) 273 | return getSuper(sup.t); 274 | return switch ctor.get().type.follow() { 275 | case TFun(args,_): 276 | args; 277 | case _: throw "assert"; 278 | } 279 | } 280 | 281 | private static function changePos(e:Expr,p) 282 | { 283 | function iter(e:Expr) 284 | { 285 | e.pos = p; 286 | e.iter(iter); 287 | } 288 | iter(e); 289 | } 290 | 291 | private static function exprFromType(ethis:Expr, field:ClassField, ?type):Expr 292 | { 293 | if (field == null) return null; 294 | if (type == null) type = field.type; 295 | var pos = field.pos; 296 | var pack = null, 297 | name = null, 298 | params = null, 299 | etype = null; 300 | switch type { 301 | case TMono(r) if (r != null): 302 | exprFromType(ethis,field,r.get()); 303 | 304 | case TMono(_) | TDynamic(_): 305 | // pack = []; name = "Dynamic"; params = []; 306 | // throw new Error('Unsupported Dynamic',pos); 307 | return null; 308 | case TEnum(e,p): 309 | var e = e.get(); 310 | etype = e; 311 | pack = e.pack; name = e.name; params = p; 312 | case TInst(c,p): 313 | var c = c.get(); 314 | pack = c.pack; name = c.name; params = p; 315 | case TAnonymous(a): 316 | var a = a.get(); 317 | var fields = a.fields; 318 | fields.sort(function(v1,v2) return Reflect.compare(getPosInfos(v1.pos).min, getPosInfos(v2.pos).min)); 319 | var arr = []; 320 | for (cf in fields) 321 | { 322 | var e = exprFromType(ethis,cf); 323 | if (e != null) 324 | arr.push(e); 325 | } 326 | return { expr: EBlock(arr), pos: pos }; 327 | case TFun(_,_): 328 | // throw new Error('Unsupported function',pos); 329 | return null; 330 | 331 | case TAbstract(t,p): 332 | var t = t.get(); 333 | pack = t.pack; name = t.name; params = p; 334 | case TType(_.get() => { pack:['unihx','inspector'], name:n },p): 335 | pack = ['unihx','inspector']; name = n; params = p; 336 | 337 | case TType(_,_): 338 | return exprFromType(ethis, field, follow(type,true)); 339 | case _: 340 | return null; 341 | // case _: throw new Error('assert',pos); 342 | } 343 | 344 | var unity = false, 345 | inspector = false; 346 | switch pack { 347 | case ['unityengine']: 348 | unity = true; 349 | case ['unihx','inspector']: 350 | unity = true; 351 | inspector = true; 352 | case _: 353 | } 354 | 355 | var docs = field.doc != null ? [ for (c in parseComments(field.doc)) (c.tag == null ? "" : c.tag.trim()) => c.contents.trim() ] : new Map(); 356 | 357 | var label = docs.get('label'); 358 | if (label == null) 359 | label = toSep(field.name, ' '.code); 360 | var tooltip = docs['']; 361 | var guiContent = if (tooltip == null) 362 | { 363 | // macro $v{label}; 364 | macro new unityengine.GUIContent($v{label}); 365 | } else { 366 | macro new unityengine.GUIContent($v{label}, $v{tooltip}); 367 | } 368 | 369 | var opts = field.doc == null ? null : nativeArray(getOptions(docs, field.pos), pos); 370 | if (opts == null) 371 | opts = macro null; 372 | // opts = macro new cs.NativeArray(0); 373 | 374 | switch name { 375 | case 'Vector2' if (unity): 376 | return macro $ethis = unityeditor.EditorGUILayout.Vector2Field($guiContent, $ethis, $opts); 377 | case 'Vector3' if (unity): 378 | return macro $ethis = unityeditor.EditorGUILayout.Vector3Field($guiContent, $ethis, $opts); 379 | case 'Vector4' if (unity): 380 | return macro $ethis = unityeditor.EditorGUILayout.Vector4Field($guiContent, $ethis, $opts); 381 | case 'AnimationCurve' if (unity): 382 | var range = parseRect(docs['range']), 383 | color = parseColor(docs['color']); 384 | if (color == null) 385 | color = parseColor('green'); 386 | if (range == null) 387 | return macro $ethis = unityeditor.EditorGUILayout.CurveField($guiContent, $ethis, $opts); 388 | else 389 | return macro $ethis = unityeditor.EditorGUILayout.CurveField($guiContent, $ethis, $color, $range, $opts); 390 | case 'Color' if (unity): 391 | return macro $ethis = unityeditor.EditorGUILayout.ColorField($guiContent, $ethis, $opts); 392 | case 'Int' if (pack.length == 0): 393 | return macro $ethis = unityeditor.EditorGUILayout.IntField($guiContent, $ethis, $opts); 394 | case 'Slider' if (inspector): 395 | switch params { 396 | case [ _.follow() => TAbstract(_.get() => { pack:[], name:name },_) ]: switch name { 397 | case "Int": 398 | return macro $ethis.value = unityeditor.EditorGUILayout.IntSlider($guiContent, $ethis.value, $ethis.minLimit, $ethis.maxLimit, $opts); 399 | case "Float" | "Single": 400 | return macro $ethis.value = unityeditor.EditorGUILayout.Slider($guiContent, $ethis.value, $ethis.minLimit, $ethis.maxLimit, $opts); 401 | case _: 402 | throw new Error("Invalid parameter for Slider: " + name, pos); 403 | } 404 | case _: 405 | throw new Error("Invalid parameter for Slider", pos); 406 | } 407 | case 'Layer' if (inspector): 408 | return macro $ethis = unityeditor.EditorGUILayout.LayerField($guiContent, $ethis, $opts); 409 | case 'Password' if (inspector): 410 | return macro $ethis = unityeditor.EditorGUILayout.PasswordField($guiContent, $ethis, $opts); 411 | case 'Range' if (inspector): 412 | return macro unityeditor.EditorGUILayout.MinMaxSlider($guiContent, $ethis.minValue, $ethis.maxValue, $ethis.minLimit, $ethis.maxLimit, $opts); 413 | case 'Rect' if (unity): 414 | return macro unityeditor.EditorGUILayout.RectField($guiContent, $ethis, $opts); 415 | case 'Select' if (inspector): 416 | return macro $ethis.selectedIndex = unityeditor.EditorGUILayout.Popup($guiContent, $ethis.selectedIndex, $ethis.options, $opts); 417 | case 'Space' if (inspector): 418 | return macro unityeditor.EditorGUILayout.Space(); 419 | case 'Tag' if (inspector): 420 | return macro $ethis = unityeditor.EditorGUILayout.TagField($guiContent, $ethis, $opts); 421 | case 'Text' | 'String': 422 | return macro $ethis = unityeditor.EditorGUILayout.TextField($guiContent, $ethis, $opts); 423 | case 'ConstLabel': 424 | return macro unityeditor.EditorGUILayout.LabelField($guiContent, $opts); 425 | case 'TextArea' if (inspector): 426 | return macro $ethis = unityeditor.EditorGUILayout.TextArea($ethis, $opts); 427 | case 'Bool' if (pack.length == 0): 428 | return macro $ethis = unityeditor.EditorGUILayout.Toggle($guiContent, $ethis, $opts); 429 | case 'Button' if (inspector): 430 | var e = macro $ethis = unityengine.GUILayout.Button($guiContent, $opts); 431 | if (docs['onclick'] != null) 432 | { 433 | var parsed = parse(docs['onclick'], pos); 434 | return macro if ($e) $parsed; 435 | } 436 | return e; 437 | case _ if (field.type.unify( getType("unityengine.Object") )): 438 | var allowSceneObjects = parseBool(docs['scene-objects']), 439 | type = parse(pack.join(".") + (pack.length == 0 ? name : "." + name),pos); 440 | if (allowSceneObjects == null) 441 | allowSceneObjects = false; 442 | return macro $ethis = cast unityeditor.EditorGUILayout.ObjectField($guiContent, $ethis, cs.Lib.toNativeType($type), $v{allowSceneObjects}, $opts); 443 | case _ if (field.type.unify( getType('unihx.inspector.InspectorBuild') )): 444 | return macro if (ethis != null) $ethis.OnGUI(); 445 | case _ if (etype != null): 446 | return macro $ethis = ${exprFromEnum(ethis, etype, type, guiContent, opts)}; 447 | case _: 448 | return null; 449 | } 450 | } 451 | 452 | private static function exprFromEnum(ethis:Expr, e:EnumType, t:Type, label, opts):Expr 453 | { 454 | //ensure created helper class 455 | var tname = ensureEnumHelper(e,t,ethis.pos); 456 | return macro $tname.editorHelper($ethis, $label, $opts); 457 | } 458 | 459 | public static function buildEnumHelper(module:String, name:String) 460 | { 461 | var type = getModule(module).find(function(v) return switch(v.follow()) { case TEnum(e,_) if (e.get().name == name): true; case _: false; }); 462 | var e = switch type { 463 | case TEnum(e,_): 464 | e.get(); 465 | default: 466 | throw new Error("assert: not an enum : " + name, currentPos()); 467 | }; 468 | var pos = currentPos(); 469 | 470 | // starting type definition 471 | var etype = type.toComplexType(); 472 | var cases = [], 473 | guiContent = [], 474 | values = []; 475 | var i = 0; 476 | for (name in e.names) 477 | { 478 | var ctor = e.constructs.get(name); 479 | var docs = ctor.doc != null ? [ for (c in parseComments(ctor.doc)) (c.tag == null ? "" : c.tag.trim() == "arg" ? c.tag.trim() + "-" + c.contents.trim().split(' ')[0] : c.tag.trim()) => c.contents.trim() ] : new Map(); 480 | 481 | var label = docs.get('label'); 482 | if (label == null) 483 | label = toSep(ctor.name, ' '.code); 484 | // var ct = macro $v{label}; 485 | var tooltip = docs['']; 486 | var ct = if (tooltip == null) 487 | { 488 | macro new unityengine.GUIContent($v{label}); 489 | } else { 490 | macro new unityengine.GUIContent($v{label}, $v{tooltip}); 491 | } 492 | guiContent.push(ct); 493 | values.push(macro $v{++i}); 494 | switch ctor.type.follow() { 495 | case TEnum(_,_): 496 | cases.push( { values:[macro $v{i}], expr:macro return ${parse( etype.toString() + '.' + name, pos )}, guard:null } ); 497 | case TFun(args,_): 498 | var exprs = [{ expr:EVars([ for (arg in args) { name:arg.name, expr:macro cast null, type:null } ]), pos:pos } ]; 499 | exprs.push(macro unityeditor.EditorGUILayout.BeginHorizontal(null)); 500 | exprs.push(macro unityeditor.EditorGUILayout.Space()); 501 | exprs.push(macro unityeditor.EditorGUILayout.BeginVertical(null)); 502 | exprs.push({ expr:ESwitch( 503 | macro current, 504 | [{ 505 | values:[{ expr:ECall(macro $i{name}, [ for (arg in args) macro $i{arg.name + "_arg"} ]), pos:pos }], 506 | expr: { expr:EBlock([ for (arg in args) macro $i{arg.name} = $i{arg.name + "_arg" } ]), pos: pos } 507 | }], 508 | macro null), 509 | pos: pos }); 510 | exprs.push( { expr:EVars([ for (arg in args) { name:arg.name + "__changed", expr:macro $i{arg.name}, type:null } ]), pos:pos } ); 511 | for (arg in args) 512 | { 513 | var ret = exprFromType( (macro $i{arg.name + "__changed"}), { 514 | name: arg.name, 515 | type: arg.t, 516 | isPublic: true, 517 | params: [], 518 | meta: null, 519 | kind: FVar(AccNormal,AccNever), 520 | expr: null, 521 | pos: ctor.pos, 522 | doc: docs['arg-' + arg.name] 523 | }); 524 | if (ret != null) 525 | exprs.push(ret); 526 | }; 527 | exprs.push(macro unityeditor.EditorGUILayout.EndVertical()); 528 | exprs.push(macro unityeditor.EditorGUILayout.EndHorizontal()); 529 | var cond = macro popup != $v{i}; 530 | for (arg in args) 531 | cond = macro $cond || !std.Type.enumEq($i{arg.name}, $i{arg.name + "__changed"}); 532 | exprs.push( 533 | macro if ($cond) 534 | return ${ { expr:ECall(parse( etype.toString() + '.' + name, pos ), [ for (arg in args) macro $i{arg.name+"__changed"} ]), pos:pos } }; 535 | else 536 | return current 537 | ); 538 | cases.push( { values:[macro $v{i}], expr: { expr:EBlock(exprs), pos:pos }, guard:null } ); 539 | case _: 540 | throw "assert"; 541 | } 542 | } 543 | var eswitch = { expr:ESwitch(macro p2, cases, macro return null), pos: pos }; 544 | var expr = macro { 545 | var popup = current == null ? 0 : std.Type.enumIndex(current) + 1; 546 | var guiContent = ${nativeArray(guiContent,pos)}; 547 | var values = ${nativeArray(values,pos)}; 548 | var p2 = unityeditor.EditorGUILayout.IntPopup( label, popup, guiContent, values, opts ); 549 | $eswitch; 550 | return null; 551 | }; 552 | 553 | var target = e.module.split('.').join('/') + ".hx"; 554 | for (path in getClassPath()) 555 | { 556 | if (exists(path + "/" + target)) 557 | { 558 | registerModuleDependency(getLocalModule(), path + "/" + target); 559 | break; 560 | } 561 | } 562 | 563 | var td = macro class { public static function editorHelper( current:Null<$etype>, label:unityengine.GUIContent, opts:cs.NativeArray ) : Null<$etype> $expr; }; 564 | return td.fields; 565 | } 566 | 567 | public static var enumHelpers = new Map(); 568 | 569 | static function __init__() 570 | { 571 | enumHelpers = new Map(); 572 | onMacroContextReused(function() { 573 | enumHelpers = new Map(); 574 | return true; 575 | }); 576 | } 577 | 578 | private static function ensureEnumHelper(e:EnumType, type:Type, pos:Position):Expr 579 | { 580 | if (e.params.length > 0) 581 | throw new Error("Enum with type parameters is currently unsupported",pos); 582 | var tname = e.pack.join('.') + (e.pack.length == 0 ? "" : ".") + e.name; 583 | if (!enumHelpers[tname]) 584 | { 585 | var td = macro class { }; 586 | switch macro @:build(unihx.inspector.Macro.buildEnumHelper($v{e.module}, $v{e.name})) "" { 587 | case { expr: EMeta(m,_) }: 588 | td.meta = [m]; 589 | default: throw "assert"; 590 | } 591 | td.name = e.name + "_Helper__"; 592 | td.pack = e.pack; 593 | try { 594 | defineType(td); 595 | } catch(e:Dynamic) { trace(e); } 596 | enumHelpers[tname] = true; 597 | } 598 | // var t = try getType(tname + "_Helper__") catch(e:Dynamic) null; 599 | // if (t == null) 600 | return parse( tname + "_Helper__", pos ); 601 | } 602 | 603 | private static function nativeArray(arr:Array,pos:Position):Expr 604 | { 605 | if (arr == null || arr.length == 0) 606 | return null; 607 | var ret = []; 608 | ret.push(macro var opts = new cs.NativeArray($v{arr.length})); 609 | for (i in 0...arr.length) 610 | { 611 | ret.push(macro opts[$v{i}] = ${arr[i]}); 612 | } 613 | ret.push(macro opts); 614 | return { expr:EBlock(ret), pos:pos }; 615 | } 616 | 617 | private static function getOptions(opts:Map,pos:Position):Array 618 | { 619 | var ret = []; 620 | var width = parseFloat(opts['width']), 621 | expandHeight = parseBool(opts['expand-height']), 622 | expandWidth = parseBool(opts['expand-width']), 623 | height = parseFloat(opts['height']), 624 | maxWidth = parseFloat(opts['max-width']), 625 | minWidth = parseFloat(opts['min-width']), 626 | maxHeight = parseFloat(opts['max-height']), 627 | minHeight = parseFloat(opts['min-height']); 628 | 629 | if (minHeight != null) 630 | ret.push(macro unityengine.GUILayout.MinHeight($v{minHeight})); 631 | if (maxHeight != null) 632 | ret.push(macro unityengine.GUILayout.MaxHeight($v{maxHeight})); 633 | if (minWidth != null) 634 | ret.push(macro unityengine.GUILayout.MinWidth($v{minWidth})); 635 | if (maxWidth != null) 636 | ret.push(macro unityengine.GUILayout.MaxWidth($v{maxWidth})); 637 | if (height != null) 638 | ret.push(macro unityengine.GUILayout.Height($v{height})); 639 | if (expandWidth != null) 640 | ret.push(macro unityengine.GUILayout.ExpandWidth($v{expandWidth})); 641 | if (expandHeight != null) 642 | ret.push(macro unityengine.GUILayout.ExpandHeight($v{expandHeight})); 643 | if (width != null) 644 | ret.push(macro unityengine.GUILayout.Width($v{width})); 645 | 646 | return ret; 647 | } 648 | 649 | private static function parseFloat(str:String):Null 650 | { 651 | if (str == null) 652 | return null; 653 | var ret = Std.parseFloat(str); 654 | if (Math.isNaN(ret)) 655 | return null; 656 | return ret; 657 | } 658 | 659 | private static function parseBool(str:String):Null 660 | { 661 | return switch str { 662 | case null: 663 | null; 664 | case 'YES' | 'yes' | 'true': 665 | true; 666 | case 'NO' | 'no' | 'false': 667 | false; 668 | case _: 669 | null; 670 | } 671 | } 672 | 673 | private static function parseRect(str:String):Null 674 | { 675 | if (str == null) 676 | return null; 677 | var arr = str.trim().split(',').map(Std.parseFloat); 678 | return macro new unityengine.Rect($v{arr[0]},$v{arr[1]},$v{arr[2]},$v{arr[3]}); 679 | } 680 | 681 | private static function parseColor(str:String):Null 682 | { 683 | if (str == null) 684 | return null; 685 | 686 | var rgba = switch str.trim() { 687 | case 'black': 688 | 0x000000ff; 689 | case 'blue': 690 | 0x0000ffff; 691 | case 'clear': 692 | 0x0; 693 | case 'cyan': 694 | 0x00FFFFFF; 695 | case 'gray': 696 | 0x808080ff; 697 | case 'magenta': 698 | 0xff00ffff; 699 | case 'red': 700 | 0xff0000ff; 701 | case 'white': 702 | 0xffffffff; 703 | case 'yellow': 704 | 0xffea04ff; 705 | case s if (s.charCodeAt(0) == '#'.code): 706 | s = s.substr(1); 707 | switch s.length { 708 | case 3: 709 | Std.parseInt('0x' + s.charAt(0) + s.charAt(0) + s.charAt(1) + s.charAt(1) + s.charAt(2) + s.charAt(2) + 'ff'); 710 | case 4: 711 | Std.parseInt('0x' + s.charAt(0) + s.charAt(0) + s.charAt(1) + s.charAt(1) + s.charAt(2) + s.charAt(2) + s.charAt(3) + s.charAt(3)); 712 | case 6: 713 | Std.parseInt('0x' + s + "ff"); 714 | case 8: 715 | Std.parseInt('0x' + s); 716 | default: 717 | return null; 718 | } 719 | case _: 720 | return null; 721 | } 722 | var r = (rgba >>> 24) & 0xFF, 723 | g = (rgba >>> 16) & 0xFF, 724 | b = (rgba >>> 8) & 0xFF, 725 | a = rgba & 0xff; 726 | return macro new unityengine.Color($v{r / 0xff}, $v{g / 0xff}, $v{b / 0xff}, $v{a / 0xff}); 727 | } 728 | 729 | private static function parseComments(c:String):Array<{ tag:Null, contents:String }> 730 | { 731 | var ret = []; 732 | var curTag = null; 733 | var txt = new StringBuf(); 734 | for (ln in c.split("\n")) 735 | { 736 | var i = 0, len = ln.length; 737 | while (i < len) 738 | { 739 | switch(ln.fastCodeAt(i)) 740 | { 741 | case ' '.code, '\t'.code, '*'.code: i++; 742 | case '@'.code: //found a tag 743 | var t = txt.toString(); 744 | txt = new StringBuf(); 745 | if (curTag != null || t.length > 0) 746 | { 747 | ret.push({ tag:curTag, contents:t }); 748 | } 749 | var begin = ++i; 750 | while(i < len) 751 | { 752 | switch(ln.fastCodeAt(i)) 753 | { 754 | case ' '.code, '\t'.code: 755 | break; 756 | default: i++; 757 | } 758 | } 759 | curTag = ln.substr(begin, i - begin); 760 | break; 761 | default: break; 762 | } 763 | } 764 | if (i < len) 765 | { 766 | txt.add(ln.substr(i).replace("\r", "").trim()); 767 | txt.addChar(' '.code); 768 | } 769 | txt.addChar('\n'.code); 770 | } 771 | 772 | var t = txt.toString().trim(); 773 | if (curTag != null || t.length > 0) 774 | ret.push({ tag:curTag, contents: t }); 775 | 776 | return ret; 777 | } 778 | 779 | private static function toSep(s:String,sep:Int):String 780 | { 781 | if (s.length <= 1) return s; //allow upper-case aliases 782 | var buf = new StringBuf(); 783 | var first = true; 784 | for (i in 0...s.length) 785 | { 786 | var chr = s.charCodeAt(i); 787 | if (chr >= 'A'.code && chr <= 'Z'.code) 788 | { 789 | if (!first) 790 | buf.addChar(sep); 791 | buf.addChar( chr - ('A'.code - 'a'.code) ); 792 | first = true; 793 | } else { 794 | buf.addChar(chr); 795 | first = false; 796 | } 797 | } 798 | 799 | return buf.toString(); 800 | } 801 | #end 802 | } 803 | -------------------------------------------------------------------------------- /unihx/inspector/ObjectField.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | 3 | //@allow-scene-objects 4 | typedef ObjectField = T; 5 | -------------------------------------------------------------------------------- /unihx/inspector/Password.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | 3 | typedef Password = String; 4 | -------------------------------------------------------------------------------- /unihx/inspector/Range.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | 3 | //@upper @lower / @min @max 4 | //MinMax 5 | /** 6 | A special slider the user can use to specify a range between a min and a max. 7 | **/ 8 | @:struct class Range 9 | { 10 | public var minLimit:Single; 11 | public var maxLimit:Single; 12 | public var minValue:Single; 13 | public var maxValue:Single; 14 | 15 | public function new(minLimit,maxLimit, ?minValue,?maxValue) 16 | { 17 | this.minLimit = minLimit; 18 | this.maxLimit = maxLimit; 19 | this.minValue = minValue == null ? minLimit : minValue; 20 | this.maxValue == null ? maxLimit : maxValue; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /unihx/inspector/Rect.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | 3 | typedef Rect = unityengine.Rect; 4 | -------------------------------------------------------------------------------- /unihx/inspector/Select.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | import cs.NativeArray; 3 | 4 | /** 5 | A generic popup selection field. 6 | **/ 7 | @:struct @:nativeGen class Select 8 | { 9 | public var options:NativeArray; 10 | public var values:NativeArray; 11 | public var selectedIndex:Int; 12 | 13 | public var selected(get,never):Null; 14 | 15 | public function new(options:Array,values:Array,selected=-1) 16 | { 17 | this.options = cs.Lib.nativeArray(options,true); 18 | this.values = cs.Lib.nativeArray(values,true); 19 | this.selectedIndex = selected; 20 | } 21 | 22 | public static function fromOptions(options:Array,selected=-1):Select 23 | { 24 | return new Select(options,options,selected); 25 | } 26 | 27 | public static function fromMap(map:Map,?selected:String) 28 | { 29 | var arr = [ for (key in map.keys()) key ], 30 | vals = [ for (k in arr) map[k] ]; 31 | var sel = if (selected == null) 32 | -1; 33 | else 34 | arr.indexOf(selected); 35 | return new Select(arr,vals,sel); 36 | } 37 | 38 | private function get_selected():Null 39 | { 40 | return selectedIndex < 0 ? null : values[selectedIndex]; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /unihx/inspector/Slider.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | 3 | /** 4 | A special slider the user can use to specify a value between a min and a max. 5 | **/ 6 | @:nativeGen @:struct class Slider 7 | { 8 | public var minLimit:T; 9 | public var maxLimit:T; 10 | public var value:T; 11 | 12 | public function new(min,max,?value) 13 | { 14 | this.minLimit = min; 15 | this.maxLimit = max; 16 | this.value = value == null ? minLimit : value; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /unihx/inspector/Space.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | 3 | typedef Space = Void; // will be removed from the builded class 4 | -------------------------------------------------------------------------------- /unihx/inspector/Tag.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | 3 | typedef Tag = String; 4 | -------------------------------------------------------------------------------- /unihx/inspector/TextArea.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | 3 | typedef TextArea = String; 4 | -------------------------------------------------------------------------------- /unihx/inspector/Vector2.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | 3 | typedef Vector2 = unityengine.Vector2; 4 | -------------------------------------------------------------------------------- /unihx/inspector/Vector3.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | 3 | typedef Vector3 = unityengine.Vector3; 4 | -------------------------------------------------------------------------------- /unihx/inspector/Vector4.hx: -------------------------------------------------------------------------------- 1 | package unihx.inspector; 2 | 3 | typedef Vector4 = unityengine.Vector4; 4 | -------------------------------------------------------------------------------- /unityengine/Bounds.hx: -------------------------------------------------------------------------------- 1 | package unityengine; 2 | 3 | private typedef Data = 4 | #if macro 5 | Void 6 | #else 7 | BoundsData 8 | #end; 9 | 10 | @:forward abstract Bounds(Data) from Data to Data 11 | { 12 | #if !macro 13 | @:extern inline public function new(center:Vector3,size:Vector3) 14 | { 15 | this = new BoundsData(center,size); 16 | } 17 | @:extern inline public static function fromData(data:BoundsData):Bounds 18 | { 19 | return data; 20 | } 21 | #end 22 | 23 | macro public function with(ethis:haxe.macro.Expr, obj:haxe.macro.Expr):haxe.macro.Expr 24 | { 25 | return unihx._internal.StructHelper.with(['center','size'], macro : unityengine.Bounds, ethis, obj); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /unityengine/BoundsData.hx: -------------------------------------------------------------------------------- 1 | package unityengine; 2 | 3 | @:final @:csNative @:native("UnityEngine.Bounds") extern class BoundsData extends cs.system.ValueType 4 | { 5 | var center(get,set) : Vector3; 6 | var extents(get,set) : Vector3; 7 | var max(get,set) : Vector3; 8 | var min(get,set) : Vector3; 9 | var size(get,set) : Vector3; 10 | @:final @:overload function new(center : Vector3, size : Vector3) : Void; 11 | @:final @:overload function Contains(point : Vector3) : Bool; 12 | @:final @:overload function Encapsulate(point : Vector3) : Void; 13 | @:final @:overload function Encapsulate(bounds : Bounds) : Void; 14 | @:final @:overload function Expand(amount : Single) : Void; 15 | @:final @:overload function Expand(amount : Vector3) : Void; 16 | @:final @:overload function IntersectRay(ray : Ray) : Bool; 17 | @:final @:overload function IntersectRay(ray : Ray, distance : cs.Ref) : Bool; 18 | @:final @:overload function Intersects(bounds : Bounds) : Bool; 19 | @:final @:overload function SetMinMax(min : Vector3, max : Vector3) : Void; 20 | @:final @:overload function SqrDistance(point : Vector3) : Single; 21 | @:final @:overload private function get_center() : Vector3; 22 | @:final @:overload private function get_extents() : Vector3; 23 | @:final @:overload private function get_max() : Vector3; 24 | @:final @:overload private function get_min() : Vector3; 25 | @:final @:overload private function get_size() : Vector3; 26 | @:final @:overload private function set_center(value : Vector3) : Vector3; 27 | @:final @:overload private function set_extents(value : Vector3) : Vector3; 28 | @:final @:overload private function set_max(value : Vector3) : Vector3; 29 | @:final @:overload private function set_min(value : Vector3) : Vector3; 30 | @:final @:overload private function set_size(value : Vector3) : Vector3; 31 | @:final @:overload static function op_Equality(lhs : Bounds, rhs : Bounds) : Bool; 32 | @:final @:overload static function op_Inequality(lhs : Bounds, rhs : Bounds) : Bool; 33 | } 34 | -------------------------------------------------------------------------------- /unityengine/Color.hx: -------------------------------------------------------------------------------- 1 | package unityengine; 2 | 3 | @:forward abstract Color(Data) from Data to Data 4 | { 5 | #if !macro 6 | @:extern inline public function new(r:Single,g:Single,b:Single,a:Single=1.0) 7 | { 8 | this = new Data(r,g,b,a); 9 | } 10 | 11 | @:extern inline public static function fromData(data:Data):Color 12 | { 13 | return data; 14 | } 15 | 16 | @:op(A+B) @:extern inline public static function add(a:Color, b:Color):Color 17 | { 18 | return Data.op_Addition(a,b); 19 | } 20 | 21 | @:op(A/B) @:extern inline public static function div(a:Color, b:Single):Color 22 | { 23 | return Data.op_Division(a,b); 24 | } 25 | 26 | @:from @:extern inline public static function fromVec4(vec:Vector4):Color 27 | { 28 | return new Color(vec.x, vec.y, vec.z, vec.w); 29 | } 30 | 31 | @:to @:extern inline public function toVec4():Vector4 32 | { 33 | return new Vector4(this.r, this.g, this.b, this.a); 34 | } 35 | 36 | @:op(A*B) @:extern inline public static function mul(a:Color, b:Color):Color 37 | { 38 | return Data.op_Multiply(a,b); 39 | } 40 | 41 | @:op(A*B) @:extern @:commutative inline public static function mulSingle(a:Color, b:Single):Color 42 | { 43 | return Data.op_Multiply(a,b); 44 | } 45 | 46 | @:op(A-B) @:extern inline public static function sub(a:Color, b:Color):Color 47 | { 48 | return Data.op_Subtraction(a,b); 49 | } 50 | 51 | @:arrayAccess @:extern inline public function get_Item(index:Int):Single 52 | { 53 | return this.get_Item(index); 54 | } 55 | 56 | @:arrayAccess @:extern inline public function set_Item(index:Int, val:Single):Single 57 | { 58 | this.set_Item(index,val); 59 | return val; 60 | } 61 | #end 62 | 63 | macro public function with(ethis:haxe.macro.Expr, obj:haxe.macro.Expr):haxe.macro.Expr 64 | { 65 | return unihx._internal.StructHelper.with(['r','g','b','a'], macro : unityengine.Color, ethis, obj); 66 | } 67 | } 68 | 69 | private typedef Data = 70 | #if macro 71 | Void 72 | #else 73 | ColorData 74 | #end; 75 | 76 | -------------------------------------------------------------------------------- /unityengine/Color32.hx: -------------------------------------------------------------------------------- 1 | package unityengine; 2 | import cs.StdTypes; 3 | 4 | @:forward abstract Color32(Data) from Data to Data 5 | { 6 | #if !macro 7 | @:extern inline public function new(r:UInt8,g:UInt8,b:UInt8,a:UInt8=0xff) 8 | { 9 | this = new Data(r,g,b,a); 10 | } 11 | 12 | @:extern inline public static function fromData(data:Data):Color32 13 | { 14 | return data; 15 | } 16 | 17 | @:from @:extern inline public static function fromColor(c:Color):Color32 18 | { 19 | return new Color32(Std.int(c.r * 0xff), Std.int(c.g * 0xff), Std.int(c.b * 0xff), Std.int(c.a * 0xff)); 20 | } 21 | 22 | @:to @:extern inline public function toColor():Color 23 | { 24 | return new Color(this.r / 0xff, this.g / 0xff, this.b / 0xff, this.a / 0xff); 25 | } 26 | #end 27 | 28 | macro public function with(ethis:haxe.macro.Expr, obj:haxe.macro.Expr):haxe.macro.Expr 29 | { 30 | return unihx._internal.StructHelper.with(['r','g','b','a'], macro : unityengine.Color32, ethis, obj); 31 | } 32 | } 33 | 34 | private typedef Data = 35 | #if macro 36 | Void 37 | #else 38 | Color32Data 39 | #end; 40 | 41 | 42 | -------------------------------------------------------------------------------- /unityengine/Color32Data.hx: -------------------------------------------------------------------------------- 1 | package unityengine; 2 | 3 | @:final @:csNative @:native("UnityEngine.Color32") extern class Color32Data extends cs.system.ValueType 4 | { 5 | var a : cs.types.UInt8; 6 | var b : cs.types.UInt8; 7 | var g : cs.types.UInt8; 8 | var r : cs.types.UInt8; 9 | @:final @:overload function new(r : cs.types.UInt8, g : cs.types.UInt8, b : cs.types.UInt8, a : cs.types.UInt8) : Void; 10 | @:final @:overload static function Lerp(a : Color32, b : Color32, t : Single) : Color32; 11 | @:final @:overload static function op_Implicit(c : Color) : Color32; 12 | @:final @:overload static function op_Implicit(c : Color32) : Color; 13 | } 14 | -------------------------------------------------------------------------------- /unityengine/ColorData.hx: -------------------------------------------------------------------------------- 1 | package unityengine; 2 | 3 | @:final @:csNative @:native("UnityEngine.Color") extern class ColorData extends cs.system.ValueType 4 | { 5 | var a : Single; 6 | var b : Single; 7 | var g : Single; 8 | var gamma(get,never) : Color; 9 | var grayscale(get,never) : Single; 10 | var linear(get,never) : Color; 11 | var r : Single; 12 | @:final @:overload function new(r : Single, g : Single, b : Single, a : Single) : Void; 13 | @:final @:overload function new(r : Single, g : Single, b : Single) : Void; 14 | @:final @:overload function get_Item(index : Int) : Single; 15 | @:final @:overload private function get_gamma() : Color; 16 | @:final @:overload private function get_grayscale() : Single; 17 | @:final @:overload private function get_linear() : Color; 18 | @:final @:overload function set_Item(index : Int, value : Single) : Void; 19 | static var black(get,never) : Color; 20 | static var blue(get,never) : Color; 21 | static var clear(get,never) : Color; 22 | static var cyan(get,never) : Color; 23 | static var gray(get,never) : Color; 24 | static var green(get,never) : Color; 25 | static var grey(get,never) : Color; 26 | static var magenta(get,never) : Color; 27 | static var red(get,never) : Color; 28 | static var white(get,never) : Color; 29 | static var yellow(get,never) : Color; 30 | @:final @:overload static function Lerp(a : Color, b : Color, t : Single) : Color; 31 | @:final @:overload static private function get_black() : Color; 32 | @:final @:overload static private function get_blue() : Color; 33 | @:final @:overload static private function get_clear() : Color; 34 | @:final @:overload static private function get_cyan() : Color; 35 | @:final @:overload static private function get_gray() : Color; 36 | @:final @:overload static private function get_green() : Color; 37 | @:final @:overload static private function get_grey() : Color; 38 | @:final @:overload static private function get_magenta() : Color; 39 | @:final @:overload static private function get_red() : Color; 40 | @:final @:overload static private function get_white() : Color; 41 | @:final @:overload static private function get_yellow() : Color; 42 | @:final @:overload static function op_Addition(a : Color, b : Color) : Color; 43 | @:final @:overload static function op_Division(a : Color, b : Single) : Color; 44 | @:final @:overload static function op_Equality(lhs : Color, rhs : Color) : Bool; 45 | @:final @:overload static function op_Implicit(c : Color) : Vector4; 46 | @:final @:overload static function op_Implicit(v : Vector4) : Color; 47 | @:final @:overload static function op_Inequality(lhs : Color, rhs : Color) : Bool; 48 | @:final @:overload static function op_Multiply(a : Color, b : Color) : Color; 49 | @:final @:overload static function op_Multiply(b : Single, a : Color) : Color; 50 | @:final @:overload static function op_Multiply(a : Color, b : Single) : Color; 51 | @:final @:overload static function op_Subtraction(a : Color, b : Color) : Color; 52 | } 53 | -------------------------------------------------------------------------------- /unityengine/HaxeBehaviour.hx: -------------------------------------------------------------------------------- 1 | package unityengine; 2 | 3 | @:nativeChildren class HaxeBehaviour extends MonoBehaviour 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /unityengine/Matrix4x4.hx: -------------------------------------------------------------------------------- 1 | package unityengine; 2 | 3 | @:forward abstract Matrix4x4(Data) from Data to Data 4 | { 5 | #if !macro 6 | @:extern inline public static function fromData(data:Data):Matrix4x4 7 | { 8 | return data; 9 | } 10 | 11 | @:op(A*B) @:extern inline public static function mul(a:Matrix4x4, b:Matrix4x4):Matrix4x4 12 | { 13 | return Data.op_Multiply(a,b); 14 | } 15 | 16 | @:op(A*B) @:extern @:commutative inline public static function mulVector(a:Matrix4x4, b:Vector4):Vector4 17 | { 18 | return Data.op_Multiply(a,b); 19 | } 20 | 21 | @:arrayAccess @:extern inline public function get_Item(index:Int):Single 22 | { 23 | return this.get_Item(index); 24 | } 25 | 26 | @:arrayAccess @:extern inline public function set_Item(index:Int, val:Single):Single 27 | { 28 | this.set_Item(index,val); 29 | return val; 30 | } 31 | #end 32 | } 33 | 34 | private typedef Data = 35 | #if macro 36 | Void 37 | #else 38 | Matrix4x4Data 39 | #end; 40 | 41 | -------------------------------------------------------------------------------- /unityengine/Matrix4x4Data.hx: -------------------------------------------------------------------------------- 1 | package unityengine; 2 | 3 | @:final @:csNative @:native("UnityEngine.Matrix4x4") extern class Matrix4x4Data extends cs.system.ValueType 4 | { 5 | var inverse(get,never) : Matrix4x4; 6 | var isIdentity(get,never) : Bool; 7 | var m00 : Single; 8 | var m01 : Single; 9 | var m02 : Single; 10 | var m03 : Single; 11 | var m10 : Single; 12 | var m11 : Single; 13 | var m12 : Single; 14 | var m13 : Single; 15 | var m20 : Single; 16 | var m21 : Single; 17 | var m22 : Single; 18 | var m23 : Single; 19 | var m30 : Single; 20 | var m31 : Single; 21 | var m32 : Single; 22 | var m33 : Single; 23 | var transpose(get,never) : Matrix4x4; 24 | @:final @:overload function GetColumn(i : Int) : Vector4; 25 | @:final @:overload function GetRow(i : Int) : Vector4; 26 | @:final @:overload function MultiplyPoint(v : Vector3) : Vector3; 27 | @:final @:overload function MultiplyPoint3x4(v : Vector3) : Vector3; 28 | @:final @:overload function MultiplyVector(v : Vector3) : Vector3; 29 | @:final @:overload function SetColumn(i : Int, v : Vector4) : Void; 30 | @:final @:overload function SetRow(i : Int, v : Vector4) : Void; 31 | @:final @:overload function SetTRS(pos : Vector3, q : Quaternion, s : Vector3) : Void; 32 | @:final @:overload function get_Item(row : Int, column : Int) : Single; 33 | @:final @:overload function get_Item(index : Int) : Single; 34 | @:final @:overload private function get_inverse() : Matrix4x4; 35 | @:final @:overload private function get_isIdentity() : Bool; 36 | @:final @:overload private function get_transpose() : Matrix4x4; 37 | @:final @:overload function set_Item(index : Int, value : Single) : Void; 38 | @:final @:overload function set_Item(row : Int, column : Int, value : Single) : Void; 39 | static var identity(get,never) : Matrix4x4; 40 | static var zero(get,never) : Matrix4x4; 41 | @:final @:overload static function Inverse(m : Matrix4x4) : Matrix4x4; 42 | @:final @:overload static function Ortho(left : Single, right : Single, bottom : Single, top : Single, zNear : Single, zFar : Single) : Matrix4x4; 43 | @:final @:overload static function Perspective(fov : Single, aspect : Single, zNear : Single, zFar : Single) : Matrix4x4; 44 | @:final @:overload static function Scale(v : Vector3) : Matrix4x4; 45 | @:final @:overload static function TRS(pos : Vector3, q : Quaternion, s : Vector3) : Matrix4x4; 46 | @:final @:overload static function Transpose(m : Matrix4x4) : Matrix4x4; 47 | @:final @:overload static private function get_identity() : Matrix4x4; 48 | @:final @:overload static private function get_zero() : Matrix4x4; 49 | @:final @:overload static function op_Equality(lhs : Matrix4x4, rhs : Matrix4x4) : Bool; 50 | @:final @:overload static function op_Inequality(lhs : Matrix4x4, rhs : Matrix4x4) : Bool; 51 | @:final @:overload static function op_Multiply(lhs : Matrix4x4, rhs : Matrix4x4) : Matrix4x4; 52 | @:final @:overload static function op_Multiply(lhs : Matrix4x4, v : Vector4) : Vector4; 53 | } 54 | -------------------------------------------------------------------------------- /unityengine/Quaternion.hx: -------------------------------------------------------------------------------- 1 | package unityengine; 2 | 3 | @:forward abstract Quaternion(Data) from Data to Data 4 | { 5 | #if !macro 6 | @:extern inline public function new(x:Single,y:Single,z:Single,w:Single) 7 | { 8 | this = new Data(x,y,z,w); 9 | } 10 | 11 | @:extern inline public static function fromData(data:Data):Quaternion 12 | { 13 | return data; 14 | } 15 | 16 | @:op(A*B) @:extern inline public static function mul(a:Quaternion, b:Quaternion):Quaternion 17 | { 18 | return Data.op_Multiply(a,b); 19 | } 20 | 21 | @:op(A*B) @:extern inline public function rotate(point:Vector3):Vector3 22 | { 23 | return Data.op_Multiply(this,point); 24 | } 25 | 26 | @:arrayAccess @:extern inline public function get_Item(index:Int):Single 27 | { 28 | return this.get_Item(index); 29 | } 30 | 31 | @:arrayAccess @:extern inline public function set_Item(index:Int, val:Single):Single 32 | { 33 | this.set_Item(index,val); 34 | return val; 35 | } 36 | #end 37 | 38 | macro public function with(ethis:haxe.macro.Expr, obj:haxe.macro.Expr):haxe.macro.Expr 39 | { 40 | return unihx._internal.StructHelper.with(['x','y','z','w'], macro : unityengine.Quaternion, ethis, obj); 41 | } 42 | } 43 | 44 | private typedef Data = 45 | #if macro 46 | Void 47 | #else 48 | QuaternionData 49 | #end; 50 | 51 | -------------------------------------------------------------------------------- /unityengine/QuaternionData.hx: -------------------------------------------------------------------------------- 1 | package unityengine; 2 | 3 | @:final @:csNative @:native("UnityEngine.Quaternion") extern class QuaternionData extends cs.system.ValueType 4 | { 5 | var eulerAngles(get,set) : Vector3; 6 | var w : Single; 7 | var x : Single; 8 | var y : Single; 9 | var z : Single; 10 | @:final @:overload function new(x : Single, y : Single, z : Single, w : Single) : Void; 11 | @:final @:overload function Set(new_x : Single, new_y : Single, new_z : Single, new_w : Single) : Void; 12 | @:final @:overload function SetAxisAngle(axis : Vector3, angle : Single) : Void; 13 | @:final @:overload function SetEulerAngles(x : Single, y : Single, z : Single) : Void; 14 | @:final @:overload function SetEulerAngles(euler : Vector3) : Void; 15 | @:final @:overload function SetEulerRotation(x : Single, y : Single, z : Single) : Void; 16 | @:final @:overload function SetEulerRotation(euler : Vector3) : Void; 17 | @:final @:overload function SetFromToRotation(fromDirection : Vector3, toDirection : Vector3) : Void; 18 | @:final @:overload function SetLookRotation(view : Vector3) : Void; 19 | @:final @:overload function SetLookRotation(view : Vector3, up : Vector3) : Void; 20 | @:final @:overload function ToAngleAxis(angle : cs.Ref, axis : cs.Ref) : Void; 21 | @:final @:overload function ToAxisAngle(axis : cs.Ref, angle : cs.Ref) : Void; 22 | @:final @:overload function ToEuler() : Vector3; 23 | @:final @:overload function ToEulerAngles() : Vector3; 24 | @:final @:overload function get_Item(index : Int) : Single; 25 | @:final @:overload private function get_eulerAngles() : Vector3; 26 | @:final @:overload function set_Item(index : Int, value : Single) : Void; 27 | @:final @:overload private function set_eulerAngles(value : Vector3) : Vector3; 28 | static var identity(get,never) : Quaternion; 29 | static var kEpsilon(default,never) : Single; 30 | @:final @:overload static function Angle(a : Quaternion, b : Quaternion) : Single; 31 | @:final @:overload static function AngleAxis(angle : Single, axis : Vector3) : Quaternion; 32 | @:final @:overload static function AxisAngle(axis : Vector3, angle : Single) : Quaternion; 33 | @:final @:overload static function Dot(a : Quaternion, b : Quaternion) : Single; 34 | @:final @:overload static function Euler(x : Single, y : Single, z : Single) : Quaternion; 35 | @:final @:overload static function Euler(euler : Vector3) : Quaternion; 36 | @:final @:overload static function EulerAngles(x : Single, y : Single, z : Single) : Quaternion; 37 | @:final @:overload static function EulerAngles(euler : Vector3) : Quaternion; 38 | @:final @:overload static function EulerRotation(x : Single, y : Single, z : Single) : Quaternion; 39 | @:final @:overload static function EulerRotation(euler : Vector3) : Quaternion; 40 | @:final @:overload static function FromToRotation(fromDirection : Vector3, toDirection : Vector3) : Quaternion; 41 | @:final @:overload static function Inverse(rotation : Quaternion) : Quaternion; 42 | @:final @:overload static function Lerp(from : Quaternion, to : Quaternion, t : Single) : Quaternion; 43 | @:final @:overload static function LookRotation(forward : Vector3, upwards : Vector3) : Quaternion; 44 | @:final @:overload static function LookRotation(forward : Vector3) : Quaternion; 45 | @:final @:overload static function RotateTowards(from : Quaternion, to : Quaternion, maxDegreesDelta : Single) : Quaternion; 46 | @:final @:overload static function Slerp(from : Quaternion, to : Quaternion, t : Single) : Quaternion; 47 | @:native("ToEulerAngles") @:final @:overload static function _ToEulerAngles(rotation : Quaternion) : Vector3; 48 | @:final @:overload static private function get_identity() : Quaternion; 49 | @:final @:overload static function op_Equality(lhs : Quaternion, rhs : Quaternion) : Bool; 50 | @:final @:overload static function op_Inequality(lhs : Quaternion, rhs : Quaternion) : Bool; 51 | @:final @:overload static function op_Multiply(lhs : Quaternion, rhs : Quaternion) : Quaternion; 52 | @:final @:overload static function op_Multiply(rotation : Quaternion, point : Vector3) : Vector3; 53 | } 54 | -------------------------------------------------------------------------------- /unityengine/Rect.hx: -------------------------------------------------------------------------------- 1 | package unityengine; 2 | 3 | @:forward abstract Rect(Data) from Data to Data 4 | { 5 | #if !macro 6 | @:extern inline public function new(left:Single,top:Single,width:Single,height:Single) 7 | { 8 | this = new Data(left,top,width,height); 9 | } 10 | 11 | @:extern inline public static function fromData(data:Data):Rect 12 | { 13 | return data; 14 | } 15 | 16 | #end 17 | 18 | macro public function with(ethis:haxe.macro.Expr, obj:haxe.macro.Expr):haxe.macro.Expr 19 | { 20 | return unihx._internal.StructHelper.with(['left','top','width','height'], macro : unityengine.Rect, ethis, obj); 21 | } 22 | } 23 | 24 | private typedef Data = 25 | #if macro 26 | Void 27 | #else 28 | RectData 29 | #end; 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /unityengine/RectData.hx: -------------------------------------------------------------------------------- 1 | package unityengine; 2 | 3 | @:final @:csNative @:native("UnityEngine.Rect") extern class RectData extends cs.system.ValueType 4 | { 5 | var bottom(get,never) : Single; 6 | var center(get,set) : Vector2; 7 | var height(get,set) : Single; 8 | var left(get,never) : Single; 9 | var right(get,never) : Single; 10 | var top(get,never) : Single; 11 | var width(get,set) : Single; 12 | var x(get,set) : Single; 13 | var xMax(get,set) : Single; 14 | var xMin(get,set) : Single; 15 | var y(get,set) : Single; 16 | var yMax(get,set) : Single; 17 | var yMin(get,set) : Single; 18 | @:final @:overload function new(left : Single, top : Single, width : Single, height : Single) : Void; 19 | @:final @:overload function new(source : Rect) : Void; 20 | @:final @:overload function Contains(point : Vector2) : Bool; 21 | @:final @:overload function Contains(point : Vector3, allowInverse : Bool) : Bool; 22 | @:final @:overload function Contains(point : Vector3) : Bool; 23 | @:final @:overload function Overlaps(other : Rect) : Bool; 24 | @:final @:overload function Overlaps(other : Rect, allowInverse : Bool) : Bool; 25 | @:final @:overload function Set(left : Single, top : Single, width : Single, height : Single) : Void; 26 | @:final @:overload private function get_bottom() : Single; 27 | @:final @:overload private function get_center() : Vector2; 28 | @:final @:overload private function get_height() : Single; 29 | @:final @:overload private function get_left() : Single; 30 | @:final @:overload private function get_right() : Single; 31 | @:final @:overload private function get_top() : Single; 32 | @:final @:overload private function get_width() : Single; 33 | @:final @:overload private function get_x() : Single; 34 | @:final @:overload private function get_xMax() : Single; 35 | @:final @:overload private function get_xMin() : Single; 36 | @:final @:overload private function get_y() : Single; 37 | @:final @:overload private function get_yMax() : Single; 38 | @:final @:overload private function get_yMin() : Single; 39 | @:final @:overload private function set_center(value : Vector2) : Vector2; 40 | @:final @:overload private function set_height(value : Single) : Single; 41 | @:final @:overload private function set_width(value : Single) : Single; 42 | @:final @:overload private function set_x(value : Single) : Single; 43 | @:final @:overload private function set_xMax(value : Single) : Single; 44 | @:final @:overload private function set_xMin(value : Single) : Single; 45 | @:final @:overload private function set_y(value : Single) : Single; 46 | @:final @:overload private function set_yMax(value : Single) : Single; 47 | @:final @:overload private function set_yMin(value : Single) : Single; 48 | @:final @:overload static function MinMaxRect(left : Single, top : Single, right : Single, bottom : Single) : Rect; 49 | @:final @:overload static function op_Equality(lhs : Rect, rhs : Rect) : Bool; 50 | @:final @:overload static function op_Inequality(lhs : Rect, rhs : Rect) : Bool; 51 | } 52 | -------------------------------------------------------------------------------- /unityengine/Vector2.hx: -------------------------------------------------------------------------------- 1 | package unityengine; 2 | 3 | @:forward abstract Vector2(Data) from Data to Data 4 | { 5 | #if !macro 6 | @:extern inline public function new(x:Single=.0,y:Single=.0) 7 | { 8 | this = new Data(x,y); 9 | } 10 | 11 | @:extern inline public static function fromData(data:Data):Vector2 12 | { 13 | return data; 14 | } 15 | 16 | @:op(A+B) @:extern inline public static function add(a:Vector2, b:Vector2):Vector2 17 | { 18 | return Data.op_Addition(a,b); 19 | } 20 | 21 | @:op(A/B) @:extern inline public static function div(a:Vector2, b:Single):Vector2 22 | { 23 | return Data.op_Division(a,b); 24 | } 25 | 26 | @:to @:extern inline public function toVec3():Vector3 27 | { 28 | return new Vector3(this.x,this.y); 29 | } 30 | 31 | @:to @:extern inline public function toVec4():Vector4 32 | { 33 | return new Vector4(this.x,this.y); 34 | } 35 | 36 | @:op(A*B) @:extern @:commutative inline public static function mul(a:Vector2, b:Single):Vector2 37 | { 38 | return Data.op_Multiply(a,b); 39 | } 40 | 41 | @:op(A-B) @:extern inline public static function sub(a:Vector2, b:Vector2):Vector2 42 | { 43 | return Data.op_Subtraction(a,b); 44 | } 45 | 46 | @:op(-A) @:extern inline public function negate():Vector2 47 | { 48 | return Data.op_UnaryNegation(this); 49 | } 50 | 51 | @:arrayAccess @:extern inline public function get_Item(index:Int):Single 52 | { 53 | return this.get_Item(index); 54 | } 55 | 56 | @:arrayAccess @:extern inline public function set_Item(index:Int, val:Single):Single 57 | { 58 | this.set_Item(index,val); 59 | return val; 60 | } 61 | #end 62 | 63 | macro public function with(ethis:haxe.macro.Expr, obj:haxe.macro.Expr):haxe.macro.Expr 64 | { 65 | return unihx._internal.StructHelper.with(['x','y'], macro : unityengine.Vector2, ethis, obj); 66 | } 67 | 68 | public static var kEpsilon(get,never) : Single; 69 | public static var one(get,never) : Vector2; 70 | public static var right(get,never) : Vector2; 71 | public static var up(get,never) : Vector2; 72 | public static var zero(get,never) : Vector2; 73 | 74 | inline static private function get_kEpsilon() : Single 75 | { 76 | return Data.kEpsilon; 77 | } 78 | inline static private function get_one() : Vector2 79 | { 80 | return Data.one; 81 | } 82 | inline static private function get_right() : Vector2 83 | { 84 | return Data.right; 85 | } 86 | inline static private function get_up() : Vector2 87 | { 88 | return Data.up; 89 | } 90 | inline static private function get_zero() : Vector2 91 | { 92 | return Data.zero; 93 | } 94 | } 95 | 96 | private typedef Data = 97 | #if macro 98 | Void 99 | #else 100 | Vector2Data 101 | #end; 102 | -------------------------------------------------------------------------------- /unityengine/Vector2Data.hx: -------------------------------------------------------------------------------- 1 | package unityengine; 2 | 3 | @:final @:csNative @:native("UnityEngine.Vector2") extern class Vector2Data extends cs.system.ValueType 4 | { 5 | var magnitude(get,never) : Single; 6 | var normalized(get,never) : Vector2; 7 | var sqrMagnitude(get,never) : Single; 8 | var x : Single; 9 | var y : Single; 10 | @:final @:overload function new(x : Single, y : Single) : Void; 11 | @:final @:overload function Normalize() : Void; 12 | @:final @:overload function Scale(scale : Vector2) : Void; 13 | @:final @:overload function Set(new_x : Single, new_y : Single) : Void; 14 | @:final @:overload function SqrMagnitude() : Single; 15 | @:final @:overload function get_Item(index : Int) : Single; 16 | @:final @:overload private function get_magnitude() : Single; 17 | @:final @:overload private function get_normalized() : Vector2; 18 | @:final @:overload private function get_sqrMagnitude() : Single; 19 | @:final @:overload function set_Item(index : Int, value : Single) : Void; 20 | static var kEpsilon(default,never) : Single; 21 | static var one(get,never) : Vector2; 22 | static var right(get,never) : Vector2; 23 | static var up(get,never) : Vector2; 24 | static var zero(get,never) : Vector2; 25 | @:final @:overload static function Angle(from : Vector2, to : Vector2) : Single; 26 | @:final @:overload static function ClampMagnitude(vector : Vector2, maxLength : Single) : Vector2; 27 | @:final @:overload static function Distance(a : Vector2, b : Vector2) : Single; 28 | @:final @:overload static function Dot(lhs : Vector2, rhs : Vector2) : Single; 29 | @:final @:overload static function Lerp(from : Vector2, to : Vector2, t : Single) : Vector2; 30 | @:final @:overload static function Max(lhs : Vector2, rhs : Vector2) : Vector2; 31 | @:final @:overload static function Min(lhs : Vector2, rhs : Vector2) : Vector2; 32 | @:final @:overload static function MoveTowards(current : Vector2, target : Vector2, maxDistanceDelta : Single) : Vector2; 33 | @:native("Scale") @:final @:overload static function _Scale(a : Vector2, b : Vector2) : Vector2; 34 | @:native("SqrMagnitude") @:final @:overload static function _SqrMagnitude(a : Vector2) : Single; 35 | @:final @:overload static private function get_one() : Vector2; 36 | @:final @:overload static private function get_right() : Vector2; 37 | @:final @:overload static private function get_up() : Vector2; 38 | @:final @:overload static private function get_zero() : Vector2; 39 | @:final @:overload static function op_Addition(a : Vector2, b : Vector2) : Vector2; 40 | @:final @:overload static function op_Division(a : Vector2, d : Single) : Vector2; 41 | @:final @:overload static function op_Equality(lhs : Vector2, rhs : Vector2) : Bool; 42 | @:final @:overload static function op_Implicit(v : Vector3) : Vector2; 43 | @:final @:overload static function op_Implicit(v : Vector2) : Vector3; 44 | @:final @:overload static function op_Inequality(lhs : Vector2, rhs : Vector2) : Bool; 45 | @:final @:overload static function op_Multiply(a : Vector2, d : Single) : Vector2; 46 | @:final @:overload static function op_Multiply(d : Single, a : Vector2) : Vector2; 47 | @:final @:overload static function op_Subtraction(a : Vector2, b : Vector2) : Vector2; 48 | @:final @:overload static function op_UnaryNegation(a : Vector2) : Vector2; 49 | } 50 | -------------------------------------------------------------------------------- /unityengine/Vector3.hx: -------------------------------------------------------------------------------- 1 | package unityengine; 2 | 3 | @:forward abstract Vector3(Data) from Data to Data 4 | { 5 | #if !macro 6 | @:extern inline public function new(x:Single=.0,y:Single=.0,z:Single=.0) 7 | { 8 | this = new Data(x,y,z); 9 | } 10 | 11 | @:extern inline public static function fromData(data:Data):Vector3 12 | { 13 | return data; 14 | } 15 | 16 | @:op(A+B) @:extern inline public static function add(a:Vector3, b:Vector3):Vector3 17 | { 18 | return Data.op_Addition(a,b); 19 | } 20 | 21 | @:op(A/B) @:extern inline public static function div(a:Vector3, b:Single):Vector3 22 | { 23 | return Data.op_Division(a,b); 24 | } 25 | 26 | @:from @:extern inline public static function fromVec2(v:Vector2):Vector3 27 | { 28 | return new Vector3(v.x,v.y,0); 29 | } 30 | 31 | @:to @:extern inline public function toVec2():Vector2 32 | { 33 | return new Vector2(this.x,this.y); 34 | } 35 | 36 | @:op(A*B) @:extern @:commutative inline public static function mul(a:Vector3, b:Single):Vector3 37 | { 38 | return Data.op_Multiply(a,b); 39 | } 40 | 41 | @:op(A-B) @:extern inline public static function sub(a:Vector3, b:Vector3):Vector3 42 | { 43 | return Data.op_Subtraction(a,b); 44 | } 45 | 46 | @:op(-A) @:extern inline public function negate():Vector3 47 | { 48 | return Data.op_UnaryNegation(this); 49 | } 50 | 51 | @:arrayAccess @:extern inline public function get_Item(index:Int):Single 52 | { 53 | return this.get_Item(index); 54 | } 55 | 56 | @:arrayAccess @:extern inline public function set_Item(index:Int, val:Single):Single 57 | { 58 | this.set_Item(index,val); 59 | return val; 60 | } 61 | #end 62 | 63 | macro public function with(ethis:haxe.macro.Expr, obj:haxe.macro.Expr):haxe.macro.Expr 64 | { 65 | return unihx._internal.StructHelper.with(['x','y','z'], macro : unityengine.Vector3, ethis, obj); 66 | } 67 | } 68 | 69 | private typedef Data = 70 | #if macro 71 | Void 72 | #else 73 | Vector3Data 74 | #end; 75 | -------------------------------------------------------------------------------- /unityengine/Vector3Data.hx: -------------------------------------------------------------------------------- 1 | package unityengine; 2 | 3 | @:final @:csNative @:native("UnityEngine.Vector3") extern class Vector3Data extends cs.system.ValueType 4 | { 5 | var magnitude(get,never) : Single; 6 | var normalized(get,never) : Vector3; 7 | var sqrMagnitude(get,never) : Single; 8 | var x : Single; 9 | var y : Single; 10 | var z : Single; 11 | @:final @:overload function new(x : Single, y : Single, z : Single) : Void; 12 | @:final @:overload function new(x : Single, y : Single) : Void; 13 | @:final @:overload function Normalize() : Void; 14 | @:final @:overload function Scale(scale : Vector3) : Void; 15 | @:final @:overload function Set(new_x : Single, new_y : Single, new_z : Single) : Void; 16 | @:final @:overload function get_Item(index : Int) : Single; 17 | @:final @:overload private function get_magnitude() : Single; 18 | @:final @:overload private function get_normalized() : Vector3; 19 | @:final @:overload private function get_sqrMagnitude() : Single; 20 | @:final @:overload function set_Item(index : Int, value : Single) : Void; 21 | static var back(get,never) : Vector3; 22 | static var down(get,never) : Vector3; 23 | static var forward(get,never) : Vector3; 24 | static var fwd(get,never) : Vector3; 25 | static var kEpsilon(default,never) : Single; 26 | static var left(get,never) : Vector3; 27 | static var one(get,never) : Vector3; 28 | static var right(get,never) : Vector3; 29 | static var up(get,never) : Vector3; 30 | static var zero(get,never) : Vector3; 31 | @:final @:overload static function Angle(from : Vector3, to : Vector3) : Single; 32 | @:final @:overload static function AngleBetween(from : Vector3, to : Vector3) : Single; 33 | @:final @:overload static function ClampMagnitude(vector : Vector3, maxLength : Single) : Vector3; 34 | @:final @:overload static function Cross(lhs : Vector3, rhs : Vector3) : Vector3; 35 | @:final @:overload static function Distance(a : Vector3, b : Vector3) : Single; 36 | @:final @:overload static function Dot(lhs : Vector3, rhs : Vector3) : Single; 37 | @:final @:overload static function Exclude(excludeThis : Vector3, fromThat : Vector3) : Vector3; 38 | @:final @:overload static function Lerp(from : Vector3, to : Vector3, t : Single) : Vector3; 39 | @:final @:overload static function Magnitude(a : Vector3) : Single; 40 | @:final @:overload static function Max(lhs : Vector3, rhs : Vector3) : Vector3; 41 | @:final @:overload static function Min(lhs : Vector3, rhs : Vector3) : Vector3; 42 | @:final @:overload static function MoveTowards(current : Vector3, target : Vector3, maxDistanceDelta : Single) : Vector3; 43 | @:final @:overload static function OrthoNormalize(normal : cs.Ref, tangent : cs.Ref) : Void; 44 | @:final @:overload static function OrthoNormalize(normal : cs.Ref, tangent : cs.Ref, binormal : cs.Ref) : Void; 45 | @:final @:overload static function Project(vector : Vector3, onNormal : Vector3) : Vector3; 46 | @:final @:overload static function Reflect(inDirection : Vector3, inNormal : Vector3) : Vector3; 47 | @:final @:overload static function RotateTowards(current : Vector3, target : Vector3, maxRadiansDelta : Single, maxMagnitudeDelta : Single) : Vector3; 48 | @:final @:overload static function Slerp(from : Vector3, to : Vector3, t : Single) : Vector3; 49 | @:final @:overload static function SmoothDamp(current : Vector3, target : Vector3, currentVelocity : cs.Ref, smoothTime : Single, maxSpeed : Single) : Vector3; 50 | @:final @:overload static function SmoothDamp(current : Vector3, target : Vector3, currentVelocity : cs.Ref, smoothTime : Single, maxSpeed : Single, deltaTime : Single) : Vector3; 51 | @:final @:overload static function SmoothDamp(current : Vector3, target : Vector3, currentVelocity : cs.Ref, smoothTime : Single) : Vector3; 52 | @:final @:overload static function SqrMagnitude(a : Vector3) : Single; 53 | @:native("Normalize") @:final @:overload static function _Normalize(value : Vector3) : Vector3; 54 | @:native("Scale") @:final @:overload static function _Scale(a : Vector3, b : Vector3) : Vector3; 55 | @:final @:overload static private function get_back() : Vector3; 56 | @:final @:overload static private function get_down() : Vector3; 57 | @:final @:overload static private function get_forward() : Vector3; 58 | @:final @:overload static private function get_fwd() : Vector3; 59 | @:final @:overload static private function get_left() : Vector3; 60 | @:final @:overload static private function get_one() : Vector3; 61 | @:final @:overload static private function get_right() : Vector3; 62 | @:final @:overload static private function get_up() : Vector3; 63 | @:final @:overload static private function get_zero() : Vector3; 64 | @:final @:overload static function op_Addition(a : Vector3, b : Vector3) : Vector3; 65 | @:final @:overload static function op_Division(a : Vector3, d : Single) : Vector3; 66 | @:final @:overload static function op_Equality(lhs : Vector3, rhs : Vector3) : Bool; 67 | @:final @:overload static function op_Inequality(lhs : Vector3, rhs : Vector3) : Bool; 68 | @:final @:overload static function op_Multiply(a : Vector3, d : Single) : Vector3; 69 | @:final @:overload static function op_Multiply(d : Single, a : Vector3) : Vector3; 70 | @:final @:overload static function op_Subtraction(a : Vector3, b : Vector3) : Vector3; 71 | @:final @:overload static function op_UnaryNegation(a : Vector3) : Vector3; 72 | } 73 | -------------------------------------------------------------------------------- /unityengine/Vector4.hx: -------------------------------------------------------------------------------- 1 | package unityengine; 2 | 3 | @:forward abstract Vector4(Data) from Data to Data 4 | { 5 | #if !macro 6 | @:extern inline public function new(x:Single=.0,y:Single=.0,z:Single=.0,w:Single=0.) 7 | { 8 | this = new Data(x,y,z,w); 9 | } 10 | 11 | @:extern inline public static function fromData(data:Data):Vector4 12 | { 13 | return data; 14 | } 15 | 16 | @:op(A+B) @:extern inline public static function add(a:Vector4, b:Vector4):Vector4 17 | { 18 | return Data.op_Addition(a,b); 19 | } 20 | 21 | @:op(A/B) @:extern inline public static function div(a:Vector4, b:Single):Vector4 22 | { 23 | return Data.op_Division(a,b); 24 | } 25 | 26 | @:from @:extern inline public static function fromVec3(v:Vector3):Vector4 27 | { 28 | return new Vector4(v.x,v.y,v.z,0); 29 | } 30 | 31 | @:from @:extern inline public static function fromVec2(v:Vector2):Vector4 32 | { 33 | return new Vector4(v.x,v.y,0,0); 34 | } 35 | 36 | @:to @:extern inline public function toVec2():Vector2 37 | { 38 | return new Vector2(this.x,this.y); 39 | } 40 | 41 | @:op(A*B) @:extern @:commutative inline public static function mul(a:Vector4, b:Single):Vector4 42 | { 43 | return Data.op_Multiply(a,b); 44 | } 45 | 46 | @:op(A-B) @:extern inline public static function sub(a:Vector4, b:Vector4):Vector4 47 | { 48 | return Data.op_Subtraction(a,b); 49 | } 50 | 51 | @:op(-A) @:extern inline public function negate():Vector4 52 | { 53 | return Data.op_UnaryNegation(this); 54 | } 55 | 56 | @:arrayAccess @:extern inline public function get_Item(index:Int):Single 57 | { 58 | return this.get_Item(index); 59 | } 60 | 61 | @:arrayAccess @:extern inline public function set_Item(index:Int, val:Single):Single 62 | { 63 | this.set_Item(index,val); 64 | return val; 65 | } 66 | #end 67 | 68 | macro public function with(ethis:haxe.macro.Expr, obj:haxe.macro.Expr):haxe.macro.Expr 69 | { 70 | return unihx._internal.StructHelper.with(['x','y','z','w'], macro : unityengine.Vector4, ethis, obj); 71 | } 72 | } 73 | 74 | private typedef Data = 75 | #if macro 76 | Void 77 | #else 78 | Vector4Data 79 | #end; 80 | -------------------------------------------------------------------------------- /unityengine/Vector4Data.hx: -------------------------------------------------------------------------------- 1 | package unityengine; 2 | 3 | @:final @:csNative @:native("UnityEngine.Vector4") extern class Vector4Data extends cs.system.ValueType 4 | { 5 | var magnitude(get,never) : Single; 6 | var normalized(get,never) : Vector4; 7 | var sqrMagnitude(get,never) : Single; 8 | var w : Single; 9 | var x : Single; 10 | var y : Single; 11 | var z : Single; 12 | @:final @:overload function new(x : Single, y : Single, z : Single, w : Single) : Void; 13 | @:final @:overload function new(x : Single, y : Single) : Void; 14 | @:final @:overload function new(x : Single, y : Single, z : Single) : Void; 15 | @:final @:overload function Normalize() : Void; 16 | @:final @:overload function Scale(scale : Vector4) : Void; 17 | @:final @:overload function Set(new_x : Single, new_y : Single, new_z : Single, new_w : Single) : Void; 18 | @:final @:overload function SqrMagnitude() : Single; 19 | @:final @:overload function get_Item(index : Int) : Single; 20 | @:final @:overload private function get_magnitude() : Single; 21 | @:final @:overload private function get_normalized() : Vector4; 22 | @:final @:overload private function get_sqrMagnitude() : Single; 23 | @:final @:overload function set_Item(index : Int, value : Single) : Void; 24 | static var kEpsilon(default,never) : Single; 25 | static var one(get,never) : Vector4; 26 | static var zero(get,never) : Vector4; 27 | @:final @:overload static function Distance(a : Vector4, b : Vector4) : Single; 28 | @:final @:overload static function Dot(a : Vector4, b : Vector4) : Single; 29 | @:final @:overload static function Lerp(from : Vector4, to : Vector4, t : Single) : Vector4; 30 | @:final @:overload static function Magnitude(a : Vector4) : Single; 31 | @:final @:overload static function Max(lhs : Vector4, rhs : Vector4) : Vector4; 32 | @:final @:overload static function Min(lhs : Vector4, rhs : Vector4) : Vector4; 33 | @:final @:overload static function MoveTowards(current : Vector4, target : Vector4, maxDistanceDelta : Single) : Vector4; 34 | @:final @:overload static function Project(a : Vector4, b : Vector4) : Vector4; 35 | @:native("Normalize") @:final @:overload static function _Normalize(a : Vector4) : Vector4; 36 | @:native("Scale") @:final @:overload static function _Scale(a : Vector4, b : Vector4) : Vector4; 37 | @:native("SqrMagnitude") @:final @:overload static function _SqrMagnitude(a : Vector4) : Single; 38 | @:final @:overload static private function get_one() : Vector4; 39 | @:final @:overload static private function get_zero() : Vector4; 40 | @:final @:overload static function op_Addition(a : Vector4, b : Vector4) : Vector4; 41 | @:final @:overload static function op_Division(a : Vector4, d : Single) : Vector4; 42 | @:final @:overload static function op_Equality(lhs : Vector4, rhs : Vector4) : Bool; 43 | @:final @:overload static function op_Implicit(v : Vector3) : Vector4; 44 | @:final @:overload static function op_Implicit(v : Vector4) : Vector2; 45 | @:final @:overload static function op_Implicit(v : Vector2) : Vector4; 46 | @:final @:overload static function op_Inequality(lhs : Vector4, rhs : Vector4) : Bool; 47 | @:final @:overload static function op_Multiply(a : Vector4, d : Single) : Vector4; 48 | @:final @:overload static function op_Multiply(d : Single, a : Vector4) : Vector4; 49 | @:final @:overload static function op_Subtraction(a : Vector4, b : Vector4) : Vector4; 50 | @:final @:overload static function op_UnaryNegation(a : Vector4) : Vector4; 51 | } 52 | --------------------------------------------------------------------------------