function out = Mouse3D_modifiedRAY(val, hObject, eventdata, parentfig, Empty_Button, Buttons, AxesAFS, AxesSOL, SegPlot, rotoff, IPonoff, FPonoff, lvText, lvSlider, usmn, usmf, lcs);
% 
% This file is a slightly modification of the file Mouse3D.m  by Gus Brown
% from the Mathworks File Exchange.
% 
% Activates 3D mouse navigation on all 3D figures.
% Allows the use of a 3Dconnexion 'magellan' 3Dmouse in 
% Matlab figure windows. Uses a com interface to the 
% 3Dmouse service (TDxInput.Device), and uses a timer 
% object (Mouse3dtimer) to poll the 3Dmouse.
%
% Use, Mouse3D to start and stop the service.
%
% Alternate syntax
% out = Mouse3D(cmd)
% where cmd can be ;
%   'start' : start 3D mouse navigation, returns com handle
%   'stop'  : stop 3D mouse navigation, returns 0
%   'get'   : returns 3dmouse position and rotation structure
%
% Example:
%    logo; 
%    Mouse3D;
% 
% Gus - 2008
% Copyright (c) 2009, Gus Brown
% 
% For the licenses of the original file see 
% http://www.mathworks.com/matlabcentral/fileexchange/view_license?file_info_id=18266

persistent srv busycntr 

varargin = {val};

period = 0.01;  % Timer frequency, should match frame rate on your graphics card
slowdown = 2;  % slowdown factor for inactive mouse
timertag = 'Mouse3D_modifiedRAYtimer';  % Unique tag for timer object

% check inputs
if nargin==0, 
  cmd = 0; 
else
  % convert string inputs to numeric eqiv
  if ischar(varargin{1}),
    switch lower(varargin{1}),
    case('view');
      cmd = 1;
    case('busy')
      cmd = 2;
    case('rotate')
      cmd = 3;
    case('start'),
      cmd = 4;
    case('stop'),   
      cmd = 5;
    case('gettimer');
      cmd = 6;
    case('get'),   
      cmd = 7;
    otherwise
      cmd = 0;
    end;
  else
    cmd = varargin{1};
  end;
end;

%% #Activities#
tim = timerfind('tag',timertag);
switch lower(cmd),
  case(1), % #view#
    % starts timer and returns a handle to the timer
    disp('start')
    start(tim);
    out = 1;
  case(2), % #busy#
    % counts each time the timer calls and the function is still busy
    busycntr = busycntr + 1;
    out = busycntr;
    if  busycntr<10, 
      % restarts the timer as it stops by default
      start(tim); 
    else
      % causes the timer to stop if too busy 
      warning('Mouse3D_modifiedRAY:stop','Mouse3D_modifiedRAY stopped');
      Mouse3D_modifiedRAY_stop(srv,tim);
    end;
  case(3), % #rotate#
    % polls the mouse and calls the relevant camera operations
    busycntr = 0;
    dt = 10*(1+busycntr)*period;
    out = Mouse3D_modifiedRAY_rotate(srv,dt,period,slowdown,tim,hObject, eventdata, parentfig, Empty_Button, Buttons, AxesAFS, AxesSOL, SegPlot, rotoff, IPonoff, FPonoff, lvText, lvSlider, usmn, usmf, lcs);
  case(4), % #start#
    % connect to com object and setup timer object
    disp('start');
    srv = Mouse3D_modifiedRAY_start(period,timertag,hObject, eventdata, parentfig, Empty_Button, Buttons, AxesAFS, AxesSOL, SegPlot, rotoff, IPonoff, FPonoff, lvText, lvSlider, usmn, usmf, lcs);
    busycntr = 0;
    out = srv;
  case(5), % #stop#
    % stop and cleanup
    srv = Mouse3D_modifiedRAY_stop(srv,tim);
    out = 0;
    disp('Mouse3D_modifiedRAY stopped!');
  case(6), % #gettimer#
    % return handle to timer
    out = timerfind('tag',timertag);
  case(7), % #get#
    % get position from the mouse
    out = Mouse3D_modifiedRAY_get(srv);

  otherwise
    if isempty(srv),
      [srv,tim] = Mouse3D_modifiedRAY_start(period,timertag,hObject, eventdata, parentfig, Empty_Button, Buttons, AxesAFS, AxesSOL, SegPlot, rotoff, IPonoff, FPonoff, lvText, lvSlider, usmn, usmf, lcs);
      out = srv;
      disp('Mouse3D_modifiedRAY started!');
      start(tim);
    elseif strcmpi(get(timerfind('tag',timertag),'Running'),'off'), 
%       out = Mouse3D_modifiedRAY_view;
    else
      srv = Mouse3D_modifiedRAY_stop(srv,tim);
      out = 0;
      disp('Mouse3D_modifiedRAY stopped!');
    end;
end;

%% ---------------------------------------------------------
% polls the mouse and callls the relavent camera operations
function out = Mouse3D_modifiedRAY_rotate(srv,dt,period,slowdown,tim,hObject, eventdata, parentfig, Empty_Button, Buttons, AxesAFS, AxesSOL, SegPlot, rotoff, IPonoff, FPonoff, lvText, lvSlider, usmn, usmf, lcs)
  m3d = Mouse3D_modifiedRAY_get(srv);
  POS = [0 0 0];
  % checks for mouse activity and slows down the time if there is none
  % needed to prevent lockup
  if (m3d.len==0 && m3d.ang==0),
    if (tim.Period == period),
      stop(tim);  % must stop timer before changing period
      tim.Period = period*slowdown;
      start(tim);
    end;
  else
    % speedup timer if it was resting
    if (tim.Period ~= period),
      stop(tim);
      tim.Period = period;
      start(tim);
    end;
    %pos = sign(m3d.pos).*(m3d.pos/1600).^2;
    %rot = sign(m3d.rot).*(m3d.rot*m3d.ang/1600).^2;
    pos = (m3d.pos/1600);
    pos = pos([1 3 2]);
    rot = (m3d.rot*m3d.ang/1600);
    rot = rot([1 3 2]);
    camorbit(30*dt*rot(3),30*dt*rot(1),'camera'); 
    VA = camva;
%     campan(-VA*dt*pos(1),VA*dt*pos(3),'camera');  
    POS = pos*dt;
%     dt*pos

    camroll(30*dt*rot(2)); 
    VA = max(1e-6,VA+5*dt*pos(2)); 
%     camva(VA); 
    drawnow; 
    
    data = get(Empty_Button,'UserData');
    axes(AxesAFS);
  end;
  
  if sum(POS.*POS) > 0
      buttonPlotSegRAY(hObject, eventdata, parentfig, Empty_Button, Buttons, AxesAFS, AxesSOL, SegPlot, rotoff, IPonoff, FPonoff, lvText, lvSlider, usmn, usmf, -1, 1, lcs, POS);
  end
  out = 0;


%% ---------------------------------------------------------
% get position from the mouse
function out = Mouse3D_modifiedRAY_get(srv)
  out.period = srv.get('Sensor').get('Period');

  opos = srv.get('Sensor').get('Translation');
  out.pos = [get(opos,'X') get(opos,'Y') get(opos,'Z')];
  out.len = get(opos,'Length');

  orot = srv.get('Sensor').get('Rotation');
  out.rot = [get(orot,'X') get(orot,'Y') get(orot,'Z')];
  out.ang = get(orot,'Angle');


%% ---------------------------------------------------------
% connect to com object and setup timer object
function [srv tim] = Mouse3D_modifiedRAY_start(period,timertag,hObject, eventdata, parentfig, Empty_Button, Buttons, AxesAFS, AxesSOL, SegPlot, rotoff, IPonoff, FPonoff, lvText, lvSlider, usmn, usmf, lcs)
  srv = actxserver('TDxInput.Device');
  tim = timerfind('tag',timertag);
  if isempty(tim),
    tim = timer;
    
    assignin('base','phObject',hObject);
    assignin('base','peventdata',eventdata);
    assignin('base','pparentfig',parentfig);
    assignin('base','pEmpty_Button',Empty_Button);
    assignin('base','pButtons',Buttons);
    assignin('base','pAxesAFS',AxesAFS);
    assignin('base','pAxesSOL',AxesSOL);
    assignin('base','pSegPlot',SegPlot);
    assignin('base','protoff',rotoff);
    assignin('base','pIPonoff',IPonoff);
    assignin('base','pFPonoff',FPonoff);
    assignin('base','plvText',lvText);
    assignin('base','plvSlider',lvSlider);
    assignin('base','plcs',lcs);
    assignin('base','pusmn',usmn);
    assignin('base','pusmf',usmf);
    
    % set(tim, 'TimerFcn','Mouse3D_modifiedRAY(3);', 'ErrorFcn', 'Mouse3D_modifiedRAY(2);', 'BusyMode','error', 'ExecutionMode','FixedRate', 'StartDelay',period, 'period',period, 'tag',timertag); 
    set(tim, 'TimerFcn','Mouse3D_modifiedRAY(3,phObject, peventdata, pparentfig, pEmpty_Button, pButtons, pAxesAFS, pAxesSOL, pSegPlot, protoff, pIPonoff, pFPonoff, plvText, plvSlider, pusmn, pusmf, plcs);', 'BusyMode','drop', 'ExecutionMode','FixedRate', 'StartDelay',period, 'period',period, 'tag',timertag); 
  else
    stop(tim);
  end;
  % srv.invoke('Connect');  % This line does not seem to be needed


%% ---------------------------------------------------------
% Stop timer and release com object
function srv = Mouse3D_modifiedRAY_stop(srv,tim)
  % srv.invoke('Disconnect'); % This line does not seem to be needed
  if ~isempty(tim),
    stop(tim);
    delete(tim);
  end;
  release(srv);
  srv = [];