# Fixed some graphical and scenario editor issues.
Atlas: Changed video format to 640x480 and losslessly compressed. Added most-recently-used files list. Stopped switching sidebar when selecting tools, since it was getting annoying. Added Slow playback mode. Fixed crash when resetting sim while projectiles exist. Renderer: Added JS-accessible renderer.shadowMapSize to override the size of shadow maps. ShadowMap: Changed default depth texture bits to 24, since that seems to go faster (see #180). PolygonSortModelRenderer: Made more similar to other renderers, so that the renderer.sortAllTransparent=true mode works better. Projectile: Fixed update, so it interpolates smoothly. Entgraph: Fixed promotion detection. This was SVN commit r4876.
This commit is contained in:
parent
7c06199d0f
commit
5e3e78ca78
@ -38,7 +38,7 @@ CVector3D CModelDef::SkinNormal(const SModelVertex& vtx,
|
||||
// inverse of the transpose. Unfortunately inverses are slow.
|
||||
// If a matrix is orthogonal, M * M^T = I and so the inverse of the transpose
|
||||
// is the original matrix. But that's not entirely relevant here, because
|
||||
// the cone matrices include translation components and so they're not
|
||||
// the bone matrices include translation components and so they're not
|
||||
// orthogonal.
|
||||
// But that's okay because we have
|
||||
// M = T * R
|
||||
|
@ -366,6 +366,7 @@ CRenderer::CRenderer()
|
||||
m_Options.m_FancyWater = false;
|
||||
|
||||
m_ShadowZBias = 0.02f;
|
||||
m_ShadowMapSize = 0;
|
||||
|
||||
for (uint i=0;i<MaxTextureUnits;i++) {
|
||||
m_ActiveTextures[i]=0;
|
||||
@ -1746,6 +1747,7 @@ void CRenderer::ScriptingInit()
|
||||
AddProperty(L"sortAllTransparent", &CRenderer::m_SortAllTransparent);
|
||||
AddProperty(L"displayFrustum", &CRenderer::m_DisplayFrustum);
|
||||
AddProperty(L"shadowZBias", &CRenderer::m_ShadowZBias);
|
||||
AddProperty(L"shadowMapSize", &CRenderer::m_ShadowMapSize);
|
||||
AddProperty(L"disableCopyShadow", &CRenderer::m_DisableCopyShadow);
|
||||
AddProperty(L"depthTextureBits", &CRenderer::JSI_GetDepthTextureBits, &CRenderer::JSI_SetDepthTextureBits);
|
||||
AddProperty(L"skipSubmit", &CRenderer::m_SkipSubmit);
|
||||
|
@ -455,6 +455,15 @@ public:
|
||||
*/
|
||||
float m_ShadowZBias;
|
||||
|
||||
/**
|
||||
* m_ShadowMapSize: Size of shadow map, or 0 for default. Typically slow but useful
|
||||
* for high-quality rendering. Changes don't take effect until the shadow map
|
||||
* is regenerated.
|
||||
*
|
||||
* Can be accessed via JS as renderer.shadowMapSize
|
||||
*/
|
||||
int m_ShadowMapSize;
|
||||
|
||||
/**
|
||||
* m_SkipSubmit: Disable the actual submission of rendering commands to OpenGL.
|
||||
* All state setup is still performed as usual.
|
||||
|
@ -43,9 +43,9 @@ struct ShadowMapInternals
|
||||
// handle of shadow map
|
||||
GLuint Texture;
|
||||
// width, height of shadow map
|
||||
u32 Width, Height;
|
||||
int Width, Height;
|
||||
// used width, height of shadow map
|
||||
u32 EffectiveWidth, EffectiveHeight;
|
||||
int EffectiveWidth, EffectiveHeight;
|
||||
// transform light space into projected light space
|
||||
// in projected light space, the shadowbound box occupies the [-1..1] cube
|
||||
// calculated on BeginRender, after the final shadow bounds are known
|
||||
@ -82,7 +82,7 @@ ShadowMap::ShadowMap()
|
||||
m->EffectiveWidth = 0;
|
||||
m->EffectiveHeight = 0;
|
||||
m->UseDepthTexture = false;
|
||||
m->DepthTextureBits = 16;
|
||||
m->DepthTextureBits = 24;
|
||||
}
|
||||
|
||||
|
||||
@ -274,12 +274,23 @@ void ShadowMapInternals::CreateTexture()
|
||||
pglGenFramebuffersEXT(1, &Framebuffer);
|
||||
}
|
||||
|
||||
// get shadow map size as next power of two up from view width and height
|
||||
Width = g_Renderer.GetWidth();
|
||||
Width = std::min(RoundUpToPowerOf2(Width), (int)ogl_max_tex_size);
|
||||
Height = g_Renderer.GetHeight();
|
||||
Height = std::min(RoundUpToPowerOf2(Height), (int)ogl_max_tex_size);
|
||||
if (g_Renderer.m_ShadowMapSize != 0)
|
||||
{
|
||||
// non-default option to override the size
|
||||
Width = Height = g_Renderer.m_ShadowMapSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
// get shadow map size as next power of two up from view width and height
|
||||
Width = RoundUpToPowerOf2(g_Renderer.GetWidth());
|
||||
Height = RoundUpToPowerOf2(g_Renderer.GetHeight());
|
||||
}
|
||||
// Clamp to the maximum texture size
|
||||
Width = std::min(Width, (int)ogl_max_tex_size);
|
||||
Height = std::min(Height, (int)ogl_max_tex_size);
|
||||
|
||||
// If we're using a framebuffer object, the whole texture is available; otherwise
|
||||
// we're limited to the part of the screen buffer that is actually visible
|
||||
if (Framebuffer)
|
||||
{
|
||||
EffectiveWidth = Width;
|
||||
@ -287,15 +298,16 @@ void ShadowMapInternals::CreateTexture()
|
||||
}
|
||||
else
|
||||
{
|
||||
EffectiveWidth = std::min(Width, (u32)g_Renderer.GetWidth());
|
||||
EffectiveHeight = std::min(Height, (u32)g_Renderer.GetHeight());
|
||||
EffectiveWidth = std::min(Width, g_Renderer.GetWidth());
|
||||
EffectiveHeight = std::min(Height, g_Renderer.GetHeight());
|
||||
}
|
||||
|
||||
const char* formatname = "LUMINANCE";
|
||||
|
||||
if (UseDepthTexture)
|
||||
{
|
||||
switch(DepthTextureBits) {
|
||||
switch(DepthTextureBits)
|
||||
{
|
||||
case 16: formatname = "DEPTH_COMPONENT16"; break;
|
||||
case 24: formatname = "DEPTH_COMPONENT24"; break;
|
||||
case 32: formatname = "DEPTH_COMPONENT32"; break;
|
||||
@ -303,20 +315,21 @@ void ShadowMapInternals::CreateTexture()
|
||||
}
|
||||
}
|
||||
|
||||
LOG(NORMAL, LOG_CATEGORY, "Creating shadow texture (size %ix%i) (format = %s)%s",
|
||||
LOG(NORMAL, LOG_CATEGORY, "Creating shadow texture (size %dx%d) (format = %s)%s",
|
||||
Width, Height, formatname, Framebuffer ? " (using EXT_framebuffer_object)" : "");
|
||||
|
||||
// create texture object
|
||||
glGenTextures(1, &Texture);
|
||||
g_Renderer.BindTexture(0, Texture);
|
||||
|
||||
u32 size = Width*Height;
|
||||
int size = Width*Height;
|
||||
|
||||
if (UseDepthTexture)
|
||||
{
|
||||
GLenum format;
|
||||
|
||||
switch(DepthTextureBits) {
|
||||
switch(DepthTextureBits)
|
||||
{
|
||||
case 16: format = GL_DEPTH_COMPONENT16; break;
|
||||
case 24: format = GL_DEPTH_COMPONENT24; break;
|
||||
case 32: format = GL_DEPTH_COMPONENT32; break;
|
||||
@ -324,9 +337,9 @@ void ShadowMapInternals::CreateTexture()
|
||||
}
|
||||
|
||||
float* buf = new float[size];
|
||||
for(uint i = 0; i < size; i++) buf[i] = 1.0;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, Width, Height, 0,
|
||||
GL_DEPTH_COMPONENT, GL_FLOAT, buf);
|
||||
for (int i = 0; i < size; i++)
|
||||
buf[i] = 1.0;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, Width, Height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, buf);
|
||||
delete[] buf;
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
|
||||
@ -335,9 +348,10 @@ void ShadowMapInternals::CreateTexture()
|
||||
}
|
||||
else
|
||||
{
|
||||
u32* buf=new u32[size];
|
||||
for (uint i=0;i<size;i++) buf[i]=0x00ffffff;
|
||||
glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE8,Width,Height,0,GL_RGBA,GL_UNSIGNED_BYTE,buf);
|
||||
u32* buf = new u32[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
buf[i] = 0x00ffffff;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE8, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
@ -367,12 +381,12 @@ void ShadowMapInternals::CreateTexture()
|
||||
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||
{
|
||||
LOG(WARNING, LOG_CATEGORY, "Framebuffer object incomplete: %04f", status);
|
||||
LOG(WARNING, LOG_CATEGORY, "Framebuffer object incomplete: %04d", status);
|
||||
|
||||
pglDeleteFramebuffersEXT(1, &Framebuffer);
|
||||
Framebuffer = 0;
|
||||
EffectiveWidth = std::min(Width, (u32)g_Renderer.GetWidth());
|
||||
EffectiveHeight = std::min(Height, (u32)g_Renderer.GetHeight());
|
||||
EffectiveWidth = std::min(Width, g_Renderer.GetWidth());
|
||||
EffectiveHeight = std::min(Height, g_Renderer.GetHeight());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -437,7 +451,7 @@ void ShadowMap::EndRender()
|
||||
if (!g_Renderer.GetDisableCopyShadow())
|
||||
{
|
||||
g_Renderer.BindTexture(0, m->Texture);
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, g_Renderer.GetWidth(), g_Renderer.GetHeight());
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m->EffectiveWidth, m->EffectiveHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,14 +268,28 @@ void PolygonSortModelRenderer::DestroyModelData(CModel* UNUSED(model), void* dat
|
||||
|
||||
|
||||
// Prepare for one rendering pass
|
||||
void PolygonSortModelRenderer::BeginPass(uint streamflags, const CMatrix3D* UNUSED(texturematrix))
|
||||
void PolygonSortModelRenderer::BeginPass(uint streamflags, const CMatrix3D* texturematrix)
|
||||
{
|
||||
debug_assert(streamflags == (streamflags & (STREAM_POS|STREAM_COLOR|STREAM_UV0)));
|
||||
debug_assert(streamflags == (streamflags & (STREAM_POS|STREAM_COLOR|STREAM_UV0|STREAM_TEXGENTOUV1)));
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if (streamflags & STREAM_UV0) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
if (streamflags & STREAM_COLOR) glEnableClientState(GL_COLOR_ARRAY);
|
||||
if (streamflags & STREAM_TEXGENTOUV1)
|
||||
{
|
||||
pglActiveTextureARB(GL_TEXTURE1);
|
||||
pglClientActiveTextureARB(GL_TEXTURE1);
|
||||
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadMatrixf(&texturematrix->_11);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
pglClientActiveTextureARB(GL_TEXTURE0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -284,6 +298,20 @@ void PolygonSortModelRenderer::EndPass(uint streamflags)
|
||||
{
|
||||
if (streamflags & STREAM_UV0) glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
if (streamflags & STREAM_COLOR) glDisableClientState(GL_COLOR_ARRAY);
|
||||
if (streamflags & STREAM_TEXGENTOUV1)
|
||||
{
|
||||
pglActiveTextureARB(GL_TEXTURE1);
|
||||
pglClientActiveTextureARB(GL_TEXTURE1);
|
||||
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
pglClientActiveTextureARB(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
@ -319,6 +347,14 @@ void PolygonSortModelRenderer::RenderModel(uint streamflags, CModel* model, void
|
||||
glVertexPointer(3, GL_FLOAT, stride, base + psmdl->m_Position.offset);
|
||||
if (streamflags & STREAM_COLOR)
|
||||
glColorPointer(3, psmdl->m_Color.type, stride, base + psmdl->m_Color.offset);
|
||||
if (streamflags & STREAM_TEXGENTOUV1)
|
||||
{
|
||||
pglClientActiveTextureARB(GL_TEXTURE1);
|
||||
pglActiveTextureARB(GL_TEXTURE1);
|
||||
glTexCoordPointer(3, GL_FLOAT, stride, base + psmdl->m_Position.offset);
|
||||
pglClientActiveTextureARB(GL_TEXTURE0);
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
// render the lot
|
||||
size_t numFaces = mdef->GetNumFaces();
|
||||
|
@ -243,10 +243,15 @@ CProjectileManager::CProjectileManager()
|
||||
|
||||
CProjectileManager::~CProjectileManager()
|
||||
{
|
||||
while( m_Projectiles.size() )
|
||||
delete( m_Projectiles[0] );
|
||||
DeleteAll();
|
||||
}
|
||||
|
||||
void CProjectileManager::DeleteAll()
|
||||
{
|
||||
while( !( m_Projectiles.empty() ) )
|
||||
delete( m_Projectiles[0] ); // removes itself from m_Projectiles
|
||||
}
|
||||
|
||||
CProjectile* CProjectileManager::AddProjectile( const CModel* Actor, const CVector3D& Position, const CVector3D& Target, float Speed, CEntity* Originator, const CScriptObject& ImpactScript, const CScriptObject& MissScript )
|
||||
{
|
||||
CProjectile* p = new CProjectile( Actor, Position, Target, Speed, Originator, ImpactScript, MissScript );
|
||||
@ -261,13 +266,12 @@ void CProjectileManager::DeleteProjectile( CProjectile* p )
|
||||
|
||||
void CProjectileManager::UpdateAll( size_t timestep )
|
||||
{
|
||||
uint i;
|
||||
for( i = 0; i < m_Projectiles.size(); i++ )
|
||||
m_LastTurnLength = timestep;
|
||||
for( size_t i = 0; i < m_Projectiles.size(); )
|
||||
if( !( m_Projectiles[i]->Update( timestep ) ) )
|
||||
{
|
||||
delete( m_Projectiles[i] );
|
||||
i--;
|
||||
}
|
||||
delete( m_Projectiles[i] ); // removes itself from m_Projectiles
|
||||
else
|
||||
i++;
|
||||
}
|
||||
|
||||
void CProjectileManager::InterpolateAll( double relativeOffset )
|
||||
|
@ -86,6 +86,8 @@ public:
|
||||
CProjectileManager();
|
||||
~CProjectileManager();
|
||||
|
||||
void DeleteAll();
|
||||
|
||||
void UpdateAll( size_t timestep );
|
||||
void InterpolateAll( double frametime );
|
||||
|
||||
|
@ -21,6 +21,15 @@ Please complain if I forget to do those things.
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(disable: 4100 4505 4510 4610)
|
||||
// Doesn't have inttypes.h, so cheat before including the ffmpeg headers
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
typedef __int8 int8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef __int64 int64_t;
|
||||
#endif
|
||||
|
||||
#include "ffmpeg/avformat.h"
|
||||
@ -32,6 +41,7 @@ struct VideoEncoderImpl
|
||||
int framerate;
|
||||
int bitrate;
|
||||
float duration;
|
||||
int width, height;
|
||||
|
||||
AVStream *video_st;
|
||||
AVFormatContext *oc;
|
||||
@ -69,31 +79,19 @@ struct VideoEncoderImpl
|
||||
c->codec_id = (CodecID)codec_id;
|
||||
c->codec_type = CODEC_TYPE_VIDEO;
|
||||
|
||||
c->bit_rate = bitrate*1000;
|
||||
c->width = 640;
|
||||
c->height = 480;
|
||||
// c->bit_rate = bitrate*1000;
|
||||
// TODO: support compressed formats, using qscale
|
||||
|
||||
c->width = width;
|
||||
c->height = height;
|
||||
|
||||
c->time_base.den = framerate;
|
||||
c->time_base.num = 1;
|
||||
|
||||
c->pix_fmt = PIX_FMT_YUV420P;
|
||||
// c->pix_fmt = PIX_FMT_YUV420P;
|
||||
c->pix_fmt = PIX_FMT_RGBA32;
|
||||
|
||||
// TODO: these compression parameters aren't necessarily any good
|
||||
|
||||
c->mb_decision = FF_MB_DECISION_RD;
|
||||
c->gop_size = 12;
|
||||
c->max_b_frames = 2;
|
||||
c->b_frame_strategy = 1;
|
||||
c->dia_size = 4;
|
||||
|
||||
c->me_cmp = c->me_sub_cmp = FF_CMP_SAD;
|
||||
c->mb_cmp = FF_CMP_SSE;
|
||||
|
||||
c->last_predictor_count = 3;
|
||||
|
||||
c->flags |= CODEC_FLAG_4MV | CODEC_FLAG_QP_RD;
|
||||
|
||||
if(!strcmp(oc->oformat->name, "mp4") || !strcmp(oc->oformat->name, "mov") || !strcmp(oc->oformat->name, "3gp"))
|
||||
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
|
||||
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||
|
||||
return st;
|
||||
@ -147,7 +145,7 @@ struct VideoEncoderImpl
|
||||
as long as they're aligned enough for the architecture, and
|
||||
they're freed appropriately (such as using av_free for buffers
|
||||
allocated with av_malloc) */
|
||||
video_outbuf_size = bitrate*1000/framerate * 8;
|
||||
video_outbuf_size = c->width * c->height * 4;
|
||||
video_outbuf = (uint8_t*)av_malloc(video_outbuf_size);
|
||||
}
|
||||
|
||||
@ -215,7 +213,7 @@ struct VideoEncoderImpl
|
||||
|
||||
if (oc->oformat->flags & AVFMT_RAWPICTURE) {
|
||||
/* raw video case. The API will change slightly in the near
|
||||
futur for that */
|
||||
future for that */
|
||||
AVPacket pkt;
|
||||
av_init_packet(&pkt);
|
||||
|
||||
@ -233,7 +231,10 @@ struct VideoEncoderImpl
|
||||
AVPacket pkt;
|
||||
av_init_packet(&pkt);
|
||||
|
||||
pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
|
||||
if (c->coded_frame->pts == AV_NOPTS_VALUE)
|
||||
pkt.pts = AV_NOPTS_VALUE;
|
||||
else
|
||||
pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
|
||||
if(c->coded_frame->key_frame)
|
||||
pkt.flags |= PKT_FLAG_KEY;
|
||||
pkt.stream_index= st->index;
|
||||
@ -276,13 +277,15 @@ void log(void* v, int i, const char* format, va_list ap)
|
||||
wxLogDebug(L"[%d] %hs", i, buf);
|
||||
}
|
||||
|
||||
VideoEncoder::VideoEncoder(const wxString& filenameStr, int framerate, int bitrate, float duration)
|
||||
VideoEncoder::VideoEncoder(const wxString& filenameStr, int framerate, int bitrate, float duration, int width, int height)
|
||||
: m(new VideoEncoderImpl)
|
||||
{
|
||||
wxCharBuffer filename = filenameStr.ToAscii();
|
||||
m->framerate = framerate;
|
||||
m->bitrate = bitrate;
|
||||
m->duration = duration;
|
||||
m->width = width;
|
||||
m->height = height;
|
||||
|
||||
/* initialize libavcodec, and register all codecs and formats */
|
||||
av_register_all();
|
||||
@ -292,7 +295,7 @@ VideoEncoder::VideoEncoder(const wxString& filenameStr, int framerate, int bitra
|
||||
/* auto detect the output format from the name. default is mpeg. */
|
||||
m->fmt = guess_format(NULL, filename, NULL);
|
||||
if (!m->fmt) {
|
||||
printf("Could not deduce output format from file extension: using MPEG.\n");
|
||||
fprintf(stderr, "Could not deduce output format from file extension: using MPEG.\n");
|
||||
m->fmt = guess_format("mpeg", NULL, NULL);
|
||||
}
|
||||
if (!m->fmt) {
|
||||
@ -312,10 +315,11 @@ VideoEncoder::VideoEncoder(const wxString& filenameStr, int framerate, int bitra
|
||||
|
||||
/* add the audio and video streams using the default format codecs
|
||||
and initialize the codecs */
|
||||
m->video_st = NULL;
|
||||
if (m->fmt->video_codec != CODEC_ID_NONE) {
|
||||
m->video_st = m->add_video_stream(m->oc, m->fmt->video_codec);
|
||||
}
|
||||
// m->video_st = NULL;
|
||||
// if (m->fmt->video_codec != CODEC_ID_NONE) {
|
||||
// m->video_st = m->add_video_stream(m->oc, m->fmt->video_codec);
|
||||
// }
|
||||
m->video_st = m->add_video_stream(m->oc, CODEC_ID_FFV1);
|
||||
|
||||
/* set the output parameters (must be done even if no
|
||||
parameters). */
|
||||
@ -373,7 +377,7 @@ VideoEncoder::~VideoEncoder()
|
||||
av_write_trailer(m->oc);
|
||||
|
||||
/* free the streams */
|
||||
for(int i = 0; i < m->oc->nb_streams; i++) {
|
||||
for(unsigned int i = 0; i < m->oc->nb_streams; i++) {
|
||||
av_freep(&m->oc->streams[i]->codec);
|
||||
av_freep(&m->oc->streams[i]);
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ struct VideoEncoderImpl;
|
||||
class VideoEncoder
|
||||
{
|
||||
public:
|
||||
VideoEncoder(const wxString& filename, int framerate, int bitrate, float duration);
|
||||
VideoEncoder(const wxString& filename, int framerate, int bitrate, float duration, int width, int height);
|
||||
void Frame(const unsigned char* buffer);
|
||||
~VideoEncoder();
|
||||
|
||||
|
@ -178,9 +178,12 @@ void VideoRecorder::RecordCinematic(wxWindow* window, const wxString& trackName,
|
||||
|
||||
wxStopWatch sw;
|
||||
|
||||
VideoEncoder venc (dlg.m_Filename, dlg.m_Framerate, dlg.m_Bitrate, duration);
|
||||
// int w = 320, h = 240;
|
||||
int w = 640, h = 480;
|
||||
|
||||
qCinemaRecord qry(trackName.c_str(), dlg.m_Framerate, duration, Callback<sCinemaRecordCB>(&callback, (void*)&venc));
|
||||
VideoEncoder venc (dlg.m_Filename, dlg.m_Framerate, dlg.m_Bitrate, duration, w, h);
|
||||
|
||||
qCinemaRecord qry(trackName.c_str(), dlg.m_Framerate, duration, w, h, Callback<sCinemaRecordCB>(&callback, (void*)&venc));
|
||||
qry.Post();
|
||||
|
||||
wxLogMessage(_("Finished recording (took %.1f seconds)\n"), sw.Time()/1000.f);
|
||||
|
@ -276,6 +276,7 @@ BEGIN_EVENT_TABLE(ScenarioEditor, wxFrame)
|
||||
EVT_MENU(ID_Open, ScenarioEditor::OnOpen)
|
||||
EVT_MENU(ID_Save, ScenarioEditor::OnSave)
|
||||
EVT_MENU(ID_SaveAs, ScenarioEditor::OnSaveAs)
|
||||
EVT_MENU_RANGE(wxID_FILE1, wxID_FILE9, ScenarioEditor::OnMRUFile)
|
||||
|
||||
EVT_MENU(ID_Quit, ScenarioEditor::OnQuit)
|
||||
EVT_MENU(wxID_UNDO, ScenarioEditor::OnUndo)
|
||||
@ -296,6 +297,7 @@ AtlasWindowCommandProc& ScenarioEditor::GetCommandProc() { return g_CommandProc;
|
||||
|
||||
ScenarioEditor::ScenarioEditor(wxWindow* parent)
|
||||
: wxFrame(parent, wxID_ANY, _T(""), wxDefaultPosition, wxSize(1024, 768))
|
||||
, m_FileHistory(_T("Scenario Editor"))
|
||||
{
|
||||
// Global application initialisation:
|
||||
|
||||
@ -324,8 +326,8 @@ ScenarioEditor::ScenarioEditor(wxWindow* parent)
|
||||
menuFile->Append(ID_SaveAs, _("Save &As..."));
|
||||
menuFile->AppendSeparator();//-----------
|
||||
menuFile->Append(ID_Quit, _("E&xit"));
|
||||
// m_FileHistory.UseMenu(menuFile);//-------
|
||||
// m_FileHistory.AddFilesToMenu();
|
||||
m_FileHistory.UseMenu(menuFile);//-------
|
||||
m_FileHistory.AddFilesToMenu();
|
||||
}
|
||||
|
||||
// m_menuItem_Save = menuFile->FindItem(ID_Save); // remember this item, to let it be greyed out
|
||||
@ -352,6 +354,8 @@ ScenarioEditor::ScenarioEditor(wxWindow* parent)
|
||||
menuMisc->Append(ID_JavaScript, _("&JS console"));
|
||||
}
|
||||
|
||||
m_FileHistory.Load(*wxConfigBase::Get());
|
||||
|
||||
|
||||
m_SectionLayout.SetWindow(this);
|
||||
|
||||
@ -362,10 +366,10 @@ ScenarioEditor::ScenarioEditor(wxWindow* parent)
|
||||
|
||||
// (button label; tooltip text; image; internal tool name; section to switch to)
|
||||
toolbar->AddToolButton(_("Default"), _("Default"), _T("default.png"), _T(""), _T(""));
|
||||
toolbar->AddToolButton(_("Move"), _("Move/rotate object"), _T("moveobject.png"), _T("TransformObject"), _T("ObjectSidebar"));
|
||||
toolbar->AddToolButton(_("Elevation"), _("Alter terrain elevation"), _T("alterelevation.png"), _T("AlterElevation"), _T("TerrainSidebar"));
|
||||
toolbar->AddToolButton(_("Flatten"), _("Flatten terrain elevation"), _T("flattenelevation.png"), _T("FlattenElevation"), _T("TerrainSidebar"));
|
||||
toolbar->AddToolButton(_("Paint Terrain"), _("Paint terrain texture"), _T("paintterrain.png"), _T("PaintTerrain"), _T("TerrainSidebar"));
|
||||
toolbar->AddToolButton(_("Move"), _("Move/rotate object"), _T("moveobject.png"), _T("TransformObject"), _T("")/*_T("ObjectSidebar")*/);
|
||||
toolbar->AddToolButton(_("Elevation"), _("Alter terrain elevation"), _T("alterelevation.png"), _T("AlterElevation"), _T("")/*_T("TerrainSidebar")*/);
|
||||
toolbar->AddToolButton(_("Flatten"), _("Flatten terrain elevation"), _T("flattenelevation.png"), _T("FlattenElevation"), _T("")/*_T("TerrainSidebar")*/);
|
||||
toolbar->AddToolButton(_("Paint Terrain"), _("Paint terrain texture"), _T("paintterrain.png"), _T("PaintTerrain"), _T("")/*_T("TerrainSidebar")*/);
|
||||
|
||||
toolbar->Realize();
|
||||
SetToolBar(toolbar);
|
||||
@ -442,6 +446,8 @@ void ScenarioEditor::OnClose(wxCloseEvent&)
|
||||
{
|
||||
SetCurrentTool(_T(""));
|
||||
|
||||
m_FileHistory.Save(*wxConfigBase::Get());
|
||||
|
||||
POST_MESSAGE(Shutdown, ());
|
||||
|
||||
qExit().Post();
|
||||
@ -491,6 +497,30 @@ void ScenarioEditor::OnRedo(wxCommandEvent&)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ScenarioEditor::OpenFile(const wxString& name)
|
||||
{
|
||||
wxBusyInfo busy(_("Loading map"));
|
||||
wxBusyCursor busyc;
|
||||
|
||||
// TODO: Work when the map is not in .../maps/scenarios/
|
||||
std::wstring map = name.c_str();
|
||||
|
||||
// Deactivate tools, so they don't carry forwards into the new CWorld
|
||||
// and crash.
|
||||
SetCurrentTool(_T(""));
|
||||
// TODO: clear the undo buffer, etc
|
||||
|
||||
POST_MESSAGE(LoadMap, (map));
|
||||
|
||||
SetOpenFilename(name);
|
||||
|
||||
// Wait for it to load, while the wxBusyInfo is telling the user that we're doing that
|
||||
qPing qry;
|
||||
qry.Post();
|
||||
|
||||
// TODO: Make this a non-undoable command
|
||||
}
|
||||
|
||||
// TODO (eventually): replace all this file-handling stuff with the Workspace Editor
|
||||
|
||||
void ScenarioEditor::OnOpen(wxCommandEvent& WXUNUSED(event))
|
||||
@ -503,26 +533,7 @@ void ScenarioEditor::OnOpen(wxCommandEvent& WXUNUSED(event))
|
||||
wxString cwd = wxFileName::GetCwd();
|
||||
|
||||
if (dlg.ShowModal() == wxID_OK)
|
||||
{
|
||||
wxBusyInfo busy(_("Loading map"));
|
||||
wxBusyCursor busyc;
|
||||
|
||||
// TODO: Work when the map is not in .../maps/scenarios/
|
||||
std::wstring map = dlg.GetFilename().c_str();
|
||||
|
||||
// Deactivate tools, so they don't carry forwards into the new CWorld
|
||||
// and crash.
|
||||
SetCurrentTool(_T(""));
|
||||
// TODO: clear the undo buffer, etc
|
||||
|
||||
POST_MESSAGE(LoadMap, (map));
|
||||
|
||||
SetOpenFilename(dlg.GetFilename());
|
||||
|
||||
// Wait for it to load, while the wxBusyInfo is telling the user that we're doing that
|
||||
qPing qry;
|
||||
qry.Post();
|
||||
}
|
||||
OpenFile(dlg.GetFilename());
|
||||
|
||||
wxCHECK_RET(cwd == wxFileName::GetCwd(), _T("cwd changed"));
|
||||
// paranoia - MSDN says OFN_NOCHANGEDIR (used when we don't give wxCHANGE_DIR)
|
||||
@ -531,6 +542,13 @@ void ScenarioEditor::OnOpen(wxCommandEvent& WXUNUSED(event))
|
||||
// TODO: Make this a non-undoable command
|
||||
}
|
||||
|
||||
void ScenarioEditor::OnMRUFile(wxCommandEvent& event)
|
||||
{
|
||||
wxString file (m_FileHistory.GetHistoryFile(event.GetId() - wxID_FILE1));
|
||||
if (file.Len())
|
||||
OpenFile(file);
|
||||
}
|
||||
|
||||
void ScenarioEditor::OnSave(wxCommandEvent& event)
|
||||
{
|
||||
if (m_OpenFilename.IsEmpty())
|
||||
@ -584,6 +602,9 @@ void ScenarioEditor::SetOpenFilename(const wxString& filename)
|
||||
(filename.IsEmpty() ? wxString(_("(untitled)")) : filename).c_str()));
|
||||
|
||||
m_OpenFilename = filename;
|
||||
|
||||
if (! filename.IsEmpty())
|
||||
m_FileHistory.AddFileToHistory(filename);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define SCENARIOEDITOR_H__
|
||||
|
||||
#include "General/AtlasWindowCommandProc.h"
|
||||
#include "CustomControls/FileHistory/FileHistory.h"
|
||||
#include "SectionLayout.h"
|
||||
|
||||
class ScenarioEditor : public wxFrame
|
||||
@ -16,6 +17,7 @@ public:
|
||||
void OnOpen(wxCommandEvent& event);
|
||||
void OnSave(wxCommandEvent& event);
|
||||
void OnSaveAs(wxCommandEvent& event);
|
||||
void OnMRUFile(wxCommandEvent& event);
|
||||
|
||||
void OnQuit(wxCommandEvent& event);
|
||||
void OnUndo(wxCommandEvent& event);
|
||||
@ -27,6 +29,8 @@ public:
|
||||
void OnMediaPlayer(wxCommandEvent& event);
|
||||
void OnJavaScript(wxCommandEvent& event);
|
||||
|
||||
void OpenFile(const wxString& name);
|
||||
|
||||
static AtlasWindowCommandProc& GetCommandProc();
|
||||
|
||||
static float GetSpeedModifier();
|
||||
@ -38,6 +42,7 @@ private:
|
||||
|
||||
void SetOpenFilename(const wxString& filename);
|
||||
wxString m_OpenFilename;
|
||||
FileHistory m_FileHistory;
|
||||
|
||||
DECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
@ -15,6 +15,7 @@ enum
|
||||
ID_GenerateRMS,
|
||||
ID_SimPlay,
|
||||
ID_SimFast,
|
||||
ID_SimSlow,
|
||||
ID_SimPause,
|
||||
ID_SimReset
|
||||
};
|
||||
@ -24,8 +25,10 @@ enum
|
||||
SimInactive,
|
||||
SimPlaying,
|
||||
SimPlayingFast,
|
||||
SimPlayingSlow,
|
||||
SimPaused
|
||||
};
|
||||
bool IsPlaying(int s) { return (s == SimPlaying || s == SimPlayingFast || s == SimPlayingSlow); }
|
||||
|
||||
MapSidebar::MapSidebar(wxWindow* sidebarContainer, wxWindow* bottomBarContainer)
|
||||
: Sidebar(sidebarContainer, bottomBarContainer), m_SimState(SimInactive)
|
||||
@ -47,6 +50,7 @@ MapSidebar::MapSidebar(wxWindow* sidebarContainer, wxWindow* bottomBarContainer)
|
||||
wxStaticBoxSizer* sizer = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Simulation test"));
|
||||
sizer->Add(new wxButton(this, ID_SimPlay, _("Play")), wxSizerFlags().Proportion(1));
|
||||
sizer->Add(new wxButton(this, ID_SimFast, _("Fast")), wxSizerFlags().Proportion(1));
|
||||
sizer->Add(new wxButton(this, ID_SimSlow, _("Slow")), wxSizerFlags().Proportion(1));
|
||||
sizer->Add(new wxButton(this, ID_SimPause, _("Pause")), wxSizerFlags().Proportion(1));
|
||||
sizer->Add(new wxButton(this, ID_SimReset, _("Reset")), wxSizerFlags().Proportion(1));
|
||||
UpdateSimButtons();
|
||||
@ -85,9 +89,13 @@ void MapSidebar::UpdateSimButtons()
|
||||
wxCHECK(button, );
|
||||
button->Enable(m_SimState != SimPlayingFast);
|
||||
|
||||
button = wxDynamicCast(FindWindow(ID_SimSlow), wxButton);
|
||||
wxCHECK(button, );
|
||||
button->Enable(m_SimState != SimPlayingSlow);
|
||||
|
||||
button = wxDynamicCast(FindWindow(ID_SimPause), wxButton);
|
||||
wxCHECK(button, );
|
||||
button->Enable(m_SimState == SimPlaying || m_SimState == SimPlayingFast);
|
||||
button->Enable(IsPlaying(m_SimState));
|
||||
|
||||
button = wxDynamicCast(FindWindow(ID_SimReset), wxButton);
|
||||
wxCHECK(button, );
|
||||
@ -103,6 +111,11 @@ void MapSidebar::OnSimPlay(wxCommandEvent& event)
|
||||
speed = 8.f;
|
||||
newState = SimPlayingFast;
|
||||
}
|
||||
else if (event.GetId() == ID_SimSlow)
|
||||
{
|
||||
speed = 0.125f;
|
||||
newState = SimPlayingSlow;
|
||||
}
|
||||
|
||||
if (m_SimState == SimInactive)
|
||||
{
|
||||
@ -120,7 +133,7 @@ void MapSidebar::OnSimPlay(wxCommandEvent& event)
|
||||
|
||||
void MapSidebar::OnSimPause(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
if (m_SimState == SimPlaying || m_SimState == SimPlayingFast)
|
||||
if (IsPlaying(m_SimState))
|
||||
{
|
||||
POST_MESSAGE(SimPlay, (0.f));
|
||||
m_SimState = SimPaused;
|
||||
@ -130,7 +143,7 @@ void MapSidebar::OnSimPause(wxCommandEvent& WXUNUSED(event))
|
||||
|
||||
void MapSidebar::OnSimReset(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
if (m_SimState == SimPlaying || m_SimState == SimPlayingFast)
|
||||
if (IsPlaying(m_SimState))
|
||||
{
|
||||
POST_MESSAGE(SimPlay, (0.f));
|
||||
POST_MESSAGE(SimStateRestore, (L"default"));
|
||||
@ -149,6 +162,7 @@ BEGIN_EVENT_TABLE(MapSidebar, Sidebar)
|
||||
EVT_BUTTON(ID_GenerateRMS, MapSidebar::GenerateRMS)
|
||||
EVT_BUTTON(ID_SimPlay, MapSidebar::OnSimPlay)
|
||||
EVT_BUTTON(ID_SimFast, MapSidebar::OnSimPlay)
|
||||
EVT_BUTTON(ID_SimSlow, MapSidebar::OnSimPlay)
|
||||
EVT_BUTTON(ID_SimPause, MapSidebar::OnSimPause)
|
||||
EVT_BUTTON(ID_SimReset, MapSidebar::OnSimReset)
|
||||
END_EVENT_TABLE();
|
||||
|
@ -34,7 +34,7 @@ QUERYHANDLER(CinemaRecord)
|
||||
CCinemaManager* manager = g_Game->GetView()->GetCinema();
|
||||
manager->SetCurrentTrack(*msg->track, false, false, false);
|
||||
|
||||
const int w = 640, h = 480;
|
||||
const int w = msg->width, h = msg->height;
|
||||
|
||||
{
|
||||
g_Renderer.Resize(w, h);
|
||||
@ -44,6 +44,7 @@ QUERYHANDLER(CinemaRecord)
|
||||
}
|
||||
|
||||
unsigned char* img = new unsigned char [w*h*3];
|
||||
unsigned char* temp = new unsigned char[w*3];
|
||||
|
||||
int num_frames = msg->framerate * msg->duration;
|
||||
|
||||
@ -63,13 +64,14 @@ QUERYHANDLER(CinemaRecord)
|
||||
glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, img);
|
||||
|
||||
// Swap the rows around, else the image will be upside down
|
||||
char temp[w*3];
|
||||
//* // TODO: BGR24 output doesn't need flipping, YUV420 and RGBA32 do
|
||||
for (int y = 0; y < h/2; ++y)
|
||||
{
|
||||
memcpy2(temp, &img[y*w*3], w*3);
|
||||
memcpy2(&img[y*w*3], &img[(h-1-y)*w*3], w*3);
|
||||
memcpy2(&img[(h-1-y)*w*3], temp, w*3);
|
||||
}
|
||||
//*/
|
||||
|
||||
// Call the user-supplied function with this data, so they can
|
||||
// store it as a video
|
||||
@ -84,6 +86,7 @@ QUERYHANDLER(CinemaRecord)
|
||||
// TODO: delete the saved state now that we don't need it any more
|
||||
|
||||
delete[] img;
|
||||
delete[] temp;
|
||||
|
||||
// Restore viewport
|
||||
{
|
||||
|
@ -109,6 +109,8 @@ QUERY(CinemaRecord,
|
||||
((std::wstring, track))
|
||||
((int, framerate))
|
||||
((float, duration))
|
||||
((int, width))
|
||||
((int, height))
|
||||
((Callback<sCinemaRecordCB>, cb))
|
||||
,
|
||||
);
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "simulation/EntityManager.h"
|
||||
#include "simulation/EntityTemplate.h"
|
||||
#include "simulation/EntityTemplateCollection.h"
|
||||
#include "simulation/Projectile.h"
|
||||
#include "simulation/Simulation.h"
|
||||
|
||||
extern void (*Atlas_GLSwapBuffers)(void* context);
|
||||
@ -306,6 +307,7 @@ void ViewGame::RestoreState(const std::wstring& label)
|
||||
CUnitManager& unitMan = g_Game->GetWorld()->GetUnitManager();
|
||||
|
||||
// delete all existing entities
|
||||
g_Game->GetWorld()->GetProjectileManager().DeleteAll();
|
||||
g_EntityManager.deleteAll();
|
||||
|
||||
if (! simState->onlyEntities)
|
||||
|
@ -25,7 +25,7 @@ for my $f (@xml) {
|
||||
$parent = $1 if $data =~ /Parent="(.*?)"/;
|
||||
|
||||
my ($upgrade, $rank);
|
||||
$upgrade = $1 if $data =~ /Up.*newentity="(.*?)"/s;
|
||||
$upgrade = $1 if $data =~ /<Entity>\s*(.*?)\s*</s;
|
||||
$rank = $1 if $data =~ /Up.*rank="(.*?)"/s;
|
||||
|
||||
my $actor;
|
||||
|
Loading…
Reference in New Issue
Block a user