Example #1
0
File: vbl.c Project: DrItanium/moo
/* Called by the time manager task in vbl_macintosh.c */
boolean input_controller(
	void)
{
	if (input_task_active)
	{
		if((heartbeat_count-dynamic_world->tick_count) < MAXIMUM_TIME_DIFFERENCE)
		{
			if (game_is_networked) // input from network
			{
				; // all handled elsewhere now. (in network.c)
			}
			else if (replay.game_is_being_replayed) // input from recorded game file
			{
				static short phase= 0; /* When this gets to 0, update the world */

				/* Minimum replay speed is a pause. */
				if(replay.replay_speed != MINIMUM_REPLAY_SPEED)
				{
					if (replay.replay_speed > 0 || (--phase<=0))
					{
						short flag_count= MAX(replay.replay_speed, 1);
					
						if (!pull_flags_from_recording(flag_count)) // oops. silly me.
						{
							if (replay.have_read_last_chunk)
							{
								assert(get_game_state()==_game_in_progress || get_game_state()==_switch_demo);
								set_game_state(_switch_demo);
							}
						}
						else
						{	
							/* Increment the heartbeat.. */
							heartbeat_count+= flag_count;
						}
	
						/* Reset the phase-> doesn't matter if the replay speed is positive */					
						/* +1 so that replay_speed 0 is different from replay_speed 1 */
						phase= -(replay.replay_speed) + 1;
					}
				}
			}
			else // then getting input from the keyboard/mouse
			{
				long action_flags= parse_keymap();
				
				process_action_flags(local_player_index, &action_flags, 1);
				heartbeat_count++; // ba-doom
			}
		} else {
// dprintf("Out of phase.. (%d);g", heartbeat_count - dynamic_world->tick_count);
		}
	}
	
	return TRUE; // tells the time manager library to reschedule this task
}
Example #2
0
void handle_global_checkbox_toggled (GtkToggleButton *togglebutton,
				     gpointer data)
{
  if (get_game_state () != GAME_NOT_RUNNING)
    {
      GtkWidget *frame;

      frame = glade_xml_get_widget (pref_xml, "frame_mouse_props");

      gtk_widget_set_sensitive (GTK_WIDGET (frame), FALSE);

      g_signal_handlers_disconnect_by_func
                                 (togglebutton,
                                  G_CALLBACK (handle_global_checkbox_toggled),
                                  data);

      gtk_toggle_button_set_active (togglebutton,
				    !gtk_toggle_button_get_active
				    (togglebutton));
    }
  else
    {
      gnome_property_box_changed (GNOME_PROPERTY_BOX (data));
    }
}
Example #3
0
	bool Run() {
		Layout();

		bool result = false;
		if (m_dialog.run() == 0) 
		{
			result = true;
		}

		if (get_game_state() == _game_in_progress) update_game_window();
		return result;
	}
Example #4
0
void update_game_window(
	WindowPtr window,
	EventRecord *event)
{
	switch(get_game_state())
	{
		case _game_in_progress:
			assert(event);
			update_screen_window(window, event);
			break;
			
		case _display_quit_screens:
		case _display_intro_screens_for_demo:
		case _display_intro_screens:
		case _display_chapter_heading:
		case _display_prologue:
		case _display_epilogue:
		case _display_credits:
		case _display_main_menu:
			update_interface_display();
			break;
			
		case _quit_game:
		case _close_game:
		case _switch_demo:
		case _change_level:
		case _revert_game:
		case _begin_display_of_epilogue:
		case _displaying_network_game_dialogs:
			break;
	
		default:
			halt();
			break;
	}
	
	return;
}
Example #5
0
void process_game_key(
	EventRecord *event,
	short key)
{
	switch(get_game_state())
	{
		case _game_in_progress:
			if ((event->modifiers&cmdKey) && event->what==keyDown)
			{
				long menu_key= MenuKey(key);
				short menuID, menuItem;

				menuID= menu_key>>16;
				menuItem= menu_key & 0x0000ffff;
				if(menuID)
				{
					assert(menuID==mGame);

					do_menu_item_command(menuID, menuItem, 
						has_cheat_modifiers(event));
				} else {
					handle_game_key(event, key);
				}
			} else {
Example #6
0
void mouse_idle(short type)
{
	if (mouse_active) {
    
  //DCW Not present on ios
/*#ifdef __APPLE__
		// In raw mode, get unaccelerated deltas from HID system
		if (input_preferences->raw_mouse_input)
			OSX_Mouse_GetMouseMovement(&snapshot_delta_x, &snapshot_delta_y);
#endif*/
		
    
		// Calculate axis deltas
		float dx = snapshot_delta_x;
		float dy = -snapshot_delta_y;
		snapshot_delta_x = 0;
		snapshot_delta_y = 0;
    
    slurpMouseDelta(&dx, &dy);
    if(dx>0 || dy>0)
    {
      snapshot_delta_x = 0;
      snapshot_delta_y = 0;
    }
    
		// Mouse inversion
		if (TEST_FLAG(input_preferences->modifiers, _inputmod_invert_mouse))
			dy = -dy;
		
		// scale input by sensitivity
		const float sensitivityScale = 1.f / (66.f * FIXED_ONE);
		float sx = sensitivityScale * input_preferences->sens_horizontal;
		float sy = sensitivityScale * input_preferences->sens_vertical;
		switch (input_preferences->mouse_accel_type)
		{
			case _mouse_accel_classic:
				sx *= MIX(1.f, fabs(dx * sx) * 4.f, input_preferences->mouse_accel_scale);
				sy *= MIX(1.f, fabs(dy * sy) * 4.f, input_preferences->mouse_accel_scale);
				break;
			case _mouse_accel_none:
			default:
				break;
		}
		dx *= sx;
		dy *= sy;
    
      //Add post-sensitivity lost precision, in case we can use it this time around.
    dx += lost_x;
    dy += lost_y;
    
		// 1 dx unit = 1 * 2^ABSOLUTE_YAW_BITS * (360 deg / 2^ANGULAR_BITS)
		//           = 90 deg
		//
		// 1 dy unit = 1 * 2^ABSOLUTE_PITCH_BITS * (360 deg / 2^ANGULAR_BITS)
		//           = 22.5 deg
		
		// Largest dx for which both -dx and +dx can be represented in 1 action flags bitset
		float dxLimit = 0.5f - 1.f / (1<<ABSOLUTE_YAW_BITS);  // 0.4921875 dx units (~44.30 deg)
		
		// Largest dy for which both -dy and +dy can be represented in 1 action flags bitset
		float dyLimit = 0.5f - 1.f / (1<<ABSOLUTE_PITCH_BITS);  // 0.46875 dy units (~10.55 deg)
		
		dxLimit = MIN(dxLimit, input_preferences->mouse_max_speed);
		dyLimit = MIN(dyLimit, input_preferences->mouse_max_speed);
		
		dx = PIN(dx, -dxLimit, dxLimit);
		dy = PIN(dy, -dyLimit, dyLimit);
		
		snapshot_delta_yaw   = static_cast<_fixed>(dx * FIXED_ONE);
		snapshot_delta_pitch = static_cast<_fixed>(dy * FIXED_ONE);
    
    //DCW what the f**k is the point of keeping the lower 9 or whatever bits in there? They just get thrown out later anyway...
    //Lets bitshift off the unused bits, so we can add in that lost precision the next time around.
    snapshot_delta_yaw >>= (FIXED_FRACTIONAL_BITS-ABSOLUTE_YAW_BITS);
    snapshot_delta_yaw <<= (FIXED_FRACTIONAL_BITS-ABSOLUTE_YAW_BITS);
    snapshot_delta_pitch >>= (FIXED_FRACTIONAL_BITS-ABSOLUTE_PITCH_BITS);
    snapshot_delta_pitch <<= (FIXED_FRACTIONAL_BITS-ABSOLUTE_PITCH_BITS);

    //DCW Lets track how much precision we lost, so we can stuff it back into the input next time this function is called.
    lost_x = (dx * (float)FIXED_ONE) - (float)snapshot_delta_yaw;
    lost_y = (dy * (float)FIXED_ONE) - (float)snapshot_delta_pitch;
    lost_x /= (float)FIXED_ONE;
    lost_y /= (float)FIXED_ONE;
    
    short game_state = get_game_state();
    smooth_mouselook = smoothMouselookPreference() ;//&& (game_state==_game_in_progress || game_state ==_switch_demo) && (game_state==_single_player || game_state==_network_player);

 	}
}
Example #7
0
static void main_event_loop(void)
{
	uint32 last_event_poll = 0;
	short game_state;

	while ((game_state = get_game_state()) != _quit_game) {
		uint32 cur_time = SDL_GetTicks();
		bool yield_time = false;
		bool poll_event = false;

		switch (game_state) {
			case _game_in_progress:
			case _change_level:
			  if (Console::instance()->input_active() || cur_time - last_event_poll >= TICKS_BETWEEN_EVENT_POLL) {
					poll_event = true;
					last_event_poll = cur_time;
			  } else {				  
					SDL_PumpEvents ();	// This ensures a responsive keyboard control
			  }
				break;

			case _display_intro_screens:
			case _display_main_menu:
			case _display_chapter_heading:
			case _display_prologue:
			case _display_epilogue:
			case _begin_display_of_epilogue:
			case _display_credits:
			case _display_intro_screens_for_demo:
			case _display_quit_screens:
			case _displaying_network_game_dialogs:
				yield_time = interface_fade_finished();
				poll_event = true;
				break;

			case _close_game:
			case _switch_demo:
			case _revert_game:
				yield_time = poll_event = true;
				break;
		}

		if (poll_event) {
			global_idle_proc();

			while (true) {
				SDL_Event event;
				bool found_event = SDL_PollEvent(&event);

				if (yield_time) {
					// The game is not in a "hot" state, yield time to other
					// processes by calling SDL_Delay() but only try for a maximum
					// of 30ms
					int num_tries = 0;
					while (!found_event && num_tries < 3) {
						SDL_Delay(10);
						found_event = SDL_PollEvent(&event);
						num_tries++;
					}
					yield_time = false;
				} else if (!found_event)
					break;

				if (found_event)
					process_event(event); 
			}
		}

		execute_timer_tasks(SDL_GetTicks());
		idle_game_state(SDL_GetTicks());

		if (game_state == _game_in_progress && !graphics_preferences->hog_the_cpu && (TICKS_PER_SECOND - (SDL_GetTicks() - cur_time)) > 10)
		{
			SDL_Delay(1);
		}
	}
}
Example #8
0
void dump_screen(void)
{
	// Find suitable file name
	FileSpecifier file;
	int i = 0;
	do {
		char name[256];
		const char* suffix;
#ifdef HAVE_PNG
		suffix = "png";
#else
		suffix = "bmp";
#endif
		if (get_game_state() == _game_in_progress)
		{
			sprintf(name, "%s_%04d.%s", to_alnum(static_world->level_name).c_str(), i, suffix);
		}
		else
		{
			sprintf(name, "Screenshot_%04d.%s", i, suffix);
		}

		file = screenshots_dir + name;
		i++;
	} while (file.Exists());

#ifdef HAVE_PNG
	// build some nice metadata
	std::vector<IMG_PNG_text> texts;
	std::map<std::string, std::string> metadata;

	metadata["Source"] = expand_app_variables("$appName$ $appVersion$ ($appPlatform$)");

	time_t rawtime;
	time(&rawtime);
	
	char time_string[32];
	strftime(time_string, 32,"%d %b %Y %H:%M:%S +0000", gmtime(&rawtime));
	metadata["Creation Time"] = time_string;

	if (get_game_state() == _game_in_progress)
	{
		const float FLOAT_WORLD_ONE = float(WORLD_ONE);
		const float AngleConvert = 360/float(FULL_CIRCLE);

		metadata["Level"] = static_world->level_name;

		char map_file_name[256];
		FileSpecifier fs = environment_preferences->map_file;
		fs.GetName(map_file_name);
		metadata["Map File"] = map_file_name;

		if (Scenario::instance()->GetName().size())
		{
			metadata["Scenario"] = Scenario::instance()->GetName();
		}

		metadata["Polygon"] = boost::lexical_cast<std::string>(world_view->origin_polygon_index);
		metadata["X"] = boost::lexical_cast<std::string>(world_view->origin.x / FLOAT_WORLD_ONE);
		metadata["Y"] = boost::lexical_cast<std::string>(world_view->origin.y / FLOAT_WORLD_ONE);
		metadata["Z"] = boost::lexical_cast<std::string>(world_view->origin.z / FLOAT_WORLD_ONE);
		metadata["Yaw"] = boost::lexical_cast<std::string>(world_view->yaw * AngleConvert);


		short pitch = world_view->pitch;
		if (pitch > HALF_CIRCLE) pitch -= HALF_CIRCLE;
		metadata["Pitch"] = boost::lexical_cast<std::string>(pitch * AngleConvert);
	}

	for (std::map<std::string, std::string>::const_iterator it = metadata.begin(); it != metadata.end(); ++it)
	{
		IMG_PNG_text text;
		text.key = const_cast<char*>(it->first.c_str());
		text.value = const_cast<char*>(it->second.c_str());
		texts.push_back(text);
	}

	IMG_PNG_text* textp = texts.size() ? &texts[0] : 0;
#endif

	// Without OpenGL, dumping the screen is easy
	if (!MainScreenIsOpenGL()) {
//#ifdef HAVE_PNG
//		aoIMG_SavePNG(file.GetPath(), MainScreenSurface(), IMG_COMPRESS_DEFAULT, textp, texts.size());
#ifdef HAVE_SDL_IMAGE
		IMG_SavePNG(MainScreenSurface(), file.GetPath());
#else
		SDL_SaveBMP(MainScreenSurface(), file.GetPath());
#endif
		return;
	}
	
	int video_w = MainScreenPixelWidth();
	int video_h = MainScreenPixelHeight();

#ifdef HAVE_OPENGL
	// Otherwise, allocate temporary surface...
	SDL_Surface *t = SDL_CreateRGBSurface(SDL_SWSURFACE, video_w, video_h, 24,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
	  0x000000ff, 0x0000ff00, 0x00ff0000, 0);
#else
	  0x00ff0000, 0x0000ff00, 0x000000ff, 0);
#endif
	if (t == NULL)
		return;

	// ...and pixel buffer
	void *pixels = malloc(video_w * video_h * 3);
	if (pixels == NULL) {
		SDL_FreeSurface(t);
		return;
	}

	// Read OpenGL frame buffer
	glPixelStorei(GL_PACK_ALIGNMENT, 1);
	glReadPixels(0, 0, video_w, video_h, GL_RGB, GL_UNSIGNED_BYTE, pixels);
	glPixelStorei(GL_PACK_ALIGNMENT, 4);  // return to default

	// Copy pixel buffer (which is upside-down) to surface
	for (int y = 0; y < video_h; y++)
		memcpy((uint8 *)t->pixels + t->pitch * y, (uint8 *)pixels + video_w * 3 * (video_h - y - 1), video_w * 3);
	free(pixels);

	// Save surface
//#ifdef HAVE_PNG
//        aoIMG_SavePNG(file.GetPath(), t, IMG_COMPRESS_DEFAULT, textp, texts.size());
#ifdef HAVE_SDL_IMAGE
	IMG_SavePNG(t, file.GetPath());
#else
	SDL_SaveBMP(t, file.GetPath());
#endif
	SDL_FreeSurface(t);
#endif
}
Example #9
0
static void process_event(const SDL_Event &event)
{
	switch (event.type) {
	case SDL_MOUSEMOTION:
		if (get_game_state() == _game_in_progress)
		{
			mouse_moved(event.motion.xrel, event.motion.yrel);
		}
		break;
	case SDL_MOUSEWHEEL:
		if (get_game_state() == _game_in_progress)
		{
			bool up = (event.wheel.y > 0);
#if SDL_VERSION_ATLEAST(2,0,4)
			if (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED)
				up = !up;
#endif
			mouse_scroll(up);
		}
		break;
	case SDL_MOUSEBUTTONDOWN:
		if (get_game_state() == _game_in_progress) 
		{
			if (!get_keyboard_controller_status())
			{
				hide_cursor();
				validate_world_window();
				set_keyboard_controller_status(true);
			}
			else
			{
				SDL_Event e2;
				memset(&e2, 0, sizeof(SDL_Event));
				e2.type = SDL_KEYDOWN;
				e2.key.keysym.sym = SDLK_UNKNOWN;
				e2.key.keysym.scancode = (SDL_Scancode)(AO_SCANCODE_BASE_MOUSE_BUTTON + event.button.button - 1);
				process_game_key(e2);
			}
		}
		else
			process_screen_click(event);
		break;
	
	case SDL_JOYBUTTONDOWN:
		if (get_game_state() == _game_in_progress)
		{
			SDL_Event e2;
			memset(&e2, 0, sizeof(SDL_Event));
			e2.type = SDL_KEYDOWN;
			e2.key.keysym.sym = SDLK_UNKNOWN;
			e2.key.keysym.scancode = (SDL_Scancode)(AO_SCANCODE_BASE_JOYSTICK_BUTTON + event.button.button);
			process_game_key(e2);
			
		}
		break;
		
	case SDL_KEYDOWN:
		process_game_key(event);
		break;

	case SDL_TEXTINPUT:
		if (Console::instance()->input_active()) {
		    Console::instance()->textEvent(event);
		}
		break;
		
	case SDL_QUIT:
		set_game_state(_quit_game);
		break;

	case SDL_WINDOWEVENT:
		switch (event.window.event) {
			case SDL_WINDOWEVENT_FOCUS_LOST:
				if (get_game_state() == _game_in_progress && get_keyboard_controller_status() && !Movie::instance()->IsRecording()) {
					darken_world_window();
					set_keyboard_controller_status(false);
					show_cursor();
				}
				break;
			case SDL_WINDOWEVENT_EXPOSED:
#if !defined(__APPLE__) && !defined(__MACH__) // double buffering :)
#ifdef HAVE_OPENGL
				if (MainScreenIsOpenGL())
					MainScreenSwap();
				else
#endif
					update_game_window();
#endif
				break;
		}
		break;
	}
	
}
Example #10
0
static void process_game_key(const SDL_Event &event)
{
	switch (get_game_state()) {
	case _game_in_progress:
#if defined(__APPLE__) && defined(__MACH__)
		if ((event.key.keysym.mod & KMOD_GUI))
#else
		if ((event.key.keysym.mod & KMOD_ALT) || (event.key.keysym.mod & KMOD_GUI))
#endif
		{
			int item = -1;
			switch (event.key.keysym.sym) {
			case SDLK_p:
				item = iPause;
				break;
			case SDLK_s:
				item = iSave;
				break;
			case SDLK_r:
				item = iRevert;
				break;
// ZZZ: Alt+F4 is also a quit gesture in Windows
#ifdef __WIN32__
			case SDLK_F4:
#endif
			case SDLK_q:
				item = iQuitGame;
				break;
			case SDLK_RETURN:
				item = 0;
				toggle_fullscreen();
				break;
			default:
				break;
			}
			if (item > 0)
				do_menu_item_command(mGame, item, event_has_cheat_modifiers(event));
			else if (item != 0)
				handle_game_key(event);
		} else
			handle_game_key(event);
		break;
	case _display_intro_screens:
	case _display_chapter_heading:
	case _display_prologue:
	case _display_epilogue:
	case _display_credits:
	case _display_quit_screens:
		if (interface_fade_finished())
			force_game_state_change();
		else
			stop_interface_fade();
		break;

	case _display_intro_screens_for_demo:
		stop_interface_fade();
		display_main_menu();
		break;

	case _quit_game:
	case _close_game:
	case _revert_game:
	case _switch_demo:
	case _change_level:
	case _begin_display_of_epilogue:
	case _displaying_network_game_dialogs:
		break;

	case _display_main_menu: 
	{
		if (!interface_fade_finished())
			stop_interface_fade();
		int item = -1;
		switch (event.key.keysym.sym) {
		case SDLK_n:
			item = iNewGame;
			break;
		case SDLK_o:
			item = iLoadGame;
			break;
		case SDLK_g:
			item = iGatherGame;
			break;
		case SDLK_j:
			item = iJoinGame;
			break;
		case SDLK_p:
			item = iPreferences;
			break;
		case SDLK_r:
			item = iReplaySavedFilm;
			break;
		case SDLK_c:
			item = iCredits;
			break;
// ZZZ: Alt+F4 is also a quit gesture in Windows
#ifdef __WIN32__
                case SDLK_F4:
#endif
		case SDLK_q:
			item = iQuit;
			break;
		case SDLK_F9:
			dump_screen();
			break;
		case SDLK_RETURN:
#if defined(__APPLE__) && defined(__MACH__)
			if ((event.key.keysym.mod & KMOD_GUI))
#else
			if ((event.key.keysym.mod & KMOD_GUI) || (event.key.keysym.mod & KMOD_ALT))
#endif
			{
				toggle_fullscreen();
			}
			break;
		case SDLK_a:
			item = iAbout;
			break;
		default:
			break;
		}
		if (item > 0) {
			draw_menu_button_for_command(item);
			do_menu_item_command(mInterface, item, event_has_cheat_modifiers(event));
		}
		break;
	}
	}
}
Example #11
0
void preferences_show_dialog (void)
{
  GtkWidget *dlg;
  GtkWidget *radio_keyboard;
  GtkWidget *radio_mouse;
  GtkWidget *check_hide_cursor;
  GtkWidget *check_lazy_dragging;
  GtkWidget *check_score_time;
  GtkWidget *scroll_sensitivity;
  GtkAdjustment *adjustment;

  pref_xml = glade_xml_new (GLADE_FILE, "dlg_properties", NULL);
  dlg = glade_xml_get_widget (pref_xml, "dlg_properties");
  g_signal_connect (dlg, "apply",
                    G_CALLBACK (handle_apply), NULL);

  /* get widget */
  radio_keyboard = glade_xml_get_widget (pref_xml, "radio_keyboard");
  radio_mouse = glade_xml_get_widget (pref_xml, "radio_mouse");
  check_hide_cursor = glade_xml_get_widget (pref_xml, "check_hide_cursor");
  check_lazy_dragging =
    glade_xml_get_widget (pref_xml, "check_lazy_dragging");
  check_score_time = glade_xml_get_widget (pref_xml, "check_score_time");
  scroll_sensitivity = glade_xml_get_widget (pref_xml, "scroll_sensitivity");

  /* set widget state */
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_mouse),
				preferences->mouse_control);
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_keyboard),
				preferences->keyboard_control);
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_hide_cursor),
				preferences->hide_cursor);
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_lazy_dragging),
				preferences->lazy_dragging);
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_score_time),
				preferences->score_time_enabled);
  adjustment = gtk_range_get_adjustment (GTK_RANGE (scroll_sensitivity));
  gtk_adjustment_set_value (GTK_ADJUSTMENT (adjustment),
			    (preferences->mouse_sensitivity / 2));

  /* enable according to game state */
  if (get_game_state () != GAME_NOT_RUNNING)
    {
      GtkWidget *frame;
      frame = glade_xml_get_widget (pref_xml, "frame_constraints");
      gtk_widget_set_sensitive (GTK_WIDGET (frame), FALSE);
      gtk_widget_set_sensitive (GTK_WIDGET (check_score_time), FALSE);
    }

  /* if keyboard control selected, disable mouse properties */
  if (preferences->keyboard_control)
    {
      GtkWidget *frame = glade_xml_get_widget (pref_xml, "frame_mouse_props");
      gtk_widget_set_sensitive (frame, FALSE);
    }

  /* connect widgets with handlers */
  g_signal_connect (radio_mouse, "toggled",
                    G_CALLBACK (handle_mouse_ctrl_toggled), dlg);
  g_signal_connect (radio_keyboard, "toggled",
                    G_CALLBACK (handle_widget_changed), dlg);
  g_signal_connect (check_hide_cursor, "toggled",
                    G_CALLBACK (handle_widget_changed), dlg);
  g_signal_connect (check_lazy_dragging, "toggled",
                    G_CALLBACK (handle_widget_changed), dlg);
  g_signal_connect (check_score_time, "toggled",
                    G_CALLBACK (handle_global_checkbox_toggled), dlg);
  g_signal_connect (adjustment, "value-changed",
                    G_CALLBACK (handle_widget_changed), dlg);

  /* show dialog */
  gtk_widget_show (dlg);
}
Example #12
0
static void	change_panel_state(
	short player_index,
	short panel_side_index)
{
	short state, make_sound= FALSE;
	struct side_data *side= get_side_data(panel_side_index);
	struct player_data *player= get_player_data(player_index);
	struct control_panel_definition *definition= get_control_panel_definition(side->control_panel_type);

	state= GET_CONTROL_PANEL_STATUS(side);
	
	/* Do the right thing, based on the panel type.. */
	switch (definition->panel_class)
	{
		case _panel_is_oxygen_refuel:
		case _panel_is_shield_refuel:
		case _panel_is_double_shield_refuel:
		case _panel_is_triple_shield_refuel:
#ifndef VULCAN
			player->control_panel_side_index= player->control_panel_side_index==panel_side_index ? NONE : panel_side_index;
			state= get_recharge_status(panel_side_index);
			SET_CONTROL_PANEL_STATUS(side, state);
			if (!state) set_control_panel_texture(side);
#endif
			break;
		case _panel_is_computer_terminal:
#ifndef VULCAN
			if (get_game_state()==_game_in_progress && !PLAYER_HAS_CHEATED(player) && !PLAYER_HAS_MAP_OPEN(player))
			{
				/* this will handle changing levels, if necessary (i.e., if weÕre finished) */
				enter_computer_interface(player_index, side->control_panel_permutation, calculate_level_completion_state());
			}
#endif
			break;
		case _panel_is_tag_switch:
			if (definition->item==NONE || (!state && try_and_subtract_player_item(player_index, definition->item)))
			{
				state= !state;
				make_sound= set_tagged_light_statuses(side->control_panel_permutation, state);
				if (try_and_change_tagged_platform_states(side->control_panel_permutation, state)) make_sound= TRUE;
				if (!side->control_panel_permutation) make_sound= TRUE;
				if (make_sound)
				{
					SET_CONTROL_PANEL_STATUS(side, state);
					set_control_panel_texture(side);
				}
			}
			break;
		case _panel_is_light_switch:
			state= !state;
			make_sound= set_light_status(side->control_panel_permutation, state);
			break;
		case _panel_is_platform_switch:
			state= !state;
			make_sound= try_and_change_platform_state(get_polygon_data(side->control_panel_permutation)->permutation, state);
			break;
		case _panel_is_pattern_buffer:
#ifndef VULCAN
			if (dynamic_world->tick_count-player->ticks_at_last_successful_save>MINIMUM_RESAVE_TICKS &&
				player_controlling_game() && !PLAYER_HAS_CHEATED(local_player) && !game_is_networked)
			{
				play_control_panel_sound(panel_side_index, _activating_sound);
//				fade_out_background_music(30);

				/* Assume a successful save- prevents vidding of the save game key.. */
				player->ticks_at_last_successful_save= dynamic_world->tick_count;
				if (!save_game()) 
				{
					// AMR 3/12/97 vidding happens with InputSprocket with this here
					//player->ticks_at_last_successful_save= 0;
				}
//				fade_in_background_music(30);
			}
#endif
			break;

		default:
			halt();
	}
	
	if (make_sound)
	{
		play_control_panel_sound(panel_side_index, state ? _activating_sound : _deactivating_sound);
	}
	
	return;	
}