GithubHelp home page GithubHelp logo

arcadia-unity / arcadia Goto Github PK

View Code? Open in Web Editor NEW
1.7K 87.0 107.0 56.55 MB

Clojure in Unity

Home Page: http://arcadia-unity.github.io/

License: Apache License 2.0

C# 6.88% Ruby 0.06% Clojure 93.06%
clojure unity game-development

arcadia's Introduction

Arcadia

Gitter

The integration of the Clojure Programming Language with the Unity 3D game engine.

Status

Arcadia is beta quality software, and we encourage you to follow our Getting Started instructions to try it out!

Community

Usage

Arcadia is documented in our GitHub wiki. The community on the Gitter is also very helpful and a great place to ask questions.

Contributing

If you're thinking of submitting code to Arcadia – thanks! We're excited to have your help. First, all contributors must read and agree to our contributor license agreement. It is based on GitHub's CLA and ensures that the code you submit remains useable by Arcadia and its community without issue. It confirms that

  1. Anyone can use your contributions anywhere, for free, forever.
  2. Your contributions do not infringe on anyone else's rights.
  3. You retain ownership of your contribution.

Once you have read and agree to it, submit a Pull Request adding your name and GitHub id to CONTRIBUTORS.md with the following commit message:

I have read and agree to the terms of the Arcadia Contributor License Agreement.

You only need to do this once. After that, we can review and merge any contributions you send us!

Name

This project was introduced at Strange Loop 2014 as "clojure-unity". The name "Arcadia" was suggested to us soon after by @ztellman, and we are eternally grateful.

Legal

Copyright © 2014-2019 Tims Gardner, Ramsey Nasser, and contributors.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this project except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

arcadia's People

Contributors

ekhart avatar gitter-badger avatar jeaye avatar jeremykross avatar lispengineer avatar max-lv avatar nasser avatar pjago avatar polyrhythm avatar saikyun avatar selfsame avatar setzer22 avatar spacepluk avatar teresy avatar timsgardner avatar ulyssesdotcodes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

arcadia's Issues

Type initializer exception: File Not Found

When I copy the Clojure folder to my project, I get an exception:
System.TypeInitializationException: An exception was thrown by the type initializer for clojure.lang.RT ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.TypeInitializationException: An exception was thrown by the type initializer for clojure/core/protocols$eval__9293__9298 ---> System.IO.FileNotFoundException: Could not load file or assembly 'clojure.core.protocols.CollReduce_9292' or one of its dependencies. The system cannot find the file specified.
File name: 'clojure.core.protocols.CollReduce_9292'

I assume there's something incredibly obvious that I'm missing (or just the hacky current state of the project). I'm using Unity 4.5.3f3 on Window 7 (x64).

System.IO.FileNotFoundException: Could not locate unity.repl.clj.dll or unity/repl.clj on load path.

I just tried to place clojure in my assets folder after issue #36 was fixed. I got this error...

System.IO.FileNotFoundException: Could not locate unity.repl.clj.dll or unity/repl.clj on load path.
at clojure.lang.RT.load (System.String relativePath, Boolean failIfNotFound) [0x00000] in :0
at clojure.lang.RT.load (System.String relativePath) [0x00000] in :0
at ClojureRepl.StartREPL () [0x00000] in C:\Users\jacob\Documents\2d Game Practice\Assets\Clojure\Editor\ClojureRepl.cs:30
at ClojureRepl..cctor () [0x00005] in C:\Users\jacob\Documents\2d Game Practice\Assets\Clojure\Editor\ClojureRepl.cs:16
UnityEditor.EditorAssemblies:SetLoadedEditorAssemblies(Assembly[])

Stack Traces

Stack traces coming out of .clj files should not show C# machinery.

Survive asset reimport

Make Clojure and the REPL survive Unity's asset reimport.

This may or may not be possible.

Does not work with webplayer

Had to switch platform (File -> Build Settings...) to PC, Mac & Linux Standalone to get a connection to the repl, since the default Web Player does not support incoming TCP connections (with good reason, I suppose).

Took me some time to notice the small warning and figure it out. Maybe this should be stated in the README?

So, I got (+ 2 2) evaluated, and I managed to create a UnityEngine.GameObject. Apart from this, I have no clue about what I'm doing ;-) Looking forward to some more documentation :-)

REPL does not start sometimes

Despite the presence of unity.repl.clj.dll in the Compiled folder, the REPL will sometimes not start, complaining that unity.repl.clj.dll could not be found.

Deleting the DLL file and reimporting repl.clj seems to fix it,

Generate Super Shim

To interop with Unity's mutable components, and to grant Clojure components visible controls in the inspector, Clojure generated classes need to inherit from a shim class that contains the mutable public fields. This is common enough that is should be part of the base clojure-unity toolset.

EDN Config

Read an EDN config file and visualize it as a Unity inspector pane.

This is where automatic compilation, load paths, etc could live.

reduce-kv broken on vectors in Clojure-CLR

Clojure JVM

user=> (reduce-kv (fn [c k v] (assoc c k (inc v))) [1 2 3 4] [1 2 3 4])
(reduce-kv (fn [c k v] (assoc c k (inc v))) [1 2 3 4] [1 2 3 4])

Clojure CLR

user=> (reduce-kv (fn [c k v] (assoc c k (inc v))) [1 2 3 4] [1 2 3 4])
System.IndexOutOfRangeException: Array index is out of range.
  at clojure.lang.PersistentVector.kvreduce (IFn f, System.Object init) [0x00000] in <filename unknown>:0 
  at clojure/core$fn__20662__20666.invoke (System.Object , System.Object , System.Object ) [0x00000] in <filename unknown>:0 
  at clojure/core/protocols$fn__20095$G__20084__20112__20115.invoke (System.Object , System.Object , System.Object ) [0x00000] in <filename unknown>:0 
  at clojure/core$reduce_kv__20716.invoke (System.Object , System.Object , System.Object ) [0x00000] in <filename unknown>:0 
  at user$eval__64__76.invoke () [0x00000] in <filename unknown>:0 
  at clojure.lang.Compiler.eval (System.Object form) [0x00000] in <filename unknown>:0 
  at clojure.lang.Compiler.eval (System.Object form) [0x00000] in <filename unknown>:0 
  at clojure/core$eval__15007.invoke (System.Object ) [0x00000] in <filename unknown>:0 
  at unity/repl$repl_eval_print$fn__3405__3409.invoke () [0x00000] in <filename unknown>:0 
  at unity/repl$repl_eval_print__3412.invoke (System.Object , System.Object ) [0x00000] in <filename unknown>:0 
  at unity/repl$repl_eval_string__3428.invoke (System.Object , System.Object ) [0x00000] in <filename unknown>:0 
  at unity/repl$repl_eval_string__3428.invoke (System.Object ) [0x00000] in <filename unknown>:0 
  at unity/repl$eval_queue$fn__3436__3440.invoke () [0x00000] in <filename unknown>:0 

REPL does not go down properly

The REPL does not do the right thing when going down most of the time. This is an example error:

ObjectDisposedException: The object was used after being disposed.
System.Net.Sockets.UdpClient.CheckDisposed () <IL 0x0001b, 0x00075>
System.Net.Sockets.UdpClient.Send (byte[],int,System.Net.IPEndPoint) <IL 0x00001, 0x00023>
(wrapper dynamic-method) object.CallSite.Target (System.Runtime.CompilerServices.Closure,System.Runtime.CompilerServices.CallSite,object,object,int,object) <IL 0x00080, 0x001cc>
unity/repl$eval_queue__13288.__interop_Send13292 (object,object,int,object) <IL 0x00011, 0x0006a>
unity/repl$eval_queue__13288.invoke () (at repl.clj:90)
clojure.lang.Var.invoke () <IL 0x00007, 0x00050>
ClojureRepl.Update () (at Assets/Clojure/Internal/Editor/ClojureRepl.cs:24)
UnityEditor.EditorApplication.Internal_CallUpdateFunctions () <IL 0x0000f, 0x0003f>

Tame compiler pipeline

The pipeline to compile a clj file into a dll and ensure that all its symbols are visible is crazy at the moment. It should be controlled and deterministic.

Wrap static methods in the Unity API

Using interop to access Unity's static methods is fine, but can be made cleaner by wrapping them in Clojure macros. This is an opportunity to fix some of Unity's API problems as well.

(defmacro noise
  ([x] `(Mathf/PerlinNoise (+ 0.1 ~x) 0))
  ([x y] `(Mathf/PerlinNoise (+ 0.1 ~x) ~y)))

Meaningless Error messages

Most of the error messages we throw are meaningless

System.InvalidCastException: Cannot cast from source type to destination type.
  at clojure.lang.ArraySeq.createFromObject (System.Object array) [0x00000] in <filename unknown>:0 
  at clojure.lang.RT.seqFrom (System.Object coll) [0x00000] in <filename unknown>:0 
  at clojure.lang.RT.seq (System.Object coll) [0x00000] in <filename unknown>:0 
  at clojure/core$seq__467.invoke (System.Object ) [0x00000] in <filename unknown>:0 
  at clojure/core$print_sequential__30479.invoke (System.Object , System.Object , System.Object , System.Object , System.Object , System.Object ) [0x0016a] in core_print.clj:46 
  at clojure/core$fn__30887__30891.invoke (System.Object , System.Object ) [0x00044] in core_print.clj:276 
  at clojure.lang.MultiFn.invoke (System.Object arg1, System.Object arg2) [0x00000] in <filename unknown>:0 
  at clojure/core$pr_on__3237.invoke (System.Object , System.Object ) [0x00000] in <filename unknown>:0 
  at clojure/core$pr__3245.invoke (System.Object ) [0x00000] in <filename unknown>:0 
  at clojure.lang.AFn.ApplyToHelper (IFn fn, ISeq argList) [0x00000] in <filename unknown>:0 
  at clojure.lang.RestFn.applyTo (ISeq arglist) [0x00000] in <filename unknown>:0 
  at clojure/core$apply__795.invoke (System.Object , System.Object ) [0x00000] in <filename unknown>:0 
  at clojure/core$prn__3263.doInvoke (System.Object ) [0x00000] in <filename unknown>:0 
  at clojure.lang.RestFn.invoke (System.Object arg1) [0x00000] in <filename unknown>:0 
  at unity/repl$repl_eval_print$fn__48__52.invoke () [0x00000] in <filename unknown>:0 
  at unity/repl$repl_eval_print__55.invoke (System.Object , System.Object ) [0x00000] in <filename unknown>:0 
  at unity/repl$repl_eval_string__71.invoke (System.Object , System.Object ) [0x00000] in <filename unknown>:0 
  at unity/repl$repl_eval_string__71.invoke (System.Object ) [0x00000] in <filename unknown>:0 
  at unity/repl$eval_queue$fn__79__83.invoke () [0x00000] in <filename unknown>:0 

rename instantiate to clone

Its a deviation from Unity's names, but the name is fucking wrong. It doesn't instantiate anything. It clones. Their documentation reflects that and I don't know why its called what it is. We can be better.

This is keeping me up at night.

Unusually long load times

Doing e.g. (require 'unity.core) from the REPL takes an unusually long time, and (require 'unity.hydrate) takes 15 minutes, indicating that the runtime is parsing and compiling .clj files even when there are compiled .dll files available.

Catastrophic slow path in RT.classForName

Clojure-CLR's class lookup by name mechanism falls back to a code path that does string based comparisons due to a bug in mono, and runs in cubic time (assemblies * types/assembly * types/assembly). This is the source of slow imports, requires, and uses, as well as the 15 minute build time for the hydration library. It has been seen to allocate ~500Mb of GC collected memory during the string comparison due to 20,000+ calls to Type.get_Name.

Hydration

Implement facilities to hydrate Clojure data structures into Unity GameObjects and Components.

into-array is buggy

user=> (into-array [1 2 3])
(1 2 3)

user=> (into-array Int32 [1 2 3])
(1 2 3)

user=> (into-array [(UnityEngine.Vector3. 1 2 3)])
System.InvalidCastException: Cannot cast from source type to destination type.
  at clojure.lang.ArraySeq.createFromObject (System.Object array) [0x00000] in <filename unknown>:0 
  at clojure.lang.RT.seqFrom (System.Object coll) [0x00000] in <filename unknown>:0 
  at clojure.lang.RT.seq (System.Object coll) [0x00000] in <filename unknown>:0 
  at clojure/core$seq__231.invoke (System.Object ) [0x00000] in <filename unknown>:0 
  at clojure/core$print_sequential__30479.invoke (System.Object , System.Object , System.Object , System.Object , System.Object , System.Object ) [0x0016a] in core_print.clj:46 
  at clojure/core$fn__30887__30891.invoke (System.Object , System.Object ) [0x00044] in core_print.clj:276 
  at clojure.lang.MultiFn.invoke (System.Object arg1, System.Object arg2) [0x00000] in <filename unknown>:0 
  at clojure/core$pr_on__3006.invoke (System.Object , System.Object ) [0x00000] in <filename unknown>:0 
  at clojure/core$pr__3014.invoke (System.Object ) [0x00000] in <filename unknown>:0 
  at clojure.lang.AFn.ApplyToHelper (IFn fn, ISeq argList) [0x00000] in <filename unknown>:0 
  at clojure.lang.RestFn.applyTo (ISeq arglist) [0x00000] in <filename unknown>:0 
  at clojure/core$apply__559.invoke (System.Object , System.Object ) [0x00000] in <filename unknown>:0 
  at clojure/core$prn__3032.doInvoke (System.Object ) [0x00000] in <filename unknown>:0 
  at clojure.lang.RestFn.invoke (System.Object arg1) [0x00000] in <filename unknown>:0 
  at unity/repl$repl_eval_print$fn__48__52.invoke () [0x00000] in <filename unknown>:0 
  at unity/repl$repl_eval_print__55.invoke (System.Object , System.Object ) [0x00000] in <filename unknown>:0 
  at unity/repl$repl_eval_string__71.invoke (System.Object , System.Object ) [0x00000] in <filename unknown>:0 
  at unity/repl$repl_eval_string__71.invoke (System.Object ) [0x00000] in <filename unknown>:0 
  at unity/repl$eval_queue$fn__79__83.invoke () [0x00000] in <filename unknown>:0 
user=> (into-array UnityEngine.Vector3 [(UnityEngine.Vector3. 1 2 3)])
System.InvalidCastException: Cannot cast from source type to destination type.
  at clojure.lang.ArraySeq.createFromObject (System.Object array) [0x00000] in <filename unknown>:0 
  at clojure.lang.RT.seqFrom (System.Object coll) [0x00000] in <filename unknown>:0 
  at clojure.lang.RT.seq (System.Object coll) [0x00000] in <filename unknown>:0 
  at clojure/core$seq__231.invoke (System.Object ) [0x00000] in <filename unknown>:0 
  at clojure/core$print_sequential__30479.invoke (System.Object , System.Object , System.Object , System.Object , System.Object , System.Object ) [0x0016a] in core_print.clj:46 
  at clojure/core$fn__30887__30891.invoke (System.Object , System.Object ) [0x00044] in core_print.clj:276 
  at clojure.lang.MultiFn.invoke (System.Object arg1, System.Object arg2) [0x00000] in <filename unknown>:0 
  at clojure/core$pr_on__3006.invoke (System.Object , System.Object ) [0x00000] in <filename unknown>:0 
  at clojure/core$pr__3014.invoke (System.Object ) [0x00000] in <filename unknown>:0 
  at clojure.lang.AFn.ApplyToHelper (IFn fn, ISeq argList) [0x00000] in <filename unknown>:0 
  at clojure.lang.RestFn.applyTo (ISeq arglist) [0x00000] in <filename unknown>:0 
  at clojure/core$apply__559.invoke (System.Object , System.Object ) [0x00000] in <filename unknown>:0 
  at clojure/core$prn__3032.doInvoke (System.Object ) [0x00000] in <filename unknown>:0 
  at clojure.lang.RestFn.invoke (System.Object arg1) [0x00000] in <filename unknown>:0 
  at unity/repl$repl_eval_print$fn__48__52.invoke () [0x00000] in <filename unknown>:0 
  at unity/repl$repl_eval_print__55.invoke (System.Object , System.Object ) [0x00000] in <filename unknown>:0 
  at unity/repl$repl_eval_string__71.invoke (System.Object , System.Object ) [0x00000] in <filename unknown>:0 
  at unity/repl$repl_eval_string__71.invoke (System.Object ) [0x00000] in <filename unknown>:0 
  at unity/repl$eval_queue$fn__79__83.invoke () [0x00000] in <filename unknown>:0 
user=> 

REPL in exported App

Optionally embed a REPL in an exported app for debugging and instrumentation.

Dehydrate

Generate Clojure data structures from Unity GameObjects and Components

Wrapping policy

Much better to have a small number of carefully-chosen features than lots of hasty ones, especially if we have all the functionality already anyway via interop. I'm nervous about the degree of wrapping we're doing. I don't think simply making all Unity methods first-class is worth the bloat to the public API, certainly not without more solid type-hinting machinery. Wrapping also causes some weird side effects, like shadowing clojure.core (happens when we wrap Mathf). On the other hand it may well be useful to bulk zap Unity utility classes into collections of (type-hinted!) functions à la carte. Manipulating vector3's, for example, should probably be easier. My instinct is that we should manually target specific pieces of functionality that need some Clojure spiffing. Then, if it is possible to do non-jankily (which it may well not be), expose defwrapper as a public macro for users to selectively wrap Unity classes.

Arithmetic Stack

Clojure CLR's arithmetic stack produces suboptimal code, even with *unchecked-math* set to true and all the proper type hints in place. This is problematic for intensive graphics and interactive code.

The following example code is adapted from @SneakyBrian's Catmull Rom Spline sample.

defn catmul-rom* [^Vector3 p0
                   ^Vector3 p1
                   ^Vector3 p2
                   ^Vector3 p3
                   t]
  (let [t  (float t)
        t0 (float (* (- (* (+ (- t) 2) t) 1) t 0.5))
        t1 (float (* (+ (* (* (- (* 3 t) 5) t) t) 2) 0.5))
        t2 (float (* (+ (* (+ (* -3 t) 4) t) 1) t 0.5))
        t3 (float (* (- t 1) t t 0.5))]
  (Vector3.
    (+ (* t0 (.x p0))
       (* t1 (.x p1))
       (* t2 (.x p2))
       (* t3 (.x p3)))
    (+ (* t0 (.y p0))
       (* t1 (.y p1))
       (* t2 (.y p2))
       (* t3 (.y p3)))
    (+ (* t0 (.z p0))
       (* t1 (.z p1))
       (* t2 (.z p2))
       (* t3 (.z p3)))))

Emits

public override object invoke (object obj, object obj2, object obj3, object obj4, object obj5)
    {
        float num = RT.uncheckedFloatCast ((object)obj5);
        float num2 = RT.uncheckedFloatCast (Numbers.unchecked_multiply (Numbers.unchecked_multiply (Numbers.unchecked_minus (Numbers.unchecked_multiply (Numbers.unchecked_add (-(double)num, 2), (double)num), 1), (double)num), 0.5));
        float num3 = RT.uncheckedFloatCast (Numbers.unchecked_multiply (Numbers.unchecked_add (Numbers.unchecked_multiply (Numbers.unchecked_multiply (Numbers.unchecked_minus (Numbers.unchecked_multiply (3, (double)num), 5), (double)num), (double)num), 2), 0.5));
        float num4 = RT.uncheckedFloatCast (Numbers.unchecked_multiply (Numbers.unchecked_multiply (Numbers.unchecked_add (Numbers.unchecked_multiply (Numbers.unchecked_add (Numbers.unchecked_multiply (-3, (double)num), 4), (double)num), 1), (double)num), 0.5));
        float num5 = RT.uncheckedFloatCast (Numbers.unchecked_multiply (Numbers.unchecked_multiply (Numbers.unchecked_multiply (Numbers.unchecked_minus ((double)num, 1), (double)num), (double)num), 0.5));
        return new Vector3 ((float)(Numbers.unchecked_multiply ((double)num2, (double)((Vector3)obj).x) + Numbers.unchecked_multiply ((double)num3, (double)((Vector3)obj2).x) + Numbers.unchecked_multiply ((double)num4, (double)((Vector3)obj3).x) + Numbers.unchecked_multiply ((double)num5, (double)((Vector3)obj4).x)), (float)(Numbers.unchecked_multiply ((double)num2, (double)((Vector3)obj).y) + Numbers.unchecked_multiply ((double)num3, (double)((Vector3)obj2).y) + Numbers.unchecked_multiply ((double)num4, (double)((Vector3)obj3).y) + Numbers.unchecked_multiply ((double)num5, (double)((Vector3)obj4).y)), (float)(Numbers.unchecked_multiply ((double)num2, (double)((Vector3)obj).z) + Numbers.unchecked_multiply ((double)num3, (double)((Vector3)obj2).z) + Numbers.unchecked_multiply ((double)num4, (double)((Vector3)obj3).z) + Numbers.unchecked_multiply ((double)num5, (double)((Vector3)obj4).z)));
    }

While the equivalent C# code

public static Vector3 PointOnCurve(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
    {
        Vector3 ret = new Vector3();

        float t2 = t * t;
        float t3 = t2 * t;

        ret.x = 0.5f * ((2.0f * p1.x) +
        (-p0.x + p2.x) * t +
        (2.0f * p0.x - 5.0f * p1.x + 4 * p2.x - p3.x) * t2 +
        (-p0.x + 3.0f * p1.x - 3.0f * p2.x + p3.x) * t3);

        ret.y = 0.5f * ((2.0f * p1.y) +
        (-p0.y + p2.y) * t +
        (2.0f * p0.y - 5.0f * p1.y + 4 * p2.y - p3.y) * t2 +
        (-p0.y + 3.0f * p1.y - 3.0f * p2.y + p3.y) * t3);

        ret.z = 0.5f * ((2.0f * p1.z) +
        (-p0.z + p2.z) * t +
        (2.0f * p0.z - 5.0f * p1.z + 4 * p2.z - p3.z) * t2 +
        (-p0.z + 3.0f * p1.z - 3.0f * p2.z + p3.z) * t3);

        return ret;
    }

Emits

    public static Vector3 PointOnCurve (Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
    {
        Vector3 result = default(Vector3);
        float num = t * t;
        float num2 = num * t;
        result.x = 0.5 * (2 * p1.x + (-p0.x + p2.x) * t + (2 * p0.x - 5 * p1.x + 4 * p2.x - p3.x) * num + (-p0.x + 3 * p1.x - 3 * p2.x + p3.x) * num2);
        result.y = 0.5 * (2 * p1.y + (-p0.y + p2.y) * t + (2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * num + (-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * num2);
        result.z = 0.5 * (2 * p1.z + (-p0.z + p2.z) * t + (2 * p0.z - 5 * p1.z + 4 * p2.z - p3.z) * num + (-p0.z + 3 * p1.z - 3 * p2.z + p3.z) * num2);
        return result;
    }

namespace for type wrangling

Keep hitting some patterns and writing the same functions for type-hint macro machinery (eg ensure-type, type-symbol?, etc), should put them somewhere nice. Also need to determine good home for borderline macros like condcast (quite possibly core, given intensity of interop, but we should make a principled decision)

Components

Be able to write components in pure Clojure.

defscript is already available and close, but has issues.

Cannot populate arrays

(populate! {:name "Trumpax"
            :mesh-renderer [{:materials [{:main-texture some-texture
                                          :color Color/red}]}]})

Does not work because there is no hydrator for UnityEngine.Material[], which is the type of Renderer.materials.

type-hinted closures and/or operators are buggy

Invalid IL exception:

(defn obj-data-translate [obj-data, ^Vector3 v]
  (update-in obj-data [:transform 0 :position]
    (fn [^Vector3 v']
      (Vector3/op_Addition v v'))))

(obj-data-translate
  {:transform [{:position (Vector3. 1 1 1)}]}
  (Vector3. 1 2 3))

Works:

(defn obj-data-translate [obj-data, v]
  (update-in obj-data [:transform 0 :position]
    (fn [^Vector3 v']
      (let [^Vector3 vump v]
        (Vector3/op_Addition vump v')))))

(obj-data-translate
  {:transform [{:position (Vector3. 1 1 1)}]}
  (Vector3. 1 2 3))

pathological type literal instantiation behavior

Type names are resolved via exhaustive scan of 21503 types even when we seem to have enough information to obtain the type directly. This creates ~2 MB of garbage, is extremely slow, and one way or another occurs at runtime during static initialization. Particularly nasty for namespaces like hydrate, which involve many mentions of types.
Can only be solved by tweaking compiler. Possible mitigating fixes include using fully-qualified type names and memoizing the lookup function. David Miller should probably be consulted.

Regard Overloaded Operators

This code:

Vector3.up * 4

Just works. Which is why this code:

(* 4 (. Vector3 up))

should just work, but there are some issues, because clojure doesn't know of the overloaded operators.

Several hints:

  1. We can infer if the type has an overloaded operator by searching in (:members (clojure/reflect thing))
  2. We can call the operator by requesting it eg op_Addition from the runtime object.

I think it's ok to give the overloaded operators different names (like a v* for vector multiplication), but we're losing a lot of generality this way. Ideas?

Some REPL messages are "too long"

(Directory/GetFiles "Assets/Clojure/Compiled" "*")
SocketException: Message too long
System.Net.Sockets.Socket.SendTo_nochecks (System.Byte[] buffer, Int32 offset, Int32 size, SocketFlags flags, System.Net.EndPoint remote_end)
System.Net.Sockets.Socket.SendTo (System.Byte[] buffer, Int32 offset, Int32 size, SocketFlags flags, System.Net.EndPoint remote_end)
System.Net.Sockets.UdpClient.DoSend (System.Byte[] dgram, Int32 bytes, System.Net.IPEndPoint endPoint)

Takes the REPL down.

SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted.

I get this error when trying to start clojure REPL.

SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted.

System.Net.Sockets.Socket.Bind (System.Net.EndPoint local_end)
System.Net.Sockets.UdpClient.InitSocket (System.Net.EndPoint localEP)
System.Net.Sockets.UdpClient..ctor (System.Net.IPEndPoint localEP)
unity/repl$start_server__13255.invokePrim (Int64 )
unity/repl$start_server__13255.invoke (System.Object )
clojure.lang.Var.invoke (System.Object arg1)
ClojureRepl.StartREPL () (at Assets/Clojure/Editor/ClojureRepl.cs:31)

Could this be because of running with subset of .NET 2.0? Cause setting it to use the full one freezes Unity.

macro support namespace

Would like to supply support for macro weirdness in the name of low-level shenanigans. In particular I think marcrolet variants and a riddley port would make sense.

Export is broken

No clojure code runs when a game is exported from the editor.

Windows support

Our compilation code assumes Unix paths. This seems to be the only obstacle to Windows support.

Cannot hydrate Materials

(populate-game-object! {:name (str "Voxel " [x y z])
                        :transform [{:position [x y z]}]
                        :mesh-renderer [{:material {:color Color/red
                                                    :main-texture tex}}] }))))))))
System.Exception: No hydrater found for type UnityEngine.Material

introspection namespace

Distinct from unity.reflect (maybe fold unity.reflect into it, though?). Place to put functions I've found invaluable for the repl, such as apropos+ and aproprint.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.