-
Notifications
You must be signed in to change notification settings - Fork 106
arcadia.core
(log & args)
Log message to the Unity console. Arguments are combined into a string.
(null->nil x)
Same as identity, except if x is a null UnityEngine.Object,
will return nil.
More details and rationale are available in the wiki.
(null? x)
Should x be considered nil? (null? x) will evalute to true if
x is in fact nil, or if x is a UnityEngine.Object instance
such that (UnityEngine.Object/op_Equality x nil) returns
true. Otherwise will return false.
More details and rationale are available in the wiki.
(instantiate original)
(instantiate original position)
(instantiate original position rotation)
Clones the original object and returns the clone. The clone can optionally be given a new position or rotation as well.
Wraps Object/Instantiate.
(create-primitive prim)
(create-primitive prim name)
Creates a game object with a primitive mesh renderer and appropriate
collider. prim can be a PrimitiveType or one of :sphere
:capsule :cylinder :cube :plane :quad. If supplied, the
third argument should be a string, and will be set as the name of
the newly created GameObject. Wraps GameObject/CreatePrimitive.
(destroy obj)
(destroy obj t)
Removes a GameObject, component or asset. When called with t, the removal
happens after t seconds. Wraps Object/Destroy.
(destroy-immediate obj)
Removes a GameObject, component or asset immediately.
Wraps Object/DestroyImmediate.
(retire obj)
If in Play mode, calls Object/Destroy, otherwise calls Object/DestroyImmediate.
(object-typed t)
Returns one live instance of UnityEngine.Object subclass type t
from the scene graph, or nil if no such object can be found. Wraps
Object/FindObjectOfType.
(objects-typed t)
Returns a sequence of all live instances of UnityEngine.Object subclass
type t in the scene graph. Wraps Object/FindObjectsOfType.
(object-named name-or-regex)
Returns one live GameObject from the scene graph, the name of which
matches name-or-regex. name-or-regex may be a string or a
regular expression object.
(objects-named name-or-regex)
Returns a sequence of all live GameObjects in the scene graph, the
name of which match name-or-regex. name-or-regex may be a string
or a regular expression object.
(object-tagged t)
Returns one live GameObject tagged t from the scene graph,
or nil if no such GameObjects exist.
Wraps GameObject/FindWithTag.
(objects-tagged t)
Returns a sequence of live GameObjects tagged tag. Returns empty
array if no GameObject was found.
Wraps GameObject/FindGameObjectsWithTag.
(gobj x)
Coerces x, expected to be a GameObject or Component, to a
corresponding live (non-destroyed) GameObject instance or to nil by
the following policy:
- If
xis a live GameObject, returns it. - If
xis a destroyed GameObject, returnsnil. - If
xis a live Component, returns its containing GameObject. - If
xis a destroyed Component, returnsnil. - If
xisnil, returnsnil. - Otherwise throws an ArgumentException.
(child+ x child)
(child+ x child world-position-stays)
Makes GameObject x the new parent of GameObject child. Returns child.
If world-position-stays is true, child retains its world position after
being reparented.
(child- x child)
(child- x child world-position-stays)
Removes GameObject x as the parent of GameObject child,
moving child to the top of the scene graph hierarchy. Returns nil.
If world-position-stays is true, child retains its world
position after being reparented.
(children x)
Gets the live children of GameObject x as a persistent vector of
GameObjects.
(parent x)
Returns the live parent of GameObject x or nil if it has none.
GameObjects at the top of the hierarchy do not have parents.
(cmpt x t)
Returns the first live Component of type t attached to GameObject
x. Returns nil if no such Component is attached.
(cmpts x t)
Returns all live Components of type t attached to GameObject x
as a (possibly empty) array.
(cmpt+ x t)
Adds a new Component of type t to GameObject x. Returns the new Component.
(cmpt- x t)
Removes every Component of type t from GameObject x. Returns nil.
(ensure-cmpt x t)
If GameObject x has a component of type t, returns it. Otherwise, adds
a component of type t and returns the new instance.
with-cmpt macro
(with-cmpt gob bindings & body)
binding => name component-type
For each binding, binds name to an instance of class
component-type attached to GameObject gob. If no such instance
is currently attached to x, a new instance of component-type
will be created, attached to x, and bound to name. body is
then evaluated in the lexical context of all bindings.
if-cmpt macro
(if-cmpt gob [cmpt-name cmpt-type] then & else)
If a component of type cmpt-type is attached to GameObject gob,
binds it to cmpt-name, then evaluates and returns then in the
lexical scope of that binding. Otherwise evaluates and returns
else, if provided, or returns nil if else is not provided.
sets! macro
(sets! o & assignments)
Set multiple fields or properties on an object instance o simultaneously.
assignment => field-name value
For each assignment, field-name is the name of a field or property
of o, and value is the new value it will be set to.
Returns the final set value.
(sets! (.transform some-game-object)
position (arcadia.linear/v3 1 2 3)
localScale (arcadia.linear/v3 1 2 3))
set-with! macro
(set-with! obj [name prop :as bindings] & body)
Access and set a field or property prop on object instance
obj. The new value at (. obj prop) will be set to the value of
body, evaluated in an implicit do, with name bound to the
preexisting value of (. obj prop). This operation is not atomic,
and should be used with caution in concurrent contexts.
As an example,
(set-with! (.transform some-game-object)
[pos position]
(arcadia.linear/v3+ pos (arcadia.linear/v3 1 0 0)))is equivalent to
(let [tr (.transform some-game-object)
pos (.position tr)]
(set! (.position tr)
(arcadia.linear/v3+ (.position tr) (arcadia.linear/v3 1 0 0))))Since the object is the first argument, multiple such assignments on
an object may be chained using doto. Returns the new value of the
field or property.
(descendents x)
Returns a sequence containing all descendents of GameObject x in
depth-first order. The descendents of x are all GameObjects
attached as children to x in the Unity hierarchy; all of those
GameObject's children; and so on.
(available-hooks)
Returns a sorted seq of all permissible hook event keywords.
(hook+ obj event-kw k f)
Attach a Clojure function, preferrably a Var instance, to GameObject
obj on key k. The function f will be invoked every time the event
identified by event-kw is triggered by Unity.
f must be a function of 2 arguments, plus however many arguments
the corresponding Unity event function takes. The first argument is
the GameObject obj that f is attached to. The second argument is
the key k it was attached with. The remaining arguments are the
arguments normally passed to the corresponding Unity event function.
Returns f.
(hook- obj event-kw key)
Removes hook function from GameObject obj on the Unity event
corresponding to event-kw at key, if it exists. Reverse of
(hook+ obj event-kw key hook-function)Returns nil.
(clear-hooks obj event-kw)
Removes all hook functions on the Unity event corresponding to
event-kw, regardless of their keys.
(hook obj event-kw key)
Retrieves an attached hook function from GameObject
obj. event-kw is a keyword specifying the Unity event of the
hook function, and key is the key of the hook function.
In other words, retrieves any hook function attached via
(hook+ obj event-kw key hook-function)or the equivalent.
(snapshot x)
Converts defmutable instance x to a persistent representation.
(maybe-snapshot x)
Unstable implementation detail, please don't use.
(mutable x)
Given a persistent representation of a mutable datatype defined via
defmutable, constructs and returns a matching instance of that
datatype.
Roundtrips with snapshot; that is, for any instance x of a type defined via defmutable,
(= (snapshot x) (snapshot (mutable (snapshot x))))(maybe-mutable x)
Unstable implementation detail, please don't use.
(lookup go k)
Returns the state of GameObject go at key k. Does not convert
defmutable instances to persistent representations.
(state go)
(state go k)
With one argument, returns the state of GameObject go on all keys
as a map. With two arguments, returns the state of GameObject go
at key k. If this state is a defmutable instance, will return a
persistent representation instead. To avoid this behavior use
lookup.
(state+ go k v)
Sets the state of GameObject go to value v at key k. Returns
v. If v is a persistent representation of a defmutable
instance, will convert it to a mutable instance before inserting in
the scene graph.
(state- go k)
Removes the state of object go at key k.
(clear-state go)
Removes all state from the GameObject go.
(update-state go k f)
(update-state go k f x)
(update-state go k f x y)
(update-state go k f x y z)
(update-state go k f x y z & args)
Updates the state of GameObject go at key k with function f and
additional arguments args. Args are applied in the same order as
. Returns the new value of the state at k.
In the special case that the value in state is a defmutable
instance, f will be applied to the persistent representation of
that value, which will then be converted to a mutable instance
again, and inserted into state at k. The returned value will be
f applied to the persistent representation.
(role- obj k)
Removes a role from GameObject obj on key k. Any hook or state
attached to obj on key k will be removed. Returns nil.
(role+ obj k r)
Adds a role r to GameObject obj on key k, replacing any
previous role on k. Keys in r corresponding to Unity event
functions, such as :update, :on-collision-enter, etc, are
expected to have values meeting the criteria for hook functions
described in the docstring for hook+. For such a key event-kw,
values will be attached to obj as though by (hook+ obj event-kw k (get r event-kw)).
If present, the value of the key :state in r will be attached to
obj as though by (state+ obj k (get r :state)).
For example,
(role+
obj,
:example-role,
{:state 45, {:update #'on-update, :on-collision-enter #'on-collision-enter}})has the same effect as
(role- obj :example-role)
(state+ obj :example-role 45)
(hook+ obj :update :example-role #'on-update)
(hook+ obj :on-collision-enter :example-role #'on-collision-enter)As with state+, persistent reprsentations defmutable data as
values in :state will be converted to mutable instances.
Returns r.
(roles+ obj rs)
Takes a GameObject obj and map rs containing role keys and role
maps as entries. For each entry in rs with key k and value r,
adds r to obj on key k as though calling
(role+ obj k r)Returns rs.
(roles- obj ks)
Takes a GameObject obj and collection of keys ks. For each key
k in ks, will remove k from obj, as if calling
(role- obj k)Returns nil.
(role obj k)
Returns a map of all hooks and state attached to GameObject obj on
key k. Within the returned map, keys will be either hook event
keywords such as :update, :on-collision-enter, etc, or :state.
(hook+ obj :update :test #'on-update)
(state+ obj :test {:speed 3, :mass 4})
(role obj :test)
;; returns:
;; {:state {:speed 3, :mass 4},
;; :update #'on-update}(roles obj)
Returns a map containing all the roles attached to GameObject
obj. For each entry in this map, the key is the key of some hooks
or state attached to obj, and the value is the map one would get
by calling (role obj k) for that key k. For example:
(hook+ obj :update :key-a #'on-update)
(state+ obj :key-a {:speed 3, :mass 4})
(hook+ obj :update :key-b #'other-on-update)
(state+ obj :key-b {:name "bob", :health 5})
(roles obj)
;; returns:
;; {:key-a {:state {:speed 3, :mass 4},
;; :update #'on-update},
;; :key-b {:state {:name "bob", :health 5},
;; :update #'other-on-update}}Roundtrips with roles+.
defrole macro
(defrole name entry*)
Macro for defining roles quickly. Each entry can be either a key-value pair with a keyword key, such as would normally occur in a map intended as an Arcadia role, or an inlined function definition.
Normal key-value pairs get inserted into the generated map. For example,
(defrole movement
:state {:speed 3}
:update #'movement-update)will expand into
(def movement
{:state {:speed 3}
:update #'movement-update})Inlined function definitions have the following syntax:
(name [args*] body)
name must be the symbol form of an Arcadia hook keyword. A function
intended for the :update hook, for example, should have the name
update:
(defrole movement
:state {:speed 3}
(update [obj k] ...))Each inlined function definition will generate a var, with a name
constructed as follows: <name of role>-<name of hook>
For example, the movement role above will generate a var named
movement-update bound to a function with the provided arguments
and body, and include that var in the generated role map, expanding
into something like:
(do
(defn movement-update [obj k] ...)
(def movement
{:state {:speed 3}
:update #'movement-update}))Note that generating vars is usually a bad idea because it messes with tooling and legibility. This macro does it anyway because the hook functions should serialize in the Unity scene graph, and that requires vars.
(mut! x kw v)
Dynamically sets field keyword kw of defmutable instance x to
new value v. Returns v.
(delete! x k)
Removes dynamic entry k from defmutable instance x.
defmutable macro
(defmutable [name [fields*] other*])
Defines a new serializable, type-hinted, mutable datatype, intended
for particularly performance or allocation sensitive operations on a
single thread (such as Unity's main game thread). These datatypes
support snapshotting to persistent data via snapshot, and
reconstruction from snapshots via mutable; snapshotting and
reconstructing are also integrated into state, state+,
update-state, role, role+, and roles.
defmutable instances may be mutated in two ways. Their fields may
be mutated directly using set! and dot syntax. Fields may also be
dynamically set using (mut! obj k v). Here, obj is the
defmutable instance, k is the keyword key for an entry, and v
is the new value of that entry to set on the defmutable instance.
Instances of these types may be converted into persistent
representations and back via snapshot and mutable. This
roundtrips, so if x is such an instance:
(= (snapshot x) (snapshot (mutable (snapshot x))))If a persistent snapshot is specified as the state argument of
set-state, or as the :state value in the map argument of
role+, the ArcadiaState component will be populated at the
appropriate key by the result of calling mutable on that
snapshot. Conversely, role and roles will automatically convert
any mutable instances that would otherwise be the values of :state
in the returned map(s) to persistent snapshots.
defmutable supports four special options to help define custom
snapshot and mutable implementations:
:snapshot:mutable:snapshot-elements:mutable-elements
:snapshot and :mutable expect their values to be in the
following form:
([this-param key-param value-param] body*)
When calling snapshot or mutable, the function defined by
:snapshot or :mutable will be called on each entry in the
defmutable instance (in the case of snapshot) or the persistent
map representation (in the case of mutable). When these functions
run, this-param will be assigned to the original defmutable
instance for snapshot, or to the original persistent map
representation for mutable; key-param will be assigned to the
keyword key of this entry; and val-param will be assigned to its
incoming value. For :snapshot, the return will be the value of the
corresponding entry in the persistent map representation. For
:mutable, the return will be the value of the corresponding entry
in the defmutable instance representation. :snapshot and
:mutable should invert each other.
:snapshot-elements and :mutable-elements support finer
specialization of snapshot and mutable behavior. They expect
their values to be maps from keyword names of possible entries, to
the same sort of function specifications taken by :snapshot and
:mutable. Specifications made with :snapshot-elements or
:mutable-elements take priority over those made with :snapshot
or :mutable.
See the online documentation for examples.
defmutable will automatically generate a constructor function. As
with deftype, the name of its var will be -> followed by the
name of the type, and its expected arguments will be the initial
values of fields, in order.
For example, given the following defmutable definition:
(defmutable Sheep [wooliness bouyancy])an instance of Sheep could be constructed using
(->Sheep 3 4)defmutable serialization, via either snapshot or Unity
scene-graph serialization, does not currently preserve reference
identity. Calling mutable on the same snapshot twice will result
in two distinct instances. It is therefore important to store any
given defmutable instance in just one place in the scene graph.
Since they define new types, reevaluating defmutable forms will
require also reevaluating all forms that refer to them via type
hints (otherwise they'll fall back to dynamic
lookups). defmutable-once is like defmutable, but will not
redefine the type if it has already been defined (similar to
defonce).
As low-level, potentially non-boxing constructs, instances of
defmutable types work particularly well with the magic library.
defmutable-once macro
(defmutable-once & [name :as args])
Like defmutable, but will only evaluate if no type with the same
name has been defined.