home *** CD-ROM | disk | FTP | other *** search
- /* newmain.c -- User interface event handling and graphics
- * Copyright (C) 1991 Douglas M. DeCarlo
- *
- * Modifications for the Amiga port Copyright (C) 1994 Torsten Klein
- *
- * This file is part of ASpringies, a mass and spring simulation system for the Amiga
- *
- * ASpringies is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 1, or (at your option)
- * any later version.
- *
- * ASpringies is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with ASpringies; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id: newmain.c,v 2.9 1994/08/19 11:52:22 Torsten_Klein Exp $
- */
-
- #include <proto/timer.h>
- #include <math.h>
-
- #include "main.h"
- #include "obj.h"
-
- #define SetFL(obj, value) (sprintf(temp, "%lf", (value)), \
- cut0s(temp),\
- setstring((obj), temp))
-
- #define FOREachSelString(command) for (i = 0; i < num_spring; i++) \
- if (springs[i].status & S_SELECTED) (command);
-
- #define GetForceGrav(obj, which) \
- mst.cur_grav_val[which] = GetFL(obj, cur_grav_min[which],cur_grav_max[which])
-
- #define GetForceMisc(obj, which) \
- mst.cur_misc_val[which] = GetFL(obj, cur_misc_min[which],cur_misc_max[which])
-
- #define DRAWLINE(rp, x1, y1, x2, y2) \
- { Move(rp, x1, y1); Draw(rp, x2, y2); }
-
- /* Mode values */
- #define M_EDIT 0L
- #define M_MASS 1L
- #define M_SPRING 2L
-
- /* Behavior function modes */
- #define M_BF 3
-
- /* Number of previous mouse state saves */
- #define MOUSE_PREV 4
-
- #define NAIL_SIZE 12
-
- /* Number of milliseconds that each drawing takes (to prevent skips) */
- #define MIN_DIFFT 3000
-
- #define AnyButton 66
- #define Button1 1
- #define Button2 2
- #define Button3 3
-
- /* local prototypes
- */
- static void redraw_system(void);
- static void view_system(void);
- static void view_subsystem(int ulx, int uly, int wid, int ht);
- static void mouse_event(int, WORD, WORD, int, int);
- static void draw_edit_frame(int, int, int, int);
- static void handle_edit_message(struct IntuiMessage *);
- static void DoVanillaKey(struct IntuiMessage *);
- static void DoRestoreState(void);
- static void DoRestore(void);
- static boolean GetCK(APTR);
- static void draw_mass(boolean, int, int, double, boolean, boolean center);
- static boolean event_handler(void);
-
- /* global vars
- */
- int draw_wid, draw_ht;
-
- t_state mst = {
- 1.0, 1.0,
- 1.0, 1.0,
- FALSE, TRUE,
- -1,
- { 0, 0, 0, 0 },
- { 10.0, 5.0, 10.0, 10000.0 },
- { 0.0, 2.0, 0.0, 1.0 },
- 0.0, 0.0,
- DEF_TSTEP, 1.0,
- FALSE, FALSE,
- 20.0,
- TRUE, TRUE, TRUE, TRUE
- };
-
- /* local vars
- */
- typedef struct {
- int x, y;
- unsigned long t;
- } mouse_info;
-
- static mouse_info mprev[MOUSE_PREV];
- static int moffset = 0;
-
- static ULONG mode = M_EDIT;
- static int front = 0; back = 1;
- static BOOL erase = TRUE;
- static boolean quitting = FALSE, action = FALSE;
-
- static t_state initst, sst;
-
- static double cur_grav_max[BF_NUM] = { 10000000.0, 10000000.0,
- 10000000.0, 10000000.0 };
- static double cur_grav_min[BF_NUM] = { 0.0, -10000000.0,
- -10000000.0, -10000000.0 };
- static double cur_misc_max[BF_NUM] = { 360.0, 10000000.0,
- 1000.0, 1000.0 };
- static double cur_misc_min[BF_NUM] = { -360.0, 0.0,
- 0.0, -0.0 };
-
- static char temp[20]; /* for SetSL */
-
- /*****************************************************/
-
- void new_main(void)
- {
- initst = sst = mst;
-
- draw_wid = anim_wnd->Width;
- draw_ht = anim_wnd->Height;
- SetDrMd(anim_rport[back], JAM1);
- SetDrMd(anim_rport[front], JAM1);
-
- redisplay_widgets();
- review_system();
- init_objects();
-
- save_state(); sst = mst; /* kludge */
-
- while (event_handler());
-
- delete_all();
- }
-
- /*****************************************************/
-
- static void cut0s(char *str)
- {
- char *cp = &str[strlen(str)-1];
-
- while (*cp=='0' && *(cp-1)!='.') *(cp--) = '\0';
- }
-
- /*****************************************************/
-
- static double GetFL(APTR obj, double min, double max)
- {
- char *contents;
- double result;
-
- get(obj, MUIA_String_Contents, &contents);
- sscanf(contents, "%lf", &result);
-
- if (result<min) result=min;
- if (result>max) result=max;
-
- SetFL(obj, result);
- return(result);
- }
-
- /*****************************************************/
-
- static boolean GetCK(APTR obj) {
- ULONG result;
-
- get(obj, MUIA_Selected, &result);
- return((boolean)result);
- }
-
- /*****************************************************/
-
- void redisplay_widgets(void)
- {
- setcheckmark(CK_Action, action);
- setcheckmark(CK_DrawSpr, mst.show_spring);
- setcheckmark(CK_AdaptTStep, mst.adaptive_step);
- setcheckmark(CK_FixedMass, mst.fix_mass);
- setcheckmark(CK_WallTop, mst.w_top);
- setcheckmark(CK_WallLeft, mst.w_left);
- setcheckmark(CK_WallRight, mst.w_right);
- setcheckmark(CK_WallBottom, mst.w_bottom);
- setcheckmark(CK_GravActive, mst.bf_mode[FR_GRAV]);
- setcheckmark(CK_CenterActive, mst.bf_mode[FR_CMASS]);
- setcheckmark(CK_PtAttrActive, mst.bf_mode[FR_PTATTRACT]);
- setcheckmark(CK_WallFActive, mst.bf_mode[FR_WALL]);
-
- setslider(SL_Grid, mst.grid_snap ? (ULONG)mst.cur_gsnap : 1L);
-
- SetFL(ST_Mass, mst.cur_mass);
- SetFL(ST_Elas, mst.cur_rest);
- SetFL(ST_Kspr, mst.cur_ks);
- SetFL(ST_Kdmp, mst.cur_kd);
- SetFL(ST_Visc, mst.cur_visc);
- SetFL(ST_Stic, mst.cur_stick);
- SetFL(ST_Step, mst.cur_dt);
- SetFL(ST_Prec, mst.cur_prec);
- SetFL(ST_GravGrav, mst.cur_grav_val[FR_GRAV]);
- SetFL(ST_GravDir, mst.cur_misc_val[FR_GRAV]);
- SetFL(ST_CenterMagn, mst.cur_grav_val[FR_CMASS]);
- SetFL(ST_CenterDamp, mst.cur_misc_val[FR_CMASS]);
- SetFL(ST_PtAttrMagn, mst.cur_grav_val[FR_PTATTRACT]);
- SetFL(ST_PtAttrExpo, mst.cur_misc_val[FR_PTATTRACT]);
- SetFL(ST_WallFMagn, mst.cur_grav_val[FR_WALL]);
- SetFL(ST_WallFExpo, mst.cur_misc_val[FR_WALL]);
- }
-
- /*****************************************************/
-
- static boolean event_handler(void)
- {
- static LONGBITS MUI_Signals;
- static boolean quitting = FALSE;
-
- struct IntuiMessage *msg;
- int i;
-
- do
- switch (DoMethod(AP_ASpringies, MUIM_Application_Input, &MUI_Signals))
- {
- case MUIV_Application_ReturnID_Quit :
- quitting = (BOOL)MUI_Request(AP_ASpringies, WI_ASpringies, 0,
- "Quit request", "Yes|*No",
- "Would you like to quit ASpringies?");
- break;
-
- case ID_RA_Mode : get(RA_Mode, MUIA_Radio_Active, &mode); break;
- case ID_CK_DrawSpr : mst.show_spring=GetCK(CK_DrawSpr); review_system();break;
- case ID_CK_AdaptTStep : mst.adaptive_step=GetCK(CK_AdaptTStep); break;
- case ID_CK_Action : action= GetCK(CK_Action); break;
- case ID_CK_FixedMass :
- mst.fix_mass = GetCK(CK_FixedMass);
- for (i = 0; i < num_mass; i++)
- if (masses[i].status & S_SELECTED) {
- if (mst.fix_mass) masses[i].status |= S_FIXED;
- else masses[i].status &= ~(S_FIXED | S_TEMPFIXED);
- }
- review_system();
- break;
-
- case ID_CK_WallTop : mst.w_top = GetCK(CK_WallTop); review_system();
- break;
- case ID_CK_WallLeft : mst.w_left = GetCK(CK_WallLeft); review_system();
- break;
- case ID_CK_WallRight : mst.w_right = GetCK(CK_WallRight); review_system();
- break;
- case ID_CK_WallBottom : mst.w_bottom = GetCK(CK_WallBottom); review_system();
- break;
-
- case ID_CK_GravActive : mst.bf_mode[FR_GRAV] =GetCK(CK_GravActive); break;
- case ID_CK_CenterActive: mst.bf_mode[FR_CMASS] =GetCK(CK_CenterActive);break;
- case ID_CK_PtAttrActive: mst.bf_mode[FR_PTATTRACT] =GetCK(CK_PtAttrActive);break;
- case ID_CK_WallFActive : mst.bf_mode[FR_WALL] =GetCK(CK_WallFActive); break;
-
- case ID_BT_SelAll : select_all(); eval_selection(); review_system(); break;
- case ID_BT_SetRLen : set_sel_restlen(); break;
- case ID_BT_SetCenter : set_center(); review_system(); break;
-
- case ID_SL_Grid : {
- ULONG result;
- get(SL_Grid, MUIA_Slider_Level, &result);
- mst.grid_snap = (mst.cur_gsnap = result) != 1;
- }
- break;
-
- case ID_ST_Mass :
- mst.cur_mass = GetFL(ST_Mass, 0.01, 10000000.0);
- for (i = 0; i < num_mass; i++)
- if (masses[i].status & S_SELECTED) {
- masses[i].mass = mst.cur_mass;
- masses[i].radius = mass_radius(mst.cur_mass);
- }
- review_system();
- break;
- case ID_ST_Elas :
- mst.cur_rest = GetFL(ST_Elas, 0.0, 1.0);
- for (i = 0; i < num_mass; i++) {
- if (masses[i].status & S_SELECTED)
- masses[i].elastic = mst.cur_rest;
- }
- break;
- case ID_ST_Kspr :
- mst.cur_ks = GetFL(ST_Kspr, 0.01, 10000000.0);
- FOREachSelString(springs[i].ks = mst.cur_ks);
- break;
- case ID_ST_Kdmp :
- mst.cur_kd = GetFL(ST_Kdmp, 0.0, 10000000.0);
- FOREachSelString(springs[i].kd = mst.cur_kd);
- break;
- case ID_ST_Visc : mst.cur_visc = GetFL(ST_Visc, 0.0, 10000000.0); break;
- case ID_ST_Stic : mst.cur_stick = GetFL(ST_Stic, 0.0, 10000000.0); break;
- case ID_ST_Step : mst.cur_dt = GetFL(ST_Step, 0.0001, 1.0); break;
- case ID_ST_Prec : mst.cur_prec = GetFL(ST_Prec, 0.0001, 1000.0); break;
-
- case ID_ST_GravGrav : GetForceGrav(ST_GravGrav, FR_GRAV); break;
- case ID_ST_GravDir : GetForceMisc(ST_GravDir, FR_GRAV); break;
- case ID_ST_CenterMagn : GetForceGrav(ST_CenterMagn, FR_CMASS); break;
- case ID_ST_CenterDamp : GetForceMisc(ST_CenterDamp, FR_CMASS); break;
- case ID_ST_PtAttrMagn : GetForceGrav(ST_PtAttrMagn, FR_PTATTRACT); break;
- case ID_ST_PtAttrExpo : GetForceMisc(ST_PtAttrExpo, FR_PTATTRACT); break;
- case ID_ST_WallFMagn : GetForceGrav(ST_WallFMagn, FR_WALL); break;
- case ID_ST_WallFExpo : GetForceMisc(ST_WallFExpo, FR_WALL); break;
-
- case ID_ME_About : DoInfo(); break;
- case ID_ME_Help :
- DoMethod(AP_ASpringies, MUIM_Application_ShowHelp, WI_ASpringies,
- HELP_FILE, "Main", 0);
- break;
- case ID_ME_Load : FileIO(F_LOAD); break;
- case ID_ME_Insert : FileIO(F_INSERT); break;
- case ID_ME_Save : FileIO(F_SAVE); break;
- case ID_ME_SaveAs : FileIO(F_SAVEAS); break;
- case ID_ME_DupSel : duplicate_selected(); review_system(); break;
- case ID_ME_DeleteSel : delete_selected(); review_system(); break;
- case ID_ME_Restore :
- if (MUI_Request(AP_ASpringies, WI_ASpringies, 0, "Restore request", "Yes|*No",
- "Restore last Snapshot?"))
- DoRestoreState();
- break;
- case ID_ME_Snapshot : save_state(); sst = mst; break;
- case ID_ME_Reset :
- if (MUI_Request(AP_ASpringies, WI_ASpringies, 0, "Reset request", "Yes|*No",
- "Reset ASpringies?"))
- DoRestore();
- break;
- case ID_ME_ScreenMode : /* noch besser machen! */
- CloseAnimDisplay(); OpenAnimDisplay(TRUE);
- draw_wid = anim_wnd->Width;
- draw_ht = anim_wnd->Height;
- SetDrMd(anim_rport[back], JAM1);
- SetDrMd(anim_rport[front], JAM1);
- review_system();
- break;
- case ID_KY_AnimToFront :
- ScreenToFront(anim_scr);
- ActivateWindow(anim_wnd);
- break;
- } while (!MUI_Signals);
-
- if (quitting)
- return(FALSE);
-
- if (action && animate_obj()) {
- static struct timeval tp, tpo;
- static int totaldiff = 0;
- static boolean started = FALSE;
- static ULONG av_fps, fpscount;
- int difft;
-
- if (!started) {
- GetSysTime(&tp);
- started = TRUE;
- }
- tpo = tp;
-
- GetSysTime(&tp);
- difft = (tp.tv_secs - tpo.tv_secs) * 1000000 + (tp.tv_micro - tpo.tv_micro);
-
- if (difft < MIN_DIFFT)
- difft = MIN_DIFFT;
-
- if (difft > 0) {
- totaldiff += difft;
-
- fpscount++;
- av_fps += (ULONG)(1.e6/difft+.5);
- if (fpscount == 10) {
- set(TX_Fps, MUIA_Text_Contents, (sprintf(temp, "%2ld", av_fps/10), temp));
- av_fps = fpscount = 0;
- }
- /* Do updates about 30 frames per second */
- if ((totaldiff > MIN_DIFFT)) {
- review_system();
- }
- }
- }
- else if (!action && MUI_Signals) {
- Wait(MUI_Signals | (1 << anim_wnd->UserPort->mp_SigBit));
- }
-
- while (msg= (struct IntuiMessage *)GetMsg(anim_wnd->UserPort))
- handle_edit_message(msg);
-
- return(TRUE);
- }
-
- /*****************************************************/
-
- static void handle_edit_message(struct IntuiMessage *msg)
- {
- int
- shifted = msg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT),
- alt = msg->Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT);
-
- switch (msg->Class)
- {
- case IDCMP_MOUSEBUTTONS:
- switch(msg->Code)
- {
- case SELECTDOWN:
- msg->IDCMPWindow->Flags |= WFLG_REPORTMOUSE;
- memset(mprev, 0, sizeof(mprev));
- mouse_event(M_DOWN, msg->MouseX, msg->MouseY,
- alt ? Button2 : Button1, shifted);
- break;
-
- case SELECTUP:
- msg->IDCMPWindow->Flags &= ~WFLG_REPORTMOUSE;
- mouse_event(M_UP, msg->MouseX, msg->MouseY,
- alt ? Button2 : Button1, FALSE);
- break;
-
- case MIDDLEDOWN: alt = TRUE;
- case MENUDOWN:
- msg->IDCMPWindow->Flags |= WFLG_REPORTMOUSE;
- memset(mprev, 0, sizeof(mprev));
- mouse_event(M_DOWN, msg->MouseX, msg->MouseY,
- alt ? Button2 : Button3, shifted);
- break;
-
- case MIDDLEUP: alt = TRUE;
- case MENUUP:
- msg->IDCMPWindow->Flags &= ~WFLG_REPORTMOUSE;
- mouse_event(M_UP, msg->MouseX, msg->MouseY,
- alt ? Button2 : Button3, FALSE);
- break;
- }
- case IDCMP_MOUSEMOVE:
- mprev[moffset].x = msg->MouseX;
- mprev[moffset].y = msg->MouseY;
- mprev[moffset].t = (unsigned long)1000 * msg->Seconds + .001 * msg->Micros;
- moffset = (moffset + 1) % MOUSE_PREV;
- mouse_event(M_DRAG, msg->MouseX, msg->MouseY, AnyButton, FALSE);
- break;
- case IDCMP_VANILLAKEY:
- DoVanillaKey(msg);
- break;
- case IDCMP_RAWKEY:
- break;
- }
- ReplyMsg((struct Message *)msg);
- }
-
- /*****************************************************/
-
-
- static void DoVanillaKey(struct IntuiMessage *msg)
- {
- switch(msg->Code)
- {
- case IECODE_ASCII_DEL : delete_selected(); review_system(); break;
- case '0' : erase = FALSE; break;
- case '1' : erase = TRUE; break;
- case ' ' :
- DoMethod(WI_ASpringies, MUIM_Window_ScreenToFront);
- DoMethod(WI_ASpringies, MUIM_Window_ToFront);
- set(WI_ASpringies, MUIA_Window_Activate, TRUE);
- break;
- }
- }
-
- /*****************************************************/
-
- int mass_radius(double m)
- {
- int rad;
-
- rad = (int)(2 * log(4.0 * m + 1.0));
-
- if (rad < 1) rad = 1;
- if (rad > 64) rad = 64;
-
- return rad;
- }
-
- /*****************************************************/
-
- static void mouse_vel(int *mx, int *my)
- {
- int i, totalx = 0, totaly = 0, scale = 0, dx, dy, dt;
- int fudge = 256;
-
- for (i = 0; i < MOUSE_PREV - 1; i++) {
- dx = mprev[(moffset + 2 + i) % MOUSE_PREV].x
- - mprev[(moffset + 1 + i) % MOUSE_PREV].x;
- dy = mprev[(moffset + 2 + i) % MOUSE_PREV].y
- - mprev[(moffset + 1 + i) % MOUSE_PREV].y;
- dt = mprev[(moffset + 2 + i) % MOUSE_PREV].t
- - mprev[(moffset + 1 + i) % MOUSE_PREV].t;
-
- if (dt) {
- scale += 64 * i * i;
- totalx += 64 * i * i * fudge * dx / dt;
- totaly += 64 * i * i * fudge * dy / dt;
- }
- }
-
- if (scale) {
- totalx /= scale;
- totaly /= scale;
- }
-
- *mx = totalx;
- *my = totaly;
- }
-
- /*****************************************************/
-
- static void view_subsystem(int ulx, int uly, int wid, int ht)
- {
- if (ulx < 0) {
- wid += ulx;
- ulx = 0;
- }
- if (uly < 0) {
- ht += uly;
- uly = 0;
- }
- if (wid < 0 || ht < 0)
- return;
-
- if (ulx + wid >= draw_wid)
- wid -= (ulx + wid - draw_wid);
- if (uly + ht >= draw_ht)
- ht -= (uly + ht - draw_ht);
-
- if (wid < 0 || ht < 0)
- return;
-
- if (!action)
- ClipBlit(anim_rport[back], ulx, uly, anim_rport[front], ulx, uly,
- wid, ht, 0xC0);
- }
-
- /*****************************************************/
-
- void review_system(void)
- {
- /* Clear the old pixmap */
- if (erase) SetRast(anim_rport[back], 0);
-
- redraw_system();
- view_system();
-
- mouse_event(M_REDISPLAY, 0, 0, AnyButton, FALSE);
-
- if (mst.adaptive_step)
- SetFL(ST_Step, mst.cur_dt);
- }
-
- /*****************************************************/
-
- static void mouse_event(int type, WORD mx, WORD my, int mbutton, int shifted)
- {
- static int
- startx = 0, prevx = 0, starty = 0, prevy = 0,
- cur_button = 0, selection = -1;
- static boolean
- active = FALSE, cur_shift = FALSE, static_spring = FALSE;
-
- /* Skip restarts when active or continuations when inactive */
- if ((type != M_DOWN && !active) || (type == M_DOWN && active))
- return;
-
- /* Do grid snapping operation */
- if (mst.grid_snap && mode != M_EDIT ){
- mx = ((mx + (int)mst.cur_gsnap/2)/(int)mst.cur_gsnap) * (int)mst.cur_gsnap;
- my = ((my + (int)mst.cur_gsnap/2)/(int)mst.cur_gsnap) * (int)mst.cur_gsnap;
- }
-
- switch (type)
- {
- case M_REDISPLAY:
- switch (mode)
- {
- case M_EDIT:
- switch (cur_button)
- {
- case Button1:
- if (selection < 0)
- draw_edit_frame(startx, starty, prevx, prevy);
- break;
- case Button2:
- break;
- case Button3:
- break;
- }
- break;
- case M_MASS:
- draw_mass(TRUE, prevx, prevy, mst.cur_mass, FALSE, mst.fix_mass);
- break;
- case M_SPRING:
- if (static_spring) {
- startx = COORD_X(masses[selection].x);
- starty = COORD_Y(masses[selection].y);
- DRAWLINE(anim_rport[front], startx, starty, prevx, prevy);
- }
- break;
- }
- break;
-
- case M_DOWN:
- review_system();
- startx = prevx = mx;
- starty = prevy = my;
- cur_button = mbutton;
- active = TRUE;
- cur_shift = shifted;
-
- switch (mode)
- {
- case M_EDIT:
- switch (cur_button)
- {
- case Button1:
- {
- boolean is_mass = FALSE;
- selection = nearest_object(COORD_X(mx), COORD_Y(my), &is_mass);
-
- /* If not shift clicking, unselect all currently selected items
- */
- if (!shifted) {
- unselect_all();
- review_system();
- }
- }
- break;
- case Button2:
- case Button3:
- tempfixed_obj(TRUE);
- break;
- }
- break;
- case M_MASS:
- draw_mass(TRUE, mx, my, mst.cur_mass, FALSE, mst.fix_mass);
- break;
- case M_SPRING: /* start setting a new spring */
- {
- boolean is_mass = TRUE;
-
- /* static = doesn't affect the mass it's attached to
- */
- static_spring = (!action || cur_button == Button3);
-
- selection = nearest_object(COORD_X(mx), COORD_Y(my), &is_mass);
- if (selection >= 0 && is_mass) {
- startx = COORD_X(masses[selection].x);
- starty = COORD_Y(masses[selection].y);
- if (static_spring) {
- DRAWLINE(anim_rport[front], startx, starty, prevx, prevy);
- } else {
- attach_fake_spring(selection);
- move_fake_mass(COORD_X(mx), COORD_Y(my));
- review_system();
- }
- } else {
- active = FALSE;
- }
- }
- break;
- }
- break;
-
- case M_DRAG:
- switch (mode)
- {
- case M_EDIT:
- switch (cur_button)
- {
- case Button1:
- if (selection < 0) { /* redraw frame */
- view_subsystem(MIN(startx, prevx), MIN(starty, prevy),
- ABS(prevx - startx)+1, ABS(prevy - starty)+1);
- prevx = mx;
- prevy = my;
- draw_edit_frame(startx, starty, prevx, prevy);
- }
- break;
- case Button2:
- case Button3:
- /* Move objects relative to mouse */
- translate_selobj(COORD_DX(mx - prevx), COORD_DY(my - prevy));
- review_system();
- prevx = mx;
- prevy = my;
- break;
- }
- break;
- case M_MASS: /* move dragged mass to new position */
- {
- int rad = mst.fix_mass ? NAIL_SIZE : mass_radius(mst.cur_mass);
- view_subsystem(prevx - rad, prevy - rad, rad * 2 + 1, rad * 2 + 1);
- }
- prevx = mx;
- prevy = my;
- draw_mass(TRUE, prevx, prevy, mst.cur_mass, FALSE, mst.fix_mass);
- break;
- case M_SPRING: /* redraw spring being edited to new end position */
- if (static_spring) {
- view_subsystem(MIN(startx, prevx), MIN(starty, prevy),
- ABS(prevx - startx) + 1, ABS(prevy - starty) + 1);
- prevx = mx;
- prevy = my;
- startx = COORD_X(masses[selection].x);
- starty = COORD_Y(masses[selection].y);
- DRAWLINE(action ? anim_rport[back] : anim_rport[front], startx, starty, prevx, prevy);
- } else {
- move_fake_mass(COORD_X(mx), COORD_Y(my));
- }
- break;
- }
- break;
-
- case M_UP:
- active = FALSE;
- switch (mode) {
- case M_EDIT:
- switch (cur_button) {
- case Button1:
- if (selection < 0) { /* select objects in current frame*/
- select_objects(MIN(COORD_X(startx), COORD_X(mx)),
- MIN(COORD_Y(starty), COORD_Y(my)),
- MAX(COORD_X(startx), COORD_X(mx)),
- MAX(COORD_Y(starty), COORD_Y(my)), cur_shift);
- eval_selection();
- review_system();
- } else { /* select single object */
- boolean is_mass = FALSE;
-
- if ((selection = nearest_object(COORD_X(mx), COORD_Y(my),
- &is_mass)) >= 0) {
- select_object(selection, is_mass, cur_shift);
- eval_selection();
- review_system();
- }
- }
- break;
- case Button2:
- tempfixed_obj(FALSE);
- review_system();
- break;
- case Button3: /* throw objects */
- {
- int mvx, mvy;
-
- mouse_vel(&mvx, &mvy);
-
- changevel_selobj(COORD_DX(mvx), COORD_DY(mvy), FALSE);
- tempfixed_obj(FALSE);
- review_system();
- }
- break;
- }
- break;
- case M_MASS: /* create new mass */
- {
- int newm;
-
- newm = create_mass();
-
- masses[newm].x = COORD_X((double)mx);
- masses[newm].y = COORD_Y((double)my);
- masses[newm].mass = mst.cur_mass;
- masses[newm].radius = mass_radius(mst.cur_mass);
- masses[newm].elastic = mst.cur_rest;
- if (mst.fix_mass) masses[newm].status |= S_FIXED;
-
- review_system();
- }
- break;
-
- case M_SPRING: /* create new spring */
- {
- boolean is_mass = TRUE;
- int start_sel = selection, news, endx, endy;
-
- if (!static_spring)
- kill_fake_spring();
-
- selection = nearest_object(COORD_X(mx), COORD_Y(my), &is_mass);
- if ((static_spring || !action || cur_button == Button1)
- && selection >= 0 && is_mass && selection != start_sel) {
- startx = COORD_X(masses[start_sel].x);
- starty = COORD_Y(masses[start_sel].y);
- endx = COORD_X(masses[selection].x);
- endy = COORD_Y(masses[selection].y);
-
- news = create_spring();
- springs[news].m1 = start_sel;
- springs[news].m2 = selection;
- springs[news].ks = mst.cur_ks;
- springs[news].kd = mst.cur_kd;
- springs[news].restlen = sqrt( (double)SQR(startx - endx)
- + (double)SQR(starty - endy));
- add_massparent(start_sel, news);
- add_massparent(selection, news);
- }
- review_system();
- }
- break;
- }
- break;
- }
- }
-
- /*****************************************************/
-
- static void view_system(void)
- {
- int old_back = back;
-
- ShowView(back);
- back = front;
- front = old_back;
- }
-
- /*****************************************************/
-
- static void redraw_system(void)
- {
- int i, rad, num_spr;
- mass *m1ptr, *m2ptr;
- spring *sptr;
-
- num_spr = (mst.show_spring) ? num_spring : 1;
-
- SetDrPt(anim_rport[back], 0xffff);
- if (mst.w_top) DRAWLINE(anim_rport[back],1, 1, draw_wid-2, 1 );
- if (mst.w_left) DRAWLINE(anim_rport[back],1, 1, 1, draw_ht-2);
- if (mst.w_right) DRAWLINE(anim_rport[back],draw_wid-2, 1, draw_wid-2, draw_ht-2);
- if (mst.w_bottom) DRAWLINE(anim_rport[back],1, draw_ht-2, draw_wid-2, draw_ht-2);
-
- {
- static UWORD selspringpat = 0x0f0f;
-
- if (action)
- selspringpat = (selspringpat >> 15) + (selspringpat << 1);
-
- for (i=0, sptr = springs; i<num_spr; i++, sptr++) {
- m1ptr = masses + sptr->m1;
- m2ptr = masses + sptr->m2;
- if (sptr->status & S_ALIVE) {
- if (sptr->status & S_SELECTED)
- SetDrPt(anim_rport[back], selspringpat);
- DRAWLINE(anim_rport[back], (int)COORD_X(m1ptr->x), (int)COORD_Y(m1ptr->y),
- (int)COORD_X(m2ptr->x), (int)COORD_Y(m2ptr->y));
- SetDrPt(anim_rport[back], 0xffff);
- }
- }
- }
-
- for (i=0, m1ptr = masses; i<num_mass; i++, m1ptr++)
- if (m1ptr->status & S_ALIVE)
- draw_mass(FALSE, (int)(COORD_X(m1ptr->x)), (int)(COORD_Y(m1ptr->y)),
- m1ptr->mass, (boolean)(m1ptr->status & S_SELECTED),
- (boolean)((m1ptr->status & S_FIXED)
- && !(m1ptr->status & S_TEMPFIXED)));
-
-
- if (mst.center_id != -1)
- if (((m1ptr = &masses[mst.center_id])->status & S_FIXED)
- && !(m1ptr->status & S_TEMPFIXED)) {
- /* Draw center (fixed mass) */
- int
- cx = (int)COORD_X(m1ptr->x),
- cy = (int)COORD_Y(m1ptr->y);
-
- SetAPen(anim_rport[back], 1);
- Move(anim_rport[back], cx-6, cy-12);
- Draw(anim_rport[back], cx+6, cy-12);
- Draw(anim_rport[back], cx+6, cy+1);
- Draw(anim_rport[back], cx-6, cy+1);
- Draw(anim_rport[back], cx-6, cy-12);
- }
- else {
- rad = m1ptr->radius;
-
- SetAPen(anim_rport[back], 0);
- SetAfPt(anim_rport[back], 0,1);
- RectFill(anim_rport[back],
- (int)COORD_X(m1ptr->x) - rad + 1, (int)COORD_Y(m1ptr->y) - rad + 1,
- (int)COORD_X(m1ptr->x) + rad - 1, (int)COORD_Y(m1ptr->y) + rad - 1);
- SetAPen(anim_rport[back], 1);
- }
- }
-
- /*****************************************************/
-
- static void draw_mass
- (
- boolean to_front_rp,
- int mx,
- int my,
- double mass,
- boolean selected,
- boolean fixed
- )
- {
- static __chip UWORD
- data_unsel[20] = {7936,24768,32800,32800,32800,57568,32704,7936,1024,
- 1024,1024},
- data_sel[20] = {2560,8320,32800,0,32800,0,21824,2560,1024,0,1024},
- selpattern[2] = {0x5555, 0xaaaa},
- unselpattern[2] = {0xffff, 0xffff};
- static struct Image
- UnselNailImage = {0, 0, 11,11, 1, &data_unsel[0], 0x01, 0x00, NULL},
- SelNailImage = {0, 0, 11,11, 1, &data_sel[0], 0x01, 0x00, NULL};
- struct RastPort
- *rp = to_front_rp ? anim_rport[front] : anim_rport[back];
- int
- rad = fixed ? NAIL_SIZE : mass_radius(mass);
-
- if (fixed) {
- if (mx+5 >= 0 && mx-5 <= draw_wid && my >= 0 && my-11 <= draw_ht)
- DrawImage(rp, selected ? &SelNailImage : &UnselNailImage, mx - 5, my - 11);
- } else if (mx+rad >= 0 && mx-rad <= draw_wid && my+rad >= 0 && my-rad <= draw_ht) {
- SetAfPt(rp, selected ? selpattern : unselpattern,1);
- RectFill(rp, mx - rad, my - rad, mx+rad, my+rad);
- }
- }
-
- /*****************************************************/
-
- static void draw_edit_frame(int x1, int y1, int x2, int y2)
- {
- static UWORD pattern = 0x0f0f;
-
- if (action)
- pattern = (pattern >> 15) + (pattern << 1);
- SetDrPt(anim_rport[front], pattern);
- Move(anim_rport[front], x1, y1);
- Draw(anim_rport[front], x2, y1); Draw(anim_rport[front], x2, y2);
- Draw(anim_rport[front], x1, y2); Draw(anim_rport[front], x1, y1);
- SetDrPt(anim_rport[front], 0xffff);
- }
-
- /*****************************************************/
-
- static void DoRestoreState(void)
- {
- action = FALSE;
- restore_state();
- mst = sst;
-
- redisplay_widgets();
- review_system();
- mouse_event(M_REDISPLAY, 0, 0, AnyButton, FALSE);
- }
-
- /*****************************************************/
-
- static void DoRestore(void)
- {
- action = FALSE;
- delete_all();
- mst = initst;
- init_objects();
-
- redisplay_widgets();
- review_system();
- mouse_event(M_REDISPLAY, 0, 0, AnyButton, FALSE);
- }
-
- /*****************************************************/
-