Use explicit template types with std::fill when generating messages (#307)

This fixes MSVC warnings when filling arrays/vectors with types smaller than int.

// generated from rosidl_generator_cpp/resource/msg__struct.hpp.em
// generated code does not contain a copyright notice

@#######################################################################
@# EmPy template for generating <msg>__struct.hpp files
@#
@# Context:
@#  - spec (rosidl_parser.MessageSpecification)
@#    Parsed specification of the .msg file
@#  - subfolder (string)
@#    The subfolder / subnamespace of the message
@#    Either 'msg' or 'srv'
@#  - get_header_filename_from_msg_name (function)
@#######################################################################
@
@{
header_guard_parts = [
    spec.base_type.pkg_name, subfolder,
    get_header_filename_from_msg_name(spec.base_type.type) + '__struct_hpp']
header_guard_variable = '__'.join([x.upper() for x in header_guard_parts]) + '_'
}@
#ifndef @(header_guard_variable)
#define @(header_guard_variable)

// Protect against ERROR being predefined on Windows, in case somebody defines a
// constant by that name.
#if defined(_WIN32) && defined(ERROR)
  #undef ERROR
#endif

@{
from rosidl_generator_cpp import create_init_alloc_and_member_lists
from rosidl_generator_cpp import escape_string
from rosidl_generator_cpp import msg_type_only_to_cpp
from rosidl_generator_cpp import msg_type_to_cpp
from rosidl_generator_cpp import MSG_TYPE_TO_CPP

cpp_namespace = '%s::%s::' % (spec.base_type.pkg_name, subfolder)
cpp_class = '%s_' % spec.base_type.type
cpp_full_name = '%s%s' % (cpp_namespace, cpp_class)
cpp_full_name_with_alloc = '%s<ContainerAllocator>' % (cpp_full_name)
}@
#include <rosidl_generator_cpp/bounded_vector.hpp>
#include <rosidl_generator_cpp/message_initialization.hpp>
#include <algorithm>
#include <array>
#include <memory>
#include <string>
#include <vector>

// include message dependencies
@{
includes = {}
for field in spec.fields:
    if not field.type.is_primitive_type():
        key = '%s/msg/%s.hpp' % \
            (field.type.pkg_name, get_header_filename_from_msg_name(field.type.type))
        if key not in includes:
            includes[key] = set([])
        includes[key].add(field.name)
for key in sorted(includes.keys()):
    print('#include "%s"  // %s' % (key, ', '.join(includes[key])))
}@

@{
deprecated_macro_name = \
    '_'.join(['DEPRECATED', spec.base_type.pkg_name, subfolder, spec.base_type.type])
}@
#ifndef _WIN32
# define @(deprecated_macro_name) __attribute__((deprecated))
#else
# define @(deprecated_macro_name) __declspec(deprecated)
#endif

namespace @(spec.base_type.pkg_name)
{

namespace @(subfolder)
{

// message struct
template<class ContainerAllocator>
struct @(spec.base_type.type)_
{
  using Type = @(spec.base_type.type)_<ContainerAllocator>;

@{
# The creation of the constructors for messages is a bit complicated.  The goal
# is to have a constructor where the user can control how the fields of the
# message get initialized via the _init parameter to the constructor.  See
# http://design.ros2.org/articles/generated_interfaces_cpp.html#constructors
# for a detailed explanation of the different _init parameters.
init_list, alloc_list, member_list = create_init_alloc_and_member_lists(spec)

def generate_default_string(membset):
    strlist = []
    for member in membset.members:
        if member.default_value is not None:
            if member.num_prealloc > 0:
                strlist.append('this->%s.resize(%d);' % (member.name, member.num_prealloc))
            if isinstance(member.default_value, list):
                if all(v == member.default_value[0] for v in member.default_value):
                    # Specifying type for std::fill because of MSVC 14.12 warning about casting 'const int' to smaller types (C4244)
                    # For more info, see https://github.com/ros2/rosidl/issues/309
                    # TODO(jacobperron): Investigate reason for build warnings on Windows
                    # TODO(jacobperron): Write test case for this path of execution
                    strlist.append('std::fill<typename %s::iterator, %s>(this->%s.begin(), this->%s.end(), %s);' % (msg_type_to_cpp(member.type), msg_type_only_to_cpp(member.type), member.name, member.name, member.default_value[0]))
                else:
                    for index, val in enumerate(member.default_value):
                        strlist.append('this->%s[%d] = %s;' % (member.name, index, val))
            else:
                strlist.append('this->%s = %s;' % (member.name, member.default_value))

    return strlist

def generate_zero_string(membset, fill_args):
    strlist = []
    for member in membset.members:
        if isinstance(member.zero_value, list):
            if member.num_prealloc > 0:
                strlist.append('this->%s.resize(%d);' % (member.name, member.num_prealloc))
            if member.zero_need_array_override:
                strlist.append('this->%s.fill(%s{%s});' % (member.name, msg_type_only_to_cpp(member.type), fill_args))
            else:
                # Specifying type for std::fill because of MSVC 14.12 warning about casting 'const int' to smaller types (C4244)
                # For more info, see https://github.com/ros2/rosidl/issues/309
                # TODO(jacobperron): Investigate reason for build warnings on Windows
                strlist.append('std::fill<typename %s::iterator, %s>(this->%s.begin(), this->%s.end(), %s);' % (msg_type_to_cpp(member.type), msg_type_only_to_cpp(member.type), member.name, member.name, member.zero_value[0]))
        else:
            strlist.append('this->%s = %s;' % (member.name, member.zero_value))
    return strlist
}@
  explicit @(spec.base_type.type)_(rosidl_generator_cpp::MessageInitialization _init = rosidl_generator_cpp::MessageInitialization::ALL)
@[if init_list]@
  : @(',\n    '.join(init_list))
@[end if]@
  {
@[if not member_list]@
    (void)_init;
@[end if]@
@[for membset in member_list]@
@[ if membset.members[0].default_value is not None]@
    if (rosidl_generator_cpp::MessageInitialization::ALL == _init ||
      rosidl_generator_cpp::MessageInitialization::DEFAULTS_ONLY == _init)
    {
@[  for line in generate_default_string(membset)]@
      @(line)
@[  end for]@
@[  if membset.members[0].zero_value is not None]@
    } else if (rosidl_generator_cpp::MessageInitialization::ZERO == _init) {
@[   for line in generate_zero_string(membset, '_init')]@
      @(line)
@[   end for]@
@[  end if]@
    }
@[ elif membset.members[0].zero_value is not None]@
    if (rosidl_generator_cpp::MessageInitialization::ALL == _init ||
      rosidl_generator_cpp::MessageInitialization::ZERO == _init)
    {
@[  for line in generate_zero_string(membset, '_init')]@
      @(line)
@[  end for]@
    }
@[ end if]@
@[end for]@
  }

  explicit @(spec.base_type.type)_(const ContainerAllocator & _alloc, rosidl_generator_cpp::MessageInitialization _init = rosidl_generator_cpp::MessageInitialization::ALL)
@[if alloc_list]@
  : @(',\n    '.join(alloc_list))
@[end if]@
  {
@[if not member_list]@
    (void)_init;
@[end if]@
@[if not alloc_list]@
    (void)_alloc;
@[end if]@
@[for membset in member_list]@
@[ if membset.members[0].default_value is not None]@
    if (rosidl_generator_cpp::MessageInitialization::ALL == _init ||
      rosidl_generator_cpp::MessageInitialization::DEFAULTS_ONLY == _init)
    {
@[  for line in generate_default_string(membset)]@
      @(line)
@[  end for]@
@[  if membset.members[0].zero_value is not None]@
    } else if (rosidl_generator_cpp::MessageInitialization::ZERO == _init) {
@[   for line in generate_zero_string(membset, '_alloc, _init')]@
      @(line)
@[   end for]@
@[  end if]@
    }
@[ elif membset.members[0].zero_value is not None]@
    if (rosidl_generator_cpp::MessageInitialization::ALL == _init ||
      rosidl_generator_cpp::MessageInitialization::ZERO == _init)
    {
@[  for line in generate_zero_string(membset, '_alloc, _init')]@
      @(line)
@[  end for]@
    }
@[ end if]@
@[end for]@
  }

  // field types and members
@[for field in spec.fields]@
  using _@(field.name)_type =
    @(msg_type_to_cpp(field.type));
  _@(field.name)_type @(field.name);
@[end for]@

  // setters for named parameter idiom
@[for field in spec.fields]@
  Type * set__@(field.name)(
    const @(msg_type_to_cpp(field.type)) & _arg)
  {
    this->@(field.name) = _arg;
    return this;
  }
@[end for]@

  // constant declarations
@[for constant in spec.constants]@
@[if constant.type == 'string']
  static const @(MSG_TYPE_TO_CPP[constant.type]) @(constant.name);
@[else]@
  static constexpr @(MSG_TYPE_TO_CPP[constant.type]) @(constant.name) =
@[if constant.type in ('bool', 'byte', 'int8', 'int16', 'int32', 'int64', 'char')]@
    @(int(constant.value));
@[elif constant.type in ('uint8', 'uint16', 'uint32', 'uint64')]@
    @(int(constant.value))u;
@[else]@
    @(constant.value);
@[  end if]@
@[end if]@
@[end for]@

  // pointer types
  using RawPtr =
    @(cpp_full_name)<ContainerAllocator> *;
  using ConstRawPtr =
    const @(cpp_full_name)<ContainerAllocator> *;
  using SharedPtr =
    std::shared_ptr<@(cpp_full_name)<ContainerAllocator>>;
  using ConstSharedPtr =
    std::shared_ptr<@(cpp_full_name)<ContainerAllocator> const>;

  template<typename Deleter = std::default_delete<
      @(cpp_full_name)<ContainerAllocator>>>
  using UniquePtrWithDeleter =
    std::unique_ptr<@(cpp_full_name)<ContainerAllocator>, Deleter>;

  using UniquePtr = UniquePtrWithDeleter<>;

  template<typename Deleter = std::default_delete<
      @(cpp_full_name)<ContainerAllocator>>>
  using ConstUniquePtrWithDeleter =
    std::unique_ptr<@(cpp_full_name)<ContainerAllocator> const, Deleter>;
  using ConstUniquePtr = ConstUniquePtrWithDeleter<>;

  using WeakPtr =
    std::weak_ptr<@(cpp_full_name)<ContainerAllocator>>;
  using ConstWeakPtr =
    std::weak_ptr<@(cpp_full_name)<ContainerAllocator> const>;

  // pointer types similar to ROS 1, use SharedPtr / ConstSharedPtr instead
  // NOTE: Can't use 'using' here because GNU C++ can't parse attributes properly
  typedef @(deprecated_macro_name)
    std::shared_ptr<@(cpp_full_name)<ContainerAllocator>>
    Ptr;
  typedef @(deprecated_macro_name)
    std::shared_ptr<@(cpp_full_name)<ContainerAllocator> const>
    ConstPtr;

  // comparison operators
  bool operator==(const @(spec.base_type.type)_ & other) const
  {
@[if not spec.fields]@
    (void)other;
@[end if]@
@[for field in spec.fields]@
    if (this->@(field.name) != other.@(field.name)) {
      return false;
    }
@[end for]@
    return true;
  }
  bool operator!=(const @(spec.base_type.type)_ & other) const
  {
    return !this->operator==(other);
  }
};  // struct @(cpp_class)

// alias to use template instance with default allocator
using @(spec.base_type.type) =
  @(cpp_full_name)<std::allocator<void>>;

// constant definitions
@[for c in spec.constants]@
@[if c.type == 'string']@
template<typename ContainerAllocator>
const @(MSG_TYPE_TO_CPP[c.type])
@(spec.base_type.type)_<ContainerAllocator>::@(c.name) = "@(escape_string(c.value))";
@[ else ]@
template<typename ContainerAllocator>
constexpr @(MSG_TYPE_TO_CPP[c.type]) @(spec.base_type.type)_<ContainerAllocator>::@(c.name);
@[end if]@
@[end for]@

}  // namespace @(subfolder)

}  // namespace @(spec.base_type.pkg_name)

#endif  // @(header_guard_variable)

// generated from rosidl_generator_cpp/resource/msg__struct.hpp.em
// generated code does not contain a copyright notice

@#######################################################################
@# EmPy template for generating <msg>__struct.hpp files
@#
@# Context:
@#  - spec (rosidl_parser.MessageSpecification)
@#    Parsed specification of the .msg file
@#  - subfolder (string)
@#    The subfolder / subnamespace of the message
@#    Either 'msg' or 'srv'
@#  - get_header_filename_from_msg_name (function)
@#######################################################################
@
@{
header_guard_parts = [
    spec.base_type.pkg_name, subfolder,
    get_header_filename_from_msg_name(spec.base_type.type) + '__struct_hpp']
header_guard_variable = '__'.join([x.upper() for x in header_guard_parts]) + '_'
}@
#ifndef @(header_guard_variable)
#define @(header_guard_variable)

// Protect against ERROR being predefined on Windows, in case somebody defines a
// constant by that name.
#if defined(_WIN32) && defined(ERROR)
  #undef ERROR
#endif

@{
from rosidl_generator_cpp import create_init_alloc_and_member_lists
from rosidl_generator_cpp import escape_string
from rosidl_generator_cpp import msg_type_only_to_cpp
from rosidl_generator_cpp import msg_type_to_cpp
from rosidl_generator_cpp import MSG_TYPE_TO_CPP

cpp_namespace = '%s::%s::' % (spec.base_type.pkg_name, subfolder)
cpp_class = '%s_' % spec.base_type.type
cpp_full_name = '%s%s' % (cpp_namespace, cpp_class)
cpp_full_name_with_alloc = '%s<ContainerAllocator>' % (cpp_full_name)
}@
#include <rosidl_generator_cpp/bounded_vector.hpp>
#include <rosidl_generator_cpp/message_initialization.hpp>
#include <algorithm>
#include <array>
#include <memory>
#include <string>
#include <vector>

// include message dependencies
@{
includes = {}
for field in spec.fields:
    if not field.type.is_primitive_type():
        key = '%s/msg/%s.hpp' % \
            (field.type.pkg_name, get_header_filename_from_msg_name(field.type.type))
        if key not in includes:
            includes[key] = set([])
        includes[key].add(field.name)
for key in sorted(includes.keys()):
    print('#include "%s"  // %s' % (key, ', '.join(includes[key])))
}@

@{
deprecated_macro_name = \
    '_'.join(['DEPRECATED', spec.base_type.pkg_name, subfolder, spec.base_type.type])
}@
#ifndef _WIN32
# define @(deprecated_macro_name) __attribute__((deprecated))
#else
# define @(deprecated_macro_name) __declspec(deprecated)
#endif

namespace @(spec.base_type.pkg_name)
{

namespace @(subfolder)
{

// message struct
template<class ContainerAllocator>
struct @(spec.base_type.type)_
{
  using Type = @(spec.base_type.type)_<ContainerAllocator>;

@{
# The creation of the constructors for messages is a bit complicated.  The goal
# is to have a constructor where the user can control how the fields of the
# message get initialized via the _init parameter to the constructor.  See
# http://design.ros2.org/articles/generated_interfaces_cpp.html#constructors
# for a detailed explanation of the different _init parameters.
init_list, alloc_list, member_list = create_init_alloc_and_member_lists(spec)

def generate_default_string(membset):
    strlist = []
    for member in membset.members:
        if member.default_value is not None:
            if member.num_prealloc > 0:
                strlist.append('this->%s.resize(%d);' % (member.name, member.num_prealloc))
            if isinstance(member.default_value, list):
                if all(v == member.default_value[0] for v in member.default_value):
                    strlist.append('std::fill(this->%s.begin(), this->%s.end(), %s);' % (member.name, member.name, member.default_value[0]))
                else:
                    for index, val in enumerate(member.default_value):
                        strlist.append('this->%s[%d] = %s;' % (member.name, index, val))
            else:
                strlist.append('this->%s = %s;' % (member.name, member.default_value))

    return strlist

def generate_zero_string(membset, fill_args):
    strlist = []
    for member in membset.members:
        if isinstance(member.zero_value, list):
            if member.num_prealloc > 0:
                strlist.append('this->%s.resize(%d);' % (member.name, member.num_prealloc))
            if member.zero_need_array_override:
                strlist.append('this->%s.fill(%s{%s});' % (member.name, msg_type_only_to_cpp(member.type), fill_args))
            else:
                strlist.append('std::fill(this->%s.begin(), this->%s.end(), %s);' % (member.name, member.name, member.zero_value[0]))
        else:
            strlist.append('this->%s = %s;' % (member.name, member.zero_value))
    return strlist
}@
  explicit @(spec.base_type.type)_(rosidl_generator_cpp::MessageInitialization _init = rosidl_generator_cpp::MessageInitialization::ALL)
@[if init_list]@
  : @(',\n    '.join(init_list))
@[end if]@
  {
@[if not member_list]@
    (void)_init;
@[end if]@
@[for membset in member_list]@
@[ if membset.members[0].default_value is not None]@
    if (rosidl_generator_cpp::MessageInitialization::ALL == _init ||
      rosidl_generator_cpp::MessageInitialization::DEFAULTS_ONLY == _init)
    {
@[  for line in generate_default_string(membset)]@
      @(line)
@[  end for]@
@[  if membset.members[0].zero_value is not None]@
    } else if (rosidl_generator_cpp::MessageInitialization::ZERO == _init) {
@[   for line in generate_zero_string(membset, '_init')]@
      @(line)
@[   end for]@
@[  end if]@
    }
@[ elif membset.members[0].zero_value is not None]@
    if (rosidl_generator_cpp::MessageInitialization::ALL == _init ||
      rosidl_generator_cpp::MessageInitialization::ZERO == _init)
    {
@[  for line in generate_zero_string(membset, '_init')]@
      @(line)
@[  end for]@
    }
@[ end if]@
@[end for]@
  }

  explicit @(spec.base_type.type)_(const ContainerAllocator & _alloc, rosidl_generator_cpp::MessageInitialization _init = rosidl_generator_cpp::MessageInitialization::ALL)
@[if alloc_list]@
  : @(',\n    '.join(alloc_list))
@[end if]@
  {
@[if not member_list]@
    (void)_init;
@[end if]@
@[if not alloc_list]@
    (void)_alloc;
@[end if]@
@[for membset in member_list]@
@[ if membset.members[0].default_value is not None]@
    if (rosidl_generator_cpp::MessageInitialization::ALL == _init ||
      rosidl_generator_cpp::MessageInitialization::DEFAULTS_ONLY == _init)
    {
@[  for line in generate_default_string(membset)]@
      @(line)
@[  end for]@
@[  if membset.members[0].zero_value is not None]@
    } else if (rosidl_generator_cpp::MessageInitialization::ZERO == _init) {
@[   for line in generate_zero_string(membset, '_alloc, _init')]@
      @(line)
@[   end for]@
@[  end if]@
    }
@[ elif membset.members[0].zero_value is not None]@
    if (rosidl_generator_cpp::MessageInitialization::ALL == _init ||
      rosidl_generator_cpp::MessageInitialization::ZERO == _init)
    {
@[  for line in generate_zero_string(membset, '_alloc, _init')]@
      @(line)
@[  end for]@
    }
@[ end if]@
@[end for]@
  }

  // field types and members
@[for field in spec.fields]@
  using _@(field.name)_type =
    @(msg_type_to_cpp(field.type));
  _@(field.name)_type @(field.name);
@[end for]@

  // setters for named parameter idiom
@[for field in spec.fields]@
  Type * set__@(field.name)(
    const @(msg_type_to_cpp(field.type)) & _arg)
  {
    this->@(field.name) = _arg;
    return this;
  }
@[end for]@

  // constant declarations
@[for constant in spec.constants]@
@[if constant.type == 'string']
  static const @(MSG_TYPE_TO_CPP[constant.type]) @(constant.name);
@[else]@
  static constexpr @(MSG_TYPE_TO_CPP[constant.type]) @(constant.name) =
@[if constant.type in ('bool', 'byte', 'int8', 'int16', 'int32', 'int64', 'char')]@
    @(int(constant.value));
@[elif constant.type in ('uint8', 'uint16', 'uint32', 'uint64')]@
    @(int(constant.value))u;
@[else]@
    @(constant.value);
@[  end if]@
@[end if]@
@[end for]@

  // pointer types
  using RawPtr =
    @(cpp_full_name)<ContainerAllocator> *;
  using ConstRawPtr =
    const @(cpp_full_name)<ContainerAllocator> *;
  using SharedPtr =
    std::shared_ptr<@(cpp_full_name)<ContainerAllocator>>;
  using ConstSharedPtr =
    std::shared_ptr<@(cpp_full_name)<ContainerAllocator> const>;

  template<typename Deleter = std::default_delete<
      @(cpp_full_name)<ContainerAllocator>>>
  using UniquePtrWithDeleter =
    std::unique_ptr<@(cpp_full_name)<ContainerAllocator>, Deleter>;

  using UniquePtr = UniquePtrWithDeleter<>;

  template<typename Deleter = std::default_delete<
      @(cpp_full_name)<ContainerAllocator>>>
  using ConstUniquePtrWithDeleter =
    std::unique_ptr<@(cpp_full_name)<ContainerAllocator> const, Deleter>;
  using ConstUniquePtr = ConstUniquePtrWithDeleter<>;

  using WeakPtr =
    std::weak_ptr<@(cpp_full_name)<ContainerAllocator>>;
  using ConstWeakPtr =
    std::weak_ptr<@(cpp_full_name)<ContainerAllocator> const>;

  // pointer types similar to ROS 1, use SharedPtr / ConstSharedPtr instead
  // NOTE: Can't use 'using' here because GNU C++ can't parse attributes properly
  typedef @(deprecated_macro_name)
    std::shared_ptr<@(cpp_full_name)<ContainerAllocator>>
    Ptr;
  typedef @(deprecated_macro_name)
    std::shared_ptr<@(cpp_full_name)<ContainerAllocator> const>
    ConstPtr;

  // comparison operators
  bool operator==(const @(spec.base_type.type)_ & other) const
  {
@[if not spec.fields]@
    (void)other;
@[end if]@
@[for field in spec.fields]@
    if (this->@(field.name) != other.@(field.name)) {
      return false;
    }
@[end for]@
    return true;
  }
  bool operator!=(const @(spec.base_type.type)_ & other) const
  {
    return !this->operator==(other);
  }
};  // struct @(cpp_class)

// alias to use template instance with default allocator
using @(spec.base_type.type) =
  @(cpp_full_name)<std::allocator<void>>;

// constant definitions
@[for c in spec.constants]@
@[if c.type == 'string']@
template<typename ContainerAllocator>
const @(MSG_TYPE_TO_CPP[c.type])
@(spec.base_type.type)_<ContainerAllocator>::@(c.name) = "@(escape_string(c.value))";
@[ else ]@
template<typename ContainerAllocator>
constexpr @(MSG_TYPE_TO_CPP[c.type]) @(spec.base_type.type)_<ContainerAllocator>::@(c.name);
@[end if]@
@[end for]@

}  // namespace @(subfolder)

}  // namespace @(spec.base_type.pkg_name)

#endif  // @(header_guard_variable)


Scripted presences list now appears in gui as selected scroll.  Next: change the nearby list to be same way + find out why after change one visible from nearby to scripted column, cannot change others.

(function()
 {

     /**
      @param {std.ScriptingGui.Controller}

      @param {object: <String(visibleId):visible object>} nearbyVisMap
      -- all the visible objects that satisfy scripter's proximity
      query.

      @param {object: <String(visibleId):
      std.FileManager.FileManagerElement> scriptedVisMap -- A record
      of all visibles that we have scripted at some point.

      @param {object: <int:std.ScriptingGui.Action> actionMap -- Which
      actions are selectable by scripter.

      @param {std.ScriptingGui.Console} console -- has several
      scripting events.
      */
     std.ScriptingGui =
         function(controller,nearbyVisMap,scriptedVisMap,actionMap,console)
     {
         if (typeof(simulator) == 'undefined')
         {
             throw new Error('Cannot initialize scripting gui without ' +
                             'simulator graphics.');
         }

         this.controller       = controller;
         this.nearbyVisMap     = nearbyVisMap;
         this.scriptedVisMap   = scriptedVisMap;
         this.actionMap        = actionMap;
         this.console          = console;

         this.guiMod = simulator._simulator.addGUITextModule(
             guiName(),
             getGuiText(),
             std.core.bind(guiInitFunc,undefined,this));
         this.hasInited = false;
     };

     system.require('scriptingGuiUtil.em');

     std.ScriptingGui.prototype.redraw = function()
     {
         if (!this.hasInited)
             return;

         //trigger redraw call
         this.guiMod.call(
             'ishmaelRedraw',toHtmlNearbyMap(this),toHtmlScriptedMap(this),
             toHtmlActionMap(this));

     };

     /**
      @param {String} visId -- Id of visible.
      */
     //called by html to add the visible with id
     std.ScriptingGui.prototype.hAddVisible = function(visId)
     {
         //already can script the visible.
         if (visId in this.scriptedVisMap)
         {
             this.console.guiEvent();
             return;
         }

         if (!(visId in this.nearbyVisMap))
         {
             //visible is no longer available.
             this.console.guiEvent();
             return;
         }

         this.controller.addVisible(this.nearbyVisMap[visId]);
     };

     std.ScriptingGui.prototype.hRemoveVisible = function(visId)
     {
         //FIXME: should finish this call
         throw new Error('FIXME: must finish hRemoveVisible call ' +
                         'in scriptingGui');
     };

     // //whenever user selects an action to display, then we change
     // //model of internal action that should be displaying.
     // std.ScriptingGui.prototype.hActionSelected = function(actId)
     // {
     //     if(actId in this.actionMap)
     //         this.selectedAction = this.actionMap[actId];
     //     else
     //         this.selectedAction = undefined;
     // };

     /**
      @param {std.ScriptingGui}
      */
     function guiInitFunc(scriptingGui)
     {
         scriptingGui.hasInited = true;

         //when a user clicks on any of the nearby visibles to script
         //them, want that object to move into scripted objects.
         scriptingGui.guiMod.bind(
             'addVisible',
             std.core.bind(scriptingGui.hAddVisible,scriptingGui));

         //when a user clicks to remove any of the scripted visibles
         //from scripted map, then destroy it.
         scriptingGui.guiMod.bind(
             'removeVisible',
             std.core.bind(scriptingGui.hRemoveVisible,scriptingGui));

         scriptingGui.redraw();
     }

     /**
      @returns {object: <string (visibleId): string (visibleId)>}
      scriptingGui -- Takes the list of nearby objects and turns it
      into an object that (for now) maps visibleIds to visibleIds.

      @see ishmaelRedraw
      */
     function toHtmlNearbyMap(scriptingGui)
     {
         var returner = { };
         for (var s in scriptingGui.nearbyVisMap)
             returner[s] = s;
         return returner;
     }

     /**
      @returns {object: <string (visibleId): string (visibleId)>}
      scriptingGui -- Takes the list of nearby objects and turns it
      into an object that (for now) maps visibleIds to visibleIds.

      @see ishmaelRedraw
      */
     function toHtmlScriptedMap(scriptingGui)
     {
         var returner = { };
         for (var s in scriptingGui.scriptedVisMap)
             returner[s] = s;
         return returner;
     }

     function toHtmlActionMap(scriptingGui)
     {
         return scriptingGui.actionMap;
     }

     function guiName()
     {
         return 'ishmaelEditor';
     }

     function getGuiText()
     {

         var returner = "sirikata.ui('" + guiName() + "',";
         returner += 'function(){ ';

         returner += @

         function ishmaelWindowId()
         {
             return 'ishmael__windowID_';
         }

         //the div that surrounds all the nearby objects.
         function nearbyListId()
         {
             return 'ishmael__nearbyListID__';
         }

         //the div that surrounds all the scripted objects.
         function scriptedListId()
         {
             return 'ishmael__scriptedListID__';
         }

         function actionListId()
         {
             return 'ishmael__actionListID__';
         }

         function actionTareaId()
         {
             return 'ishmael__actionEditor__';
         }

         /**
          \param {String} nearbyObj (id of visible that we are
          communicating with).
          gives the div for each nearby object.
          */
         function generateNearbyDivId(nearbyObj)
         {
             var visIdDivable = divizeVisibleId(nearbyObj);
             return 'ishmael__nearbyDivID___' + visIdDivable;
         }

         /**
          \param {String} scriptedObj (id of visible that we are
          communicating with).
          gives the div for each scripted object.
          */
         function generateScriptedDivId(scriptedObj)
         {
             var visIdDivable = divizeVisibleId(scriptedObj);
             return 'ishmael__scriptedDivID___' + visIdDivable;
         }

         function divizeVisibleId(visId)
         {
             return visId.replace(':','');
         }

         $('
'   +

           'Scripted presences
' +
           '<select id="'+ scriptedListId() + '"  size=5>' +
           '</select>
'  +

           'Nearby presences
'      +
           '
'     +
           '
'  +

           '<select id="' + actionListId() + '" size=5>'   +
           '</select>' +

           '<textarea id="'+ actionTareaId() + '"  >' +
           '</textarea>' +

           '
' //end div at top.
          ).attr({id:ishmaelWindowId(),title:'ishmael'}).appendTo('body');

         //The id of the visible that the scripter has selected to
         //program.
         var currentlySelectedVisible = undefined;

         //int id of the currently selected action.
         var currentlySelectedAction = undefined;
         //map from int to std.ScriptingGui.Action objects.  It gets
         //updated whenever we received an ishmaelRedraw call.  Note
         //that the redraw call will not write over the text of
         //currentlySelectedAction.  This ensures that scripter
         //edits will not be lost while they are being written if some
         //other action triggers a call to ishmaelRedraw (for
         //instance, a new nearbyObject gets added).
         var allActions = undefined;

         $('#' + scriptedListId()).change(
             function()
             {
                 //loads the visible id
                 var val = $('#' + scriptedListId()).val();
                 currentlySelectedVisible = val;

                 //for debugging
                 sirikata.log(
                     'error','Selected new vis to script: ' + val.toString());
             });

         //set a listener for action list.  whenever select an option,
         //should communicate that to emerson gui, so that can keep
         //track of selected action.
         $('#' + actionListId()).change(
             function()
             {
                 var val =
                     $('#' + actionListId()).val();
                 changeActionText(parseInt(val));
                 sirikata.log('error', 'Selected action: '  + val.toString());
             });

         var inputWindow = new sirikata.ui.window(
             '#' + ishmaelWindowId(),
                 {
	             autoOpen: true,
	             height: 'auto',
	             width: 600,
                     height: 600,
                     position: 'right'
                 }
             );
         inputWindow.show();

         /**
          \param {int or undefined} idActSelected.  If an int, then
          looks through record of allActions, and sets action text
          area to that.  If undefined, then clears action text area.
          */
         function changeActionText(idActSelected)
         {
             currentlySelectedAction = idActSelected;
             var textToSetTo = '';

             if (typeof(idActSelected) !='undefined')
             {
                 if (! idActSelected in allActions)
                 {
                     sirikata.log('error','action ids out of ' +
                                  'sync with actions in scripting gui.');
                     return;
                 }

                 textToSetTo = allActions[idActSelected].text;
             }

             //actually update textarea with correct text
             $('#' + actionTareaId()).val(textToSetTo);
         }

         /**
          \param {object: <int:std.ScriptingGui.Action>} actionMap

          FIXEM: currentlySelectedAction is no longer passed. Instead,
          maintain it in html/js

          \param {int or undefined} currentlySelectedAction -- null if
          do not have a currently selected action.  the id of the
          action that is currently selected otherwise.  this id can be
          used to index into actionMap
          */
         ishmaelRedraw = function(
             nearbyObjs,scriptedObjs,actionMap)
         {
             redrawNearby(nearbyObjs);
             redrawScriptedObjs(scriptedObjs);
             redrawActionList(actionMap);
         };

         /**
          \param {object: <string (visibleId): string (visibleId)>}
          nearbyObjs -- all objects that are in vicinity.
          */
         function redrawNearby(nearbyObjs)
         {
             var newHtml = '';
             for (var s in nearbyObjs)
             {
                 newHtml += '
';
                 newHtml += s;
                 newHtml += '
';
             }
             $('#' + nearbyListId()).html(newHtml);

             for (var s in nearbyObjs)
             {
                 $('#' + generateNearbyDivId(s)).click(
                     function()
                     {
                         sirikata.event('addVisible',s);
                     });
             }
         }

         /**
          \param {object: <string (visibleId): string(visibleId)>}
          scriptedObjs -- all objects that we have a scripting
          relationship with.
          */
         function redrawScriptedObjs(scriptedObjs)
         {
             var newHtml = '';
             for (var s in scriptedObjs)
             {
                 if (s === currentlySelectedVisible)
                     newHtml += '<option selected ';
                 else
                     newHtml += '<option ';

                 newHtml += 'value="' +s +  '">';
                 newHtml += s;
                 newHtml += '</option>';
             }
             $('#' + scriptedListId()).html(newHtml);
         }

         function redrawActionList(actionMap)
         {
             var prevCurAct = null;
             if (typeof(currentlySelectedAction) != 'undefined')
                 prevCurAct = allActions[currentlySelectedAction];

             allActions = actionMap;
             //preserves edits that scripter was potentially making
             //when other action triggered redraw (eg. a new nearby
             //object).
             if (prevCurAct !== null)
                 allActions[prevCurAct.id] = prevCurAct;

             var newHtml = '';
             for (var s in actionMap)
             {
                 if (s === currentlySelectedAction)
                     newHtml += '<option selected ';
                 else
                     newHtml += '<option ';

                 newHtml += 'value="' + s + '">';
                 newHtml += actionMap[s].name ;
                 newHtml += '</option>';
             }

             $('#' + actionListId()).html(newHtml);
         }

         @;

         returner += '});';
         return returner;
     }
 })();

//do all further imports for file and gui control.
system.require('controller.em');
system.require('action.em');
system.require('console.em');
system.require('fileManagerElement.em');

(function()
 {

     /**
      @param {std.ScriptingGui.Controller}

      @param {object: <String(visibleId):visible object>} nearbyVisMap
      -- all the visible objects that satisfy scripter's proximity
      query.

      @param {object: <String(visibleId):
      std.FileManager.FileManagerElement> scriptedVisMap -- A record
      of all visibles that we have scripted at some point.

      @param {object: <int:std.ScriptingGui.Action> actionMap -- Which
      actions are selectable by scripter.

      @param {std.ScriptingGui.Console} console -- has several
      scripting events.
      */
     std.ScriptingGui =
         function(controller,nearbyVisMap,scriptedVisMap,actionMap,console)
     {
         if (typeof(simulator) == 'undefined')
         {
             throw new Error('Cannot initialize scripting gui without ' +
                             'simulator graphics.');
         }

         this.controller       = controller;
         this.nearbyVisMap     = nearbyVisMap;
         this.scriptedVisMap   = scriptedVisMap;
         this.actionMap        = actionMap;
         this.console          = console;

         this.guiMod = simulator._simulator.addGUITextModule(
             guiName(),
             getGuiText(),
             std.core.bind(guiInitFunc,undefined,this));
         this.hasInited = false;
     };

     system.require('scriptingGuiUtil.em');

     std.ScriptingGui.prototype.redraw = function()
     {
         if (!this.hasInited)
             return;

         //trigger redraw call
         this.guiMod.call(
             'ishmaelRedraw',toHtmlNearbyMap(this),toHtmlScriptedMap(this),
             toHtmlActionMap(this));

     };

     /**
      @param {String} visId -- Id of visible.
      */
     //called by html to add the visible with id
     std.ScriptingGui.prototype.hAddVisible = function(visId)
     {
         //already can script the visible.
         if (visId in this.scriptedVisMap)
         {
             this.console.guiEvent();
             return;
         }

         if (!(visId in this.nearbyVisMap))
         {
             //visible is no longer available.
             this.console.guiEvent();
             return;
         }

         this.controller.addVisible(this.nearbyVisMap[visId]);
     };

     std.ScriptingGui.prototype.hRemoveVisible = function(visId)
     {
         //FIXME: should finish this call
         throw new Error('FIXME: must finish hRemoveVisible call ' +
                         'in scriptingGui');
     };

     // //whenever user selects an action to display, then we change
     // //model of internal action that should be displaying.
     // std.ScriptingGui.prototype.hActionSelected = function(actId)
     // {
     //     if(actId in this.actionMap)
     //         this.selectedAction = this.actionMap[actId];
     //     else
     //         this.selectedAction = undefined;
     // };

     /**
      @param {std.ScriptingGui}
      */
     function guiInitFunc(scriptingGui)
     {
         scriptingGui.hasInited = true;

         //when a user clicks on any of the nearby visibles to script
         //them, want that object to move into scripted objects.
         scriptingGui.guiMod.bind(
             'addVisible',
             std.core.bind(scriptingGui.hAddVisible,scriptingGui));

         //when a user clicks to remove any of the scripted visibles
         //from scripted map, then destroy it.
         scriptingGui.guiMod.bind(
             'removeVisible',
             std.core.bind(scriptingGui.hRemoveVisible,scriptingGui));

         scriptingGui.redraw();
     }

     /**
      @returns {object: <string (visibleId): string (visibleId)>}
      scriptingGui -- Takes the list of nearby objects and turns it
      into an object that (for now) maps visibleIds to visibleIds.

      @see ishmaelRedraw
      */
     function toHtmlNearbyMap(scriptingGui)
     {
         var returner = { };
         for (var s in scriptingGui.nearbyVisMap)
             returner[s] = s;
         return returner;
     }

     /**
      @returns {object: <string (visibleId): string (visibleId)>}
      scriptingGui -- Takes the list of nearby objects and turns it
      into an object that (for now) maps visibleIds to visibleIds.

      @see ishmaelRedraw
      */
     function toHtmlScriptedMap(scriptingGui)
     {
         var returner = { };
         for (var s in scriptingGui.scriptedVisMap)
             returner[s] = s;
         return returner;
     }

     function toHtmlActionMap(scriptingGui)
     {
         return scriptingGui.actionMap;
     }

     function guiName()
     {
         return 'ishmaelEditor';
     }

     function getGuiText()
     {

         var returner = "sirikata.ui('" + guiName() + "',";
         returner += 'function(){ ';

         returner += @

         function ishmaelWindowId()
         {
             return 'ishmael__windowID_';
         }

         //the div that surrounds all the nearby objects.
         function nearbyListId()
         {
             return 'ishmael__nearbyListID__';
         }

         //the div that surrounds all the scripted objects.
         function scriptedListId()
         {
             return 'ishmael__scriptedListID__';
         }

         function actionListId()
         {
             return 'ishmael__actionListID__';
         }

         function actionTareaId()
         {
             return 'ishmael__actionEditor__';
         }

         /**
          \param {String} nearbyObj (id of visible that we are
          communicating with).
          gives the div for each nearby object.
          */
         function generateNearbyDivId(nearbyObj)
         {
             var visIdDivable = divizeVisibleId(nearbyObj);
             return 'ishmael__nearbyDivID___' + visIdDivable;
         }

         /**
          \param {String} scriptedObj (id of visible that we are
          communicating with).
          gives the div for each scripted object.
          */
         function generateScriptedDivId(scriptedObj)
         {
             var visIdDivable = divizeVisibleId(scriptedObj);
             return 'ishmael__scriptedDivID___' + visIdDivable;
         }

         function divizeVisibleId(visId)
         {
             return visId.replace(':','');
         }

         $('
'   +

           '
'   +
           '
'  +

           '
'   +
           '
'  +

           '<select id="' + actionListId() + '" size=5 multiple>' +
           '</select>' +

           '<textarea id="'+ actionTareaId() + '"  >' +
           '</textarea>' +

           '
' //end div at top.
          ).attr({id:ishmaelWindowId(),title:'ishmael'}).appendTo('body');

         //int id of the currently selected action.
         var currentlySelectedAction = undefined;
         //map from int to std.ScriptingGui.Action objects.  It gets
         //updated whenever we received an ishmaelRedraw call.  Note
         //that the redraw call will not write over the text of
         //currentlySelectedAction.  This ensures that scripter
         //edits will not be lost while they are being written if some
         //other action triggers a call to ishmaelRedraw (for
         //instance, a new nearbyObject gets added).
         var allActions = undefined;

         //set a listener for action list.  whenever select an option,
         //should communicate that to emerson gui, so that can keep
         //track of selected action.
         $('#' + actionListId()).change(
             function()
             {
                 var val =
                     $('#' + actionListId()).val();
                 changeActionText(parseInt(val));
                 sirikata.log('error', 'Selected action: '  + val.toString());
             });

         var inputWindow = new sirikata.ui.window(
             '#' + ishmaelWindowId(),
                 {
	             autoOpen: true,
	             height: 'auto',
	             width: 600,
                     height: 600,
                     position: 'right'
                 }
             );
         inputWindow.show();

         /**
          \param {int or undefined} idActSelected.  If an int, then
          looks through record of allActions, and sets action text
          area to that.  If undefined, then clears action text area.
          */
         function changeActionText(idActSelected)
         {
             currentlySelectedAction = idActSelected;
             var textToSetTo = '';

             if (typeof(idActSelected) !='undefined')
             {
                 if (! idActSelected in allActions)
                 {
                     sirikata.log('error','action ids out of ' +
                                  'sync with actions in scripting gui.');
                     return;
                 }

                 textToSetTo = allActions[idActSelected].text;
             }

             //actually update textarea with correct text
             $('#' + actionTareaId()).val(textToSetTo);
         }

         /**
          \param {object: <int:std.ScriptingGui.Action>} actionMap

          FIXEM: currentlySelectedAction is no longer passed. Instead,
          maintain it in html/js

          \param {int or undefined} currentlySelectedAction -- null if
          do not have a currently selected action.  the id of the
          action that is currently selected otherwise.  this id can be
          used to index into actionMap
          */
         ishmaelRedraw = function(
             nearbyObjs,scriptedObjs,actionMap)
         {
             redrawNearby(nearbyObjs);
             redrawScriptedObjs(scriptedObjs);
             redrawActionList(actionMap);
         };

         /**
          \param {object: <string (visibleId): string (visibleId)>}
          nearbyObjs -- all objects that are in vicinity.
          */
         function redrawNearby(nearbyObjs)
         {
             var newHtml = 'Nearby presences
';
             for (var s in nearbyObjs)
             {
                 newHtml += '
';
                 newHtml += s;
                 newHtml += '
';
             }
             $('#' + nearbyListId()).html(newHtml);

             for (var s in nearbyObjs)
             {
                 $('#' + generateNearbyDivId(s)).click(
                     function()
                     {
                         sirikata.event('addVisible',s);
                     });
             }
         }

         /**
          \param {object: <string (visibleId): string(visibleId)>}
          scriptedObjs -- all objects that we have a scripting
          relationship with.
          */
         function redrawScriptedObjs(scriptedObjs)
         {
             var newHtml = 'Scripted presences
';
             for (var s in scriptedObjs)
             {
                 newHtml += '
';
                 newHtml += s;
                 newHtml += '
';
             }
             $('#' + scriptedListId()).html(newHtml);

             for (var s in scriptedObjs)
             {
                 $('#' + generateScriptedDivId(s)).click(
                     function()
                     {
                         sirikata.log('error','\\\n\\\nClicked on scripted\\\n\\\n');
                     });
             }
         }

         function redrawActionList(actionMap)
         {
             var prevCurAct = null;
             if (typeof(currentlySelectedAction) != 'undefined')
                 prevCurAct = allActions[currentlySelectedAction];

             allActions = actionMap;
             //preserves edits that scripter was potentially making
             //when other action triggered redraw (eg. a new nearby
             //object).
             if (prevCurAct !== null)
                 allActions[prevCurAct.id] = prevCurAct;

             var newHtml = '';
             for (var s in actionMap)
             {
                 if (s === currentlySelectedAction)
                     newHtml += '<option selected ';
                 else
                     newHtml += '<option ';

                 newHtml += 'value="' + s + '">';
                 newHtml += actionMap[s].name ;
                 newHtml += '</option>';
             }

             $('#' + actionListId()).html(newHtml);
         }

         @;

         returner += '});';
         return returner;
     }
 })();

//do all further imports for file and gui control.
system.require('controller.em');
system.require('action.em');
system.require('console.em');
system.require('fileManagerElement.em');


Fix missing call for presenceList GUI, remove debug code from default graphics.

/*  Sirikata
 *  default.em
 *
 *  Copyright (c) 2011, Ewen Cheslack-Postava
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of Sirikata nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

system.require('graphics.em');
system.require('std/movement/pursue.em');
system.require('std/script/scripter.em');
system.require('inputbinding.em');
system.require('drag/move.em');
system.require('drag/rotate.em');
system.require('drag/scale.em');
system.require('std/graphics/chat.em');
system.require('std/graphics/physics.em');
system.require('std/graphics/propertybox.em');
system.require('std/graphics/presenceList.em');

(
function() {

    var ns = std.graphics;

    /** @namespace
     *  The DefaultGraphics class just contains some sane defaults for
     *  interaction, allowing you to get a decent, baseline client
     *  that only requires built-in functionality. You still define
     *  the presence and which underlying graphics system to use, but
     *  this class takes care of defining all other UI and interaction.
     */
    std.graphics.DefaultGraphics = function(pres, name, cb) {
        this._pres = pres;
        this._simulator = new std.graphics.Graphics(pres, name, std.core.bind(this.finishInit, this, cb));
    };
    std.graphics.DefaultGraphics.prototype.finishInit = function(cb, gfx) {
        // assert(gfx == this._simulator);
        this._cameraMode = 'first';

        this._selected = null;
        this._scripter = new std.script.Scripter(this);
        this._chat = new std.graphics.Chat(this._pres, this._simulator);
        this._physics = new std.graphics.PhysicsProperties(this._simulator);
        this._propertybox = new std.propertybox.PropertyBox(this);
        this._presenceList = new std.graphics.PresenceList(this._pres, this._simulator, this._scripter);
        this._moverot = new std.movement.MoveAndRotate(this._pres, std.core.bind(this.updateCameraOffset, this), 'rotation');

        this._draggers = {
            move: new std.graphics.MoveDragHandler(this._simulator),
            rotate: new std.graphics.RotateDragHandler(this._simulator),
            scale: new std.graphics.ScaleDragHandler(this._simulator)
        };

        this._binding = new std.graphics.InputBinding();
        this._simulator.inputHandler.onAnything = std.core.bind(this._binding.dispatch, this._binding);

        this._binding.addAction('quit', std.core.bind(this._simulator.quit, this._simulator));
        this._binding.addAction('screenshot', std.core.bind(this._simulator.screenshot, this._simulator));
        this._binding.addAction('toggleSuspend', std.core.bind(this._simulator.toggleSuspend, this._simulator));
        this._binding.addAction('scriptSelectedObject', std.core.bind(this.scriptSelectedObject, this));
        this._binding.addAction('scriptSelf', std.core.bind(this.scriptSelf, this));
        this._binding.addAction('togglePropertyBox', std.core.bind(this.togglePropertyBox, this));

        this._binding.addAction('toggleChat', std.core.bind(this.toggleChat, this));

        this._binding.addAction('togglePhysicsProperties', std.core.bind(this._physics.toggle, this._physics));
        this._binding.addAction('togglePresenceList', std.core.bind(this._presenceList.toggle, this._presenceList));

        this._binding.addAction('toggleCameraMode', std.core.bind(this.toggleCameraMode, this));

        this._binding.addToggleAction('moveForward', std.core.bind(this.moveSelf, this, new util.Vec3(0, 0, -1)), 1, -1);
        this._binding.addToggleAction('moveBackward', std.core.bind(this.moveSelf, this, new util.Vec3(0, 0, 1)), 1, -1);
        this._binding.addToggleAction('moveLeft', std.core.bind(this.moveSelf, this, new util.Vec3(-1, 0, 0)), 1, -1);
        this._binding.addToggleAction('moveRight', std.core.bind(this.moveSelf, this, new util.Vec3(1, 0, 0)), 1, -1);
        this._binding.addToggleAction('moveUp', std.core.bind(this.moveSelf, this, new util.Vec3(0, 1, 0)), 1, -1);
        this._binding.addToggleAction('moveDown', std.core.bind(this.moveSelf, this, new util.Vec3(0, -1, 0)), 1, -1);

        this._binding.addToggleAction('rotateUp', std.core.bind(this.rotateSelf, this, new util.Vec3(1, 0, 0)), 1, -1);
        this._binding.addToggleAction('rotateDown', std.core.bind(this.rotateSelf, this, new util.Vec3(-1, 0, 0)), 1, -1);
        this._binding.addToggleAction('rotateLeft', std.core.bind(this.rotateSelf, this, new util.Vec3(0, 1, 0)), 1, -1);
        this._binding.addToggleAction('rotateRight', std.core.bind(this.rotateSelf, this, new util.Vec3(0, -1, 0)), 1, -1);

        this._binding.addFloat2Action('pickObject', std.core.bind(this.pickObject, this));

        this._binding.addAction('updatePhysicsProperties', std.core.bind(this.updatePhysicsProperties, this));

        this._binding.addAction('startMoveDrag', std.core.bind(this.startDrag, this, this._draggers.move));
        this._binding.addAction('startRotateDrag', std.core.bind(this.startDrag, this, this._draggers.rotate));
        this._binding.addAction('startScaleDrag', std.core.bind(this.startDrag, this, this._draggers.scale));
        this._binding.addAction('forwardMousePressToDragger', std.core.bind(this.forwardMousePressToDragger, this));
        this._binding.addAction('forwardMouseDragToDragger', std.core.bind(this.forwardMouseDragToDragger, this));
        this._binding.addAction('updatePropertyBox', std.core.bind(this.updatePropertyBox, this));
        this._binding.addAction('forwardMouseReleaseToDragger', std.core.bind(this.forwardMouseReleaseToDragger, this));
        this._binding.addAction('stopDrag', std.core.bind(this.stopDrag, this));

        /** Bindings are an *ordered* list of keys and actions. Keys
         *  are a combination of the type of event, the primary key
         *  for the event (key or mouse button), and modifiers.
         *  Modifiers are tricky to handle. You can specify a string
         *  indicating which to filter on. If you omit the string, it
         *  is equivalent to 'none'. The special values '*' and 'any'
         *  are equivalent and will match any modifier, i.e. the event
         *  will always be triggered. There isn't support
         *  for matching combinations of modifiers.
         */
        var bindings = [
            { key: ['button-pressed', 'escape'], action: 'quit' },
            { key: ['button-pressed', 'i'], action: 'screenshot' },
            { key: ['button-pressed', 'm'], action: 'toggleSuspend' },
            { key: ['button-pressed', 's', 'alt' ], action: 'scriptSelectedObject' },
            { key: ['button-pressed', 's', 'ctrl' ], action: 'scriptSelf' },

            { key: ['button-pressed', 'c', 'ctrl' ], action: 'toggleChat' },
            { key: ['button-pressed', 'p', 'ctrl' ], action: 'togglePhysicsProperties' },
            { key: ['button-pressed', 'p', 'alt' ], action: 'togglePropertyBox' },
            { key: ['button-pressed', 'l', 'ctrl' ], action: 'togglePresenceList' },

            { key: ['mouse-click', 3], action: 'pickObject' },
            { key: ['mouse-click', 3], action: 'scriptSelectedObject' },

            { key: ['button-pressed', 'c' ], action: 'toggleCameraMode' },

            { key: ['button', 'w' ], action: 'moveForward' },
            { key: ['button', 'up' ], action: 'moveForward' },
            { key: ['button', 's' ], action: 'moveBackward' },
            { key: ['button', 'down' ], action: 'moveBackward' },
            { key: ['button', 'a' ], action: 'moveLeft' },
            { key: ['button', 'd' ], action: 'moveRight' },
            { key: ['button', 'q' ], action: 'moveUp' },
            { key: ['button', 'z' ], action: 'moveDown' },

            { key: ['button', 'up', 'shift' ], action: 'rotateUp' },
            { key: ['button', 'down', 'shift' ], action: 'rotateDown' },
            { key: ['button', 'left' ], action: 'rotateLeft' },
            { key: ['button', 'right' ], action: 'rotateRight' },

            { key: ['mouse-press', 1 ], action: 'pickObject' },

            { key: ['mouse-press', 1 ], action: 'updatePhysicsProperties' },

            // Note that the ordering of registration here is critical.
            { key: ['mouse-press', 1, 'none' ], action: 'startMoveDrag' },
            { key: ['mouse-press', 1, 'ctrl' ], action: 'startRotateDrag' },
            { key: ['mouse-press', 1, 'alt' ], action: 'startScaleDrag' },
            { key: ['mouse-press', 1, '*'], action: 'forwardMousePressToDragger' },
            { key: ['mouse-press', 1, '*'], action: 'updatePropertyBox' },
            { key: ['mouse-drag', 1, '*'], action: 'forwardMouseDragToDragger' },
            { key: ['mouse-release', 1, '*'], action: 'forwardMouseReleaseToDragger' },
            { key: ['mouse-release', 1, '*'], action: 'stopDrag' }
        ];

        this._binding.addBindings(bindings);

        if (cb && typeof(cb) === "function")
            cb(this);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.simulator = function() {
        return this._simulator;
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.invoke = function() {
        // Just forward manual invoke commands directly
        return this._simulator.invoke.apply(this._simulator, arguments);
    };

    /** Request that the given URL be added as a module in the UI. */
    std.graphics.DefaultGraphics.prototype.addGUIModule = function(name, url, cb) {
        return this._simulator.addGUIModule(name, url, cb);
    };

    //by default how to scale translational velocity from keypresses.  (movement
    //is agonizingly slow if just set this to 1.  I really recommend 5.)
    /** @public */
    std.graphics.DefaultGraphics.prototype.defaultVelocityScaling = 5;
    //by default how to scale rotational velocity from keypresses
    /** @public */
    std.graphics.DefaultGraphics.prototype.defaultRotationalVelocityScaling = .5;

    /** @function */
    std.graphics.DefaultGraphics.prototype.toggleChat = function() {
        this._chat.toggle();
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.scriptSelf = function() {
        this._scripter.script(system.self);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.togglePropertyBox = function() {
        this._propertybox.TogglePropertyBox();
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.scriptSelectedObject = function() {
        this._presenceList.addObject(this._selected.toString(), 'Scripted');
        this._scripter.script(this._selected);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.toggleCameraMode = function(evt) {
        this._cameraMode = this._cameraMode == 'first' ? 'third' : 'first';
        this._simulator.setCameraMode(this._cameraMode);
        this.updateCameraOffset();
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.updateCameraOffset = function(evt) {
        if (this._cameraMode == 'third') {
            var orient = this._pres.getOrientation();
            this._simulator.setCameraOffset(orient.mul(<0, 1.5, 4>));
        }
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.moveSelf = function(dir, val) {
        this._moverot.move(dir, this.defaultVelocityScaling * val);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.rotateSelf = function(about, val) {
        this._moverot.rotate(about, this.defaultRotationalVelocityScaling * val);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.pickObject = function(x, y) {
        if (this._selected) {
            this._simulator.bbox(this._selected, false);
            this._selected = null;
        }

        var clicked = this._simulator.pick(x, y);
        if (clicked) {
            this._selected = clicked;
            this._simulator.bbox(this._selected, true);
        }
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.updatePhysicsProperties = function() {
        // Update even if not selected so display can be disabled
        this._physics.update(this._selected);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.startDrag = function(dragger, evt) {
        if (this._selected)
            this._dragger = dragger;
        if (this._dragger)
            this._dragger.selected(this._selected, this._simulator.pickedPosition(), evt);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.forwardMousePressToDragger = function(evt) {
        if (this._dragger) this._dragger.onMousePress(evt);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.forwardMouseDragToDragger = function(evt) {
        if (this._dragger) this._dragger.onMouseDrag(evt);
        this._propertybox.HandleUpdateProperties(this._selected);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.updatePropertyBox = function(evt) {
        this._propertybox.HandleUpdateProperties(this._selected);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.forwardMouseReleaseToDragger = function(evt) {
        if (this._dragger) this._dragger.onMouseRelease(evt);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.stopDrag = function() {
        delete this._dragger;
    };

})();

/*  Sirikata
 *  default.em
 *
 *  Copyright (c) 2011, Ewen Cheslack-Postava
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of Sirikata nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

system.require('graphics.em');
system.require('std/movement/pursue.em');
system.require('std/script/scripter.em');
system.require('inputbinding.em');
system.require('drag/move.em');
system.require('drag/rotate.em');
system.require('drag/scale.em');
system.require('std/graphics/chat.em');
system.require('std/graphics/physics.em');
system.require('std/graphics/propertybox.em');
system.require('std/graphics/presenceList.em');

(
function() {

    var ns = std.graphics;

    /** @namespace
     *  The DefaultGraphics class just contains some sane defaults for
     *  interaction, allowing you to get a decent, baseline client
     *  that only requires built-in functionality. You still define
     *  the presence and which underlying graphics system to use, but
     *  this class takes care of defining all other UI and interaction.
     */
    std.graphics.DefaultGraphics = function(pres, name, cb) {
        this._pres = pres;
        this._simulator = new std.graphics.Graphics(pres, name, std.core.bind(this.finishInit, this, cb));
    };
    std.graphics.DefaultGraphics.prototype.randomDestination=function() {
        return <Math.random()*40,Math.random()*30, Math.random()*30>;
    };
    std.graphics.DefaultGraphics.prototype.finishInit = function(cb, gfx) {
        // assert(gfx == this._simulator);
        this._cameraMode = 'first';

        this._selected = null;
        this._scripter = new std.script.Scripter(this);
        this._chat = new std.graphics.Chat(this._pres, this._simulator);
        this._physics = new std.graphics.PhysicsProperties(this._simulator);
        this._propertybox = new std.propertybox.PropertyBox(this);
        this._presenceList = new std.graphics.PresenceList(this._pres, this._simulator, this._scripter);
        this._moverot = new std.movement.MoveAndRotate(this._pres, std.core.bind(this.updateCameraOffset, this), 'rotation');

        this._draggers = {
            move: new std.graphics.MoveDragHandler(this._simulator),
            rotate: new std.graphics.RotateDragHandler(this._simulator),
            scale: new std.graphics.ScaleDragHandler(this._simulator)
        };

        this._binding = new std.graphics.InputBinding();
        this._simulator.inputHandler.onAnything = std.core.bind(this._binding.dispatch, this._binding);

        this._binding.addAction('quit', std.core.bind(this._simulator.quit, this._simulator));
        this._binding.addAction('screenshot', std.core.bind(this._simulator.screenshot, this._simulator));
        this._binding.addAction('toggleSuspend', std.core.bind(this._simulator.toggleSuspend, this._simulator));
        this._binding.addAction('scriptSelectedObject', std.core.bind(this.scriptSelectedObject, this));
        this._binding.addAction('scriptSelf', std.core.bind(this.scriptSelf, this));
        this._binding.addAction('togglePropertyBox', std.core.bind(this.togglePropertyBox, this));

        this._binding.addAction('toggleChat', std.core.bind(this.toggleChat, this));

        this._binding.addAction('togglePhysicsProperties', std.core.bind(this._physics.toggle, this._physics));
        this._binding.addAction('togglePresenceList', std.core.bind(this._presenceList.toggle, this._presenceList));

        this._binding.addAction('toggleCameraMode', std.core.bind(this.toggleCameraMode, this));

        this._binding.addToggleAction('moveForward', std.core.bind(this.moveSelf, this, new util.Vec3(0, 0, -1)), 1, -1);
        this._binding.addToggleAction('moveBackward', std.core.bind(this.moveSelf, this, new util.Vec3(0, 0, 1)), 1, -1);
        this._binding.addToggleAction('moveLeft', std.core.bind(this.moveSelf, this, new util.Vec3(-1, 0, 0)), 1, -1);
        this._binding.addToggleAction('moveRight', std.core.bind(this.moveSelf, this, new util.Vec3(1, 0, 0)), 1, -1);
        this._binding.addToggleAction('moveUp', std.core.bind(this.moveSelf, this, new util.Vec3(0, 1, 0)), 1, -1);
        this._binding.addToggleAction('moveDown', std.core.bind(this.moveSelf, this, new util.Vec3(0, -1, 0)), 1, -1);

        this._binding.addToggleAction('rotateUp', std.core.bind(this.rotateSelf, this, new util.Vec3(1, 0, 0)), 1, -1);
        this._binding.addToggleAction('rotateDown', std.core.bind(this.rotateSelf, this, new util.Vec3(-1, 0, 0)), 1, -1);
        this._binding.addToggleAction('rotateLeft', std.core.bind(this.rotateSelf, this, new util.Vec3(0, 1, 0)), 1, -1);
        this._binding.addToggleAction('rotateRight', std.core.bind(this.rotateSelf, this, new util.Vec3(0, -1, 0)), 1, -1);

        this._binding.addFloat2Action('pickObject', std.core.bind(this.pickObject, this));

        this._binding.addAction('updatePhysicsProperties', std.core.bind(this.updatePhysicsProperties, this));

        this._binding.addAction('startMoveDrag', std.core.bind(this.startDrag, this, this._draggers.move));
        this._binding.addAction('startRotateDrag', std.core.bind(this.startDrag, this, this._draggers.rotate));
        this._binding.addAction('startScaleDrag', std.core.bind(this.startDrag, this, this._draggers.scale));
        this._binding.addAction('forwardMousePressToDragger', std.core.bind(this.forwardMousePressToDragger, this));
        this._binding.addAction('forwardMouseDragToDragger', std.core.bind(this.forwardMouseDragToDragger, this));
        this._binding.addAction('updatePropertyBox', std.core.bind(this.updatePropertyBox, this));
        this._binding.addAction('forwardMouseReleaseToDragger', std.core.bind(this.forwardMouseReleaseToDragger, this));
        this._binding.addAction('stopDrag', std.core.bind(this.stopDrag, this));

        /** Bindings are an *ordered* list of keys and actions. Keys
         *  are a combination of the type of event, the primary key
         *  for the event (key or mouse button), and modifiers.
         *  Modifiers are tricky to handle. You can specify a string
         *  indicating which to filter on. If you omit the string, it
         *  is equivalent to 'none'. The special values '*' and 'any'
         *  are equivalent and will match any modifier, i.e. the event
         *  will always be triggered. There isn't support
         *  for matching combinations of modifiers.
         */
        var bindings = [
            { key: ['button-pressed', 'escape'], action: 'quit' },
            { key: ['button-pressed', 'i'], action: 'screenshot' },
            { key: ['button-pressed', 'm'], action: 'toggleSuspend' },
            { key: ['button-pressed', 's', 'alt' ], action: 'scriptSelectedObject' },
            { key: ['button-pressed', 's', 'ctrl' ], action: 'scriptSelf' },

            { key: ['button-pressed', 'c', 'ctrl' ], action: 'toggleChat' },
            { key: ['button-pressed', 'p', 'ctrl' ], action: 'togglePhysicsProperties' },
            { key: ['button-pressed', 'p', 'alt' ], action: 'togglePropertyBox' },
            { key: ['button-pressed', 'l', 'ctrl' ], action: 'togglePresenceList' },

            { key: ['mouse-click', 3], action: 'pickObject' },
            { key: ['mouse-click', 3], action: 'scriptSelectedObject' },

            { key: ['button-pressed', 'c' ], action: 'toggleCameraMode' },

            { key: ['button', 'w' ], action: 'moveForward' },
            { key: ['button', 'up' ], action: 'moveForward' },
            { key: ['button', 's' ], action: 'moveBackward' },
            { key: ['button', 'down' ], action: 'moveBackward' },
            { key: ['button', 'a' ], action: 'moveLeft' },
            { key: ['button', 'd' ], action: 'moveRight' },
            { key: ['button', 'q' ], action: 'moveUp' },
            { key: ['button', 'z' ], action: 'moveDown' },

            { key: ['button', 'up', 'shift' ], action: 'rotateUp' },
            { key: ['button', 'down', 'shift' ], action: 'rotateDown' },
            { key: ['button', 'left' ], action: 'rotateLeft' },
            { key: ['button', 'right' ], action: 'rotateRight' },

            { key: ['mouse-press', 1 ], action: 'pickObject' },

            { key: ['mouse-press', 1 ], action: 'updatePhysicsProperties' },

            // Note that the ordering of registration here is critical.
            { key: ['mouse-press', 1, 'none' ], action: 'startMoveDrag' },
            { key: ['mouse-press', 1, 'ctrl' ], action: 'startRotateDrag' },
            { key: ['mouse-press', 1, 'alt' ], action: 'startScaleDrag' },
            { key: ['mouse-press', 1, '*'], action: 'forwardMousePressToDragger' },
            { key: ['mouse-press', 1, '*'], action: 'updatePropertyBox' },
            { key: ['mouse-drag', 1, '*'], action: 'forwardMouseDragToDragger' },
            { key: ['mouse-release', 1, '*'], action: 'forwardMouseReleaseToDragger' },
            { key: ['mouse-release', 1, '*'], action: 'stopDrag' }
        ];

        this._binding.addBindings(bindings);

        if (cb && typeof(cb) === "function")
            cb(this);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.simulator = function() {
        return this._simulator;
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.invoke = function() {
        // Just forward manual invoke commands directly
        return this._simulator.invoke.apply(this._simulator, arguments);
    };

    /** Request that the given URL be added as a module in the UI. */
    std.graphics.DefaultGraphics.prototype.addGUIModule = function(name, url, cb) {
        return this._simulator.addGUIModule(name, url, cb);
    };

    //by default how to scale translational velocity from keypresses.  (movement
    //is agonizingly slow if just set this to 1.  I really recommend 5.)
    /** @public */
    std.graphics.DefaultGraphics.prototype.defaultVelocityScaling = 5;
    //by default how to scale rotational velocity from keypresses
    /** @public */
    std.graphics.DefaultGraphics.prototype.defaultRotationalVelocityScaling = .5;

    /** @function */
    std.graphics.DefaultGraphics.prototype.toggleChat = function() {
        this._chat.toggle();
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.scriptSelf = function() {
        this._scripter.script(system.self);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.togglePropertyBox = function() {
        this._propertybox.TogglePropertyBox();
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.scriptSelectedObject = function() {
        this._scripter.script(this._selected);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.toggleCameraMode = function(evt) {
        this._cameraMode = this._cameraMode == 'first' ? 'third' : 'first';
        this._simulator.setCameraMode(this._cameraMode);
        this.updateCameraOffset();
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.updateCameraOffset = function(evt) {
        if (this._cameraMode == 'third') {
            var orient = this._pres.getOrientation();
            this._simulator.setCameraOffset(orient.mul(<0, 1.5, 4>));
        }
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.moveSelf = function(dir, val) {
        this._moverot.move(dir, this.defaultVelocityScaling * val);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.rotateSelf = function(about, val) {
        this._moverot.rotate(about, this.defaultRotationalVelocityScaling * val);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.pickObject = function(x, y) {
        if (this._selected) {
            this._simulator.bbox(this._selected, false);
            this._selected = null;
        }

        var clicked = this._simulator.pick(x, y);
        if (clicked) {
            this._selected = clicked;
            this._simulator.bbox(this._selected, true);
        }
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.updatePhysicsProperties = function() {
        // Update even if not selected so display can be disabled
        this._physics.update(this._selected);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.startDrag = function(dragger, evt) {
        if (this._selected)
            this._dragger = dragger;
        if (this._dragger)
            this._dragger.selected(this._selected, this._simulator.pickedPosition(), evt);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.forwardMousePressToDragger = function(evt) {
        if (this._dragger) this._dragger.onMousePress(evt);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.forwardMouseDragToDragger = function(evt) {
        if (this._dragger) this._dragger.onMouseDrag(evt);
        this._propertybox.HandleUpdateProperties(this._selected);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.updatePropertyBox = function(evt) {
        this._propertybox.HandleUpdateProperties(this._selected);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.forwardMouseReleaseToDragger = function(evt) {
        if (this._dragger) this._dragger.onMouseRelease(evt);
    };

    /** @function */
    std.graphics.DefaultGraphics.prototype.stopDrag = function() {
        delete this._dragger;
    };

})();