A lot of the built-in functionality in skelescript is written in skelescript itself. Only the core functionality for reading Lightwave states, creating variables, defining procedures, etc. is coded in C++. All of the built-in functionality which can be derived from a combination of the core functionality and the commands available in Layout is defined in an internal skelescript. This allows me to build and test the library rapidly without having to recompile my code. It also helps me to test skelescript. Provided here is the script code for the internal skelescript library. Understanding it requires intermediate to advanced knowledge of writing skelescripts. If you can understand most of the code here, you are in extremely good shape.

; *****************************************************************************
define_command __init_internals
{
    ; This procedure is called once to initialize all the pre-defined
    ; global constants and state variables used by skelescript.

    ; Pre-defined constants:
    global_const number pi, 3.14159265358979323846264
    global_const number meters_per_foot, 0.3048
    global_const number feet_per_meter, (1 / meters_per_foot)
    global_const number middle_tolerance, .00000001
    global_const string empty_string, ""
    
    global_const int shape_standard, 0
    global_const int shape_box, 1
    global_const int shape_ball, 2
    global_const int shape_pyramid, 3
    global_const int shape_diamond, 4
    global_const int shape_tetra, 5
    global_const int shape_ring, 6
    global_const int shape_grid, 7
    global_const int shape_none, 8

    global_const int axis_x, 0
    global_const int axis_y, 1
    global_const int axis_z, 2

    global_const int justify_left, 0
    global_const int justify_center, 1
    global_const int justify_right, 2

    global_const int color_black, 0
    global_const int color_blue, 1
    global_const int color_green, 2
    global_const int color_teal, 3
    global_const int color_red, 4
    global_const int color_purple, 5
    global_const int color_brown, 6
    global_const int color_gray, 7
    global_const int color_bright_blue, 8
    global_const int color_bright_green, 9
    global_const int color_cyan, 10
    global_const int color_bright_red, 11
    global_const int color_magenta, 12
    global_const int color_yellow, 13
    global_const int color_white, 14

    ; Global state variables:
    global bool __auto_confirm, false

    global bool flip_left_x, false
    global bool flip_right_x, false
    
    global bool flip_left_heading, false
    global bool flip_left_pitch, false
    global bool flip_left_bank, false
    global bool flip_right_heading, false
    global bool flip_right_pitch, false
    global bool flip_right_bank, false
    
    global string left_side_name, "left"
    global string middle_side_name, "middle"
    global string right_side_name, "right"
}

; *****************************************************************************
; For declaring variables and constants:
define_command local(int data_type, identifier name, any value) {__local 0, data_type, name, value, 1}
define_command const(int data_type, identifier name, any value) {__local 1, data_type, name, value, 1}
define_command global(int data_type, identifier name, any value) {__global 0, data_type, name, value}
define_command global_const(int data_type, identifier name, any value) {__global 1, data_type, name, value}

; *****************************************************************************
; For declaring local variables:
define_command any(identifier name, any value=0) {__local false, any, name, value, 1 }
define_command string(identifier name, string value="") {__local false, string, name, value, 1 }
define_command number(identifier name, number value=0.0) {__local false, number, name, value, 1 }
define_command int(identifier name, int value=0) {__local false, int, name, value, 1 }
define_command bool(identifier name, bool value=false) {__local false, bool, name, value, 1 }
define_command item_id(identifier name, item_id value=selected) {__local false, item_id, name, value, 1 }
define_command collection(identifier name, collection value=create_collection) {__local false, collection, name, value, 1 }
define_command identifier(identifier name, identifier value) {__local false, identifier, name, value, 1 }

; For declaring local constants:
define_command const_any(identifier name, any value=0) {__local true, any, name, value, 1 }
define_command const_string(identifier name, string value="") {__local true, string, name, value, 1 }
define_command const_number(identifier name, number value=0.0) {__local true, number, name, value, 1 }
define_command const_int(identifier name, int value=0) {__local true, int, name, value, 1 }
define_command const_bool(identifier name, bool value=false) {__local true, bool, name, value, 1 }
define_command const_item_id(identifier name, item_id value=selected) {__local true, item_id, name, value, 1 }
define_command const_collection(identifier name, collection value=create_collection) {__local true, collection, name, value, 1 }
define_command const_identifier(identifier name, identifier value) {__local true, identifier, name, value, 1 }

; For declaring global variables:
define_command global_any(identifier name, any value=0) {__global false, any, name, value}
define_command global_string(identifier name, string value="") {__global false, string, name, value}
define_command global_number(identifier name, number value=0.0) {__global false, number, name, value}
define_command global_int(identifier name, int value=0) {__global false, int, name, value}
define_command global_bool(identifier name, bool value=false) {__global false, bool, name, value}
define_command global_item_id(identifier name, item_id value=selected) {__global false, item_id, name, value}
define_command global_collection(identifier name, collection value=create_collection) {__global false, collection, name, value}
define_command global_identifier(identifier name, identifier value) {__global false, identifier, name, value}

; For declaring global constants:
define_command global_const_any(identifier name, any value=0) {__global true, any, name, value}
define_command global_const_string(identifier name, string value="") {__global true, string, name, value}
define_command global_const_number(identifier name, number value=0.0) {__global true, number, name, value}
define_command global_const_int(identifier name, int value=0) {__global true, int, name, value}
define_command global_const_bool(identifier name, bool value=false) {__global true, bool, name, value}
define_command global_const_item_id(identifier name, item_id value=selected) {__global true, item_id, name, value}
define_command global_const_collection(identifier name, collection value=create_collection) {__global true, collection, name, value}
define_command global_const_identifier(identifier name, identifier value) {__global true, identifier, name, value}

; *****************************************************************************
define_function collection __server_collection(item_id item, string plugin_class)
{
    ; Returns a collection of the plugins applied to the item under the specific
    ; class. Example of a plugin_class would be "CustomObjHandler" and
    ; "ItemMotionHandler". Examine scene files to learn different plugin classes
    ; and the formats of each plugin.
    
    Collection c, create_collection(string)
    int j, 1
    string plugin_name
    while (set(plugin_name, __server(item, plugin_class, post_inc(j)) ) != "") {push c, plugin_name}
    return c
}

; *****************************************************************************
define_command add_item_shape(
    item_id item = selected,
    int shape = shape_ball, 
    number scale = 0.2,
    bool filled = false, 
    number opacity = 1.0,
    int axis = axis_y, 

    collection selected_color = empty_collection,
    collection unselected_color = empty_collection, 
    collection text_color = empty_collection, 

    string label = empty_string,
    int justify = justify_center,
    item_id draw_to_item = null_item)
{
    ; scale specifies the size of the shape in meters.

    collection plugins, __server_collection(item, "CustomObjHandler")
    if (find_element(plugins, "LW_ItemShape") != -1) {error "Cannot add Item Shape plugin to object. An Item Shape plugin already exists."}

    int flags, 0
    if (justify == justify_left) {set flags, bitwise_or(flags, 8) }
    else_if (justify == justify_right)
    {
        set flags, bitwise_or(flags, 8)
        set flags, bitwise_or(flags, 16)
    }
    
    if (collection_empty(selected_color) )  {set selected_color, rgb(0, 0, 0) }
    else {set flags, bitwise_or(flags, 1) }
    
    if (collection_empty(unselected_color) )  {set unselected_color, rgb(0, 0, 0) }
    else {set flags, bitwise_or(flags, 2) }

    if (collection_empty(text_color) )  {set text_color, rgb(0, 0, 0) }
    else {set flags, bitwise_or(flags, 4) }

    string str
    if (label != empty_string) {concat_line str, ("// LABEL=" & label) }

    concat_line str, ("Plugin CustomObjHandler " & (collection_size(plugins) + 1) & " LW_ItemShape")
    
    concat_line str, 4
    concat_line str, concat_lines(scale, axis, shape, filled, flags)
    concat_line str, collection_text(rgb_to_float(selected_color), " ")
    concat_line str, collection_text(rgb_to_float(unselected_color), " ")
    concat_line str, collection_text(rgb_to_float(text_color), " ")
    concat_line str, opacity
    concat_line str, __raw_id(draw_to_item)
    concat_line str, ("\"" & label & "\"")

    concat_line str, ("EndPlugin")

    __scene_modification item, str
}

; *****************************************************************************
define_command add_gravity(item_id item = selected, int start_frame = 1, int end_frame = 60, number ground_level = 0.0, number strength = 1.0, number elasticity = 0.25, integer axis = axis_y)
{
    collection plugins, __server_collection(item, "ItemMotionHandler")
    if (find_element(plugins, "LW_Gravity") != -1) {error "Cannot add LW_Gravity plugin to object. An LW_Gravity plugin already exists."}

    string str, ("Plugin ItemMotionHandler " & (collection_size(plugins) + 1) & " LW_Gravity")
    
    concat_line str, ("Axis " & axis & " Strength " & strength)
    concat_line str, ("Start " & start_frame & " End " & end_frame)
    concat_line str, ("Ground " & ground_level & " Elasticity " & sqrt(elasticity) )

    concat_line str, ("EndPlugin")

    __scene_modification item, str
}

; *****************************************************************************
define_command add_simple_follower(item_id item = selected,
    bool after_ik = false, bool heading_active = true, bool pitch_active = true, bool bank_active = true, 
    item_id item1 = null_item, number heading1 = 0.0, number pitch1 = 0.0, number bank1 = 0.0,
    item_id item2  = null_item, number heading2 = 0.0, number pitch2  = 0.0, number bank2 = 0.0)
{
    collection plugins, __server_collection(item, "ItemMotionHandler")
    if (find_element(plugins, "SimpleFollower") != -1) {error "Cannot add SimpleFollower plugin to object. A SimpleFollower plugin already exists."}

    string str, ("Plugin ItemMotionHandler " & (collection_size(plugins) + 1) & " SimpleFollower")
    
    concat_line str, 1
    concat_line str, __raw_id(item1)
    concat_line str, __raw_id(item2)
    concat_line str, after_ik
    concat_line str, concat_lines(heading_active, heading1, heading2)
    concat_line str, concat_lines(pitch_active, pitch1, pitch2)
    concat_line str, concat_lines(bank_active, bank1, bank2)

    concat_line str, ("EndPlugin")

    __scene_modification item, str
}

; *****************************************************************************
; Procedures for working with angle type values. Valid angle_type constants 
; are: angle_heading, angle_pitch, and angle_bank.

define_function string angle_type_name(int angle_type)
{
    ; Returns a string for the name of the specified angle type.
    if (angle_type == angle_heading) {return "heading"}
    if (angle_type == angle_pitch) {return "pitch"}
    if (angle_type == angle_bank) {return "bank"}
    __error_invalid_angle_type angle_type
}

define_command assert_valid_angle_type(int angle_type)
{
    if (angle_type == angle_heading || angle_type == angle_pitch || angle_type == angle_bank) {return}
    __error_invalid_angle_type(angle_type)
}

define_command __error_invalid_angle_type(int angle_type)
{
    ; Displays an error message telling the user that the specified angle type is invalid.
    error ("Invalid angle type: " & angle_type & ". Valid values are: angle_heading, angle_pitch, and angle_bank.")
}

; *****************************************************************************
define_function bool is_only_item_selected(item_id item)
{
    ; Returns true if the item is selected and no other items
    ; are selected.
    return (num_selected == 1 && item == selected)
}

; *****************************************************************************
define_function collection rgb(int red, int green, int blue)
{
    if (red < 0 || red > 255) {error "Invalid color. The red component must be in the range of 0 to 255."}
    if (green < 0 || green > 255) {error "Invalid color. The green component must be in the range of 0 to 255."}
    if (blue < 0 || blue > 255) {error "Invalid color. The blue component must be in the range of 0 to 255."}
    return create_collection(int, red, green, blue)
}

define_function collection rgb_to_float(collection c)
{
    ; Converts an integer-based RGB color collection with values ranging from 0
    ; to 255 to a floating value-based RGB color collection with values ranging
    ; from 0 to 1.0.
    return create_collection(number, c(0) / 255.0, c(1) / 255.0,  c(2) / 255.0)
}

; *****************************************************************************
define_function string concat(any lhs, ~any remaining)
{
    ; Concatenates the specified values to form a single,
    ; combined string which is returned by the function.
    string str, tostring(lhs)
    for_each remaining, arg {concat str, arg}
    return str
}

; *****************************************************************************
define_function string concat_lines(any lhs, ~any remaining)
{
    ; Concatenates the specified lines to form a single,
    ; multi-line string which is returned by the function.
    string str, tostring(lhs)
    for_each remaining, arg {concat str, ("\n" & tostring(arg)) }
    return str
}

; *****************************************************************************
define_function string command_line(string command, ~any remaining)
{
    ; Returns a command line formed from the specified command
    ; and the arguments with the arguments separated by spaces.
    string str, command
    for_each remaining, arg
    {
        concat str, " "
        concat str, arg
    }
    return str
}

; *****************************************************************************
; Unit Conversion Functions

define_function number radians_to_degrees(number radians) {return mul(radians / pi, 180.0) }
define_function number degrees_to_radians(number degrees) {return mul(degrees / 180.0, pi) }

define_function number feet_to_meters(number feet) {return mul(feet, meters_per_foot) }
define_function number meters_to_feet(number meters) {return mul(meters, feet_per_meter) }

; *****************************************************************************
; The following allows the user to set the auto-confirm status. Skelescripts
; keeps track of the auto-confirm status.

define_command AutoConfirm(bool value)
{
    ; Overrides the native AutoConfirm command with the additional
    ; function of keeping track of the auto-confirm status.
    __native_command ("AutoConfirm " & set(__auto_confirm, value) )
}

define_get bool auto_confirm {return __auto_confirm }
define_set bool auto_confirm {AutoConfirm value}

; *****************************************************************************
define_function string side(item_id item = selected, string left_str = left_side_name, string middle_str = middle_side_name, string right_str = right_side_name)
{
    if (world_x(item) < -middle_tolerance) {return left_str}
    if (world_x(item) > middle_tolerance) {return right_str}
    return middle_str
}

; *****************************************************************************
define_command move_to_ground (item_id item = selected)
{
    ; Moves the specified item so that it's y position is 0.
    if (local_y == world_y) {execute_for_item item, "Position world_x, 0, world_z"}
    else {execute_for_item item, "AddPosition 0, (-world_y), 0"}
}
    

; *****************************************************************************
define_command delete(item_id item = selected)
{
    ; Deletes the specified item without confirmation.
    bool prev_auto_confirm auto_confirm
    set auto_confirm, true
    execute_for_item item, "ClearSelected"
    set auto_confirm, prev_auto_confirm
}

; *****************************************************************************
define_command lock_all_channels(item_id item = selected)
{
    ; Locks all the channels available with the current layout tool for the
    ; specified item.
    execute_for_item item, "enableXH\nenableYP\nenableZB"
}

; *****************************************************************************
define_command lock_movement(item_id item = selected)
{
    ; locks all the movement channels for the specified item.
    movetool
    lock_all_channels item
}

; *****************************************************************************
define_command lock_rotation(item_id item = selected)
{
    ; locks all the rotational channels for the specified item.
    rotatetool
    lock_all_channels item
}

; *****************************************************************************
; Returns the current frame based on the current time and the
; number of frames per second. Fractional frames are not currently
; supported.
define_get int current_frame {return round(current_time * fps) }

; Sets the current frame.
define_set int current_frame {(GoToFrame value}

; Returns the current fps.
define_set int fps {FramesPerSecond value}

; *****************************************************************************
define_function collection empty_collection
{
    ; Returns an empty collection.
    return create_collection(any)
}

; *****************************************************************************
define_function string collection_text(collection c, string separator = ", ", string empty_text = "empty", string inner_prefix = "(", string inner_suffix = ") ")
{
    ; converts a collection to a string which specifies its elements. Unlike
    ; tostring, this function gives you control over how to output the collection.
    if (collection_empty(c)) {return empty_text}
    
    int num_elements, collection_size(c)
    int j, 0
    string str, __collection_text_impl(j, c, separator, empty_text, inner_prefix, inner_suffix)
    while (inc(j) < num_elements) {concat str, (separator & __collection_text_impl(j, c, separator, empty_text, inner_prefix, inner_suffix)) }
    
    return str
}

define_function string __collection_text_impl(int j, collection c, string separator = ", ", string empty_text = "empty", string inner_prefix = "(", string inner_suffix = ")")
{
    any element, c(j)
    if (is_collection(element) )  {return (inner_prefix & collection_text(element, separator, empty_text, inner_prefix, inner_suffix) & inner_suffix) }
    return tostring(element)
}
; *****************************************************************************
define_command push(collection c, any element)
{
    ; Pushes an element to the back of the collection.
    assert collection_insert(c, element)
}

define_function any pop(collection c)
{
    ; Removes and returns the element at the back of the collection.
    if (collection_empty(c)) {error "Cannot pop elements from an empty collection."}
    int last_index, (collection_size(c) - 1)
    any element, c(last_index)
    assert collection_erase(c, last_index)
    return element
}
define_command pop(collection c) {run pop(c) }

; *****************************************************************************
define_function int find_element(any c, any search_element)
{
    ; Searches the specified collection/string for the specified element/character.
    ; The function returns an index (greater than or equal to 0) if the element is
    ; found. Otherwise, the function returns -1.
    int num_elements, size(c)
    int j, -1
    while (inc(j) < num_elements)
    {
        if (element(c, j) == search_element) {return j}
    }
    return -1
}

; *****************************************************************************
define_function int size(any c)
{
    if (is_collection(c)) {return collection_size(c)}
    if (is_string(c)) {return length(c)}
    error "The argument passed to the size function must be a string or a collection."
}

; *****************************************************************************
define_get any element(any elements, any pos)
{
    ; Returns the specified element in a collection or a string. For strings,
    ; a single character is returned.
    if (is_collection(elements) ) {return elements(pos) }
    else_if (is_string(elements) ) {return char_at(elements, pos) }
    else {error "Invalid data type specified for element property. Expected a string or a collection."}
}

; *****************************************************************************
define_set any element(any& elements, any position)
{
    ; Sets the value of the specified element in a collection or a string.
    if (is_collection(elements) ) {set elements(position), value}
    else_if (is_string(elements) ) {set char_at(elements, position), value }
    else {error "Invalid data type specified for element property. Expected a string or a collection."}
}

; *****************************************************************************
define_get string char_at(string str, int pos)
{
    ; Returns the character at the specified position.
    ; The set procedure of char_at is defined internally.
    return substr(str, pos, 1)
}

; *****************************************************************************
define_command swap(any& value1, any& value2)
{
    ; Swaps the values of two variables. The variables must be of 
    ; compatible data types.
    local any, temp, value1
    set value1, value2
    set value2, temp
}

; *****************************************************************************
; Increments the specified variable by the specified amount. The function
; also returns the resulting value.
define_command inc(number& source, number amount = 1) {run inc(source, amount) }
define_function number inc(number& source, number amount = 1) {return set(source, source + amount)}

; Decrements the specified variable by the specified amount. The function
; also returns the resulting value.
define_command dec(number& source, number amount = 1) {run dec(source, amount) }
define_function number dec(number& source, number amount = 1) {return set(source, source - amount)}

define_function number post_inc(number& source, number amount = 1) 
{
    ; Increments the specified variable by the specified amount and 
    ; returns the original value before incrementing.
    int temp, source
    run inc(source, amount)
    return temp
}

define_function number post_dec(number& source, number amount = 1) 
{
    ; Decrements the specified variable by the specified amount and 
    ; returns the original value before decrementing.
    int temp, source
    run dec(source, amount)
    return temp
}

; *****************************************************************************
; Arithmetical Functions:

define_function number add(number lhs, ~number remaining)
{
    ; Returns the sum of two or more numbers.
    for_each remaining, element {inc lhs, element}
    return lhs
}

define_function number sub(number lhs, ~number remaining)
{
    ; Returns the difference of two or more numbers
    ; (calculated from left to right).
    for_each remaining, element {dec lhs, element}
    return lhs
}

define_function number mul(number lhs, ~number remaining)
{
    ; Returns the product of two or more numbers.
    for_each remaining, element {mul lhs, element}
    return lhs
}
define_command mul(number& lhs, number rhs) {set lhs, (lhs * rhs) }

define_function number div(number lhs, ~number remaining)
{
    ; Returns the quotient of after dividing two or more numbers.
    for_each remaining, element {div lhs, element}
    return lhs
}
define_command div(number& lhs, number rhs) {set lhs, (lhs / rhs) }

; *****************************************************************************
; These functions return the absolute position relative to an item with
; a given offset. Ex - the relative_x function with an item with the X position 
; of 30 will return 20 if the offset is -10. Moreover, the functions accomodate for
; position flipping, so if flip_right_x is on, the function will return 40 instead of 
; 20 since it'll flip the -10 offset into 10 since an X position of 30 means that the
;  item is on the right side.

define_function number relative_x(item_id item, number add_x)
{
    number item_x, world_x(item)

    ; Flip the offset if the item is on the left side flip_left_x is on or if 
    ; it's on the right side flip_right_x is on.
    if ( (item_x < 0 && flip_left_x) || (item_x > 0 && flip_right_x) ) {set add_x, (add_x * -1.0) }

    return (add_x + item_x)
}

define_function number relative_y(item_id item, number add_y) {return (add_y + world_y(item)) }
define_function number relative_z(item_id item, number add_z) {return (add_z + world_z(item)) }

; *****************************************************************************
; Functions to create nulls for various purposes.

define_function item_id create_null(string name, number x = 0, number y = 0, number z = 0)
{
    ; Creates a null at the specified position and returns the ID.
    store_selection

    AddNull name
    item_id null_id, selected
    Position x, y, z

    restore_selection
    return null_id
}

define_function item_id create_null_at(item_id item, string name, number add_x = 0, number add_y = 0, number add_z = 0)
{
    ; Creates a null at a position relative to the specified item's position and 
    ; returns the ID. If orient_null is true, the newly created null will be oriented
    ; to match the item's orientation.
    return create_null(name, relative_x(item, add_x), relative_y(item, add_y), relative_z(item, add_z) )
}
define_function item_id create_oriented_null_at(item_id item, string name, number add_x = 0, number add_y = 0, number add_z = 0)
{
    ; Creates and returns the ID of a null that is oriented to match the selected 
    ; item's orientation. The null is created at a position that is relative to the 
    ; specified item's position. 
    store_selection
    bool prev_parent_in_place, parent_in_place

    AddNull name

    set parent_in_place, false
    set parent, item
    set parent_in_place, true
    set parent, null_item
    
    AddPosition add_x, add_y, add_z

    item_id null_id, selected

    restore_selection
    set parent_in_place, prev_parent_in_place
    return null_id
}

define_command create_goal(bool full_time = true, string null_name = concat(name, "_goal"), number add_x = 0, number add_y = 0, number add_z = 0)
{
    ; Creates a goal null for the selected item at the specified relative 
    ; position. The ID for the new null can be retrieved with the
    ; goal property.
    set goal, create_null_at(selected, null_name, add_x, add_y, add_z)
    if (full_time) {FullTimeIK}
}
define_function item_id create_goal(bool full_time = true, string null_name = concat(name, "_goal"), number add_x = 0, number add_y = 0, number add_z = 0)
{
    create_goal full_time, null_name, add_x, add_y, add_z
    return goal
}

define_command create_oriented_goal(bool full_time = true, string null_name = concat(name, "_goal"), number add_x = 0, number add_y = 0, number add_z = 0)
{
    ; Creates a goal null for the selected item at the specified relative 
    ; position which matches the selected item's orientation. The ID for the 
    ; new null can be retrieved with the goal property.
    set goal, create_oriented_null_at(selected, null_name, add_x, add_y, add_z)
    if (full_time) {FullTimeIK}
}
define_function item_id create_oriented_goal(bool full_time = true, string null_name = concat(name, "_goal"), number add_x = 0, number add_y = 0, number add_z = 0)
{
    create_oriented_goal full_time, null_name, add_x, add_y, add_z
    return goal
}

define_command create_target(string null_name = concat(name, "_target"), number add_x = 0, number add_y = 0, number add_z = 0)
{
    ; Creates a target null for the selected item at the specified relative 
    ; position. The ID for the new null can be retrieved with the
    ; target property.
    set target, create_null_at(selected, null_name, add_x, add_y, add_z)
}
define_function item_id create_target(string null_name = concat(name, "_target"), number add_x = 0, number add_y = 0, number add_z = 0)
{
    create_target null_name, add_x, add_y, add_z
    return target
}

define_command create_oriented_target(string null_name = concat(name, "_target"), number add_x = 0, number add_y = 0, number add_z = 0)
{
    ; Creates a target null for the selected item at the specified relative 
    ; position. The ID for the new null can be retrieved with the
    ; target property.
    set target, create_oriented_null_at(selected, null_name, add_x, add_y, add_z)
}
define_function item_id create_oriented_target(string null_name = concat(name, "_target"), number add_x = 0, number add_y = 0, number add_z = 0)
{
    create_oriented_target null_name, add_x, add_y, add_z
    return target
}

; *****************************************************************************
; Procedures for working with selections.

define_function item_id selected(int index = 0)
{
    assert_selection "Cannot retrieve selected item. Nothing is selected."
    return __selected(index)
}

define_command assert_selection(string error_message = "One or more items must be selected.")
{
    ; Displays the specified error message if no items are selected.
    if (no_selection) {error error_message}
}

define_command select(item_id id)
{
    ; Like the SelectItem command, but shorter and quicker to type.
    ; Unlike the SelectItem command, the Select command checks 
    ; to make sure that the specified ID is valid.
    __native_command ("SelectItem " & __raw_id(id) )
}

define_function bool no_selection
{
    ; Returns true if there are no items selected.
    return (num_selected == 0)
}

define_function collection get_selected_items
{
    ; Creates a returns a collection containing the item IDs of the currently
    ; selected group of items.
    collection items, create_collection(item_id)
    int size, num_selected
    int j, -1
    while (inc(j) < num_selected) {push items, selected(j) }
    return items
}

; *****************************************************************************
define_function bool is_null_item(item_id item = selected)
{
    ; Returns true if the item is a null.
    ; return (item_type(item) == item_type_object && !has_geometry(item) )
    return (item_type(item) == item_type_object && !has_geometry(item) )
}

; *****************************************************************************
; These functions return item parameter values. Positions are returned as meters,
; angles are returned as degrees.

define_function number local_x(item_id item = selected) {return __item_parameter(item, __ip_position, current_time, 0) }
define_function number local_y(item_id item = selected) {return __item_parameter(item, __ip_position, current_time, 1) }
define_function number local_z(item_id item = selected) {return __item_parameter(item, __ip_position, current_time, 2) }

define_function number world_x(item_id item = selected) {return __item_parameter(item, __ip_world_position, current_time, 0) }
define_function number world_y(item_id item = selected) {return __item_parameter(item, __ip_world_position, current_time, 1) }
define_function number world_z(item_id item = selected) {return __item_parameter(item, __ip_world_position, current_time, 2) }

define_function number heading(item_id item = selected) {return radians_to_degrees(__item_parameter(item, __ip_rotation, current_time, 0)) }
define_function number pitch(item_id item = selected) {return radians_to_degrees(__item_parameter(item, __ip_rotation, current_time, 1)) }
define_function number bank(item_id item = selected) {return radians_to_degrees(__item_parameter(item, __ip_rotation, current_time, 2)) }

define_function number scale_x(item_id item = selected) {return __item_parameter(item, __ip_scaling, current_time, 0) }
define_function number scale_y(item_id item = selected) {return __item_parameter(item, __ip_scaling, current_time, 1) }
define_function number scale_z(item_id item = selected) {return __item_parameter(item, __ip_scaling, current_time, 2) }

define_function number pivot_x(item_id item = selected) {return __item_parameter(item, __ip_pivot, current_time, 0) }
define_function number pivot_y(item_id item = selected) {return __item_parameter(item, __ip_pivot, current_time, 1) }
define_function number pivot_z(item_id item = selected) {return __item_parameter(item, __ip_pivot, current_time, 2) }

define_function number pivot_heading(item_id item = selected) {return radians_to_degrees(__item_parameter(item, __ip_pivot_rotation, current_time, 0)) }
define_function number pivot_pitch(item_id item = selected) {return radians_to_degrees(__item_parameter(item, __ip_pivot_rotation, current_time, 1)) }
define_function number pivot_bank(item_id item = selected) {return radians_to_degrees(__item_parameter(item, __ip_pivot_rotation, current_time, 2)) }

; *****************************************************************************
; Procedures for working with rotational limits.

; Returns whether the specified limits are on/off.
define_get bool limit_heading(item_id item = selected) {return limits_on(item, angle_heading) }
define_get bool limit_pitch(item_id item = selected) {return limits_on(item, angle_pitch) }
define_get bool limit_bank(item_id item = selected) {return limits_on(item, angle_bank) }

; Sets the specified limits on/off.
define_set bool limit_heading(item_id item = selected) {set limits_on(item, angle_heading), value}
define_set bool limit_pitch(item_id item = selected) {set limits_on(item, angle_pitch), value}
define_set bool limit_bank(item_id item = selected) {set limits_on(item, angle_bank), value}

; Returns the specified limit values.
define_get number min_heading(item_id item = selected) {return __limits(item, angle_heading, false) }
define_get number min_pitch(item_id item = selected) {return __limits(item, angle_pitch, false) }
define_get number min_bank(item_id item = selected) {return __limits(item, angle_bank, false) }
define_get number max_heading(item_id item = selected) {return __limits(item, angle_heading, true) }
define_get number max_pitch(item_id item = selected) {return __limits(item, angle_pitch, true) }
define_get number max_bank(item_id item = selected) {return __limits(item, angle_bank, true) }

; Sets the specified limit values.
define_set number min_heading(item_id item = selected) {set __limits(item, angle_heading, false), value}
define_set number min_pitch(item_id item = selected) {set __limits(item, angle_pitch, false), value}
define_set number min_bank(item_id item = selected) {set __limits(item, angle_bank, false), value}
define_set number max_heading(item_id item = selected) {set __limits(item, angle_heading, true), value}
define_set number max_pitch(item_id item = selected) {set __limits(item, angle_pitch, true), value}
define_set number max_bank(item_id item = selected) {set __limits(item, angle_bank, true), value}

define_command relative_limits(int angle_type, number min, number max)
{
    ; Sets the relative rotational limits for the currently selected item.
    ; Working with angles relative to an item's current orientation is often 
    ; more intuitive than working with absolute angles. Furthermore,
    ; this procedure will flip the min/max relative values if flip_* flags 
    ; are set and the item is on the appropriate side.

    ; Automatically turn of limits for the specified angle type if they aren't
    ; already on.
    set limits_on(selected, angle_type), true

    number current_angle, eval(angle_type_name(angle_type) )
    if (min > max) {error "max must be greater than or equal to min."}
    __swap_relative_limits_if_necessary selected, angle_type, min, max
    __native_command (__set_limits_command(angle_type) & " " & current_angle + min & " " & current_angle + max)
}
define_command relative_hlimits(number min, number max) {relative_limits angle_heading, min, max}
define_command relative_plimits(number min, number max) {relative_limits angle_pitch, min, max}
define_command relative_blimits(number min, number max) {relative_limits angle_bank, min, max}

; *****************************************************************************
define_function string __toggle_limits_command(int angle_type)
{
    ; Returns the native command to toggle limits on/off for the specified
    ; angle type.
    if (angle_type == angle_heading) {return "LimitH"}
    if (angle_type == angle_pitch) {return "LimitP"}
    if (angle_type == angle_bank) {return "LimitB"}
    __error_invalid_angle_type angle_type
}

define_function string __set_limits_command(int angle_type)
{
    ; Returns the native command to set limit values for the specified
    ; angle type.
    if (angle_type == angle_heading) {return "HLimits"}
    if (angle_type == angle_pitch) {return "PLimits"}
    if (angle_type == angle_bank) {return "BLimits"}
    __error_invalid_angle_type angle_type
}

; *****************************************************************************
define_set bool limits_on(item_id item, int angle_type)
{
    ; Sets whether limits are on/off for the specified angle type. The get
    ; procedure for this property is defined internally.
    if (limits_on(item, angle_type) != value) {execute_for_item item, __toggle_limits_command(angle_type) }
}

; *****************************************************************************
define_command __swap_relative_limits(number& min, number& max)
{
    number temp, min;
    set min, (max * -1.0)
    set max, (temp * -1.0)
}

define_command __swap_relative_limits_if_necessary(item_id item, int angle_type, number& min, number& max)
{
    bool flip_left, eval("flip_left_" & angle_type_name(angle_type) )
    bool flip_right eval("flip_right_" & angle_type_name(angle_type) )
    number x, world_x(item)
    if ( (x < 0 && flip_left) || (x > 0 && flip_right) ) {__swap_relative_limits min, max }
}

define_get number __limits(item_id item, int angle_type, bool max)
{
    ; Returns the limit values for the specified angle type.
    if (!limits_on(item, angle_type)) {error ("Cannot retrieve limits for " & angle_type_name(angle_type)  & " because " & angle_type_name(angle_type)  & " limits are disabled.") }
    return __limits_impl(item, angle_type, max)
}

define_set number __limits(item_id item, int angle_type, bool is_max)
{
    ; Sets the limit values for the specified angle type.
    number min
    number max
    
    ; Automatically turn of limits for the specified angle type if they aren't
    ; already on.
    set limits_on(item, angle_type), true

    if (is_max)
    {
        set max, value
        set min, __limits(item, angle_type, false)
        if (min > max) {set min, max}
    }
    else
    {
        set min, value
        set max, __limits(item, angle_type, true)
        if (max < min) {set max, min}
    }
    execute_for_item item, (__set_limits_command(angle_type) & ", min, max")
}

; *****************************************************************************
; Sets/gets motion controllers for heading, pitch, and bank. Valid values are:
; controller_keyframes, controller_targeting, controller_align_to_path, and
; controller_ik.

define_set int heading_controller(item_id item = selected) {execute_for_item item, "HController value" }
define_set int pitch_controller(item_id item = selected) {execute_for_item item, "PController value" }
define_set int bank_controller(item_id item = selected) {execute_for_item item, "BController value" }

define_get int heading_controller(item_id item = selected) {return __controller(item, angle_heading) }
define_get int pitch_controller(item_id item = selected) {return __controller(item, angle_pitch) }
define_get int bank_controller(item_id item = selected) {return __controller(item, angle_bank) }

; *****************************************************************************
; Procedures that deal with layout states.

; Local item states:
define_set item_id parent(item_id item = selected) {execute_for_item item, "ParentItem value"}
define_set item_id target(item_id item = selected) {execute_for_item item, "TargetItem value"}
define_set item_id goal(item_id item = selected) {execute_for_item item, "GoalItem value"}
define_function item_id child(int index = 0, item_id item = selected) {return __child(index, item) }

define_set int color(item_id item = selected) {execute_for_item item, "ItemColor value"}

define_get bool active(item_id item = selected) {return bitwise_and(__item_flags(item), __itemf_active) }
define_get bool full_time_ik(item_id item = selected) {return bitwise_and(__item_flags(item), __itemf_full_time_ik) }
define_get bool match_goal_orientation(item_id item = selected) {return bitwise_and(__item_flags(item), __itemf_goal_orient) }
define_get bool keep_goal_within_reach(item_id item = selected) {return bitwise_and(__item_flags(item), __itemf_reach_goal) }
define_get bool unaffected_by_ik(item_id item = selected) {return bitwise_and(__item_flags(item), __itemf_unaffect_by_ik) }

define_set bool active(item_id item = selected) {execute_for_item item, "ItemActive value"}
define_set number look_ahead(item_id item = selected) {execute_for_item item, "PathAlignLookAhead value"}
define_set number goal_strength(item_id item = selected) {execute_for_item item, "GoalStrength value"}
define_set bool full_time_ik(item_id item = selected) {execute_for_item item, choose(full_time_ik(item) != value, "FullTimeIK", empty_string) }
define_set bool match_goal_orientation(item_id item = selected) {execute_for_item item, choose(match_goal_orientation(item) != value, "MatchGoalOrientation", empty_string) }
define_set bool keep_goal_within_reach(item_id item = selected) {execute_for_item item, choose(keep_goal_within_reach(item) != value, "KeepGoalWithinReach", empty_string) }
define_set bool unaffected_by_ik(item_id item = selected) {execute_for_item item, choose(unaffected_by_ik(item) != value, "UnaffectedByIK", empty_string) }

; Returns the rotational stiffness of the specified item for the specified angle type.
define_get number __stiffness(item_id item, int angle_type)
{
    assert_valid_angle_type angle_type
    return __stiffness_impl(item, angle_type)
}
define_get number hstiffness(item_id item = selected) {return __stiffness(item, angle_heading) }
define_get number pstiffness(item_id item = selected) {return __stiffness(item, angle_pitch) }
define_get number bstiffness(item_id item = selected) {return __stiffness(item, angle_bank) }

; Sets the rotational stiffness of the specified item for the specified angle type.
define_set number __stiffness(item_id item, int angle_type)
{
    if (angle_type == angle_heading) {execute_for_item item, "HStiffness value"}
    else_if (angle_type == angle_pitch) {execute_for_item item, "PStiffness value"}
    else_if (angle_type == angle_bank) {execute_for_item item, "BStiffness value"}
    else {__error_invalid_angle_type angle_type}
}
define_set number hstiffness(item_id item = selected) {set __stiffness(item, angle_heading) , value}
define_set number pstiffness(item_id item = selected) {set __stiffness(item, angle_pitch), value}
define_set number bstiffness(item_id item = selected) {set __stiffness(item, angle_bank), value}

; Global states:
define_get bool auto_key {return bitwise_and(__general_flags, __generalf_auto_key) }
define_get bool parent_in_place {return bitwise_and(__general_flags, __generalf_parent_in_place) }

define_set bool auto_key  {execute choose(auto_key != value, "AutoKey", empty_string) }
define_set bool parent_in_place {execute choose(parent_in_place != value, "ParentInPlace", empty_string) }

; *****************************************************************************
define_command MoveToItem(item_id target_item, number add_x = 0, number add_y = 0, number add_z = 0)
{
    ; Moves the selected item to the position of the specified
    ; target item.
    Position world_x(target_item), world_y(target_item), world_z(target_item)
}

; *****************************************************************************
; The following override native commands for setting item positions.
; They have been overriden to provide type-safety and to handle
; flipping if flip_left_x or flip_right_x is set to true.

define_command Position(number x, number y, number z)
{
    ; Sets the absolute position of the selected item. The command 
    ; is unaffected by flip_left_x and flip_right_x since it doesn't
    ; work with the item's previous position.
    __native_command ("Position " & x & " " & y & " " & z) 
    RefreshNow
}

define_command AddPosition(number x, number y, number z)
{
    ; Sets the position of the selected items relative to its previous 
    ; position.
    if (num_selected == 1)
    {
        number item_x, world_x
        if ( (item_x < 0 && flip_left_x) || (item_x > 0 && flip_right_x) ) {__native_command command_line("AddPosition", (-x), y, z) }
        else {__native_command command_line("AddPosition", x, y, z) }
    }
    else
    {
        store_selection
        collection c, get_selected_items
        for_each c
        {
            selectitem element
            number item_x, world_x
            if ( (item_x < 0 && flip_left_x) || (item_x > 0 && flip_right_x) ) {__native_command command_line("AddPosition", (-x), y, z) }
            else {__native_command command_line("AddPosition", x, y, z) }
        }
        restore_selection
    }
    RefreshNow
}

; *****************************************************************************
define_command AddRotation(number add_heading, number add_pitch, number add_bank)
{
    ; Overrides the native command to flip the angles if necessary.

    if (num_selected == 1) {__AddRotation_impl selected, add_heading, add_pitch, add_bank}
    else
    {
        store_selection
        collection c, get_selected_items
        for_each c {__AddRotation_impl element, add_heading, add_pitch, add_bank}
        restore_selection
    }
    RefreshNow
}

define_command __AddRotation_impl(item_id item, number add_heading, number add_pitch, number add_bank)
{
    select item
    if (world_x < 0)
    {
        if (flip_left_heading) {set add_heading, (-add_heading) }
        if (flip_left_pitch) {set add_pitch, (-add_pitch) }
        if (flip_left_bank) {set add_bank, (-add_bank) }
    }
    else_if (world_x > 0)
    {
        if (flip_right_heading) {set add_heading, (-add_heading) }
        if (flip_right_pitch) {set add_pitch, (-add_pitch) }
        if (flip_right_bank) {set add_bank, (-add_bank) }
    }
    __native_command command_line("AddRotation", add_heading, add_pitch, add_bank)
    RefreshNow
}

; *****************************************************************************
__init_internals
Return to index.
Return to Kung Fu Tools page..
Return to main page.