home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-09-29 | 33.4 KB | 1,203 lines | [TEXT/KAHL] |
- #include <assert.h>
- #include <ctype.h>
- #include <math.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include <fstream.h>
- #include <iostream.h>
- #include <strstream.h>
-
- #include <Fonts.h>
- #include <Menus.h>
- #include <Packages.h>
- #include <SegLoad.h>
- #include <ToolUtils.h>
- #include <TextEdit.h>
- #include <GestaltEqu.h>
- #include <Windows.h>
- #include <QuickDraw.h>
- #include <QDOffscreen.h>
- #include <Palettes.h>
- #include <Resources.h>
- #include <Timer.h>
- #include <Retrace.h>
- #include <Devices.h>
-
- #include "general.h"
- #include "application.h"
- #include "port.h"
- #include "window.h"
- #include "depthChange.h"
- #include "fullscreen.h"
- #include "C_randomizer.h"
- #include "stopwatch.h"
- #include "macutilities.h"
- #include "vretrace.h"
-
- #include "streamutils.h"
-
- #include "outputfile.h"
- #include "flowsettings.h"
- #include "phaser.h"
- #include "dotcollection.h"
- #include "screenarea.h"
- #include "screendots.h"
- #include "flowdots.h"
-
- #ifndef __CONDITIONALMACROS__
- #define SelectDialogItemText SelIText
- #define GetDialogItem GetDItem
- #define GetDialogItemText GetIText
- #define SetDialogItemText SetIText
- #define SetControlValue SetCtlValue
- #define GetControlValue GetCtlValue
- #define TETextBox TextBox
- #define ShowDialogItem ShowDItem
- #define HideDialogItem HideDItem
- #endif
- //
- // use_movingnoise is a hack to allow one to study moving noise
- //
- #define use_movingnoise
-
- #ifdef use_movingnoise
- #define noisedots movingnoisedots
- #include "movingnoisedots.h"
- #else
- #include "noisedots.h"
- #endif
- //
- #define acceleration_factor 5.0
-
- #include "Differential main.h"
-
- int step_once( flowdots &alive, flowdots &kicking,
- noisedots &alive_noise, noisedots &kicking_noise,
- double d_log, double d_rot, double d_trans, Boolean switched = false);
-
- // void main();
- void one_loop( opts *the_opts, flowsettings &alive_settings, flowsettings &kicking_settings);
- //
- // the default options get passed because some of the options are not settable
- // in the dialog. Thus, they do not get passed via the path
- // default_options => dialog => options,
- // but must be passed directly from the default options to the options.
- //
- void Dialog2options( const DialogPtr theDialog,
- const opts *default_options, opts *the_options);
-
- void options2Dialog( const opts *the_options, DialogPtr theDialog);
- void FlipItem( DialogPtr myDialog, short theItem);
-
- short GetItemValue( const DialogPtr myDialog, short theItem);
- void SetItemValue( DialogPtr myDialog, short theItem, short value);
-
- long GetItemLong( const DialogPtr myDialog, short theItem);
- void SetItemLong( DialogPtr myDialog, short theItem, long theValue);
-
- void UpdateSensitivityItems( DialogPtr theDialog, long allow_modifications);
-
- void showParams( const flowdots &alive, const flowdots &kicking, short xPos);
-
- void showLegends( short xPos);
- //
- // DrawNumber does for numbers what DrawString does for strings. As a bonus
- // it can draw numbers with an implicit decimal point. implicitDecimal
- // may be anything between zero and eight, inclusive.
- // DrawNumber with a double parameter draws with three digits after the decimal point.
- //
- void DrawNumber( long theNumber, int implicitDecimal = 0);
- void DrawNumber( double theNumber);
-
- int main( int argc, char *argv[])
- {
- application me;
- //
- // The background screen is included to force a restore of some
- // useful palette when the main dialog is made visible again.
- // The stimulus generation really messes up the display, and uses
- // an 8-bit fullscreen. By creating a four-bit one here we force the
- // desctructor of the stimulus fullscreen to switch back to four-bit
- // mode, thus giving us a color table we can live with.
- // The alternative of simply creating and immediately disposing of a
- // fullscreen of 1, 2, or 4 bits does work, too, but is even more
- // awful to watch (it flashes black-white-black-almost white).
- // This won't work if the main device doesn't support 4-bit mode, and
- // we do not check for that, but there already are plenty of other
- // things we do not check for.
- // (e.g. 68030+, FPU, color QuickDraw,…)
- //
- fullscreen background( 4, (unsigned char)false);
-
- Handle theResource = Get1Resource( 'pref', 128);
- assert( theResource != 0);
- assert( (*theResource) != 0);
- opts *default_opts = (opts *)*theResource;
-
- opts *the_opts = new opts;
-
- DialogRecord myDialogRecord;
- DialogPtr myDialog =
- GetNewDialog( 128, &myDialogRecord, (WindowPtr)-1);
- if( myDialog == 0)
- {
- DebugStr( "\pCould not get the dialog!");
- exit( EXIT_FAILURE);
- }
- short itemHit = 0;
-
- options2Dialog( default_opts, myDialog);
- SelectDialogItemText( myDialog, iNumDots1, 0, 32767);
-
- flowsettings alive_settings;
- flowsettings kicking_settings;
-
- do
- {
- #ifdef __MWERKS__
- {
- depthChange een( 1);
- depthChange twee( 2);
- depthChange vier( 4);
- depthChange acht( 8);
- }
- #endif
- ModalDialog( 0L, &itemHit);
- switch( itemHit)
- {
- case iRun:
- Dialog2options( myDialog, default_opts, the_opts);
- one_loop( the_opts, alive_settings, kicking_settings);
- FlushEvents( everyEvent, 0L);
- break;
-
- case iQuit:
- break;
-
- case iDefaults:
- options2Dialog( default_opts, myDialog);
- SelectDialogItemText( myDialog, iNumDots1, 0, 32767);
- break;
-
- case iNumDots1:
- case iNumDots2:
- case iNumNoiseDots1:
- case iNumNoiseDots2:
-
- case iLife1:
- case iLife2:
- case iNoiseLife1:
- case iNoiseLife2:
- case iDiffusion1:
- case iDiffusion2:
-
- case iSwitchInterval:
-
- case i_dLog:
- case i_dTrans:
- case i_dRotDir:
- DebugStr( "\pThat item should not be enabled");
- break;
-
- case iTransparant:
- case iAnnulus:
- case iHalves:
- case iQuarts:
- case iEighths:
- case iCheckers8:
- case iCheckers16:
- case iSurprise:
- {
- short itemType;
- Handle itemHandle;
- Rect itemBox;
- for( int itemNo = iTransparant; itemNo <= iSurprise; itemNo++)
- {
- GetDialogItem( myDialog, itemNo,
- &itemType, &itemHandle, &itemBox);
- SetControlValue( (ControlHandle)itemHandle, (itemNo == itemHit));
- }
- }
- break;
-
- case iFixationDot:
- case iLogClicks:
- case iCircularMask:
- case iFlickering:
- case iStepThrough:
- FlipItem( myDialog, itemHit);
- break;
-
- case i128x128:
- case i256x256:
- case i512x512:
- case i1024x1024:
- {
- short itemType;
- Handle itemHandle;
- Rect itemBox;
- for( int itemNo = i128x128; itemNo <= i1024x1024; itemNo++)
- {
- GetDialogItem( myDialog, itemNo,
- &itemType, &itemHandle, &itemBox);
- SetControlValue( (ControlHandle)itemHandle, (itemNo == itemHit));
- }
- }
- break;
-
- case iAllowModifications:
- FlipItem( myDialog, itemHit);
- UpdateSensitivityItems( myDialog,
- GetItemValue( myDialog, iAllowModifications));
- break;
-
- default:
- DebugStr( "\pHit an item I haven't been told to exist!");
- }
- } while( itemHit != iQuit);
- ReleaseResource( theResource);
- CloseDialog( myDialog);
- delete the_opts;
-
- return EXIT_SUCCESS;
- }
-
- void one_loop( opts *the_opts, flowsettings &alive_settings, flowsettings &kicking_settings)
- {
- //
- // 'clut' 100 contains 256 entries and is divided into four equal parts
- // which all start with black.
- //
- // 0- 63 contains a pattern which is so that '64' stays black when adding
- // up to seven times '8', and becomes white when adding '1' up to seven
- // times, and adding '1' dominates adding '8'.
- //
- // 64-127 contains a pattern which is so that '64' stays black when adding
- // up to seven times '1', and becomes white when adding '8' up to seven
- // times, and adding '8' dominates adding '1'.
- //
- // 128-191 contains one black and 63 white entries. Thus, adding up to seven
- // times '8' and/or up to seven times '1' makes the pattern white.
- //
- // 192-254 contains 64 black entries. => '0' stays black when adding
- // 1 and/or 8, each up to seven times.
- //
- // 255 is a special gray value, used to make legends less obnoxious
- //
- // We draw our pattern using the four indices 0, 64, 128, and 192.
- //
- // 0 = stimulus one visible
- // 64 = stimulus two visible
- // 128 = both stimuli visible
- // 192 = always black
- //
- CTabHandle theColorTable = (CTabHandle)Get1Resource( 'clut', 100);
-
- fullscreen thescreen( 8, theColorTable, (unsigned char)true);
- Rect screenrect;
-
- thescreen.get_rect( &screenrect);
-
- const int screenHeight = screenrect.bottom - screenrect.top;
- const int screenWidth = screenrect.right - screenrect.left;
-
- HideCursor();
-
- const int numdots_1 = (const int)the_opts->numdots_1;
- const int numdots_2 = (const int)the_opts->numdots_2;
- const int num_noise_1 = (const int)the_opts->num_noise_1;
- const int num_noise_2 = (const int)the_opts->num_noise_2;
-
- const int lifetime_1 = (const int)the_opts->lifetime_1;
- const int lifetime_2 = (const int)the_opts->lifetime_2;
- const int noise_life_1 = (const int)the_opts->noise_life_1;
- const int noise_life_2 = (const int)the_opts->noise_life_2;
-
- const int noise_diffusion_1 = (const int)the_opts->diffusion_1;
- const int noise_diffusion_2 = (const int)the_opts->diffusion_2;
-
- const int switch_interval = (const int)the_opts->switchinterval;
-
- const int stimType = the_opts->stim_type + iTransparant;
- const int numBits = the_opts->resolution_type;
-
- const int do_output = (the_opts->create_output != 0);
- const int fixation_dot = (the_opts->fixation_dot != 0);
- const int round_frame = (the_opts->round_frame != 0);
- const int flickering = (the_opts->flickering != 0);
-
- const double d_log = ((double)the_opts->d_log) / 1000.0;
- const double d_rot = ((double)the_opts->d_rot_dir) / 1000.0;
- const double d_trans = ((double)the_opts->d_trans) / 1000.0;
-
- const int num_timingloops = the_opts->numtimingloops;
-
- const Boolean stepping = the_opts->stepping;
-
- ofstream *outfile = 0;
- if( do_output)
- {
- //
- // 941118: outputfile::outputfile creates a Macintosh file, but doesn't open
- // it. This way we can have the best of both worlds, with outputfile::outputfile
- // setting creator and type of the file, and yet we can use iostream functions
- // to format output.
- //
- outputfile outfileName( "Differential out");
- outfile =
- #ifdef __MWERKS__
- new ofstream( outfileName(), ios::app | ios::out);
- #else
- new ofstream( outfileName(), ios::translated | ios::app | ios::out);
- #endif
- }
- const int size = (1 << numBits);
- const int half_size = size / 2;
-
- const int half_screenHeight = screenHeight / 2;
- const int half_screenWidth = screenWidth / 2;
- PicHandle the_pict = (PicHandle)Get1Resource( 'PICT', 128);
- const short pict_height = (*the_pict)->picFrame.bottom - (*the_pict)->picFrame.top;
- const short pict_width = (*the_pict)->picFrame.right - (*the_pict)->picFrame.left;
-
- const int xpos = max( 0, half_screenWidth - half_size - pict_width);
- const int ypos = half_screenHeight - half_size;
-
- flowdots alive( numBits, xpos, ypos, numdots_1, lifetime_1);
- flowdots kicking( numBits, xpos, ypos, numdots_2, lifetime_2);
-
- alive.setsettings( alive_settings);
- kicking.setsettings( kicking_settings);
-
- #ifdef use_movingnoise
- movingnoisedots alive_noise( numBits, xpos, ypos,
- num_noise_1, noise_life_1, noise_diffusion_1);
- movingnoisedots kicking_noise( numBits, xpos, ypos,
- num_noise_2, noise_life_2, noise_diffusion_2);
- #else
- noisedots alive_noise( numBits, xpos, ypos, num_noise_1, noise_life_1);
- noisedots kicking_noise( numBits, xpos, ypos, num_noise_2, noise_life_2);
- #endif
- const Rect stimulusrect = { ypos, xpos, ypos + size, xpos + size};
-
- PmForeColor( 192);
- PaintRect( &stimulusrect);
- if( round_frame)
- {
- RgnHandle theClip = NewRgn();
- OpenRgn();
- Rect ovalRect = stimulusrect;
- if( ovalRect.top < 0)
- {
- InsetRect( &ovalRect, -ovalRect.top, -ovalRect.top);
- }
- FrameOval( &ovalRect);
- CloseRgn( theClip);
- SetClip( theClip);
- DisposeRgn( theClip);
- }
- switch( stimType)
- {
- case iTransparant:
- PmForeColor( 128);
- PaintRect( &stimulusrect);
- break;
-
- case iAnnulus:
- {
- PmForeColor( 0);
- PaintRect( &stimulusrect);
- Rect ovalrect = stimulusrect;
- //
- // Note: on a 640x480 screen the circular annulus does not fill half the
- // stimulus area since 32 scanlines (512-32) are dropped at the top and
- // bottom edges of the screen.
- //
- const int the_inset = (size * 76L) / 512L; // 256 - 256 / √2 ≈ 76
- InsetRect( &ovalrect, the_inset, the_inset);
- PmForeColor( 64);
- PaintOval( &ovalrect);
- }
- break;
-
- case iHalves:
- {
- Rect left_half = stimulusrect;
- left_half.right = (stimulusrect.left + stimulusrect.right) / 2;
- PmForeColor( 64);
- PaintRect( &left_half);
- Rect right_half = stimulusrect;
- right_half.left = left_half.right;
- PmForeColor( 0);
- PaintRect( &right_half);
- }
- break;
-
- case iQuarts:
- {
- Rect a_quart = stimulusrect;
- a_quart.right = (stimulusrect.left + stimulusrect.right ) / 2;
- a_quart.bottom = (stimulusrect.top + stimulusrect.bottom) / 2;
- PmForeColor( 0);
- PaintRect( &a_quart);
-
- OffsetRect( &a_quart, half_size, 0);
- PmForeColor( 64);
- PaintRect( &a_quart);
-
- OffsetRect( &a_quart, 0, half_size);
- PmForeColor( 0);
- PaintRect( &a_quart);
-
- OffsetRect( &a_quart, -half_size, 0);
- PmForeColor( 64);
- PaintRect( &a_quart);
- }
- break;
-
- case iEighths:
- {
- Rect bigRect = stimulusrect;
- InsetRect( &bigRect, -5000, -5000);
- int currentcolor = 0;
- for( int i = 0; i < 8; i++)
- {
- PmForeColor( currentcolor);
- currentcolor = 64 - currentcolor;
- PaintArc( &bigRect, 45 * i, 45);
- }
- }
- break;
-
- case iCheckers8:
- case iCheckers16:
- {
- const int num_checkers = (stimType == iCheckers8) ? 8 : 16;
- Rect a_rect = stimulusrect;
- const int checker_size = size / num_checkers;
- a_rect.right = a_rect.left + checker_size;
- a_rect.bottom = a_rect.top + checker_size;
-
- int currentcolor = 0;
- for( int y = 0; y < num_checkers; y++)
- {
- for( int x = 0; x < num_checkers; x++)
- {
- PmForeColor( currentcolor);
- currentcolor = 64 - currentcolor;
- PaintRect( &a_rect);
- OffsetRect( &a_rect, checker_size, 0);
- }
- currentcolor = 64 - currentcolor;
- OffsetRect( &a_rect, -size, checker_size);
- }
- }
- break;
-
- case iSurprise:
- {
- PmForeColor( 64);
- PaintRect( &stimulusrect);
- PmForeColor( 0);
- PmBackColor( 64);
- TextSize( size / 5);
- TextFont( helvetica);
- TextStyle( bold);
- TextMode( srcCopy);
- const char text[] =
- "\rWritten by\rReinder Verlinde";
- const int length = sizeof( text) - 1; // zero terminator
- TETextBox( text, length, &stimulusrect, teJustCenter);
- }
- break;
-
- default:
- DebugStr( "\pUnimplemented stimulus type. This is a bug!");
- }
- const Rect bigRect = {-32767, -32767, 32767, 32767};
- ClipRect( &bigRect);
- //
- // Add the fixation dot
- //
- if( fixation_dot)
- {
- Rect fixationRect = stimulusrect;
-
- PmForeColor( 1);
- const short the_inset = half_size - 2; // leave 4x4 pixels
- InsetRect( &fixationRect, the_inset, the_inset);
- PaintRect( &fixationRect);
- }
- TextMode( srcCopy);
- TextFont( monaco);
- //
- // Note: TextSizes 9 and 12 don't work (maybe because that font is in ROM,
- // or because it is a bitmapped version of Monaco; I don't see why
- // either of these should make a difference, but apparently they do)
- //
- TextSize( 10);
-
- const int params_x = screenWidth - 112; // stimulusrect.right + 16;
-
- PmForeColor( 255);
- showLegends( params_x);
- //
- // Draw the key legends
- //
- Rect pict_rect;
-
- pict_rect.top = screenHeight - pict_height;
- pict_rect.left = screenWidth - pict_width;
- pict_rect.bottom = screenHeight;
- pict_rect.right = screenWidth;
-
- DrawPicture( the_pict, &pict_rect);
- //
- // The set-up is completed. Compute the display speed.
- //
- const double framerate = framerate_of_main_monitor();
-
- const int num_flicker_frames = stepping ? 60 : 1;
- vretrace flicker( num_flicker_frames);
-
- stopwatch omega;
- int i;
- omega.start();
-
- for( i = 0; i < num_timingloops; i++)
- {
- (void)step_once( alive, kicking,
- alive_noise, kicking_noise,
- d_log, d_rot, d_trans);
- }
- const double async_milliseconds =
- stopwatch::milliseconds( omega.stop()) / (double)num_timingloops;
- flicker.start();
-
- (void)flicker.sync();
- omega.start();
- for( i = 0; i < num_timingloops; i++)
- {
- (void)step_once( alive, kicking,
- alive_noise, kicking_noise,
- d_log, d_rot, d_trans);
- (void)flicker.sync();
- }
- const double sync_milliseconds =
- stopwatch::milliseconds( omega.stop()) / (double)num_timingloops;
- const int frames_per_update = (int)(sync_milliseconds * framerate / 1000.0 + 0.5);
- //
- // 941121: OOPS! in real life 'how_often' should not be expressed in the duration
- // of the framerate of the monitor, but simply as a frequency, so instead of doing
- //
- // alive.set_how_often( frames_per_update);
- // kicking.set_how_often( frames_per_update);
- //
- // We have to do
- //
- alive.set_how_often( 1000.0 / sync_milliseconds);
- kicking.set_how_often( 1000.0 / sync_milliseconds);
- //
- // For the standard settings of this program this makes a difference
- // We have:
- // sync_milliseconds ≈ 45ms (about three frames)
- // frames_per_update = 3
- // 1000.0 / sync_milliseconds ≈ 22
- //
- // This wasn't a real problem since this program has only been used as a demo up till now.
- //
- if( do_output)
- {
- (*outfile) << "Two 'flowdots' instances with "
- << numdots_1 << " and " << numdots_2 << " dots\n"
- "frame timing without syncing: "
- << async_milliseconds << "ms ("
- << 1000.0 / async_milliseconds << " frames/sec)\n"
- "frame timing with syncing: "
- << sync_milliseconds << "ms ("
- << 1000.0 / sync_milliseconds << " frames/sec)\n"
- "monitor frame takes : "
- << 1000.0 / framerate << "ms ("
- << framerate << " frames/sec)\n\n"
- << frames_per_update << " Vertical blanks per frame\n"
- << "\nOption settings were:"
- << "\nd_log = " << d_log
- << "\nd_rot = " << d_rot
- << "\nd_trans = " << d_trans
- << "\nstimulus= " << stimType
- << "\nlife 1 = " << lifetime_1
- << "\nlife 2 = " << lifetime_2
- << "\nswitching interval = " << switch_interval
- << "\n\n";
- }
- int ready = false;
- int button_was_down = false;
- int current_switch = switch_interval;
-
- Boolean switched = false;
- while( !ready)
- {
- ready = step_once( alive, kicking, alive_noise, kicking_noise, d_log, d_rot, d_trans, switched);
- (void)flicker.sync();
-
- if( flickering)
- {
- alive.EraseDots();
- kicking.EraseDots();
- (void)flicker.sync();
- }
- if( switch_interval != 0)
- {
- current_switch -= 1;
-
- if( current_switch == 0)
- {
- const flowsettings alive_temp = alive;
- const flowsettings kicking_temp = kicking;
-
- alive.setsettings( kicking_temp);
- kicking.setsettings( alive_temp);
-
- current_switch = switch_interval;
- switched = !switched;
- }
- }
-
- const int button_is_down = Button();
-
- if( button_is_down && !button_was_down)
- {
- //
- // First show the current flow parameters on the screen
- //
- if( switched)
- {
- showParams( kicking, alive, params_x);
- } else {
- showParams( alive, kicking, params_x);
- }
- //
- // Then also print them to the output file
- //
- if( do_output)
- {
- (*outfile)
- << (flowsettings &)alive << '\n'
- << (flowsettings &)kicking
- << "\n\n" << endl;
- }
- }
- button_was_down = button_is_down;
- }
- //
- // remember current settings
- //
- if( switched)
- {
- alive_settings = kicking;
- kicking_settings = alive;
- } else {
- alive_settings = alive;
- kicking_settings = kicking;
- }
-
- ReleaseResource( (Handle)the_pict);
- if( do_output)
- {
- outfile->flush();
- outfile->close();
- delete outfile;
- }
- ShowCursor();
-
- ReleaseResource( (Handle)theColorTable);
- }
-
- int step_once( flowdots &alive, flowdots &kicking,
- noisedots &alive_noise, noisedots &kicking_noise,
- double d_log, double d_rot, double d_trans, Boolean switched)
- {
- alive.make_a_move( 8);
- kicking.make_a_move( 1);
- alive_noise.make_a_move( 8);
- kicking_noise.make_a_move( 1);
- //
- // Compute new flow parameters:
- //
- KeyMap thekeys;
-
- GetKeys( thekeys);
-
- const int key_one = thekeys[ 1];
- const int caps_is_down = (key_one & 0x00000002) != 0;
- const int shift_is_down = (key_one & 0x00000001) != 0;
- const int control_is_down = (key_one & 0x00000008) != 0;
- const int escape_is_down = (key_one & 0x00002000) != 0;
- const int option_is_down = (key_one & 0x00000004) != 0;
-
- const long the_value = thekeys[ 2];
-
- flowdots *theflow = caps_is_down
- ? (switched ? &alive : &kicking)
- : (switched ? &kicking : &alive);
-
- if( control_is_down && !shift_is_down) // finger might slip to control key
- {
- theflow->expansion = 1.0;
- theflow->rotation = 0.0;
- theflow->shear_magnitude = 1.0;
- theflow->shear_direction = 0.0;
- theflow->translation_x = 0.0;
- theflow->translation_y = 0.0;
- theflow->changed();
- } else {
- if( the_value != 0)
- {
- const double scale = shift_is_down ? acceleration_factor : 1.0;
- const double power_scale =
- shift_is_down ? pow( d_log, acceleration_factor) : d_log;
- //
- // Note: the following bitmasks are hard-coded for
- // the Apple Extended keyboard II's numeric keypad.
- //
- if( option_is_down)
- {
- double div = log( theflow->expansion);
- double rot = DegreesToRadians( theflow->rotation);
-
- double r;
- double fi;
- CartesianToPolar( div, rot, &r, &fi);
-
- if( the_value & 0x00080000) r += power_scale - 1.0;
- if( the_value & 0x80000000) r -= power_scale - 1.0;
- if( the_value & 0x00000200) r = 0.0;
- if( r < 0.0)
- {
- r = 0.0;
- }
-
- if( the_value & 0x00000002) fi += DegreesToRadians( scale);
- if( the_value & 0x00000010) fi -= DegreesToRadians( scale);
- if( the_value & 0x00000008) fi = 0.0;
-
- PolarToCartesian( r, fi, &div, &rot);
-
- theflow->expansion = exp( div);
- theflow->rotation = RadiansToDegrees( rot);
- } else {
- if( the_value & 0x00080000) theflow->expansion *= power_scale;
- if( the_value & 0x80000000) theflow->expansion /= power_scale;
- if( the_value & 0x00000200) theflow->expansion = 1.00;
-
- if( the_value & 0x00000002) theflow->rotation -= d_rot * scale;
- if( the_value & 0x00000010) theflow->rotation += d_rot * scale;
- if( the_value & 0x00000008) theflow->rotation = 0.00;
- }
- if( the_value & 0x00000001) theflow->shear_magnitude *= power_scale;
- if( the_value & 0x00004000) theflow->shear_magnitude /= power_scale;
- if( the_value & 0x00008000) theflow->shear_magnitude = 1.00;
-
- if( the_value & 0x00000800) theflow->shear_direction -= d_rot * scale;
- if( the_value & 0x00002000) theflow->shear_direction += d_rot * scale;
- if( the_value & 0x00001000) theflow->shear_direction = 0.00;
-
- if( option_is_down)
- {
- double dx = theflow->translation_x;
- double dy = theflow->translation_y;
-
- double r;
- double fi;
- CartesianToPolar( dx, dy, &r, &fi);
-
- if( the_value & 0x00000400) r -= d_trans * scale;
- if( the_value & 0x00100000) r += d_trans * scale;
- if( the_value & 0x02000000) r = 0.0;
- if( r < 0.0)
- {
- r = 0.0;
- }
-
- if( the_value & 0x08000000) fi -= DegreesToRadians( scale);
- if( the_value & 0x20000000) fi += DegreesToRadians( scale);
- if( the_value & 0x00400000) fi = 0.0;
-
- PolarToCartesian( r, fi, &dx, &dy);
-
- theflow->translation_x = dx;
- theflow->translation_y = dy;
- } else {
- if( the_value & 0x00000400) theflow->translation_x -= d_trans * scale;
- if( the_value & 0x00100000) theflow->translation_x += d_trans * scale;
- if( the_value & 0x02000000) theflow->translation_x = 0;
-
- if( the_value & 0x08000000) theflow->translation_y -= d_trans * scale;
- if( the_value & 0x20000000) theflow->translation_y += d_trans * scale;
- if( the_value & 0x00400000) theflow->translation_y = 0;
- }
- theflow->changed();
- }
- }
- return escape_is_down;
- }
-
- void FlipItem( DialogPtr myDialog, short theItem)
- {
- short itemType;
- ControlHandle itemHandle;
- Rect itemBox;
- GetDialogItem( myDialog, theItem, &itemType, (Handle *)&itemHandle, &itemBox);
- SetControlValue( itemHandle, 1 - GetControlValue( itemHandle));
- }
-
- short GetItemValue( const DialogPtr myDialog, short theItem)
- {
- short itemType;
- ControlHandle itemHandle;
- Rect itemBox;
- GetDialogItem( myDialog, theItem, &itemType, (Handle *)&itemHandle, &itemBox);
- return GetControlValue( itemHandle);
- }
-
- void SetItemValue( DialogPtr myDialog, short theItem, short value)
- {
- short itemType;
- ControlHandle itemHandle;
- Rect itemBox;
- GetDialogItem( myDialog, theItem, &itemType, (Handle *)&itemHandle, &itemBox);
- SetControlValue( itemHandle, value);
- }
-
- long GetItemLong( const DialogPtr myDialog, short theItem)
- {
- short itemType;
- ControlHandle itemHandle;
- Rect itemBox;
- GetDialogItem( myDialog, theItem, &itemType, (Handle *)&itemHandle, &itemBox);
-
- Str255 text;
- GetDialogItemText( (Handle)itemHandle, text);
- long result;
- StringToNum( text, &result);
- return result;
- }
-
- void SetItemLong( DialogPtr myDialog, short theItem, long theValue)
- {
- short itemType;
- ControlHandle itemHandle;
- Rect itemBox;
- GetDialogItem( myDialog, theItem, &itemType, (Handle *)&itemHandle, &itemBox);
-
- Str255 text;
- NumToString( theValue, text);
- SetDialogItemText( (Handle)itemHandle, text);
- }
-
- void showParams( const flowdots &alive, const flowdots &kicking, short xPos)
- {
- MoveTo( xPos, 35);
- DrawNumber( alive.expansion); DrawNumber( kicking.expansion);
-
- MoveTo( xPos, 75);
- DrawNumber( alive.rotation); DrawNumber( kicking.rotation);
-
- MoveTo( xPos, 115);
- DrawNumber( alive.shear_magnitude); DrawNumber( kicking.shear_magnitude);
-
- MoveTo( xPos, 155);
- DrawNumber( alive.shear_direction); DrawNumber( kicking.shear_direction);
-
- MoveTo( xPos, 195);
- DrawNumber( alive.translation_x); DrawNumber( kicking.translation_x);
-
- MoveTo( xPos, 235);
- DrawNumber( alive.translation_y); DrawNumber( kicking.translation_y);
- }
-
- void showLegends( short xPos)
- {
- MoveTo( xPos, 20);
- DrawString( "\pdiv (/sec)");
-
- MoveTo( xPos, 60);
- DrawString( "\pcurl (°/sec)");
-
- MoveTo( xPos, 100);
- DrawString( "\pshear (/sec)");
-
- MoveTo( xPos, 140);
- DrawString( "\pshear dir (°)");
-
- MoveTo( xPos, 180);
- DrawString( "\pTranslation.x");
-
- MoveTo( xPos, 220);
- DrawString( "\pTranslation.y");
- }
-
- void DrawNumber( double theNumber)
- {
- DrawNumber( (long)(1000.0 * theNumber), 3);
- }
-
- #define help_the_optimizer
-
- void DrawNumber( long theNumber, int implicitDecimal)
- {
- #define MAXLENGTH 8
-
- assert( implicitDecimal < MAXLENGTH - 3);
-
- unsigned char string[ MAXLENGTH + 1];
- string[ 0] = MAXLENGTH;
-
- const unsigned char digits[ 11] = "0123456789";
-
- #ifdef help_the_optimizer
- unsigned char *currentptr = &string[ MAXLENGTH];
- const unsigned char *currentlimit = &string[ 1];
- #else
- int currentindex = MAXLENGTH;
- #endif
- //
- // remember the sign (C: the most readable language in the world)
- //
- const unsigned char zodiac = " -"[ theNumber < 0];
-
- if( theNumber < 0)
- {
- theNumber = -theNumber;
- }
- //
- // Output all digits up to the decimal point:
- //
- for( int i = 0; i < implicitDecimal; i++)
- {
- const int lastdigit = theNumber % 10;
- #ifdef help_the_optimizer
- *currentptr-- = digits[ lastdigit];
- #else
- string[ currentindex--] = digits[ lastdigit];
- #endif
- theNumber /= 10;
- }
- //
- // then output the decimal point, if needed
- //
- if( implicitDecimal > 0)
- {
- #ifdef help_the_optimizer
- *currentptr-- = '.';
- #else
- string[ currentindex--] = '.';
- #endif
- }
- //
- // Then output all other digits. Output at least one other digit,
- // and also check whether we run out of space. We did not have to
- // do that above, since 'implicitDecimal < MAXLENGTH - 3' does hold.
- //
- #ifdef help_the_optimizer
- do
- {
- const int lastdigit = theNumber % 10;
- *currentptr-- = digits[ lastdigit];
- theNumber /= 10;
- } while( (theNumber != 0) && (currentptr > currentlimit));
- #else
- do
- {
- const int lastdigit = theNumber % 10;
- string[ currentindex--] = digits[ lastdigit];
- theNumber /= 10;
- } while( (theNumber != 0) && (currentindex > 1));
- #endif
- //
- // Prepend the sign or a character to signal overflow
- //
- #ifdef help_the_optimizer
- if( theNumber == 0)
- {
- *currentptr-- = zodiac;
- } else {
- *currentptr-- = '…';
- }
- #else
- if( theNumber == 0)
- {
- string[ currentindex--] = zodiac;
- } else {
- string[ currentindex--] = '…';
- }
- #endif
- //
- // And prepend spaces for the rest of the string:
- //
- #ifdef help_the_optimizer
- while( currentptr > string)
- {
- *currentptr-- = ' ';
- }
- #else
- while( currentindex > 0)
- {
- string[ currentindex--] = ' ';
- }
- #endif
- //
- // Finally draw the Pascal string we created:
- //
- DrawString( string);
- }
-
- #ifdef help_the_optimizer
- #undef help_the_optimizer
- #endif
-
- void Dialog2options( const DialogPtr theDialog,
- const opts *default_options, opts *the_options)
- {
- the_options->numdots_1 = GetItemLong( theDialog, iNumDots1);
- the_options->numdots_2 = GetItemLong( theDialog, iNumDots2);
- the_options->num_noise_1 = GetItemLong( theDialog, iNumNoiseDots1);
- the_options->num_noise_2 = GetItemLong( theDialog, iNumNoiseDots2);
-
- the_options->lifetime_1 = GetItemLong( theDialog, iLife1);
- the_options->lifetime_2 = GetItemLong( theDialog, iLife2);
- the_options->noise_life_1 = GetItemLong( theDialog, iNoiseLife1);
- the_options->noise_life_2 = GetItemLong( theDialog, iNoiseLife2);
-
- the_options->diffusion_1 = GetItemLong( theDialog, iDiffusion1);
- the_options->diffusion_2 = GetItemLong( theDialog, iDiffusion2);
-
- the_options->switchinterval = GetItemLong( theDialog, iSwitchInterval);
-
- for( int itemNo = iTransparant; itemNo <= iSurprise; itemNo++)
- {
- if( GetItemValue( theDialog, itemNo) != 0)
- {
- the_options->stim_type = itemNo - iTransparant;
- }
- }
-
- if( GetItemValue( theDialog, i128x128) != 0)
- {
- the_options->resolution_type = 7;
- } else if( GetItemValue( theDialog, i256x256) != 0) {
- the_options->resolution_type = 8;
- } else if( GetItemValue( theDialog, i512x512) != 0) {
- the_options->resolution_type = 9;
- } else {
- the_options->resolution_type = 10;
- }
-
- the_options->create_output = GetItemValue( theDialog, iLogClicks);
- the_options->fixation_dot = GetItemValue( theDialog, iFixationDot);
- the_options->round_frame = GetItemValue( theDialog, iCircularMask);
- the_options->flickering = GetItemValue( theDialog, iFlickering);
-
- the_options->d_log = GetItemLong( theDialog, i_dLog);
- the_options->d_rot_dir = GetItemLong( theDialog, i_dRotDir);
- the_options->d_trans = GetItemLong( theDialog, i_dTrans);
- the_options->allow_modifications
- = GetItemValue( theDialog, iAllowModifications);
-
- the_options->stepping = (GetItemValue( theDialog, iStepThrough) != 0);
- the_options->numtimingloops = default_options->numtimingloops;
- }
-
- void options2Dialog( const opts *the_options, DialogPtr theDialog)
- {
- SetItemLong( theDialog, iNumDots1, the_options->numdots_1);
- SetItemLong( theDialog, iNumDots2, the_options->numdots_2);
- SetItemLong( theDialog, iNumNoiseDots1, the_options->num_noise_1);
- SetItemLong( theDialog, iNumNoiseDots2, the_options->num_noise_2);
-
- SetItemLong( theDialog, iLife1, the_options->lifetime_1);
- SetItemLong( theDialog, iLife2, the_options->lifetime_2);
- SetItemLong( theDialog, iNoiseLife1, the_options->noise_life_1);
- SetItemLong( theDialog, iNoiseLife2, the_options->noise_life_2);
-
- SetItemLong( theDialog, iDiffusion1, the_options->diffusion_1);
- SetItemLong( theDialog, iDiffusion2, the_options->diffusion_2);
-
- SetItemLong( theDialog, iSwitchInterval, the_options->switchinterval);
-
- const int theItemToSet = the_options->stim_type + iTransparant;
-
- for( int itemNo = iTransparant; itemNo <= iSurprise; itemNo++)
- {
- SetItemValue( theDialog, itemNo, (theItemToSet == itemNo));
- }
-
- SetItemValue( theDialog, i128x128, (the_options->resolution_type == 7));
- SetItemValue( theDialog, i256x256, (the_options->resolution_type == 8));
- SetItemValue( theDialog, i512x512, (the_options->resolution_type == 9));
- SetItemValue( theDialog, i1024x1024, (the_options->resolution_type == 10));
-
- SetItemValue( theDialog, iLogClicks, the_options->create_output);
- SetItemValue( theDialog, iFixationDot, the_options->fixation_dot);
- SetItemValue( theDialog, iCircularMask, the_options->round_frame);
- SetItemValue( theDialog, iFlickering, the_options->flickering);
-
- SetItemLong( theDialog, i_dLog, the_options->d_log);
- SetItemLong( theDialog, i_dRotDir, the_options->d_rot_dir);
- SetItemLong( theDialog, i_dTrans, the_options->d_trans);
-
- SetItemValue( theDialog, iAllowModifications, the_options->allow_modifications);
- SetItemValue( theDialog, iStepThrough, the_options->stepping);
-
- UpdateSensitivityItems( theDialog, the_options->allow_modifications);
- }
-
- void UpdateSensitivityItems( DialogPtr theDialog, long allow_modifications)
- {
- //
- // this routine should use some kind of table, but it works…
- //
- if( allow_modifications)
- {
- ShowDialogItem( theDialog, i_dLog);
- ShowDialogItem( theDialog, i_dTrans);
- ShowDialogItem( theDialog, i_dRotDir);
-
- HideDialogItem( theDialog, i_dLogStatic);
- HideDialogItem( theDialog, i_dTransStatic);
- HideDialogItem( theDialog, i_dRotDirStatic);
- } else {
- HideDialogItem( theDialog, i_dLog);
- HideDialogItem( theDialog, i_dTrans);
- HideDialogItem( theDialog, i_dRotDir);
-
- SetItemLong( theDialog, i_dLogStatic, GetItemLong( theDialog, i_dLog));
- SetItemLong( theDialog, i_dTransStatic, GetItemLong( theDialog, i_dTrans));
- SetItemLong( theDialog, i_dRotDirStatic, GetItemLong( theDialog, i_dRotDir));
-
- ShowDialogItem( theDialog, i_dLogStatic);
- ShowDialogItem( theDialog, i_dTransStatic);
- ShowDialogItem( theDialog, i_dRotDirStatic);
- }
- }
-
- void PolarToCartesian( double r, double fi, double *x, double *y)
- {
- *x = r * cos( fi);
- *y = r * sin( fi);
- }
-
- void CartesianToPolar( double x, double y, double *r, double *fi)
- {
- //
- // 950614: hacking 'hypot' in. It is defined in fp.h, but leads to
- // link errors => using a crude macro equivalent
- // We don't have to worry about overflow here.
- //
- #define hypot(a,b) sqrt( a * a + b * b)
- *r = hypot( x, y);
- *fi = atan2( y, x);
- #undef hypot
- }
-