Refactored BitmapImageSource (moved core functionality into a new class - BitmapImage). Changed BitmapTransitionSource to use BitmapImage - implements #102
This commit is contained in:
parent
6a46761c3c
commit
96e400fd91
@ -62,7 +62,8 @@
|
|||||||
<WindowsSDK80Path Condition="('$(WindowsSDK80Path)'=='')And(!Exists('C:\Program Files (x86)\Windows Kits\8.0\'))">$(WindowsSdkDir)</WindowsSDK80Path>
|
<WindowsSDK80Path Condition="('$(WindowsSDK80Path)'=='')And(!Exists('C:\Program Files (x86)\Windows Kits\8.0\'))">$(WindowsSdkDir)</WindowsSDK80Path>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Label="MSBuild Dynamic Preprocessor Definitions">
|
<PropertyGroup Label="MSBuild Dynamic Preprocessor Definitions">
|
||||||
<DynamicDefines> </DynamicDefines>
|
<DynamicDefines>
|
||||||
|
</DynamicDefines>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
|
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
|
||||||
@ -252,6 +253,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="Source\API.cpp" />
|
<ClCompile Include="Source\API.cpp" />
|
||||||
<ClCompile Include="Source\BandwidthAnalysis.cpp" />
|
<ClCompile Include="Source\BandwidthAnalysis.cpp" />
|
||||||
|
<ClCompile Include="Source\BitmapImage.cpp" />
|
||||||
<ClCompile Include="Source\BitmapImageSource.cpp" />
|
<ClCompile Include="Source\BitmapImageSource.cpp" />
|
||||||
<ClCompile Include="Source\BitmapTransitionSource.cpp" />
|
<ClCompile Include="Source\BitmapTransitionSource.cpp" />
|
||||||
<ClCompile Include="Source\BlankAudioPlayback.cpp" />
|
<ClCompile Include="Source\BlankAudioPlayback.cpp" />
|
||||||
@ -300,6 +302,7 @@
|
|||||||
<ClCompile Include="Source\WindowStuff.cpp" />
|
<ClCompile Include="Source\WindowStuff.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="Source\BitmapImage.h" />
|
||||||
<ClInclude Include="Source\CodeTokenizer.h" />
|
<ClInclude Include="Source\CodeTokenizer.h" />
|
||||||
<ClInclude Include="Source\CrashDumpHandler.h" />
|
<ClInclude Include="Source\CrashDumpHandler.h" />
|
||||||
<ClInclude Include="Source\D3D10System.h" />
|
<ClInclude Include="Source\D3D10System.h" />
|
||||||
|
@ -145,6 +145,9 @@
|
|||||||
<ClCompile Include="Source\Encoder_NVENC.cpp">
|
<ClCompile Include="Source\Encoder_NVENC.cpp">
|
||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Source\BitmapImage.cpp">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Source\D3D10System.h">
|
<ClInclude Include="Source\D3D10System.h">
|
||||||
@ -186,6 +189,9 @@
|
|||||||
<ClInclude Include="Source\Settings.h">
|
<ClInclude Include="Source\Settings.h">
|
||||||
<Filter>Headers</Filter>
|
<Filter>Headers</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Source\BitmapImage.h">
|
||||||
|
<Filter>Headers</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="cursor1.cur">
|
<None Include="cursor1.cur">
|
||||||
|
284
Source/BitmapImage.cpp
Normal file
284
Source/BitmapImage.cpp
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
#include "BitmapImage.h"
|
||||||
|
|
||||||
|
void *BI_def_bitmap_create(int width, int height) {return Allocate(width * height * 4);}
|
||||||
|
void BI_def_bitmap_set_opaque(void *bitmap, BOOL opaque) {}
|
||||||
|
BOOL BI_def_bitmap_test_opaque(void *bitmap) {return false;}
|
||||||
|
unsigned char *BI_def_bitmap_get_buffer(void *bitmap) {return (unsigned char*)bitmap;}
|
||||||
|
void BI_def_bitmap_destroy(void *bitmap) {Free(bitmap);}
|
||||||
|
void BI_def_bitmap_modified(void *bitmap) {}
|
||||||
|
|
||||||
|
|
||||||
|
BitmapImage::BitmapImage()
|
||||||
|
{
|
||||||
|
bitmap_callbacks.bitmap_create = BI_def_bitmap_create;
|
||||||
|
bitmap_callbacks.bitmap_destroy = BI_def_bitmap_destroy;
|
||||||
|
bitmap_callbacks.bitmap_get_buffer = BI_def_bitmap_get_buffer;
|
||||||
|
bitmap_callbacks.bitmap_modified = BI_def_bitmap_modified;
|
||||||
|
bitmap_callbacks.bitmap_set_opaque = BI_def_bitmap_set_opaque;
|
||||||
|
bitmap_callbacks.bitmap_test_opaque = BI_def_bitmap_test_opaque;
|
||||||
|
}
|
||||||
|
|
||||||
|
BitmapImage::~BitmapImage()
|
||||||
|
{
|
||||||
|
if(bIsAnimatedGif)
|
||||||
|
{
|
||||||
|
gif_finalise(&gif);
|
||||||
|
Free(animationFrameCache);
|
||||||
|
Free(animationFrameData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lpGifData)
|
||||||
|
Free(lpGifData);
|
||||||
|
|
||||||
|
EnableFileMonitor(false);
|
||||||
|
|
||||||
|
delete texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void BitmapImage::CreateErrorTexture(void)
|
||||||
|
{
|
||||||
|
LPBYTE textureData = (LPBYTE)Allocate(32*32*4);
|
||||||
|
msetd(textureData, 0xFF0000FF, 32*32*4);
|
||||||
|
|
||||||
|
texture = CreateTexture(32, 32, GS_RGB, textureData, FALSE);
|
||||||
|
fullSize.Set(32.0f, 32.0f);
|
||||||
|
|
||||||
|
Free(textureData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void BitmapImage::SetPath(String path)
|
||||||
|
{
|
||||||
|
filePath = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitmapImage::EnableFileMonitor(bool bMonitor)
|
||||||
|
{
|
||||||
|
if (changeMonitor)
|
||||||
|
{
|
||||||
|
OSMonitorFileDestroy(changeMonitor);
|
||||||
|
changeMonitor = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bMonitor)
|
||||||
|
changeMonitor = OSMonitorFileStart(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitmapImage::Init(void)
|
||||||
|
{
|
||||||
|
if(bIsAnimatedGif)
|
||||||
|
{
|
||||||
|
bIsAnimatedGif = false;
|
||||||
|
gif_finalise(&gif);
|
||||||
|
|
||||||
|
Free(animationFrameCache);
|
||||||
|
animationFrameCache = NULL;
|
||||||
|
Free(animationFrameData);
|
||||||
|
animationFrameData = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lpGifData)
|
||||||
|
{
|
||||||
|
Free(lpGifData);
|
||||||
|
lpGifData = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
animationTimes.Clear();
|
||||||
|
|
||||||
|
delete texture;
|
||||||
|
texture = NULL;
|
||||||
|
|
||||||
|
CTSTR lpBitmap = filePath;
|
||||||
|
if(!lpBitmap || !*lpBitmap)
|
||||||
|
{
|
||||||
|
AppWarning(TEXT("BitmapImage::Init: Empty path"));
|
||||||
|
CreateErrorTexture();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
|
||||||
|
if(GetPathExtension(lpBitmap).CompareI(TEXT("gif")))
|
||||||
|
{
|
||||||
|
bool bFail = false;
|
||||||
|
|
||||||
|
gif_create(&gif, &bitmap_callbacks);
|
||||||
|
|
||||||
|
XFile gifFile;
|
||||||
|
if(!gifFile.Open(lpBitmap, XFILE_READ, XFILE_OPENEXISTING))
|
||||||
|
{
|
||||||
|
AppWarning(TEXT("BitmapImage::Init: could not open gif file '%s'"), lpBitmap);
|
||||||
|
CreateErrorTexture();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DWORD fileSize = (DWORD)gifFile.GetFileSize();
|
||||||
|
lpGifData = (LPBYTE)Allocate(fileSize);
|
||||||
|
gifFile.Read(lpGifData, fileSize);
|
||||||
|
|
||||||
|
gif_result result;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
result = gif_initialise(&gif, fileSize, lpGifData);
|
||||||
|
if(result != GIF_OK && result != GIF_WORKING)
|
||||||
|
{
|
||||||
|
bFail = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}while(result != GIF_OK);
|
||||||
|
|
||||||
|
if(gif.frame_count > 1)
|
||||||
|
{
|
||||||
|
if(result == GIF_OK || result == GIF_WORKING)
|
||||||
|
bIsAnimatedGif = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bIsAnimatedGif)
|
||||||
|
{
|
||||||
|
gif_decode_frame(&gif, 0);
|
||||||
|
texture = CreateTexture(gif.width, gif.height, GS_RGBA, gif.frame_image, FALSE, FALSE);
|
||||||
|
|
||||||
|
animationFrameCache = (BYTE **)Allocate(gif.frame_count * sizeof(BYTE *));
|
||||||
|
memset(animationFrameCache, 0, gif.frame_count * sizeof(BYTE *));
|
||||||
|
|
||||||
|
animationFrameData = (BYTE *)Allocate(gif.frame_count * gif.width * gif.height * 4);
|
||||||
|
memset(animationFrameData, 0, gif.frame_count * gif.width * gif.height * 4);
|
||||||
|
|
||||||
|
for(UINT i=0; i<gif.frame_count; i++)
|
||||||
|
{
|
||||||
|
float frameTime = float(gif.frames[i].frame_delay)*0.01f;
|
||||||
|
if (frameTime == 0.0f)
|
||||||
|
frameTime = 0.1f;
|
||||||
|
animationTimes << frameTime;
|
||||||
|
|
||||||
|
if (gif_decode_frame(&gif, i) != GIF_OK)
|
||||||
|
Log (TEXT("BitmapImage: Warning, couldn't decode frame %d of %s"), i, lpBitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
gif_decode_frame(&gif, 0);
|
||||||
|
|
||||||
|
fullSize.x = float(gif.width);
|
||||||
|
fullSize.y = float(gif.height);
|
||||||
|
|
||||||
|
curTime = 0.0f;
|
||||||
|
curFrame = 0;
|
||||||
|
lastDecodedFrame = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gif_finalise(&gif);
|
||||||
|
Free(lpGifData);
|
||||||
|
lpGifData = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!bIsAnimatedGif)
|
||||||
|
{
|
||||||
|
texture = GS->CreateTextureFromFile(lpBitmap, TRUE);
|
||||||
|
if(!texture)
|
||||||
|
{
|
||||||
|
AppWarning(TEXT("BitmapImage::Init: could not create texture '%s'"), lpBitmap);
|
||||||
|
CreateErrorTexture();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fullSize.x = float(texture->Width());
|
||||||
|
fullSize.y = float(texture->Height());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Vect2 BitmapImage::GetSize(void) const
|
||||||
|
{
|
||||||
|
return fullSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture* BitmapImage::GetTexture(void) const
|
||||||
|
{
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitmapImage::Tick(float fSeconds)
|
||||||
|
{
|
||||||
|
if(bIsAnimatedGif)
|
||||||
|
{
|
||||||
|
UINT totalLoops = (UINT)gif.loop_count;
|
||||||
|
if(totalLoops >= 0xFFFF)
|
||||||
|
totalLoops = 0;
|
||||||
|
|
||||||
|
if(!totalLoops || curLoop < totalLoops)
|
||||||
|
{
|
||||||
|
UINT newFrame = curFrame;
|
||||||
|
|
||||||
|
curTime += fSeconds;
|
||||||
|
while(curTime > animationTimes[newFrame])
|
||||||
|
{
|
||||||
|
curTime -= animationTimes[newFrame];
|
||||||
|
if(++newFrame == animationTimes.Num())
|
||||||
|
{
|
||||||
|
if(!totalLoops || ++curLoop < totalLoops)
|
||||||
|
newFrame = 0;
|
||||||
|
else if (curLoop == totalLoops)
|
||||||
|
{
|
||||||
|
newFrame--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(newFrame != curFrame)
|
||||||
|
{
|
||||||
|
UINT lastFrame;
|
||||||
|
|
||||||
|
if (!animationFrameCache[newFrame])
|
||||||
|
{
|
||||||
|
//animation might have looped, if so make sure we decode from frame 0
|
||||||
|
if (newFrame < lastDecodedFrame)
|
||||||
|
lastFrame = 0;
|
||||||
|
else
|
||||||
|
lastFrame = lastDecodedFrame + 1;
|
||||||
|
|
||||||
|
//we need to decode any frames we missed for consistency
|
||||||
|
for (UINT i = lastFrame; i < newFrame; i++)
|
||||||
|
{
|
||||||
|
if (gif_decode_frame(&gif, i) != GIF_OK)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//now decode and display the actual frame we want
|
||||||
|
int ret = gif_decode_frame(&gif, newFrame);
|
||||||
|
if (ret == GIF_OK)
|
||||||
|
{
|
||||||
|
animationFrameCache[newFrame] = animationFrameData + (newFrame * (gif.width * gif.height * 4));
|
||||||
|
memcpy(animationFrameCache[newFrame], gif.frame_image, gif.width * gif.height * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastDecodedFrame = newFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animationFrameCache[newFrame])
|
||||||
|
texture->SetImage(animationFrameCache[newFrame], GS_IMAGEFORMAT_RGBA, gif.width*4);
|
||||||
|
|
||||||
|
curFrame = newFrame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateImageTime)
|
||||||
|
{
|
||||||
|
updateImageTime -= fSeconds;
|
||||||
|
if (updateImageTime <= 0.0f)
|
||||||
|
{
|
||||||
|
updateImageTime = 0.0f;
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changeMonitor && OSFileHasChanged(changeMonitor))
|
||||||
|
updateImageTime = 1.0f;
|
||||||
|
}
|
40
Source/BitmapImage.h
Normal file
40
Source/BitmapImage.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Main.h"
|
||||||
|
#include "libnsgif.h"
|
||||||
|
|
||||||
|
|
||||||
|
class BitmapImage{
|
||||||
|
Texture *texture;
|
||||||
|
Vect2 fullSize;
|
||||||
|
|
||||||
|
bool bIsAnimatedGif;
|
||||||
|
gif_animation gif;
|
||||||
|
LPBYTE lpGifData;
|
||||||
|
List<float> animationTimes;
|
||||||
|
BYTE **animationFrameCache;
|
||||||
|
BYTE *animationFrameData;
|
||||||
|
UINT curFrame, curLoop, lastDecodedFrame;
|
||||||
|
float curTime;
|
||||||
|
float updateImageTime;
|
||||||
|
|
||||||
|
String filePath;
|
||||||
|
OSFileChangeData *changeMonitor;
|
||||||
|
|
||||||
|
gif_bitmap_callback_vt bitmap_callbacks;
|
||||||
|
|
||||||
|
void CreateErrorTexture(void);
|
||||||
|
|
||||||
|
public:
|
||||||
|
BitmapImage();
|
||||||
|
~BitmapImage();
|
||||||
|
|
||||||
|
void SetPath(String path);
|
||||||
|
void EnableFileMonitor(bool bMonitor);
|
||||||
|
void Init(void);
|
||||||
|
|
||||||
|
Vect2 GetSize(void) const;
|
||||||
|
Texture* GetTexture(void) const;
|
||||||
|
|
||||||
|
void Tick(float fSeconds);
|
||||||
|
};
|
@ -18,16 +18,9 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "Main.h"
|
#include "Main.h"
|
||||||
#include "libnsgif.h"
|
#include "BitmapImage.h"
|
||||||
|
|
||||||
|
|
||||||
void *def_bitmap_create(int width, int height) {return Allocate(width * height * 4);}
|
|
||||||
void def_bitmap_set_opaque(void *bitmap, BOOL opaque) {}
|
|
||||||
BOOL def_bitmap_test_opaque(void *bitmap) {return false;}
|
|
||||||
unsigned char *def_bitmap_get_buffer(void *bitmap) {return (unsigned char*)bitmap;}
|
|
||||||
void def_bitmap_destroy(void *bitmap) {Free(bitmap);}
|
|
||||||
void def_bitmap_modified(void *bitmap) {return;}
|
|
||||||
|
|
||||||
struct ColorSelectionData
|
struct ColorSelectionData
|
||||||
{
|
{
|
||||||
HDC hdcDesktop;
|
HDC hdcDesktop;
|
||||||
@ -121,22 +114,11 @@ struct ConfigDesktopSourceInfo
|
|||||||
StringList strClasses;
|
StringList strClasses;
|
||||||
};
|
};
|
||||||
|
|
||||||
gif_bitmap_callback_vt bitmap_callbacks =
|
|
||||||
{
|
|
||||||
def_bitmap_create,
|
|
||||||
def_bitmap_destroy,
|
|
||||||
def_bitmap_get_buffer,
|
|
||||||
def_bitmap_set_opaque,
|
|
||||||
def_bitmap_test_opaque,
|
|
||||||
def_bitmap_modified
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class BitmapImageSource : public ImageSource
|
class BitmapImageSource : public ImageSource
|
||||||
{
|
{
|
||||||
Texture *texture;
|
BitmapImage bitmapImage;
|
||||||
|
|
||||||
Vect2 fullSize;
|
|
||||||
XElement *data;
|
XElement *data;
|
||||||
|
|
||||||
bool bUseColorKey;
|
bool bUseColorKey;
|
||||||
@ -146,35 +128,14 @@ class BitmapImageSource : public ImageSource
|
|||||||
DWORD opacity;
|
DWORD opacity;
|
||||||
DWORD color;
|
DWORD color;
|
||||||
|
|
||||||
bool bIsAnimatedGif;
|
|
||||||
gif_animation gif;
|
|
||||||
LPBYTE lpGifData;
|
|
||||||
List<float> animationTimes;
|
|
||||||
BYTE **animationFrameCache;
|
|
||||||
BYTE *animationFrameData;
|
|
||||||
UINT curFrame, curLoop, lastDecodedFrame;
|
|
||||||
float curTime;
|
|
||||||
float updateImageTime;
|
|
||||||
|
|
||||||
Shader *colorKeyShader, *alphaIgnoreShader;
|
Shader *colorKeyShader, *alphaIgnoreShader;
|
||||||
OSFileChangeData *changeMonitor;
|
|
||||||
|
|
||||||
void CreateErrorTexture()
|
|
||||||
{
|
|
||||||
LPBYTE textureData = (LPBYTE)Allocate(32*32*4);
|
|
||||||
msetd(textureData, 0xFF0000FF, 32*32*4);
|
|
||||||
|
|
||||||
texture = CreateTexture(32, 32, GS_RGB, textureData, FALSE);
|
|
||||||
fullSize.Set(32.0f, 32.0f);
|
|
||||||
|
|
||||||
Free(textureData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BitmapImageSource(XElement *data)
|
BitmapImageSource(XElement *data)
|
||||||
{
|
{
|
||||||
//EnableMemoryTracking(true);
|
|
||||||
this->data = data;
|
this->data = data;
|
||||||
|
|
||||||
UpdateSettings();
|
UpdateSettings();
|
||||||
|
|
||||||
colorKeyShader = CreatePixelShaderFromFile(TEXT("shaders\\ColorKey_RGB.pShader"));
|
colorKeyShader = CreatePixelShaderFromFile(TEXT("shaders\\ColorKey_RGB.pShader"));
|
||||||
@ -185,107 +146,19 @@ public:
|
|||||||
|
|
||||||
~BitmapImageSource()
|
~BitmapImageSource()
|
||||||
{
|
{
|
||||||
if(bIsAnimatedGif)
|
|
||||||
{
|
|
||||||
gif_finalise(&gif);
|
|
||||||
Free(animationFrameCache);
|
|
||||||
Free(animationFrameData);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(lpGifData)
|
|
||||||
Free(lpGifData);
|
|
||||||
|
|
||||||
delete colorKeyShader;
|
delete colorKeyShader;
|
||||||
delete alphaIgnoreShader;
|
delete alphaIgnoreShader;
|
||||||
|
|
||||||
if (changeMonitor)
|
|
||||||
OSMonitorFileDestroy(changeMonitor);
|
|
||||||
|
|
||||||
delete texture;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tick(float fSeconds)
|
void Tick(float fSeconds)
|
||||||
{
|
{
|
||||||
if(bIsAnimatedGif)
|
bitmapImage.Tick(fSeconds);
|
||||||
{
|
|
||||||
UINT totalLoops = (UINT)gif.loop_count;
|
|
||||||
if(totalLoops >= 0xFFFF)
|
|
||||||
totalLoops = 0;
|
|
||||||
|
|
||||||
if(!totalLoops || curLoop < totalLoops)
|
|
||||||
{
|
|
||||||
UINT newFrame = curFrame;
|
|
||||||
|
|
||||||
curTime += fSeconds;
|
|
||||||
while(curTime > animationTimes[newFrame])
|
|
||||||
{
|
|
||||||
curTime -= animationTimes[newFrame];
|
|
||||||
if(++newFrame == animationTimes.Num())
|
|
||||||
{
|
|
||||||
if(!totalLoops || ++curLoop < totalLoops)
|
|
||||||
newFrame = 0;
|
|
||||||
else if (curLoop == totalLoops)
|
|
||||||
{
|
|
||||||
newFrame--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(newFrame != curFrame)
|
|
||||||
{
|
|
||||||
UINT lastFrame;
|
|
||||||
|
|
||||||
if (!animationFrameCache[newFrame])
|
|
||||||
{
|
|
||||||
//animation might have looped, if so make sure we decode from frame 0
|
|
||||||
if (newFrame < lastDecodedFrame)
|
|
||||||
lastFrame = 0;
|
|
||||||
else
|
|
||||||
lastFrame = lastDecodedFrame + 1;
|
|
||||||
|
|
||||||
//we need to decode any frames we missed for consistency
|
|
||||||
for (UINT i = lastFrame; i < newFrame; i++)
|
|
||||||
{
|
|
||||||
if (gif_decode_frame(&gif, i) != GIF_OK)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//now decode and display the actual frame we want
|
|
||||||
int ret = gif_decode_frame(&gif, newFrame);
|
|
||||||
if (ret == GIF_OK)
|
|
||||||
{
|
|
||||||
animationFrameCache[newFrame] = animationFrameData + (newFrame * (gif.width * gif.height * 4));
|
|
||||||
memcpy(animationFrameCache[newFrame], gif.frame_image, gif.width * gif.height * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
lastDecodedFrame = newFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (animationFrameCache[newFrame])
|
|
||||||
texture->SetImage(animationFrameCache[newFrame], GS_IMAGEFORMAT_RGBA, gif.width*4);
|
|
||||||
|
|
||||||
curFrame = newFrame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updateImageTime)
|
|
||||||
{
|
|
||||||
updateImageTime -= fSeconds;
|
|
||||||
if (updateImageTime <= 0.0f)
|
|
||||||
{
|
|
||||||
updateImageTime = 0.0f;
|
|
||||||
UpdateSettings();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changeMonitor && OSFileHasChanged(changeMonitor))
|
|
||||||
updateImageTime = 1.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Render(const Vect2 &pos, const Vect2 &size)
|
void Render(const Vect2 &pos, const Vect2 &size)
|
||||||
{
|
{
|
||||||
|
Texture *texture = bitmapImage.GetTexture();
|
||||||
|
|
||||||
if(texture)
|
if(texture)
|
||||||
{
|
{
|
||||||
if(bUseColorKey)
|
if(bUseColorKey)
|
||||||
@ -316,126 +189,9 @@ public:
|
|||||||
|
|
||||||
void UpdateSettings()
|
void UpdateSettings()
|
||||||
{
|
{
|
||||||
if(bIsAnimatedGif)
|
bitmapImage.SetPath(data->GetString(TEXT("path")));
|
||||||
{
|
bitmapImage.EnableFileMonitor(data->GetInt(TEXT("monitor"), 0) == 1);
|
||||||
bIsAnimatedGif = false;
|
bitmapImage.Init();
|
||||||
gif_finalise(&gif);
|
|
||||||
|
|
||||||
Free(animationFrameCache);
|
|
||||||
animationFrameCache = NULL;
|
|
||||||
Free(animationFrameData);
|
|
||||||
animationFrameData = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(lpGifData)
|
|
||||||
{
|
|
||||||
Free(lpGifData);
|
|
||||||
lpGifData = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
animationTimes.Clear();
|
|
||||||
|
|
||||||
delete texture;
|
|
||||||
texture = NULL;
|
|
||||||
|
|
||||||
CTSTR lpBitmap = data->GetString(TEXT("path"));
|
|
||||||
if(!lpBitmap || !*lpBitmap)
|
|
||||||
{
|
|
||||||
AppWarning(TEXT("BitmapImageSource::UpdateSettings: Empty path"));
|
|
||||||
CreateErrorTexture();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------
|
|
||||||
|
|
||||||
if(GetPathExtension(lpBitmap).CompareI(TEXT("gif")))
|
|
||||||
{
|
|
||||||
bool bFail = false;
|
|
||||||
|
|
||||||
gif_create(&gif, &bitmap_callbacks);
|
|
||||||
|
|
||||||
XFile gifFile;
|
|
||||||
if(!gifFile.Open(lpBitmap, XFILE_READ, XFILE_OPENEXISTING))
|
|
||||||
{
|
|
||||||
AppWarning(TEXT("BitmapImageSource::UpdateSettings: could not open gif file '%s'"), lpBitmap);
|
|
||||||
CreateErrorTexture();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DWORD fileSize = (DWORD)gifFile.GetFileSize();
|
|
||||||
lpGifData = (LPBYTE)Allocate(fileSize);
|
|
||||||
gifFile.Read(lpGifData, fileSize);
|
|
||||||
|
|
||||||
gif_result result;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
result = gif_initialise(&gif, fileSize, lpGifData);
|
|
||||||
if(result != GIF_OK && result != GIF_WORKING)
|
|
||||||
{
|
|
||||||
bFail = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}while(result != GIF_OK);
|
|
||||||
|
|
||||||
if(gif.frame_count > 1)
|
|
||||||
{
|
|
||||||
if(result == GIF_OK || result == GIF_WORKING)
|
|
||||||
bIsAnimatedGif = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bIsAnimatedGif)
|
|
||||||
{
|
|
||||||
gif_decode_frame(&gif, 0);
|
|
||||||
texture = CreateTexture(gif.width, gif.height, GS_RGBA, gif.frame_image, FALSE, FALSE);
|
|
||||||
|
|
||||||
animationFrameCache = (BYTE **)Allocate(gif.frame_count * sizeof(BYTE *));
|
|
||||||
memset(animationFrameCache, 0, gif.frame_count * sizeof(BYTE *));
|
|
||||||
|
|
||||||
animationFrameData = (BYTE *)Allocate(gif.frame_count * gif.width * gif.height * 4);
|
|
||||||
memset(animationFrameData, 0, gif.frame_count * gif.width * gif.height * 4);
|
|
||||||
|
|
||||||
for(UINT i=0; i<gif.frame_count; i++)
|
|
||||||
{
|
|
||||||
float frameTime = float(gif.frames[i].frame_delay)*0.01f;
|
|
||||||
if (frameTime == 0.0f)
|
|
||||||
frameTime = 0.1f;
|
|
||||||
animationTimes << frameTime;
|
|
||||||
|
|
||||||
if (gif_decode_frame(&gif, i) != GIF_OK)
|
|
||||||
Log (TEXT("BitmapImageSource: Warning, couldn't decode frame %d of %s"), i, data->GetString(TEXT("path")));
|
|
||||||
}
|
|
||||||
|
|
||||||
gif_decode_frame(&gif, 0);
|
|
||||||
|
|
||||||
fullSize.x = float(gif.width);
|
|
||||||
fullSize.y = float(gif.height);
|
|
||||||
|
|
||||||
curTime = 0.0f;
|
|
||||||
curFrame = 0;
|
|
||||||
lastDecodedFrame = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gif_finalise(&gif);
|
|
||||||
Free(lpGifData);
|
|
||||||
lpGifData = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!bIsAnimatedGif)
|
|
||||||
{
|
|
||||||
texture = GS->CreateTextureFromFile(lpBitmap, TRUE);
|
|
||||||
if(!texture)
|
|
||||||
{
|
|
||||||
AppWarning(TEXT("BitmapImageSource::UpdateSettings: could not create texture '%s'"), lpBitmap);
|
|
||||||
CreateErrorTexture();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fullSize.x = float(texture->Width());
|
|
||||||
fullSize.y = float(texture->Height());
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------
|
//------------------------------------
|
||||||
|
|
||||||
@ -444,16 +200,6 @@ public:
|
|||||||
if(opacity > 100)
|
if(opacity > 100)
|
||||||
opacity = 100;
|
opacity = 100;
|
||||||
|
|
||||||
if (changeMonitor)
|
|
||||||
{
|
|
||||||
OSMonitorFileDestroy(changeMonitor);
|
|
||||||
changeMonitor = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int monitor = data->GetInt(TEXT("monitor"), 0);
|
|
||||||
if (monitor)
|
|
||||||
changeMonitor = OSMonitorFileStart(lpBitmap);
|
|
||||||
|
|
||||||
bool bNewUseColorKey = data->GetInt(TEXT("useColorKey"), 0) != 0;
|
bool bNewUseColorKey = data->GetInt(TEXT("useColorKey"), 0) != 0;
|
||||||
keyColor = data->GetInt(TEXT("keyColor"), 0xFFFFFFFF);
|
keyColor = data->GetInt(TEXT("keyColor"), 0xFFFFFFFF);
|
||||||
keySimilarity = data->GetInt(TEXT("keySimilarity"), 10);
|
keySimilarity = data->GetInt(TEXT("keySimilarity"), 10);
|
||||||
@ -462,7 +208,7 @@ public:
|
|||||||
bUseColorKey = bNewUseColorKey;
|
bUseColorKey = bNewUseColorKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vect2 GetSize() const {return fullSize;}
|
Vect2 GetSize() const {return bitmapImage.GetSize();}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#include "Main.h"
|
#include "Main.h"
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "BitmapImage.h"
|
||||||
|
|
||||||
#define MIN_TRANSITION_TIME 3
|
#define MIN_TRANSITION_TIME 3
|
||||||
#define MAX_TRANSITION_TIME 600
|
#define MAX_TRANSITION_TIME 600
|
||||||
|
|
||||||
@ -29,7 +31,7 @@ extern "C" double round(double val);
|
|||||||
|
|
||||||
class BitmapTransitionSource : public ImageSource
|
class BitmapTransitionSource : public ImageSource
|
||||||
{
|
{
|
||||||
List<Texture*> textures;
|
List<BitmapImage*> bitmapImages;
|
||||||
|
|
||||||
Vect2 fullSize;
|
Vect2 fullSize;
|
||||||
double baseAspect;
|
double baseAspect;
|
||||||
@ -55,17 +57,6 @@ class BitmapTransitionSource : public ImageSource
|
|||||||
return int( ( (double)rand() / (RAND_MAX + 1) ) * limit );
|
return int( ( (double)rand() / (RAND_MAX + 1) ) * limit );
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateErrorTexture()
|
|
||||||
{
|
|
||||||
LPBYTE textureData = (LPBYTE)Allocate(32*32*4);
|
|
||||||
msetd(textureData, 0xFF0000FF, 32*32*4);
|
|
||||||
|
|
||||||
textures << CreateTexture(32, 32, GS_RGB, textureData, FALSE);
|
|
||||||
fullSize.Set(32.0f, 32.0f);
|
|
||||||
|
|
||||||
Free(textureData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BitmapTransitionSource(XElement *data)
|
BitmapTransitionSource(XElement *data)
|
||||||
{
|
{
|
||||||
@ -76,13 +67,16 @@ public:
|
|||||||
|
|
||||||
~BitmapTransitionSource()
|
~BitmapTransitionSource()
|
||||||
{
|
{
|
||||||
for(UINT i=0; i<textures.Num(); i++)
|
for(UINT i=0; i<bitmapImages.Num(); i++)
|
||||||
delete textures[i];
|
delete bitmapImages[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tick(float fSeconds)
|
void Tick(float fSeconds)
|
||||||
{
|
{
|
||||||
if(bTransitioning && textures.Num() > 1)
|
for(UINT i=0; i<bitmapImages.Num(); i++)
|
||||||
|
bitmapImages[i]->Tick(fSeconds);
|
||||||
|
|
||||||
|
if(bTransitioning && bitmapImages.Num() > 1)
|
||||||
{
|
{
|
||||||
if(bDisableFading)
|
if(bDisableFading)
|
||||||
curFadeValue = fadeTime;
|
curFadeValue = fadeTime;
|
||||||
@ -97,14 +91,14 @@ public:
|
|||||||
if(bRandomize)
|
if(bRandomize)
|
||||||
{
|
{
|
||||||
curTexture = nextTexture;
|
curTexture = nextTexture;
|
||||||
while((nextTexture = lrand(textures.Num())) == curTexture);
|
while((nextTexture = lrand(bitmapImages.Num())) == curTexture);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(++curTexture == textures.Num())
|
if(++curTexture == bitmapImages.Num())
|
||||||
curTexture = 0;
|
curTexture = 0;
|
||||||
|
|
||||||
nextTexture = (curTexture == textures.Num()-1) ? 0 : curTexture+1;
|
nextTexture = (curTexture == bitmapImages.Num()-1) ? 0 : curTexture+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,7 +120,7 @@ public:
|
|||||||
Vect2 pos = Vect2(0.0f, 0.0f);
|
Vect2 pos = Vect2(0.0f, 0.0f);
|
||||||
Vect2 size = fullSize;
|
Vect2 size = fullSize;
|
||||||
|
|
||||||
Vect2 itemSize = Vect2((float)textures[texID]->Width(), (float)textures[texID]->Height());
|
Vect2 itemSize = bitmapImages[texID]->GetSize();
|
||||||
|
|
||||||
double sourceAspect = double(itemSize.x)/double(itemSize.y);
|
double sourceAspect = double(itemSize.x)/double(itemSize.y);
|
||||||
if(!CloseDouble(baseAspect, sourceAspect))
|
if(!CloseDouble(baseAspect, sourceAspect))
|
||||||
@ -151,14 +145,14 @@ public:
|
|||||||
Vect2 lr;
|
Vect2 lr;
|
||||||
lr = pos + (size/fullSize*startSize);
|
lr = pos + (size/fullSize*startSize);
|
||||||
|
|
||||||
DrawSprite(textures[texID], (curAlpha<<24) | 0xFFFFFF, pos.x, pos.y, lr.x, lr.y);
|
DrawSprite(bitmapImages[texID]->GetTexture(), (curAlpha<<24) | 0xFFFFFF, pos.x, pos.y, lr.x, lr.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Render(const Vect2 &pos, const Vect2 &size)
|
void Render(const Vect2 &pos, const Vect2 &size)
|
||||||
{
|
{
|
||||||
if(textures.Num())
|
if(bitmapImages.Num())
|
||||||
{
|
{
|
||||||
if(bTransitioning && textures.Num() > 1)
|
if(bTransitioning && bitmapImages.Num() > 1)
|
||||||
{
|
{
|
||||||
float curAlpha = MIN(curFadeValue/fadeTime, 1.0f);
|
float curAlpha = MIN(curFadeValue/fadeTime, 1.0f);
|
||||||
if(bFadeInOnly)
|
if(bFadeInOnly)
|
||||||
@ -175,9 +169,9 @@ public:
|
|||||||
|
|
||||||
void UpdateSettings()
|
void UpdateSettings()
|
||||||
{
|
{
|
||||||
for(UINT i=0; i<textures.Num(); i++)
|
for(UINT i=0; i<bitmapImages.Num(); i++)
|
||||||
delete textures[i];
|
delete bitmapImages[i];
|
||||||
textures.Clear();
|
bitmapImages.Clear();
|
||||||
|
|
||||||
//------------------------------------
|
//------------------------------------
|
||||||
|
|
||||||
@ -194,27 +188,21 @@ public:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture *texture = GS->CreateTextureFromFile(strBitmap, TRUE);
|
BitmapImage *bitmapImage = new BitmapImage;
|
||||||
if(!texture)
|
bitmapImage->SetPath(strBitmap);
|
||||||
{
|
bitmapImage->EnableFileMonitor(false);
|
||||||
AppWarning(TEXT("BitmapTransitionSource::UpdateSettings: could not create texture '%s'"), strBitmap.Array());
|
bitmapImage->Init();
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bFirst)
|
if(bFirst)
|
||||||
{
|
{
|
||||||
fullSize.x = float(texture->Width());
|
fullSize = bitmapImage->GetSize();
|
||||||
fullSize.y = float(texture->Height());
|
|
||||||
baseAspect = double(fullSize.x)/double(fullSize.y);
|
baseAspect = double(fullSize.x)/double(fullSize.y);
|
||||||
bFirst = false;
|
bFirst = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
textures << texture;
|
bitmapImages << bitmapImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(textures.Num() == 0)
|
|
||||||
CreateErrorTexture();
|
|
||||||
|
|
||||||
//------------------------------------
|
//------------------------------------
|
||||||
|
|
||||||
transitionTime = data->GetFloat(TEXT("transitionTime"));
|
transitionTime = data->GetFloat(TEXT("transitionTime"));
|
||||||
@ -237,14 +225,14 @@ public:
|
|||||||
if(bRandomize)
|
if(bRandomize)
|
||||||
{
|
{
|
||||||
srand( (unsigned)time( NULL ) );
|
srand( (unsigned)time( NULL ) );
|
||||||
if(textures.Num() > 1)
|
if(bitmapImages.Num() > 1)
|
||||||
{
|
{
|
||||||
curTexture = lrand(textures.Num());
|
curTexture = lrand(bitmapImages.Num());
|
||||||
while((nextTexture = lrand(textures.Num())) == curTexture);
|
while((nextTexture = lrand(bitmapImages.Num())) == curTexture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
nextTexture = (curTexture == textures.Num()-1) ? 0 : curTexture+1;
|
nextTexture = (curTexture == bitmapImages.Num()-1) ? 0 : curTexture+1;
|
||||||
|
|
||||||
bTransitioning = false;
|
bTransitioning = false;
|
||||||
curFadeValue = 0.0f;
|
curFadeValue = 0.0f;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user