1
0
forked from 0ad/0ad

# 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:
Ykkrosh 2007-02-09 17:04:55 +00:00
parent 7c06199d0f
commit 5e3e78ca78
17 changed files with 221 additions and 100 deletions

View File

@ -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

View File

@ -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);

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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 )

View File

@ -86,6 +86,8 @@ public:
CProjectileManager();
~CProjectileManager();
void DeleteAll();
void UpdateAll( size_t timestep );
void InterpolateAll( double frametime );

View File

@ -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]);
}

View File

@ -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();

View File

@ -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);

View File

@ -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);
}
//////////////////////////////////////////////////////////////////////////

View File

@ -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();
};

View File

@ -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();

View File

@ -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
{

View File

@ -109,6 +109,8 @@ QUERY(CinemaRecord,
((std::wstring, track))
((int, framerate))
((float, duration))
((int, width))
((int, height))
((Callback<sCinemaRecordCB>, cb))
,
);

View File

@ -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)

View File

@ -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;