diff options
| author | Eugene Sandulenko | 2004-04-12 21:40:49 +0000 | 
|---|---|---|
| committer | Eugene Sandulenko | 2004-04-12 21:40:49 +0000 | 
| commit | f3d340fb0ce72b9db59b8c701153bc82b595f75e (patch) | |
| tree | bf250cf3a1e6aee35c7f40d766994b0c2c188e5c /saga/events.cpp | |
| parent | 0a0a0c7b0609d8774cef849e7511e7b21d12c5db (diff) | |
| download | scummvm-rg350-f3d340fb0ce72b9db59b8c701153bc82b595f75e.tar.gz scummvm-rg350-f3d340fb0ce72b9db59b8c701153bc82b595f75e.tar.bz2 scummvm-rg350-f3d340fb0ce72b9db59b8c701153bc82b595f75e.zip  | |
WIP for SAGA engine.
 o text formatting is not consistent with rules, just indent utility is too
   dumb for that
 o it does not use OSystem, i.e. it runs on direct SDL calls
 o it may not even compile on your box
 o if you enable it, expect zillions of warnings
 o no sound
Now it runs ITE intro as reinherit did
svn-id: r13564
Diffstat (limited to 'saga/events.cpp')
| -rw-r--r-- | saga/events.cpp | 613 | 
1 files changed, 613 insertions, 0 deletions
diff --git a/saga/events.cpp b/saga/events.cpp new file mode 100644 index 0000000000..6dcfe4ff06 --- /dev/null +++ b/saga/events.cpp @@ -0,0 +1,613 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2004 The ScummVM project + * + * The ReInherit Engine is (C)2000-2003 by Daniel Balsom. + * + * This program 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 2 + * of the License, or (at your option) any later version. + + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. + * + * $Header$ + * + */ +/* + + Description:    +  +    Event management module + + Notes:  +*/ + +#include "reinherit.h" + +#include "yslib.h" + +/* + * Uses the following modules: +\*--------------------------------------------------------------------------*/ +#include "animation_mod.h" +#include "console_mod.h" +#include "scene_mod.h" +#include "gfx_mod.h" +#include "interface_mod.h" +#include "text_mod.h" +#include "palanim_mod.h" +#include "render_mod.h" +#include "sndres_mod.h" + +/* + * Begin module +\*--------------------------------------------------------------------------*/ +#include "events_mod.h" +#include "events.h" + +namespace Saga { + +static YS_DL_LIST *EventList; + +int EVENT_Init(void) +{ +	R_printf(R_STDOUT, "Initializing event subsystem...\n"); + +	EventList = ys_dll_create(); + +	return (EventList != NULL) ? R_SUCCESS : R_FAILURE; +} + +int EVENT_Shutdown(void) +{ +	R_printf(R_STDOUT, "Shutting down event subsystem...\n"); + +	EVENT_FreeList(); + +	return R_SUCCESS; +} + +int EVENT_HandleEvents(long msec) +/*--------------------------------------------------------------------------*\ + * Function to process event list once per frame.  + * First advances event times, then processes each event with the appropriate + *  handler depending on the type of event. +\*--------------------------------------------------------------------------*/ +{ +	YS_DL_NODE *walk_node; +	YS_DL_NODE *next_node; + +	R_EVENT *event_p; + +	long delta_time; +	int result; + +	/* Advance event times +	 * \*------------------------------------------------------------- */ +	ProcessEventTime(msec); + +	/* Process each event in list +	 * \*------------------------------------------------------------- */ +	for (walk_node = ys_dll_head(EventList); +	    walk_node != NULL; walk_node = next_node) { + +		event_p = (R_EVENT *)ys_dll_get_data(walk_node); + +		/* Save next event in case current event is handled and removed */ +		next_node = ys_dll_next(walk_node); + +		/* Call the appropriate event handler for the specific event type */ +		switch (event_p->type) { + +		case R_ONESHOT_EVENT: +			result = HandleOneShot(event_p); +			break; + +		case R_CONTINUOUS_EVENT: +			result = HandleContinuous(event_p); +			break; + +		case R_INTERVAL_EVENT: +			result = HandleInterval(event_p); +			break; + +		default: +			result = R_EVENT_INVALIDCODE; +			R_printf(R_STDERR, +			    "Invalid event code encountered.\n"); +			break; +		} + +		/* Process the event appropriately based on result code from  +		 * handler */ +		if ((result == R_EVENT_DELETE) || +		    (result == R_EVENT_INVALIDCODE)) { + +			/* If there is no event chain, delete the base event. */ +			if (event_p->chain == NULL) { +				ys_dll_delete(walk_node); +			} else { +				/* If there is an event chain present, move the next event  +				 * in the chain up, adjust it by the previous delta time,  +				 * and reprocess the event by adjusting next_node. */ +				delta_time = event_p->time; + +				ys_dll_replace(walk_node, event_p->chain, +				    sizeof *event_p); + +				event_p = (R_EVENT *)ys_dll_get_data(walk_node); +				event_p->time += delta_time; + +				next_node = walk_node; +			} +		} else if (result == R_EVENT_BREAK) { + +			break; +		} + +	}			/* end for () */ + +	return R_SUCCESS; +} + +int HandleContinuous(R_EVENT * event) +{ + +	double event_pc = 0.0;	/* Event completion percentage */ +	int event_done = 0; + +	R_BUFFER_INFO buf_info; +	SCENE_BGINFO bg_info; +	R_SURFACE *back_buf; + +	event_pc = ((double)event->duration - event->time) / event->duration; + +	if (event_pc >= 1.0) { +		/* Cap percentage to 100 */ +		event_pc = 1.0; +		event_done = 1; +	} + +	if (event_pc < 0.0) { +		/* Event not signaled, skip it */ +		return R_EVENT_CONTINUE; +	} else if (!(event->code & R_SIGNALED)) { +		/* Signal event */ +		event->code |= R_SIGNALED; +		event_pc = 0.0; +	} + +	switch (event->code & R_EVENT_MASK) { + +	case R_PAL_EVENT: + +		switch (event->op) { + +		case EVENT_BLACKTOPAL: + +			back_buf = SYSGFX_GetBackBuffer(); + +			SYSGFX_BlackToPal(back_buf, (PALENTRY *)event->data, event_pc); +			break; + +		case EVENT_PALTOBLACK: + +			back_buf = SYSGFX_GetBackBuffer(); + +			SYSGFX_PalToBlack(back_buf, (PALENTRY *)event->data, event_pc); +			break; + +		default: +			break; +		}		/* end switch() */ + +		break; + +	case R_TRANSITION_EVENT: + +		switch (event->op) { + +		case EVENT_DISSOLVE: + +			RENDER_GetBufferInfo(&buf_info); +			SCENE_GetBGInfo(&bg_info); + +			TRANSITION_Dissolve(buf_info.r_bg_buf, +			    buf_info.r_bg_buf_w, +			    buf_info.r_bg_buf_h, +			    buf_info.r_bg_buf_w, +			    bg_info.bg_buf, bg_info.bg_p, 0, event_pc); + +			break; + +		default: +			break; +		} + +		break; + +	case R_CONSOLE_EVENT: + +		switch (event->op) { + +		case EVENT_ACTIVATE: + +			CON_DropConsole(event_pc); +			break; + +		case EVENT_DEACTIVATE: + +			CON_RaiseConsole(event_pc); +			break; + +		default: +			break; +		} + +		break; + +	default: +		break; + +	}			/* end switch( event->event_code ) */ + +	if (event_done) { +		return R_EVENT_DELETE; +	} + +	return R_EVENT_CONTINUE; +} + +static int HandleOneShot(R_EVENT * event) +{ + +	R_SURFACE *back_buf; + +	static SCENE_BGINFO bginfo; + +	if (event->time > 0) { +		return R_EVENT_CONTINUE; +	} + +	/* Event has been signaled */ + +	switch (event->code & R_EVENT_MASK) { + +	case R_TEXT_EVENT: + +		switch (event->op) { + +		case EVENT_DISPLAY: + +			TEXT_SetDisplay((R_TEXTLIST_ENTRY *)event->data, 1); +			break; + +		case EVENT_REMOVE: +			{ +				R_SCENE_INFO scene_info; + +				SCENE_GetInfo(&scene_info); + +				TEXT_DeleteEntry(scene_info.text_list, +								 (R_TEXTLIST_ENTRY *)event->data); +			} +			break; + +		default: +			break; +		} + +		break; + +	case R_VOICE_EVENT: + +		SND_PlayVoice(event->param); +		break; + +	case R_MUSIC_EVENT: + +		SYSMUSIC_Play(event->param, event->param2); +		break; + +	case R_BG_EVENT: +		{ +			R_BUFFER_INFO rbuf_info; +			R_POINT bg_pt; + +			if (SCENE_GetMode() == R_SCENE_MODE_NORMAL) { + +				back_buf = SYSGFX_GetBackBuffer(); + +				RENDER_GetBufferInfo(&rbuf_info); +				SCENE_GetBGInfo(&bginfo); + +				bg_pt.x = bginfo.bg_x; +				bg_pt.y = bginfo.bg_y; + +				GFX_BufToBuffer(rbuf_info.r_bg_buf, +				    rbuf_info.r_bg_buf_w, +				    rbuf_info.r_bg_buf_h, +				    bginfo.bg_buf, +				    bginfo.bg_w, bginfo.bg_h, NULL, &bg_pt); + +				if (event->param == SET_PALETTE) { + +					PALENTRY *pal_p; + +					SCENE_GetBGPal(&pal_p); +					SYSGFX_SetPalette(back_buf, pal_p); +				} +			} +		} +		break; + +	case R_ANIM_EVENT: + +		switch (event->op) { + +		case EVENT_FRAME: + +			ANIM_Play(event->param, event->time); +			break; + +		default: +			break; +		} + +		break; + +	case R_SCENE_EVENT: + +		switch (event->op) { + +		case EVENT_END: + +			SCENE_Next(); + +			return R_EVENT_BREAK; +			break; + +		default: +			break; +		} + +		break; + +	case R_PALANIM_EVENT: + +		switch (event->op) { + +		case EVENT_CYCLESTART: + +			PALANIM_CycleStart(); +			break; + +		case EVENT_CYCLESTEP: + +			PALANIM_CycleStep(event->time); +			break; + +		default: +			break; +		} +		break; + +	case R_INTERFACE_EVENT: + +		switch (event->op) { + +		case EVENT_ACTIVATE: + +			INTERFACE_Activate(); +			break; + +		default: +			break; +		} + +		break; + +	default: +		break; + +	}			/* end switch( event->code ) */ + +	return R_EVENT_DELETE; +} + +static int HandleInterval(R_EVENT * event) +{ +	YS_IGNORE_PARAM(event); + +	return R_EVENT_DELETE; +} + +R_EVENT *EVENT_Queue(R_EVENT * event) +/*--------------------------------------------------------------------------*\ + * Schedules an event in the event list; returns a pointer to the scheduled + * event suitable for chaining if desired. +\*--------------------------------------------------------------------------*/ +{ +	YS_DL_NODE *new_node; +	R_EVENT *queued_event; + +	event->chain = NULL; + +	new_node = ys_dll_add_tail(EventList, event, sizeof *event); + +	if (new_node == NULL) { +		return NULL; +	} + +	queued_event = (R_EVENT *)ys_dll_get_data(new_node); + +	InitializeEvent(queued_event); + +	return queued_event; +} + +R_EVENT *EVENT_Chain(R_EVENT * head_event, R_EVENT * add_event) +/*--------------------------------------------------------------------------*\ + * Places a 'add_event' on the end of an event chain given by 'head_event' + * (head_event may be in any position in the event chain) +\*--------------------------------------------------------------------------*/ +{ +	R_EVENT *walk_event; +	R_EVENT *new_event; + +	/* Allocate space for new event */ +	new_event = (R_EVENT *)malloc(sizeof *new_event); +	if (new_event == NULL) { +		return NULL; +	} + +	/* Copy event data to new event */ +	*new_event = *add_event; + +	/* Walk to end of chain */ +	for (walk_event = head_event; +	    walk_event->chain != NULL; walk_event = walk_event->chain) { + +		continue; +	} + +	/* Place new event */ +	walk_event->chain = new_event; +	new_event->chain = NULL; + +	InitializeEvent(new_event); + +	return new_event; +} + +static int InitializeEvent(R_EVENT * event) +{ + +	switch (event->type) { + +	case R_ONESHOT_EVENT: +		break; + +	case R_CONTINUOUS_EVENT: +		event->time += event->duration; +		break; + +	case R_INTERVAL_EVENT: +		break; + +	default: +		return R_FAILURE; +		break; +	} + +	return R_SUCCESS; +} + +int EVENT_ClearList(void) +/*--------------------------------------------------------------------------*\ + * Removes all events from the list except NODESTROY (engine) events +\*--------------------------------------------------------------------------*/ +{ +	YS_DL_NODE *walk_node; +	YS_DL_NODE *next_node; + +	struct R_EVENT_tag *chain_walk; +	struct R_EVENT_tag *next_chain; + +	R_EVENT *event_p; + +	/* Walk down event list */ +	for (walk_node = ys_dll_head(EventList); +	    walk_node != NULL; walk_node = next_node) { + +		next_node = ys_dll_next(walk_node); +		event_p = (R_EVENT *)ys_dll_get_data(walk_node); + +		/* Only remove events not marked R_NODESTROY (engine events) */ +		if (!(event_p->code & R_NODESTROY)) { + +			/* Remove any events chained off this one */ +			for (chain_walk = event_p->chain; +			    chain_walk != NULL; chain_walk = next_chain) { + +				next_chain = chain_walk->chain; +				free(chain_walk); +			} + +			ys_dll_delete(walk_node); +		} +	} + +	return R_SUCCESS; +} + +int EVENT_FreeList(void) +/*--------------------------------------------------------------------------*\ + * Removes all events from the list (even R_NODESTROY) +\*--------------------------------------------------------------------------*/ +{ +	YS_DL_NODE *walk_node; +	YS_DL_NODE *next_node; + +	struct R_EVENT_tag *chain_walk; +	struct R_EVENT_tag *next_chain; + +	R_EVENT *event_p; + +	/* Walk down event list */ +	for (walk_node = ys_dll_head(EventList); +	    walk_node != NULL; walk_node = next_node) { + +		event_p = (R_EVENT *)ys_dll_get_data(walk_node); + +		/* Remove any events chained off current node */ +		for (chain_walk = event_p->chain; +		    chain_walk != NULL; chain_walk = next_chain) { + +			next_chain = chain_walk->chain; +			free(chain_walk); +		} + +		/* Delete current node */ +		next_node = ys_dll_next(walk_node); +		ys_dll_delete(walk_node); +	} + +	return R_SUCCESS; +} + +static int ProcessEventTime(long msec) +/*--------------------------------------------------------------------------*\ + * Walks down the event list, updating event times by 'msec'. +\*--------------------------------------------------------------------------*/ +{ +	YS_DL_NODE *walk_node; +	R_EVENT *event_p; + +	uint event_count = 0; + +	for (walk_node = ys_dll_head(EventList); +	    walk_node != NULL; walk_node = ys_dll_next(walk_node)) { + +		event_p = (R_EVENT *)ys_dll_get_data(walk_node); +		event_p->time -= msec; + +		event_count++; + +		if (event_count > R_EVENT_WARNINGCOUNT) { +			R_printf(R_STDERR, +			    "WARNING: Event list exceeds %u.\n"); +		} +	} + +	return R_SUCCESS; +} + +} // End of namespace Saga  | 
