Improvements to flashing code. Overlays work right too, now.

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3249 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
Meep-Eep
2009-10-25 01:11:41 +00:00
parent a82b17e1c9
commit c02ca9e000
3 changed files with 179 additions and 57 deletions
+156 -43
View File
@@ -14,20 +14,28 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
// NOTE: A lot of this code is untested. Only highlite flash areas drawing // NOTE: A lot of this code is untested. Only highlite and overlay flash
// directly to the screen, using a cache are currently in use. // areas drawing directly to the screen, using a cache are
// currently in use.
// TODO: // TODO:
// - Add Flash_setHighlight() to change the brightness as in // - Add Flash_setHighlight() to change the brightness as in
// Flash_createHighlight(), for an already created flash area. // Flash_createHighlight(), for an already created flash area.
// - Add Flash_setOverlay() to change the overlay frame as in // - Be able to set a minimum and maximum merge factor for overlay and
// Flash_createOverlay(), for an already created flash area. // transition areas, as the numer/denom with highlights.
// - During a few frames during the sequence, the frame to be displayed
// is equal to a frame which was supplied as a parameter to the flash
// sequence (instead of generated during the sequence). It is not
// necessary to make a copy in this case. Instead, the original can be
// used. I had code to do this, but this doesn't work anymore with the
// addition of startNumer, endNumer, and denom. This code is still
// present, but disabled with BEGIN_AND_END_FRAME_EXCEPTIONS.
#define FLASH_INTERNAL #define FLASH_INTERNAL
#include "flash.h" #include "flash.h"
#include "setup.h" #include "setup.h"
// For GraphicsLock.
#include "libs/log.h" #include "libs/log.h"
#include "libs/memlib.h" #include "libs/memlib.h"
#include "libs/threadlib.h" #include "libs/threadlib.h"
@@ -66,6 +74,10 @@ Flash_create (CONTEXT gfxContext, FRAME parent)
context->original = 0; context->original = 0;
context->startNumer = 0;
context->endNumer = 1;
context->denom = 1;
context->fadeInTime = Flash_DEFAULT_FADE_IN_TIME; context->fadeInTime = Flash_DEFAULT_FADE_IN_TIME;
context->onTime = Flash_DEFAULT_ON_TIME; context->onTime = Flash_DEFAULT_ON_TIME;
context->fadeOutTime = Flash_DEFAULT_FADE_OUT_TIME; context->fadeOutTime = Flash_DEFAULT_FADE_OUT_TIME;
@@ -88,19 +100,18 @@ Flash_create (CONTEXT gfxContext, FRAME parent)
return context; return context;
} }
// 'startNumer / denom' is the brightness in the start state of the flash. // 'startNumer / denom' is the brightness in the start state of the sequence.
// 'endNumer / denom' is the brightness in the end state of the flash. // 'endNumer / denom' is the brightness in the end state of the sequence.
// These numbers are relative to the brighness of the original image. // These numbers are relative to the brighness of the original image.
FlashContext * FlashContext *
Flash_createHighlight (CONTEXT gfxContext, FRAME parent, const RECT *rect, Flash_createHighlight (CONTEXT gfxContext, FRAME parent, const RECT *rect)
int startNumer, int endNumer, int denom)
{ {
FlashContext *context = Flash_create (gfxContext, parent); FlashContext *context = Flash_create (gfxContext, parent);
if (rect == NULL) if (rect == NULL)
{ {
// No rectangle specified. Should be later with Flash_setRect() // No rectangle specified. It should be specified later with
// before calling Flash_start(). // Flash_setRect(), before calling Flash_start().
context->rect.corner.x = 0; context->rect.corner.x = 0;
context->rect.corner.y = 0; context->rect.corner.y = 0;
context->rect.extent.width = 0; context->rect.extent.width = 0;
@@ -110,10 +121,6 @@ Flash_createHighlight (CONTEXT gfxContext, FRAME parent, const RECT *rect,
context->rect = *rect; context->rect = *rect;
context->type = FlashType_highlight; context->type = FlashType_highlight;
context->u.highlight.startNumer = startNumer;
context->u.highlight.endNumer = endNumer;
context->u.highlight.denom = denom;
return context; return context;
} }
@@ -141,15 +148,25 @@ Flash_createOverlay (CONTEXT gfxContext, FRAME parent,
context->type = FlashType_overlay; context->type = FlashType_overlay;
context->u.overlay.frame = overlay; if (origin == NULL || overlay == NULL) {
GetFrameRect (overlay, &context->rect); // No overlay specified. It should be specified later with
context->rect.corner = *origin; // Flash_setOverlay(), before calling Flash_start().
context->u.overlay.frame = NULL;
context->rect.corner.x = 0;
context->rect.corner.y = 0;
context->rect.extent.width = 0;
context->rect.extent.height = 0;
} else
Flash_setOverlay (context, origin, overlay);
return context; return context;
} }
// Set the current state. 'timeSpentInState' determines how much time should
// be considered to be already spent in this state.
void void
Flash_setState (FlashContext *context, FlashState state) Flash_setState (FlashContext *context, FlashState state,
TimeCount timeSpentInState)
{ {
TimeCount now; TimeCount now;
@@ -157,10 +174,12 @@ Flash_setState (FlashContext *context, FlashState state)
context->state = state; context->state = state;
Flash_fixState (context); Flash_fixState (context);
Flash_drawCurrentFrame (context);
context->lastStateTime = now; context->lastStateTime = now - timeSpentInState;
context->lastFrameTime = now; context->lastFrameTime = now;
if (context->started)
Flash_drawCurrentFrame (context);
} }
void void
@@ -303,6 +322,43 @@ Flash_setSpeed (FlashContext *context, TimeCount fadeInTime,
context->offTime = offTime; context->offTime = offTime;
} }
// Determines how the brightness of the flashing changes.
// For highlights:
// 'startNumer / denom' is the brightness, at the start state of the flash.
// 'endNumer / denom' is the brightness, at the end state of the flash.
// For overlays:
// 'startNumer / denom' is the brightness of the image to overlay, at
// the start state of the flash.
// 'endNumer / denom' is the brightness of the image to overlay, at
// the end state of the flash.
// For transitions:
// 'startNumer / denom' is the brightness of the second image, at
// the start state of the flash; '1 - startNumer / denom' is the
// brightness of the first image at the start state of the flash.
// 'endNumer / denom' is the brightness of the second image, at
// the end state of the flash; '1 - endNumer / denom' is the
// brightness of the first image at the end state of the flash.
// These numbers are relative to the brighness of each original image.
void
Flash_setMergeFactors(FlashContext *context, int startNumer, int endNumer,
int denom) {
if (context->started)
{
Flash_drawFrame (context, context->original);
Flash_clearCache (context);
}
context->startNumer = startNumer;
context->endNumer = endNumer;
context->denom = denom;
if (context->started)
{
Flash_grabOriginal (context);
Flash_drawCurrentFrame (context);
}
}
// Set the time between updates of the flash area. // Set the time between updates of the flash area.
void void
Flash_setFrameTime (FlashContext *context, TimeCount frameTime) { Flash_setFrameTime (FlashContext *context, TimeCount frameTime) {
@@ -339,6 +395,7 @@ Flash_clearCache (FlashContext *context)
{ {
COUNT i; COUNT i;
#ifdef BEGIN_AND_END_FRAME_EXCEPTIONS
if (context->type == FlashType_transition || if (context->type == FlashType_transition ||
context->type == FlashType_overlay) context->type == FlashType_overlay)
{ {
@@ -352,6 +409,7 @@ Flash_clearCache (FlashContext *context)
// we shouldn't free it. // we shouldn't free it.
context->cache[context->cacheSize - 1] = (FRAME) 0; context->cache[context->cacheSize - 1] = (FRAME) 0;
} }
#endif /* BEGIN_AND_END_FRMAE_EXCEPTIONS */
for (i = 0; i < context->cacheSize; i++) for (i = 0; i < context->cacheSize; i++)
{ {
@@ -366,6 +424,8 @@ Flash_clearCache (FlashContext *context)
void void
Flash_setRect (FlashContext *context, const RECT *rect) Flash_setRect (FlashContext *context, const RECT *rect)
{ {
assert(context->type == FlashType_highlight);
if (context->started) if (context->started)
{ {
Flash_drawFrame (context, context->original); Flash_drawFrame (context, context->original);
@@ -390,20 +450,49 @@ Flash_getRect (FlashContext *context, RECT *rect)
*rect = context->rect; *rect = context->rect;
} }
void
Flash_setOverlay (FlashContext *context, const POINT *origin,
FRAME overlay) {
assert(context->type = FlashType_overlay);
if (context->started)
{
Flash_drawFrame (context, context->original);
Flash_clearCache (context);
}
context->u.overlay.frame = overlay;
GetFrameRect (overlay, &context->rect);
context->rect.corner.x += origin->x;
context->rect.corner.y += origin->y;
if (context->started)
{
Flash_grabOriginal (context);
Flash_drawCurrentFrame (context);
}
}
// Call before you update the graphics in the currently flashing area. // Call before you update the graphics in the currently flashing area.
void void
Flash_preUpdate (FlashContext *context) Flash_preUpdate (FlashContext *context)
{ {
Flash_drawFrame (context, context->original); if (context->started)
Flash_clearCache (context); {
Flash_drawFrame (context, context->original);
Flash_clearCache (context);
}
} }
// Call after you update the graphics in the currently flashing area. // Call after you update the graphics in the currently flashing area.
void void
Flash_postUpdate (FlashContext *context) Flash_postUpdate (FlashContext *context)
{ {
Flash_grabOriginal (context); if (context->started)
Flash_drawCurrentFrame (context); {
Flash_grabOriginal (context);
Flash_drawCurrentFrame (context);
}
} }
// Pre: context->original has been initialised. // Pre: context->original has been initialised.
@@ -482,16 +571,14 @@ Flash_blendFraction (FlashContext *context, int numer, int denom,
// F1 = context->u.highlight.endNumer / context->u.highlight.denom // F1 = context->u.highlight.endNumer / context->u.highlight.denom
// P = *numer / *denom // P = *numer / *denom
// R = P * F1 + (1 - P) * F0 // R = P * F1 + (1 - P) * F0
// = numer * context->u.highlight.endNumer / // = numer * context->endNumer / (denom * context->denom) +
// (denom * context->u.highlight.denom) + // (denom - numer) * startNumer / denom * context->denom
// (denom - numer) * u.highlight.startNumer /
// denom * context->u.highlight.denom
assert (numer >= 0 && numer <= denom); assert (numer >= 0 && numer <= denom);
*resNumer = numer * context->u.highlight.endNumer + *resNumer = numer * context->endNumer +
(denom - numer) * context->u.highlight.startNumer; (denom - numer) * context->startNumer;
*resDenom = denom * context->u.highlight.denom; *resDenom = denom * context->denom;
} }
static void static void
@@ -499,18 +586,18 @@ Flash_makeFrame (FlashContext *context, FRAME dest, RECT *destRect,
int numer, int denom) int numer, int denom)
{ {
RECT orgRect; RECT orgRect;
int blendedNumer;
int blendedDenom;
orgRect.corner.x = 0; orgRect.corner.x = 0;
orgRect.corner.y = 0; orgRect.corner.y = 0;
orgRect.extent = context->rect.extent; orgRect.extent = context->rect.extent;
Flash_blendFraction (context, numer, denom, &blendedNumer, &blendedDenom);
switch (context->type) { switch (context->type) {
case FlashType_highlight: case FlashType_highlight:
{ {
int blendedNumer;
int blendedDenom;
Flash_blendFraction (context, numer, denom, &blendedNumer,
&blendedDenom);
arith_frame_blit (context->original, &orgRect, dest, destRect, arith_frame_blit (context->original, &orgRect, dest, destRect,
blendedNumer, blendedDenom); blendedNumer, blendedDenom);
break; break;
@@ -528,21 +615,43 @@ Flash_makeFrame (FlashContext *context, FRAME dest, RECT *destRect,
final = context->original; final = context->original;
arith_frame_blit (first, &orgRect, dest, destRect, arith_frame_blit (first, &orgRect, dest, destRect,
denom - numer, denom); blendedDenom - blendedNumer, blendedDenom);
arith_frame_blit (final, &orgRect, dest, destRect, arith_frame_blit (final, &orgRect, dest, destRect,
numer, -denom); blendedNumer, -blendedDenom);
break; break;
} }
case FlashType_overlay: case FlashType_overlay:
arith_frame_blit (context->original, &orgRect, dest, destRect, {
denom, denom); int addOrSubtractNumer;
int addOrSubtractDenom;
if (blendedNumer < 0)
{
// Subtractive blit.
blendedNumer = -blendedNumer;
addOrSubtractNumer = -1;
addOrSubtractDenom = 1;
}
else
{
// Additive blit.
addOrSubtractNumer = 1;
addOrSubtractDenom = -1;
}
// Draw the overlay at partial strength:
arith_frame_blit (context->u.overlay.frame, &orgRect, arith_frame_blit (context->u.overlay.frame, &orgRect,
dest, destRect, numer, -denom); dest, destRect, blendedNumer, blendedDenom);
// Merge the original in at full strength:
// For additive blit: dest = context->original + dest
// For subtractive blit blit: dest = context->original - dest
arith_frame_blit (context->original, &orgRect, dest, destRect,
addOrSubtractNumer, addOrSubtractDenom);
break; break;
}
} }
} }
// Prepare an entry in the cache. // Prepare an entry in the cache.
static inline void static inline void
Flash_prepareCacheFrame (FlashContext *context, COUNT index) Flash_prepareCacheFrame (FlashContext *context, COUNT index)
@@ -550,6 +659,7 @@ Flash_prepareCacheFrame (FlashContext *context, COUNT index)
if (context->cache[index] != (FRAME) 0) if (context->cache[index] != (FRAME) 0)
return; return;
#ifdef BEGIN_AND_END_FRAME_EXCEPTIONS
if (index == 0 && context->type == FlashType_overlay) if (index == 0 && context->type == FlashType_overlay)
context->cache[index] = context->original; context->cache[index] = context->original;
else if (index == 0 && context->type == FlashType_transition) else if (index == 0 && context->type == FlashType_transition)
@@ -560,6 +670,7 @@ Flash_prepareCacheFrame (FlashContext *context, COUNT index)
context->cache[index] = context->u.transition.final != (FRAME) 0 ? context->cache[index] = context->u.transition.final != (FRAME) 0 ?
context->u.transition.final : context->original; context->u.transition.final : context->original;
else else
#endif /* BEGIN_AND_END_FRMAE_EXCEPTIONS */
{ {
context->cache[index] = CaptureDrawable (CreateDrawable (WANT_PIXMAP, context->cache[index] = CaptureDrawable (CreateDrawable (WANT_PIXMAP,
context->rect.extent.width, context->rect.extent.height, 1)); context->rect.extent.width, context->rect.extent.height, 1));
@@ -606,6 +717,7 @@ Flash_drawCacheFrame (FlashContext *context, COUNT index)
static inline void static inline void
Flash_drawUncachedFrame (FlashContext *context, int numer, int denom) Flash_drawUncachedFrame (FlashContext *context, int numer, int denom)
{ {
#ifdef BEGIN_AND_END_FRAME_EXCEPTIONS
// 'lastFrameIndex' is 0 for the first image, 1 for the final // 'lastFrameIndex' is 0 for the first image, 1 for the final
// image, and 2 otherwise. // image, and 2 otherwise.
@@ -638,6 +750,7 @@ Flash_drawUncachedFrame (FlashContext *context, int numer, int denom)
} }
context->lastFrameIndex = 2; context->lastFrameIndex = 2;
#endif /* BEGIN_AND_END_FRMAE_EXCEPTIONS */
if (context->parent == NULL) if (context->parent == NULL)
{ {
+20 -12
View File
@@ -20,8 +20,7 @@
/* /*
* This code can draw three kinds of flashing areas. * This code can draw three kinds of flashing areas.
* - a rectangular highlight area. The brightness of the area oscilates. * - a rectangular highlight area. The brightness of the area oscilates.
* - an overlay; an image is overlayed over an area, with oscilating * - an overlay; an image is laid over an area, with oscilating brightness.
* brightness.
* - a transition/cross-fade between two images. * - a transition/cross-fade between two images.
* *
* NB. The graphics lock should not be held when any of the Flash functions * NB. The graphics lock should not be held when any of the Flash functions
@@ -32,8 +31,11 @@
* *
* // We create the flash context; it is used to manipulate the flash * // We create the flash context; it is used to manipulate the flash
* // rectangle while it exists. * // rectangle while it exists.
* FlashContext *fc = Flash_createHighlight (context, (FRAME) 0, rect, * FlashContext *fc = Flash_createHighlight (context, (FRAME) 0, rect);
* 2, 3, 2); *
* // Specify how bright the flash is at the beginning and ending of the
* // sequence.
* Flash_setMergeFactors(context, 2, 3, 2);
* *
* // We change the flashing speed from the defaults. * // We change the flashing speed from the defaults.
* Flash_setSpeed (ONE_SECOND, ONE_SECOND, ONE_SECOND, ONE_SECOND); * Flash_setSpeed (ONE_SECOND, ONE_SECOND, ONE_SECOND, ONE_SECOND);
@@ -116,12 +118,6 @@ struct FlashContext {
union { union {
struct { struct {
int startNumer;
// Numerator for the brightness for the on state.
int endNumer;
// Numerator for the brightness for the off state.
int denom;
// Denominator for the brightness.
} highlight; } highlight;
struct { struct {
FRAME first; FRAME first;
@@ -136,6 +132,13 @@ struct FlashContext {
} overlay; } overlay;
} u; } u;
int startNumer;
// Numerator for the merge factor for the on state.
int endNumer;
// Numerator for the merge factor for the off state.
int denom;
// Denominator for the merge factor.
TimeCount fadeInTime; TimeCount fadeInTime;
TimeCount onTime; TimeCount onTime;
TimeCount fadeOutTime; TimeCount fadeOutTime;
@@ -173,13 +176,14 @@ struct FlashContext {
FlashContext *Flash_createHighlight (CONTEXT gfxContext, FRAME parent, FlashContext *Flash_createHighlight (CONTEXT gfxContext, FRAME parent,
const RECT *rect, int startNumer, int endNumer, int denom); const RECT *rect);
FlashContext *Flash_createTransition (CONTEXT gfxContext, FRAME parent, FlashContext *Flash_createTransition (CONTEXT gfxContext, FRAME parent,
const POINT *origin, FRAME first, FRAME final); const POINT *origin, FRAME first, FRAME final);
FlashContext *Flash_createOverlay (CONTEXT gfxContext, FRAME parent, FlashContext *Flash_createOverlay (CONTEXT gfxContext, FRAME parent,
const POINT *origin, FRAME overlay); const POINT *origin, FRAME overlay);
void Flash_setState (FlashContext *context, FlashState state); void Flash_setState (FlashContext *context, FlashState state,
TimeCount timeSpentInState);
void Flash_start (FlashContext *context); void Flash_start (FlashContext *context);
void Flash_terminate (FlashContext *context); void Flash_terminate (FlashContext *context);
void Flash_pause (FlashContext *context); void Flash_pause (FlashContext *context);
@@ -187,10 +191,14 @@ void Flash_continue (FlashContext *context);
void Flash_process (FlashContext *context); void Flash_process (FlashContext *context);
void Flash_setSpeed (FlashContext *context, TimeCount fadeInTime, void Flash_setSpeed (FlashContext *context, TimeCount fadeInTime,
TimeCount onTime, TimeCount fadeOutTime, TimeCount offTime); TimeCount onTime, TimeCount fadeOutTime, TimeCount offTime);
void Flash_setMergeFactors(FlashContext *context, int startNumer,
int endNumer, int denom);
void Flash_setFrameTime (FlashContext *context, TimeCount frameTime); void Flash_setFrameTime (FlashContext *context, TimeCount frameTime);
TimeCount Flash_nextTime (FlashContext *context); TimeCount Flash_nextTime (FlashContext *context);
void Flash_setRect (FlashContext *context, const RECT *rect); void Flash_setRect (FlashContext *context, const RECT *rect);
void Flash_getRect (FlashContext *context, RECT *rect); void Flash_getRect (FlashContext *context, RECT *rect);
void Flash_setOverlay(FlashContext *context, const POINT *origin,
FRAME overlay);
void Flash_preUpdate (FlashContext *context); void Flash_preUpdate (FlashContext *context);
void Flash_postUpdate (FlashContext *context); void Flash_postUpdate (FlashContext *context);
void Flash_setCacheSize (FlashContext *context, COUNT size); void Flash_setCacheSize (FlashContext *context, COUNT size);
+2 -1
View File
@@ -582,7 +582,8 @@ GetMeleeStarShips (COUNT playerMask, HSTARSHIP *ships)
#endif #endif
gmstate.player[playerI].flashContext = gmstate.player[playerI].flashContext =
Flash_createHighlight (ScreenContext, (FRAME) 0, NULL, Flash_createHighlight (ScreenContext, (FRAME) 0, NULL);
Flash_setMergeFactors (gmstate.player[playerI].flashContext,
2, 3, 2); 2, 3, 2);
Flash_setFrameTime (gmstate.player[playerI].flashContext, Flash_setFrameTime (gmstate.player[playerI].flashContext,
ONE_SECOND / 16); ONE_SECOND / 16);