commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
608
include/modules/viewer_base/viewer_base.cpp
Normal file
608
include/modules/viewer_base/viewer_base.cpp
Normal file
@ -0,0 +1,608 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "viewer_base/viewer_base.h"
|
||||
#include "viewer_base/viewer_base_debugger.h"
|
||||
#include "physic_bullet/bullet_world.h"
|
||||
#include "io_archive/io_archive.h"
|
||||
#include "raytracer/raytracer_core.h"
|
||||
#include "font_freetype/ft2_font_factory.h"
|
||||
#include "script_squirrel/engine_vm_debugger.h"
|
||||
#include "script_squirrel/engine_vm.h"
|
||||
#include "script/script_variant.h"
|
||||
#include "ui/ui.h"
|
||||
#include "gpu/gpu_triangle_batch.h"
|
||||
#include "gpu/gpu_renderer.h"
|
||||
#include "core/embedded_resource_extractor.h"
|
||||
#include "core/renderer_toolbox.h"
|
||||
#include "metafile/nml_object.h"
|
||||
#include "picture/pict_io.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "filesystem/io_cfile.h"
|
||||
#include "input/input_system.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool ViewerBase::OpenViewer()
|
||||
{
|
||||
// Check core file system.
|
||||
if (!Platform::Get().io->Exists("@core/noise.tga"))
|
||||
__ERR__(__LOG_E__ << "@core is not properly mounted.\n", false)
|
||||
|
||||
// Embedded resources will be extracted to a ram disk.
|
||||
IEmbeddedResourceHandler::Set(new EmbeddedResourceExtractor(true));
|
||||
|
||||
// Create outputs.
|
||||
factories = new ResourceFactories;
|
||||
if (!CreateRenderer() || !CreateMixer())
|
||||
return false;
|
||||
|
||||
// Load renderer configuration.
|
||||
NML::Parser::Load(config_path, renderer->registry);
|
||||
|
||||
// Open output subsystems.
|
||||
if (!OpenVideo() || !OpenAudio())
|
||||
return false;
|
||||
|
||||
profiler_font[0] = new Render::RasterFont;
|
||||
profiler_font[0]->Load(*factories->render, "@core/fonts/profiler_base.nml", "@core/fonts/profiler_base");
|
||||
profiler_font[1] = new Render::RasterFont;
|
||||
profiler_font[1]->Load(*factories->render, "@core/fonts/profiler_bold.nml", "@core/fonts/profiler_bold");
|
||||
|
||||
fps_font = new Render::RasterFont;
|
||||
fps_font->Load(*factories->render, "@core/fonts/fps.nml", "@core/fonts/fps");
|
||||
|
||||
gpu_batch = new GPU::TriangleBatch((GPU::Renderer &)*renderer);
|
||||
|
||||
// Initialize input interface.
|
||||
Platform::Get().input_system->SetHandle(renderer->GetCurrentSystemWindowHandle());
|
||||
|
||||
state = SessionSetup;
|
||||
return true;
|
||||
}
|
||||
void ViewerBase::CloseViewer()
|
||||
{
|
||||
CloseSession();
|
||||
|
||||
for (uint n = 0; n < 2; ++n)
|
||||
_safe_delete(profiler_font[n]);
|
||||
_safe_delete(fps_font);
|
||||
|
||||
factories = NULL;
|
||||
|
||||
if (renderer.IsValid())
|
||||
{
|
||||
renderer->Close();
|
||||
renderer = NULL;
|
||||
}
|
||||
if (mixer.IsValid())
|
||||
{
|
||||
mixer->Close();
|
||||
mixer = NULL;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool ViewerBase::SetupSessionSource() // session
|
||||
{
|
||||
switch (session_source)
|
||||
{
|
||||
case SessionSourceFilesystem:
|
||||
Platform::Get().io->Mount(new IO::CFile(session_source_path));
|
||||
break;
|
||||
case SessionSourceArchive:
|
||||
Platform::Get().io->Mount(new IO::Archive(session_source_path));
|
||||
break;
|
||||
case SessionSourceArchiveBootstrap:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool ViewerBase::OpenScriptVM() // session
|
||||
{
|
||||
// Compile core library.
|
||||
if (!script_vm->CompileFile("@core/script/nad.nut"))
|
||||
return false;
|
||||
|
||||
// Set defines.
|
||||
ListForeachPtr(Variant *, prop, define_list)
|
||||
script_vm->Set(prop->id, *prop);
|
||||
|
||||
// Load optional includes.
|
||||
for (uint n = 0; n < include_list.GetCount(); ++n)
|
||||
if (!script_vm->CompileFile(include_list.ObjectAt(n)))
|
||||
return false;
|
||||
|
||||
// Compile bootstrap.
|
||||
if (!bootstrap_script.IsEmpty() && !script_vm->Compile(bootstrap_script, bootstrap_script.Len(), NULL, "Bootstrap"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
void ViewerBase::SetVMGlobals()
|
||||
{
|
||||
script_vm->Set("g_project", Script::Variant(project, Script::typetag_Project));
|
||||
|
||||
script_vm->Set("g_factory", Script::Variant(factories, Script::typetag_ResourceFactories));
|
||||
script_vm->Set("g_render", Script::Variant(renderer, Script::typetag_Renderer));
|
||||
script_vm->Set("g_mixer", Script::Variant(mixer, Script::typetag_Mixer));
|
||||
|
||||
script_vm->Set("g_dt_frame", 1.f / 60.f);
|
||||
script_vm->Set("g_raw_dt_frame", 1.f / 60.f);
|
||||
script_vm->Set("g_clock", 0);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool ViewerBase::LoadSessionData()
|
||||
{
|
||||
if (remote)
|
||||
session_type = remote_scene.isEmpty() ? SessionProject : SessionScene;
|
||||
|
||||
__LOG__ << "Session type: " << session_type << "\n";
|
||||
|
||||
using namespace NML;
|
||||
|
||||
if (session_type == SessionProject)
|
||||
{
|
||||
if (!remote)
|
||||
{
|
||||
if (!LoadFromFile(*project, input_path))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if (!LoadFromFile(*project, remote_project))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!project->Open(session_type == SessionProject))
|
||||
return false;
|
||||
|
||||
switch (session_type)
|
||||
{
|
||||
case SessionScene:
|
||||
{
|
||||
// Determine the scene type.
|
||||
if (!remote)
|
||||
if (!Parser::Load(input_path, remote_scene)) // load local scene over the remote_scene meta file
|
||||
return false;
|
||||
|
||||
Tag *t_scene2d = remote_scene.GetTag("Scene2D"),
|
||||
*t_scene3d = remote_scene.GetTag("Scene");
|
||||
|
||||
//
|
||||
if (t_scene3d)
|
||||
{
|
||||
scene_3d = new S3D::Scene(script_vm);
|
||||
scene_3d->SetClock(project->clock);
|
||||
|
||||
if (!scene_3d->Create(project->iproject_factory->NewPhysicWorld()))
|
||||
return false;
|
||||
if (!scene_3d->FromMetaTag(*t_scene3d, tool_mode ? ToolPreview : NoTool))
|
||||
return false;
|
||||
|
||||
scene_3d->name = input_path;
|
||||
scene_3d->SetAsScriptGlobalScene();
|
||||
scene_3d->InstanceSetup();
|
||||
scene_3d->RenderSetup(factories);
|
||||
scene_3d->Setup(tool_mode ? ToolPreview : NoTool);
|
||||
scene_3d->Reset();
|
||||
}
|
||||
else if (t_scene2d)
|
||||
{
|
||||
scene_2d = new S2D::Scene(script_vm);
|
||||
scene_2d->SetClock(project->clock);
|
||||
|
||||
if (!scene_2d->FromMetaTag(*t_scene2d, tool_mode ? ToolPreview : NoTool))
|
||||
return false;
|
||||
|
||||
scene_2d->name = input_path;
|
||||
scene_2d->SetAsScriptGlobalScene();
|
||||
scene_2d->RenderSetup(factories);
|
||||
scene_2d->Setup();
|
||||
scene_2d->Reset();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SessionProject:
|
||||
project->Setup();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool ViewerBase::OpenSession()
|
||||
{
|
||||
if (!OpenScriptVM())
|
||||
return false;
|
||||
|
||||
missing_resource = false;
|
||||
|
||||
// Create project.
|
||||
struct ProjectFactory : public IProjectFactory
|
||||
{ S3D::PhysicWorld *NewPhysicWorld() const { return new S3D::BulletWorld; } };
|
||||
|
||||
project = new Project(factories, new Freetype2FontFactory, script_vm);
|
||||
project->iproject_factory = new ProjectFactory;
|
||||
|
||||
SetVMGlobals();
|
||||
|
||||
// Setup data source.
|
||||
if (!SetupSessionSource())
|
||||
return false;
|
||||
|
||||
// Load viewer data.
|
||||
if (!LoadSessionData())
|
||||
return false;
|
||||
|
||||
time_start = Platform::Get().GetClock();
|
||||
return true;
|
||||
}
|
||||
void ViewerBase::CloseSession()
|
||||
{
|
||||
paused = false;
|
||||
|
||||
scene_2d = NULL;
|
||||
scene_3d = NULL;
|
||||
project = NULL;
|
||||
|
||||
// [EJ] explicitly close the VM now as is may hold references to render resources
|
||||
if (script_vm.IsValid())
|
||||
script_vm->Close();
|
||||
|
||||
// script_vm = NULL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void ViewerBase::ExecuteSession()
|
||||
{
|
||||
if (scene_3d)
|
||||
scene_3d->profiler.ResetProfiles();
|
||||
|
||||
project->ResetStatistics();
|
||||
renderer->ResetStatistics();
|
||||
|
||||
// Start frame.
|
||||
if (!paused)
|
||||
{
|
||||
project->clock->Update();
|
||||
project->UpdateScriptClock();
|
||||
}
|
||||
|
||||
float x = 32, y = 32;
|
||||
bool end_session = false;
|
||||
|
||||
switch (session_type)
|
||||
{
|
||||
case SessionScene:
|
||||
if (scene_2d.IsValid())
|
||||
{
|
||||
renderer->Clear(0, 0, 0);
|
||||
|
||||
if (!paused)
|
||||
scene_2d->Update();
|
||||
|
||||
// nGPUTriangleBatch batch(*renderer);
|
||||
scene_2d->Render(*renderer/*, &batch*/);
|
||||
}
|
||||
if (scene_3d.IsValid())
|
||||
{
|
||||
if (!paused)
|
||||
scene_3d->Update();
|
||||
scene_3d->Render(*renderer);
|
||||
scene_3d->RenderUI(*renderer, gpu_batch);
|
||||
|
||||
// Viewer-specific
|
||||
{
|
||||
if (enable_profiler)
|
||||
scene_3d->DrawProfilerText(*renderer, profiler_font, x, y);
|
||||
|
||||
if (scene_3d->flags.IsSet(S3D::Scene::FlagEnd))
|
||||
end_session = true;
|
||||
|
||||
if (!raytrace_path.IsEmpty())
|
||||
{
|
||||
int w = raytrace_width == -1 ? width : raytrace_width,
|
||||
h = raytrace_height == -1 ? height : raytrace_height;
|
||||
|
||||
__LOG_H__ << "Raytracing frame " << frame_count << " (" << w << "x" << h << ")...\n";
|
||||
Raytrace::Raytracer ray(factories->graphic);
|
||||
|
||||
if (ray.SetScene(scene_3d))
|
||||
{
|
||||
Picture out;
|
||||
ray.GetConfiguration().aa_sample = raytrace_aa;
|
||||
if (ray.Render(out, w, h))
|
||||
PictureIO::Get().TgaSave(out, String::Format("%s/out_%05d.tga", raytrace_path.c_str(), frame_count));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SessionProject:
|
||||
if (!paused)
|
||||
project->Update(SceneUpdateAll);
|
||||
|
||||
project->Render(*renderer);
|
||||
|
||||
// Viewer-specific
|
||||
{
|
||||
if (enable_profiler)
|
||||
project->DrawProfilerText(*renderer, profiler_font, x, y);
|
||||
|
||||
if (project->flags.IsSet(Project::ProjectFlagEnd))
|
||||
end_session = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// End frame.
|
||||
fRect viewport = renderer->GetViewport();
|
||||
|
||||
if (enable_profiler)
|
||||
{
|
||||
float x = viewport.GetWidth() - 400.f, y = 32.f;
|
||||
renderer->DrawProfilerText(profiler_font, x, y);
|
||||
}
|
||||
else if (memory_profiler)
|
||||
{
|
||||
float x = 0, y = 0;
|
||||
DrawAllocProfilerText(*renderer, profiler_font, x, y);
|
||||
}
|
||||
|
||||
if (enable_profiler || display_fps)
|
||||
{
|
||||
Color shadow(0, 0, 0, 0.5);
|
||||
Render::Renderer::WriterConfig config(false);
|
||||
|
||||
float x = 32, y = viewport.GetHeight() - 102;
|
||||
renderer->Write(*fps_font, String::Format("%02.01f\n", fps.GetFps()), x, y, config, 1, &shadow);
|
||||
y = viewport.GetHeight() - 112;
|
||||
renderer->Write(*fps_font, String::Format("%02.01f\n", fps.GetFps()), x, y, config);
|
||||
}
|
||||
|
||||
renderer->ShowFrame();
|
||||
frame_count++;
|
||||
|
||||
// Pause support.
|
||||
/* if (Input::Device *keyboard = Platform::Get().input_system->GetDevice("keyboard"))
|
||||
if (keyboard->WasPressed(Input::Device::Key_P))
|
||||
{
|
||||
paused = !paused;
|
||||
if (!paused)
|
||||
project->clock->EatDeltaClock();
|
||||
}
|
||||
*/
|
||||
// Check session runtime error.
|
||||
if (CheckRuntimeError())
|
||||
end_session = true;
|
||||
if (time_live && ((Platform::Get().GetClock() - time_start) > (time_live * Platform::Get().GetClockFrequency())))
|
||||
end_session = true;
|
||||
|
||||
if (end_session)
|
||||
state = SessionClose;
|
||||
}
|
||||
bool ViewerBase::CheckRuntimeError()
|
||||
{
|
||||
// Check VM state.
|
||||
switch (script_vm->GetState())
|
||||
{
|
||||
case Script::IVM::StateDead:
|
||||
case Script::IVM::StateExceptionThrown:
|
||||
return true;
|
||||
|
||||
case Script::IVM::StateOk:
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for a missing resource error.
|
||||
if (missing_resource && !ignore_missing_resource)
|
||||
__ERR__(__LOG_E__ << "Closing session due to missing resources.\n", true)
|
||||
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Script::NetworkDebugger *ViewerBase::CreateVMDebugInterface()
|
||||
{
|
||||
return new Script::ViewerBaseDebugger(*this, new Script::EngineDebugger((Script::EngineVM &)*script_vm), NULL, remote_port);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
ViewerBase::State ViewerBase::Execute()
|
||||
{
|
||||
fps.MarkLoop();
|
||||
|
||||
Platform::Get().input_system->Update();
|
||||
bool platform_update = PlatformUpdate();
|
||||
|
||||
switch (state)
|
||||
{
|
||||
//----------------------------------------------------------------------
|
||||
case ViewerSetup:
|
||||
script_vm = new Script::EngineVM;
|
||||
script_vm->Open();
|
||||
|
||||
if (active_debug)
|
||||
script_vm->SetDebugInterface(script_debugger, true);
|
||||
|
||||
if (remote)
|
||||
{
|
||||
script_debugger = CreateVMDebugInterface();
|
||||
script_vm->SetDebugInterface(script_debugger, true);
|
||||
|
||||
// @FIXME make sure the network thread is running ok.
|
||||
|
||||
__LOG_H__ << "Waiting for controller connection...\n";
|
||||
state = WaitRemoteController;
|
||||
}
|
||||
else
|
||||
state = SessionSetup; // local setup done
|
||||
break;
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
case WaitRemoteController:
|
||||
if (script_debugger && script_debugger->IsConnected())
|
||||
{
|
||||
__LOG_H__ << "Controller connected.\n";
|
||||
state = WaitRemoteSetup;
|
||||
}
|
||||
if (!platform_update)
|
||||
state = ViewerClose;
|
||||
break;
|
||||
|
||||
case WaitRemoteSetup:
|
||||
if (script_debugger && !script_debugger->IsConnected())
|
||||
{
|
||||
__LOG_H__ << "Controller lost, waiting for controller connection...\n";
|
||||
state = WaitRemoteController;
|
||||
}
|
||||
break; // state will be altered by the monitor
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
case SessionSetup:
|
||||
if (OpenViewer() && OpenSession())
|
||||
{
|
||||
__LOG_H__ << "Session running.\n";
|
||||
state = SessionRunning;
|
||||
}
|
||||
else
|
||||
state = remote ? WaitRemoteSetup : SessionClose;
|
||||
break;
|
||||
|
||||
case SessionRunning:
|
||||
ExecuteSession();
|
||||
|
||||
if (state == SessionRunning)
|
||||
{
|
||||
if (script_debugger && !script_debugger->IsConnected())
|
||||
state = SessionClose;
|
||||
|
||||
if (!platform_update)
|
||||
state = SessionClose;
|
||||
}
|
||||
|
||||
if (state != SessionRunning)
|
||||
__LOG_H__ << "Closing session.\n";
|
||||
break;
|
||||
|
||||
case SessionClose:
|
||||
CloseSession();
|
||||
CloseViewer();
|
||||
|
||||
if (remote)
|
||||
{
|
||||
script_debugger->Stop();
|
||||
|
||||
if (remote_fs.IsValid())
|
||||
{
|
||||
Platform::Get().io->Unmount(remote_fs);
|
||||
remote_fs = NULL;
|
||||
}
|
||||
|
||||
state = ViewerSetup;
|
||||
}
|
||||
else
|
||||
state = ViewerClose;
|
||||
break;
|
||||
|
||||
case ViewerClose:
|
||||
break;
|
||||
}
|
||||
|
||||
if (script_debugger)
|
||||
while (script_debugger->async.Execute());
|
||||
|
||||
Platform::Get().Sleep(1);
|
||||
return state;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void ViewerBase::Suspend() // app sent to background (iOS/Android)
|
||||
{
|
||||
if (script_vm && script_vm->SetupFunctionCall("OnSuspend"))
|
||||
script_vm->DoFunctionCall();
|
||||
if (mixer)
|
||||
mixer->SuspendWorkerThread();
|
||||
}
|
||||
void ViewerBase::Resume() // app sent back to foreground (iOS/Android)
|
||||
{
|
||||
if (script_vm && script_vm->SetupFunctionCall("OnResume"))
|
||||
script_vm->DoFunctionCall();
|
||||
if (mixer)
|
||||
mixer->ResumeWorkerThread();
|
||||
|
||||
if (project.IsValid())
|
||||
project->clock->EatDeltaClock();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
ViewerBase::ViewerBase()
|
||||
{
|
||||
state = ViewerSetup;
|
||||
|
||||
paused = false;
|
||||
missing_resource = false;
|
||||
|
||||
time_start = 0;
|
||||
time_live = 0;
|
||||
frame_count = 0;
|
||||
|
||||
raytrace_width = -1;
|
||||
raytrace_height = -1;
|
||||
|
||||
session_source = SessionSourceFilesystem;
|
||||
session_type = SessionScene;
|
||||
session_source_path = "./";
|
||||
input_path = "scene.nms";
|
||||
|
||||
active_debug = false;
|
||||
|
||||
remote = false;
|
||||
remote_port = 999;
|
||||
|
||||
tool_mode = false;
|
||||
|
||||
script_debugger = NULL;
|
||||
|
||||
safe_mode = false;
|
||||
ignore_esc = false;
|
||||
ignore_missing_resource = false;
|
||||
fullscreen = false;
|
||||
|
||||
enable_profiler = false;
|
||||
memory_profiler = false;
|
||||
display_fps = false;
|
||||
|
||||
enable_pause = false;
|
||||
|
||||
for (int n = 0; n < 2; ++n)
|
||||
profiler_font[n] = NULL;
|
||||
fps_font = NULL;
|
||||
|
||||
width = 800;
|
||||
height = 600;
|
||||
aspect_ratio = 1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
431
include/modules/viewer_base/viewer_base_command_line.cpp
Normal file
431
include/modules/viewer_base/viewer_base_command_line.cpp
Normal file
@ -0,0 +1,431 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "viewer_base/viewer_base.h"
|
||||
#include <iostream>
|
||||
#include "io_archive/io_archive.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "core/engine.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "filesystem/io_cfile.h"
|
||||
#include "platform.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
// [EJ] 4/4: Do not use Log to output the command line as it will be eaten by a release build.
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void ViewerBase::PrintHeader()
|
||||
{
|
||||
std::cout << "GameStart stand-alone.\n";
|
||||
std::cout << "http://www.gamestart3d.com\n";
|
||||
std::cout << "Version: " << Core::Version << "\n";
|
||||
std::cout << "Emmanuel Julien 2001-2013.\n\n";
|
||||
}
|
||||
String ViewerBase::GetBaseCommandLineParm() const
|
||||
{
|
||||
String parm;
|
||||
|
||||
parm << "Basic usage:\n\n";
|
||||
parm << "-P : Execute a project (default: execute scene).\n";
|
||||
parm << "-C <config path> : Configuration file path.\n";
|
||||
parm << "\n";
|
||||
|
||||
parm << "Data source (default: -f ./):\n\n";
|
||||
parm << "-f <base path> : Input data from the file system.\n";
|
||||
parm << "-A <archive path> : Input data from an archive.\n";
|
||||
parm << "-version <name> : Run a specific project version.\n";
|
||||
parm << "\n";
|
||||
|
||||
parm << "Resource path:\n\n";
|
||||
parm << "-CC <path> : Mount a file system directory as core.\n";
|
||||
parm << "-MD <path> <mount> : Mount a file system directory.\n";
|
||||
parm << "-S <path> : Add search path.\n";
|
||||
parm << "\n";
|
||||
|
||||
parm << "Data output (default: -r gl2 -m al):\n\n";
|
||||
parm << "-r <ID> : Output renderer ('list' for details).\n";
|
||||
parm << "-m <ID> : Output audio mixer ('nengine dummy -m list' for valid IDs).\n";
|
||||
parm << "-w <Width> : Display width in pixels.\n";
|
||||
parm << "-h <Height> : Display height in pixels.\n";
|
||||
parm << "\n";
|
||||
|
||||
parm << "Script interface:\n\n";
|
||||
parm << "-I <include> : Include a script.\n";
|
||||
parm << "-Ds <var> <string> : Define and initialize a variable.\n";
|
||||
parm << "-Di <var> <int> : Define and initialize a variable.\n";
|
||||
parm << "-Df <var> <float> : Define and initialize a variable.\n";
|
||||
parm << "\n";
|
||||
|
||||
parm << "Raytracer interface (scene view only):\n\n";
|
||||
parm << "-R <path> : Raytrace each frame to a directory.\n";
|
||||
parm << "-Rw <int> : Specify the raytracer frame width.\n";
|
||||
parm << "-Rh <int> : Specify the raytracer frame height.\n";
|
||||
parm << "-Raa <int> : Specify the raytracer AA grid size (default: 4).\n";
|
||||
parm << "\n";
|
||||
|
||||
parm << "Program flags:\n\n";
|
||||
parm << "-remote : Start the viewer in remote mode (must be first argument).\n";
|
||||
parm << "-remote_port <int> : Set the remote mode listening port.\n";
|
||||
parm << "\n";
|
||||
parm << "-ignore_esc : Do not exit when escape is pressed.\n";
|
||||
parm << "-ignore_missing : Do not exit on missing resource.\n";
|
||||
parm << "-ignore_bootstrap : Ignore the bootstrap file.\n";
|
||||
parm << "\n";
|
||||
parm << "-tool_mode : Execute as if ran in the editor.\n";
|
||||
parm << "-safe_mode : Enable renderer/mixer safe-mode.\n";
|
||||
parm << "\n";
|
||||
parm << "-enable_pause : Enable 'p' key to pause engine.\n";
|
||||
parm << "\n";
|
||||
parm << "-fallback_disk_fs : Enable disk file system fallback.\n";
|
||||
parm << "\n";
|
||||
parm << "-enable_profiler : Enable on-screen performance profiler.\n";
|
||||
parm << "-memory_profiler : Enable on-screen memory profiler.\n";
|
||||
parm << "\n";
|
||||
parm << "-log_level <mask> : Set the engine log level mask (eg. -log_level !S*).\n";
|
||||
parm << " n: None\n";
|
||||
parm << " s: Standard\n";
|
||||
parm << " H: Header\n";
|
||||
parm << " *: Warning\n";
|
||||
parm << " !: Error\n";
|
||||
parm << " V: Verbose\n";
|
||||
parm << " S: Script\n";
|
||||
parm << " a: All (default)\n";
|
||||
parm << "-time_live <sec> : Set runtime time-to-live in seconds.\n";
|
||||
|
||||
return parm;
|
||||
}
|
||||
void ViewerBase::PrintUsage()
|
||||
{
|
||||
std::cout << "Usage: gsviewer input(.nms|.ngp) <-P> <-f|-A> <-S>\n\n";
|
||||
std::cout << GetBaseCommandLineParm() << "\n";
|
||||
PrintAdditionalUsage();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool ViewerBase::LocateAndParseBootstrap(Stack <String> &_arg)
|
||||
{
|
||||
SharedPtr <IO::Base> io;
|
||||
AutoPtr <IO::Handle> h;
|
||||
|
||||
// Look for a naked bootstrap file.
|
||||
if ((h = Platform::Get().io->Open("bootstrap.txt")) != NULL)
|
||||
session_source = SessionSourceFilesystem;
|
||||
|
||||
else
|
||||
{
|
||||
// Mount core to default archive.
|
||||
io = new IO::Archive("@root/native/000.gsa");
|
||||
Platform::Get().io->Mount(io, "@core/");
|
||||
|
||||
// Look for an archived bootstrap.
|
||||
h = Platform::Get().io->Open("@core/bootstrap.txt");
|
||||
if (h.IsNull())
|
||||
{
|
||||
Platform::Get().io->Unmount("@core/"); // [EJ] unmount on fail to locate bootstrap
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set archive as the data source.
|
||||
session_source = SessionSourceArchiveBootstrap;
|
||||
Platform::Get().io->Mount(io);
|
||||
}
|
||||
|
||||
// Parse bootstrap.
|
||||
String bootstrap;
|
||||
|
||||
size_t s = h->GetSize();
|
||||
Array <char> s_buffer(s);
|
||||
h->Read(s_buffer, s);
|
||||
|
||||
bootstrap.Set(s_buffer.c_ptr(), &s_buffer.c_ptr()[s]);
|
||||
bootstrap.Split(" ", _arg, '\"');
|
||||
|
||||
h = NULL;
|
||||
return true;
|
||||
}
|
||||
void ViewerBase::SetupVersion(const char *name)
|
||||
{
|
||||
using namespace NML;
|
||||
|
||||
File file;
|
||||
if (!Parser::Load("@root/.reserved/versions.rls", file))
|
||||
return;
|
||||
|
||||
if (Tag *versions = file.GetTag("Versions;"))
|
||||
{
|
||||
NMLTagForeach(v, *versions)
|
||||
if (Tag *n = v->GetTypedTag("Name", Variant::VariantString))
|
||||
if (String(n->GetString()) == name)
|
||||
if (Tag *s = v->GetTypedTag("BootstrapScript", Variant::VariantString))
|
||||
{
|
||||
bootstrap_script = s->GetString();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ViewerBase::ParseCommandLine(Stack <String> &_arg)
|
||||
{
|
||||
if ((_arg.GetCount() < 1) && !LocateAndParseBootstrap(_arg))
|
||||
__ERR__(PrintUsage(), false)
|
||||
|
||||
session_type = SessionScene; // assume scene session
|
||||
|
||||
// Remote is a special flag
|
||||
int n = 0;
|
||||
if (_arg[0] != "-remote")
|
||||
input_path = _arg[n++];
|
||||
|
||||
// Parse optional arguments.
|
||||
int narg = (int)_arg.GetCount();
|
||||
for ( ; n < narg; ++n)
|
||||
{
|
||||
String arg(_arg[n]);
|
||||
|
||||
if (arg == "-P")
|
||||
session_type = SessionProject;
|
||||
|
||||
// Version.
|
||||
else if (arg == "-version")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-version: Missing version name.\n", false);
|
||||
SetupVersion(_arg[n]);
|
||||
}
|
||||
|
||||
// Time to live.
|
||||
else if (arg == "-time_live")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-time_live: Missing mask.\n", false);
|
||||
time_live = String::atoi(_arg[n]);
|
||||
}
|
||||
|
||||
// Log filter.
|
||||
else if (arg == "-log_level")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-log_level: Missing mask.\n", false);
|
||||
|
||||
uint mask = 0;
|
||||
for (const char *p_flag = _arg[n]; p_flag[0]; ++p_flag)
|
||||
switch (p_flag[0])
|
||||
{
|
||||
case 'n': mask = EngineLogNone; break;
|
||||
case 's': mask |= EngineLogStandard; break;
|
||||
case 'H': mask |= EngineLogHeader; break;
|
||||
case '*': mask |= EngineLogWarning; break;
|
||||
case '!': mask |= EngineLogError; break;
|
||||
case 'V': mask |= EngineLogVerbose; break;
|
||||
case 'S': mask |= EngineLogScript; break;
|
||||
case 'a': mask |= EngineLogAll; break;
|
||||
}
|
||||
|
||||
LogSystem::Get().GetLog().SetLogLevel(mask);
|
||||
}
|
||||
|
||||
else if (arg == "-debug")
|
||||
active_debug = true;
|
||||
|
||||
else if (arg == "-ignore_bootstrap")
|
||||
ignore_bootstrap = true;
|
||||
else if (arg == "-ignore_esc")
|
||||
ignore_esc = true;
|
||||
else if (arg == "-ignore_missing")
|
||||
ignore_missing_resource = true;
|
||||
|
||||
else if (arg == "-tool_mode")
|
||||
tool_mode = true;
|
||||
|
||||
else if (arg == "-fallback_disk_fs")
|
||||
Platform::Get().io->Mount(new IO::CFile);
|
||||
|
||||
else if (arg == "-safe_mode")
|
||||
safe_mode = true;
|
||||
|
||||
else if (arg == "-enable_profiler")
|
||||
enable_profiler = true;
|
||||
else if (arg == "-memory_profiler")
|
||||
memory_profiler = true;
|
||||
|
||||
else if (arg == "-enable_pause")
|
||||
enable_pause = true;
|
||||
|
||||
// Config path.
|
||||
else if (arg == "-C")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-C: Missing configuration file path.\n", false);
|
||||
config_path = _arg[n];
|
||||
}
|
||||
|
||||
// File system source.
|
||||
else if (arg == "-f")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-f: Missing root path.\n", false);
|
||||
session_source_path = _arg[n];
|
||||
session_source = SessionSourceFilesystem;
|
||||
}
|
||||
|
||||
// Archive source.
|
||||
else if (arg == "-A")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-A: Missing archive path.\n", false);
|
||||
session_source_path = _arg[n];
|
||||
session_source = SessionSourceArchive;
|
||||
}
|
||||
|
||||
// Renderer.
|
||||
else if (arg == "-r")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-r: Missing renderer id.\n", false);
|
||||
s_render = _arg[n];
|
||||
}
|
||||
|
||||
else if (arg == "-w")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-w: Missing width value.\n", false);
|
||||
width = String::atoi(_arg[n]);
|
||||
}
|
||||
else if (arg == "-h")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-h: Missing height value.\n", false);
|
||||
height = String::atoi(_arg[n]);
|
||||
}
|
||||
|
||||
// Mixer.
|
||||
else if (arg == "-m")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-m: Missing mixer id.\n", false);
|
||||
s_mixer = _arg[n];
|
||||
}
|
||||
|
||||
// Search path.
|
||||
else if (arg == "-S")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-S: Missing search path.\n", false);
|
||||
|
||||
Platform::Get().io->Mount(new IO::CFile(_arg[n]));
|
||||
}
|
||||
|
||||
// Mount core.
|
||||
else if (arg == "-CC")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-CC: Missing core path.\n", false);
|
||||
|
||||
String c_path = _arg[n];
|
||||
Platform::Get().io->Mount(new IO::CFile(c_path), "@core/");
|
||||
Platform::Get().io->Mount(new IO::CFile(c_path)); // FIXME
|
||||
}
|
||||
|
||||
// Mount point.
|
||||
else if (arg == "-MD")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-MD: Missing directory path.\n", false);
|
||||
String dir_path = _arg[n];
|
||||
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-MD: Missing mount point.\n", false);
|
||||
String mount_point = _arg[n];
|
||||
|
||||
Platform::Get().io->Mount(new IO::CFile(dir_path), mount_point);
|
||||
}
|
||||
|
||||
// Raytrace path.
|
||||
else if (arg == "-R")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-R: Missing raytracer output path.\n", false);
|
||||
raytrace_path = _arg[n];
|
||||
}
|
||||
|
||||
// Raytrace width.
|
||||
else if (arg == "-Rw")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-Rw: Missing raytracer frame width.\n", false);
|
||||
raytrace_width = String::atoi(_arg[n]);
|
||||
}
|
||||
|
||||
// Raytrace height.
|
||||
else if (arg == "-Rh")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-Rh: Missing raytracer frame height.\n", false);
|
||||
raytrace_height = String::atoi(_arg[n]);
|
||||
}
|
||||
|
||||
// Raytrace AA.
|
||||
else if (arg == "-Raa")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-Raa: Missing raytracer AA grid size.\n", false);
|
||||
raytrace_aa = String::atoi(_arg[n]);
|
||||
}
|
||||
|
||||
// Include.
|
||||
else if (arg == "-I")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-I: Missing include path.\n", false);
|
||||
|
||||
if (!include_list.Add(_arg[n]))
|
||||
__ERR__(__LOG_E__ << "Failed to allocate include structure.\n", false);
|
||||
}
|
||||
|
||||
// Variable.
|
||||
else if (arg == "-Ds")
|
||||
{
|
||||
n += 2;
|
||||
if (n == narg)
|
||||
__ERR__(__LOG_E__ << "-Ds: Incomplete key-value pair. (eg. -Ds my_var \"String Value\")\n", false);
|
||||
Variant *yo = new Variant(_arg[n - 1], _arg[n]);
|
||||
if (!define_list.Add(new Variant(_arg[n - 1], _arg[n])))
|
||||
__ERR__(__LOG_E__ << "Failed to allocate define structure.\n", false);
|
||||
}
|
||||
|
||||
// Variable.
|
||||
else if (arg == "-Di")
|
||||
{
|
||||
n += 2;
|
||||
if (n == narg)
|
||||
__ERR__(__LOG_E__ << "-Di: Incomplete key-value pair. (eg. -Di my_var 5)\n", false);
|
||||
|
||||
if (!define_list.Add(new Variant(_arg[n - 1], String::atoi(_arg[n]))))
|
||||
__ERR__(__LOG_E__ << "Failed to allocate define structure.\n", false);
|
||||
}
|
||||
|
||||
// Variable.
|
||||
else if (arg == "-Df")
|
||||
{
|
||||
n += 2;
|
||||
if (n == narg)
|
||||
__ERR__(__LOG_E__ << "-Df: Incomplete key-value pair. (eg. -Df my_var 5.5)\n", false);
|
||||
|
||||
if (!define_list.Add(new Variant(_arg[n - 1], String::atof(_arg[n]))))
|
||||
__ERR__(__LOG_E__ << "Failed to allocate define structure.\n", false);
|
||||
}
|
||||
|
||||
else if (!OnUnknownCommandLineParam(_arg, n))
|
||||
__ERR__(__LOG_E__ << "Unknown command line parameter '" << arg << "'\n", false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
33
include/modules/viewer_base/viewer_base_config.cpp
Normal file
33
include/modules/viewer_base/viewer_base_config.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "viewer_base/viewer_base.h"
|
||||
#include "core/renderer.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool ViewerBase::LoadViewerConfig(const char *path)
|
||||
{
|
||||
if (!NML::Parser::Load(path, config_file))
|
||||
return false;
|
||||
|
||||
NML::Tag *tag;
|
||||
if ((tag = config_file.GetTypedTag("Fullscreen", Variant::VariantBool)) != NULL)
|
||||
fullscreen = tag->GetBool();
|
||||
if ((tag = config_file.GetTypedTag("Width", Variant::VariantInteger)) != NULL)
|
||||
width = tag->GetInteger();
|
||||
if ((tag = config_file.GetTypedTag("Height", Variant::VariantInteger)) != NULL)
|
||||
height = tag->GetInteger();
|
||||
if ((tag = config_file.GetTypedTag("AspectRatio", Variant::VariantFloat)) != NULL)
|
||||
aspect_ratio = tag->GetReal();
|
||||
|
||||
if (renderer)
|
||||
renderer->SetGlobalAspectRatio(aspect_ratio);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
114
include/modules/viewer_base/viewer_base_debugger.cpp
Normal file
114
include/modules/viewer_base/viewer_base_debugger.cpp
Normal file
@ -0,0 +1,114 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "viewer_base/viewer_base_debugger.h"
|
||||
#include "viewer_base/viewer_base.h"
|
||||
#include "io_net/io_net_client.h"
|
||||
#include "async/task_loop.h"
|
||||
#include "filesystem/io_buffer.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void ViewerBaseDebugger::SetViewerStatus(const char *status)
|
||||
{ __LOG__ << "Viewer: " << status << "\n"; }
|
||||
IO::Base *ViewerBaseDebugger::WrapRemoteFileSystem(IO::Base *remote_fs)
|
||||
{ return new IO::Buffer(remote_fs, 65536, 65536); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void ViewerBaseDebugger::OnControllerPacketReceived(const Array <char> &data)
|
||||
{
|
||||
using namespace NML;
|
||||
|
||||
Tag tag;
|
||||
Parser::ParseTag(tag, data.Start(), data.End());
|
||||
|
||||
if (tag.name == "ShowPerformanceProfiler")
|
||||
viewer.enable_profiler = tag.GetBool();
|
||||
else if (tag.name == "ShowMemoryProfiler")
|
||||
viewer.memory_profiler = tag.GetBool();
|
||||
else if (tag.name == "DebugPhysics")
|
||||
{
|
||||
if (viewer.project.IsValid())
|
||||
viewer.project->flags.Raise(GS::Core::Project::ProjectFlagDebugPhysics, tag.GetBool());
|
||||
if (viewer.scene_3d.IsValid())
|
||||
viewer.scene_3d->flags.Raise(GS::S3D::Scene::FlagDebugPhysics, tag.GetBool());
|
||||
}
|
||||
|
||||
// Remote session setup.
|
||||
else if (tag.name == "MountRemoteFileSystem")
|
||||
{
|
||||
SetViewerStatus("Connecting to file server");
|
||||
|
||||
String address = GetPeerAddress();
|
||||
|
||||
int port = -1;
|
||||
if (Tag *port_tag = tag.GetTypedTag("Port", GS::Variant::VariantInteger))
|
||||
port = port_tag->GetInteger();
|
||||
|
||||
__LOG_H__ << "Mounting remote file system from " << address << " on port " << port << ".\n";
|
||||
|
||||
if (!address.IsEmpty() && (port != -1))
|
||||
{
|
||||
SharedPtr <IO::Net> net(new IO::Net);
|
||||
|
||||
bool connection_status = false;
|
||||
|
||||
if (net->Connect(address, port))
|
||||
{
|
||||
// Wait for connection...
|
||||
__LOG_H__ << "Waiting for remote file system connection...\n";
|
||||
|
||||
StartTaskLoop(net->IsConnected() == false, 10000) // 10s timeout
|
||||
Platform::Get().Sleep(1);
|
||||
EndTaskLoop
|
||||
|
||||
if ((connection_status = net->IsConnected()) == true)
|
||||
{
|
||||
// Mount net FS through an IO cache layer.
|
||||
viewer.remote_fs = WrapRemoteFileSystem(net);
|
||||
Platform::Get().io->Mount(viewer.remote_fs);
|
||||
|
||||
// Remote FS ready.
|
||||
BroadcastNetworkCommand("<RemoteFileSystemOk>");
|
||||
}
|
||||
}
|
||||
|
||||
if (connection_status == false)
|
||||
SetViewerStatus("File server connection failed");
|
||||
}
|
||||
}
|
||||
else if (tag.name == "SetSessionInput")
|
||||
{
|
||||
SetViewerStatus("Loading session");
|
||||
|
||||
viewer.remote_project.Clear();
|
||||
if (Tag *t = tag.GetTag("Environment"))
|
||||
viewer.remote_project.AddRoot(t->Clone());
|
||||
|
||||
viewer.remote_scene.Clear();
|
||||
if (Tag *t = tag.GetTag("Scene"))
|
||||
viewer.remote_scene.AddRoot(t->Clone());
|
||||
else if (Tag *t = tag.GetTag("Scene2D"))
|
||||
viewer.remote_scene.AddRoot(t->Clone());
|
||||
|
||||
BroadcastNetworkCommand("<SetSessionInputOK>");
|
||||
}
|
||||
else if (tag.name == "StartSession")
|
||||
{
|
||||
SetViewerStatus("Session Running");
|
||||
viewer.state = ViewerBase::SessionSetup; // setup session before starting it
|
||||
}
|
||||
else
|
||||
NetworkDebugger::OnControllerPacketReceived(data);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ViewerBaseDebugger::ViewerBaseDebugger(ViewerBase &v, IDebugger *idbg, const char *address, int port) : NetworkDebugger(v.script_vm, idbg, address, port), viewer(v) {}
|
||||
36
include/modules/viewer_base/viewer_base_vmhook.cpp
Normal file
36
include/modules/viewer_base/viewer_base_vmhook.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "viewer_base/viewer_base_vmhook.h"
|
||||
#include "viewer_base/viewer_base.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void ViewerEventHookTable::OnStep(char type, const char *source, int line, const char *funcname)
|
||||
{}
|
||||
void ViewerEventHookTable::Kill(const char *reason)
|
||||
{ viewer->DisplayUserMessage(ViewerBase::MessageWarning, String::Format("The script VM was killed:\n\n%s", reason)); }
|
||||
void ViewerEventHookTable::OnCompilerError(const char *error, const char *source, int line)
|
||||
{ viewer->DisplayUserMessage(ViewerBase::MessageNormal, String::Format("Script compiler error.\n\nSource: %s\nLine: %d\n\n%s", source, line, error)); }
|
||||
void ViewerEventHookTable::OnRuntimeException(const char *error)
|
||||
{
|
||||
String msg = String::Format("Script runtime exception:\n\n%s", error);
|
||||
|
||||
AutoList <IVM::CallStackEntry *> callstack;
|
||||
viewer->project->vm->GetCallStack(callstack);
|
||||
|
||||
msg += "\n\nCallstack:\n\n";
|
||||
ListForeachPtr(IVM::CallStackEntry *, cs, callstack)
|
||||
msg += String::Format(" - %s() (line %d) in \"%s\"\n", cs->function.c_str(), cs->line, cs->source.c_str());
|
||||
|
||||
__LOG_E__ << "Squirrel Compiler Error: '" << msg << "'\n";
|
||||
|
||||
viewer->DisplayUserMessage(ViewerBase::MessageNormal, msg);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user