@@ -263,7 +263,7 @@ configure() | |||
CPPFLAGS="$CPPFLAGS -I$PWD/external/gtk-2.22.1/include/gdk-pixbuf-2.0" | |||
CPPFLAGS="$CPPFLAGS -I$PWD/external/gtk-2.22.1/include/atk-1.0" | |||
CPPFLAGS="$CPPFLAGS -I$PWD/external/gtkglarea-2.0.1/include" | |||
CPPFLAGS="$CPPFLAGS -I$PWD/external/imgui-1.36/include" | |||
CPPFLAGS="$CPPFLAGS -I$PWD/external/imgui-1.37/include" | |||
CPPFLAGS="$CPPFLAGS -mms-bitfields" | |||
LDFLAGS="$LDFLAGS -static-libgcc -static-libstdc++" | |||
GTK_LIBS="$GTK_LIBS -lgtkgl-2.0 -lopengl32 -lglew32 -lgdi32" | |||
@@ -9,7 +9,7 @@ | |||
<PegtlIncludes>$(PegtlDir)\include</PegtlIncludes> | |||
<!-- imgui --> | |||
<ImguiDir>$(ExternalDir)\imgui-1.36</ImguiDir> | |||
<ImguiDir>$(ExternalDir)\imgui-1.37</ImguiDir> | |||
<ImguiIncludes>$(ImguiDir)</ImguiIncludes> | |||
<!-- libgcc (from mingw-w64) --> | |||
@@ -295,7 +295,7 @@ fi | |||
dnl Use Imgui? Yes, always | |||
if true; then | |||
LOL_CFLAGS="$LOL_CFLAGS -I\$(top_srcdir)/external/imgui-1.36" | |||
LOL_CFLAGS="$LOL_CFLAGS -I\$(top_srcdir)/external/imgui-1.37" | |||
fi | |||
@@ -54,10 +54,10 @@ | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</None> | |||
<None Include="data/meshviewer_buffer.lua"> | |||
<None Include="data/meshviewer_init.lua"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</None> | |||
<None Include="data/meshviewer_init.lua"> | |||
<None Include="data\meshviewer.easymesh.lua"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</None> | |||
<None Include="meshviewer/meshviewer.index.html"> | |||
@@ -23,18 +23,19 @@ using namespace lol; | |||
static int const TEXTURE_WIDTH = 256; | |||
#define NO_NACL_EM (!__native_client__ && !EMSCRIPTEN) | |||
#define NACL_EM (__native_client__ || EMSCRIPTEN) | |||
#define NO_NACL_EM_INPUT (1) | |||
//Basic build defines --------------------------------------------------------- | |||
#define HAS_WEB (__native_client__ || EMSCRIPTEN) | |||
#define HAS_INPUT (_WIN32 && !HAS_WEB) | |||
//Basic config defines -------------------------------------------------------- | |||
#define R_M 1.f | |||
#if NACL_EM | |||
#if HAS_WEB | |||
#define DEFAULT_WIDTH (800.f * R_M) | |||
#define DEFAULT_HEIGHT (400.f * R_M) | |||
#else | |||
#define DEFAULT_WIDTH (1200.f * R_M) | |||
#define DEFAULT_HEIGHT (400.f * R_M) | |||
#endif //NACL_EM | |||
#endif //HAS_WEB | |||
#define WIDTH ((float)Video::GetSize().x) | |||
#define HEIGHT ((float)Video::GetSize().y) | |||
#define SCREEN_W (10.f / WIDTH) | |||
@@ -65,27 +66,7 @@ static int const TEXTURE_WIDTH = 256; | |||
LOLFX_RESOURCE_DECLARE(shinyfur); | |||
LOLFX_RESOURCE_DECLARE(shinymvtexture); | |||
enum GizmoType | |||
{ | |||
GZ_Editor = 0, | |||
GZ_LightPos, | |||
GZ_LightDir, | |||
GZ_MAX | |||
}; | |||
struct LightData | |||
{ | |||
LightData(vec3 pos, vec4 col) | |||
{ | |||
m_pos = pos; | |||
m_col = col; | |||
} | |||
vec3 m_pos; | |||
vec4 m_col; | |||
}; | |||
//TargetCamera ---------------------------------------------------------------- | |||
class TargetCamera | |||
{ | |||
public: | |||
@@ -114,21 +95,203 @@ public: | |||
array<vec3> m_targets; | |||
}; | |||
MeshViewer::MeshViewer(char const *file_name = "data/mesh-buffer.txt") | |||
//EasyMeshLoadJob ------------------------------------------------------------- | |||
bool EasyMeshLoadJob::DoWork() | |||
{ | |||
if (m_loader.ExecLuaFile(m_path)) | |||
{ | |||
array<EasyMeshLuaObject*>& objs = m_loader.GetInstances(); | |||
for (EasyMeshLuaObject* obj : objs) | |||
m_meshes << new EasyMeshViewerObject(obj->GetMesh()); | |||
} | |||
return !!m_meshes.count(); | |||
} | |||
//----------------------------------------------------------------------------- | |||
MeshViewerLoadJob* EasyMeshLoadJob::GetInstance(String const& path) | |||
{ | |||
if (Check(path)) | |||
return new MeshViewerLoadJob(path); | |||
return nullptr; | |||
} | |||
//----------------------------------------------------------------------------- | |||
void EasyMeshLoadJob::RetrieveResult(class MeshViewer* app) | |||
{ | |||
for (EasyMeshViewerObject* mesh : m_meshes) | |||
app->AddViewerObj(mesh); | |||
m_meshes.Empty(); | |||
} | |||
//MeshViewer ------------------------------------------------------------------ | |||
MeshViewer::MeshViewer(char const *file_name) | |||
: m_file_name(file_name) | |||
{ } | |||
//----------------------------------------------------------------------------- | |||
MeshViewer::~MeshViewer() | |||
{ | |||
m_init = false; | |||
m_first_tick = false; | |||
Stop(); | |||
} | |||
// Message Service | |||
MessageService::Setup(); | |||
//----------------------------------------------------------------------------- | |||
void MeshViewer::Start() | |||
{ | |||
/** OLD STUFF **/ | |||
//Prepare(); | |||
//Scene setup | |||
m_setup_loader.ExecLuaFile("meshviewer_init.lua"); | |||
//Threads setup | |||
m_entities << (m_file_check = new FileUpdateTester()); | |||
m_file_status = m_file_check->RegisterFile(m_file_name); | |||
m_entities << (m_file_loader = new DefaultThreadManager(1, 1)); | |||
//Camera setup | |||
m_camera = new Camera(); | |||
m_camera->SetView(vec3(0.f, 0.f, 10.f), vec3::zero, vec3::axis_y); | |||
m_camera->SetProjection(0.f, .0001f, 2000.f, WIDTH * SCREEN_W, RATIO_HW); | |||
m_camera->UseShift(true); | |||
g_scene->PushCamera(m_camera); | |||
#if HAS_INPUT | |||
InputProfile& ip = m_profile; | |||
ip.AddBindings<MeshViewerKeyInput, MeshViewerKeyInput::KBD_BEG, MeshViewerKeyInput::KBD_END>(InputProfileType::Keyboard); | |||
ip.AddBindings<MeshViewerKeyInput, MeshViewerKeyInput::MSE_BEG, MeshViewerKeyInput::MSE_END>(InputProfileType::Keyboard); | |||
m_entities << (m_controller = new Controller("MeshViewer")); | |||
m_controller->Init(m_profile); | |||
#endif //HAS_INPUT | |||
/** ----- Register all entities ----- **/ | |||
for (Entity* entity : m_entities) Ticker::Ref(entity); | |||
/** ----- Init is done ----- **/ | |||
m_init = true; | |||
/** ----- Start threads ----- **/ | |||
m_file_check->Start(); | |||
} | |||
//----------------------------------------------------------------------------- | |||
void MeshViewer::Stop() | |||
{ | |||
//Destroy core stuff | |||
if (m_camera) g_scene->PopCamera(m_camera); | |||
if (m_ssetup) delete m_ssetup; | |||
m_file_check->UnregisterFile(m_file_status); | |||
//Register all entities | |||
for (Entity* entity : m_entities) Ticker::Unref(entity); | |||
//Delete objs | |||
while (m_objs.count()) delete m_objs.Pop(); | |||
//Nullify all | |||
m_ssetup = nullptr; | |||
m_camera = nullptr; | |||
m_controller = nullptr; | |||
m_file_check = nullptr; | |||
m_file_loader = nullptr; | |||
//Scene setup | |||
m_setup_loader.ExecLuaFile("meshviewer_init.lua"); | |||
/** ----- Init is needed ----- **/ | |||
m_init = false; | |||
} | |||
//----------------------------------------------------------------------------- | |||
MeshViewerLoadJob* MeshViewer::GetLoadJob(String const& path) | |||
{ | |||
MeshViewerLoadJob* job = nullptr; | |||
if (job = EasyMeshLoadJob::GetInstance(path)) return job; | |||
return job; | |||
} | |||
//----------------------------------------------------------------------------- | |||
void MeshViewer::TickGame(float seconds) | |||
{ | |||
super::TickGame(seconds); | |||
if (!m_init && g_scene) Start(); | |||
if (!m_init) return; | |||
m_first_tick = true; | |||
//Check file update | |||
ASSERT(m_file_status); | |||
if (m_file_status->HasUpdated()) | |||
{ | |||
MeshViewerLoadJob* job = GetLoadJob(m_file_name); | |||
if (!job) | |||
m_file_loader->AddWork(job); | |||
} | |||
//Check work done | |||
{ | |||
array<ThreadJob*> result; | |||
m_file_loader->GetWorkResult(result); | |||
if (result.count()) | |||
{ | |||
for (ThreadJob* job : result) | |||
{ | |||
if (job->GetJobType() == ThreadJobType::WORK_SUCCESSED) | |||
{ | |||
MeshViewerLoadJob* mvjob = static_cast<MeshViewerLoadJob*>(job); | |||
mvjob->RetrieveResult(this); | |||
} | |||
delete job; | |||
} | |||
} | |||
} | |||
/** OLD STUFF **/ | |||
//Update(seconds); | |||
} | |||
//----------------------------------------------------------------------------- | |||
void MeshViewer::TickDraw(float seconds, Scene &scene) | |||
{ | |||
super::TickDraw(seconds, scene); | |||
/** OLD STUFF **/ | |||
//Draw(seconds); | |||
} | |||
//The basic main -------------------------------------------------------------- | |||
int main(int argc, char **argv) | |||
{ | |||
System::Init(argc, argv); | |||
Application app("MeshViewer", ivec2((int)DEFAULT_WIDTH, (int)DEFAULT_HEIGHT), 60.0f); | |||
if (argc > 1) | |||
new MeshViewer(argv[1]); | |||
else | |||
new MeshViewer(); | |||
app.Run(); | |||
return EXIT_SUCCESS; | |||
} | |||
//------------------------------------------------------------------------- | |||
//OLD --------------------------------------------------------------------- | |||
//------------------------------------------------------------------------- | |||
#if HAS_INPUT | |||
bool MeshViewer::KeyReleased(MVKeyboardList index) { return (HAS_KBOARD && m_controller->WasKeyReleasedThisFrame(index)); } | |||
bool MeshViewer::KeyPressed(MVKeyboardList index) { return (HAS_KBOARD && m_controller->WasKeyPressedThisFrame(index)); } | |||
bool MeshViewer::KeyDown(MVKeyboardList index) { return (HAS_KBOARD && m_controller->IsKeyPressed(index)); } | |||
bool MeshViewer::KeyReleased(MVMouseKeyList index) { return (HAS_MOUSE && m_controller->WasKeyReleasedThisFrame(index)); } | |||
bool MeshViewer::KeyPressed(MVMouseKeyList index) { return (HAS_MOUSE && m_controller->WasKeyPressedThisFrame(index)); } | |||
bool MeshViewer::KeyDown(MVMouseKeyList index) { return (HAS_MOUSE && m_controller->IsKeyPressed(index)); } | |||
float MeshViewer::AxisValue(MVMouseAxisList index) { return (HAS_MOUSE) ? (m_controller->GetAxisValue(index)) : (0.f); } | |||
#endif //HAS_INPUT | |||
void MeshViewer::Prepare() | |||
{ | |||
// Message Service | |||
MessageService::Setup(); | |||
//Compile ref meshes | |||
m_gizmos << new EasyMesh(); | |||
@@ -175,44 +338,18 @@ MeshViewer::MeshViewer(char const *file_name = "data/mesh-buffer.txt") | |||
//stream update | |||
m_stream_update_time = 2.0f; | |||
m_stream_update_timer = 1.0f; | |||
} | |||
MeshViewer::~MeshViewer() | |||
{ | |||
if (m_camera) | |||
g_scene->PopCamera(m_camera); | |||
if (m_ssetup) | |||
delete m_ssetup; | |||
MessageService::Destroy(); | |||
m_controller = nullptr; | |||
m_camera = nullptr; | |||
m_ssetup = nullptr; | |||
} | |||
#if NO_NACL_EM_INPUT | |||
bool MeshViewer::KeyReleased(MVKeyboardList index) { return (HAS_KBOARD && m_controller->WasKeyReleasedThisFrame(index)); } | |||
bool MeshViewer::KeyPressed(MVKeyboardList index) { return (HAS_KBOARD && m_controller->WasKeyPressedThisFrame(index)); } | |||
bool MeshViewer::KeyDown(MVKeyboardList index) { return (HAS_KBOARD && m_controller->IsKeyPressed(index)); } | |||
bool MeshViewer::KeyReleased(MVMouseKeyList index) { return (HAS_MOUSE && m_controller->WasKeyReleasedThisFrame(index)); } | |||
bool MeshViewer::KeyPressed(MVMouseKeyList index) { return (HAS_MOUSE && m_controller->WasKeyPressedThisFrame(index)); } | |||
bool MeshViewer::KeyDown(MVMouseKeyList index) { return (HAS_MOUSE && m_controller->IsKeyPressed(index)); } | |||
float MeshViewer::AxisValue(MVMouseAxisList index) { return (HAS_MOUSE) ? (m_controller->GetAxisValue(index)) : (0.f); } | |||
#endif //NO_NACL_EM_INPUT | |||
void MeshViewer::Init() | |||
{ | |||
m_init = true; | |||
m_input_usage = 0; | |||
#if NO_NACL_EM_INPUT | |||
#if HAS_INPUT | |||
/* Register an input controller for the keyboard */ | |||
m_controller = new Controller("Default"); | |||
m_controller->SetInputCount(MAX_KEYS, MAX_AXIS); | |||
if (InputDevice::Get(g_name_mouse.C())) | |||
{ | |||
m_input_usage |= (1<<IPT_MV_MOUSE); | |||
m_input_usage |= (1 << IPT_MV_MOUSE); | |||
m_controller->GetKey(MSE_CAM_ROT).BindMouse("Left"); | |||
m_controller->GetKey(MSE_CAM_POS).BindMouse("Right"); | |||
@@ -224,17 +361,17 @@ void MeshViewer::Init() | |||
if (InputDevice::Get(g_name_keyboard.C())) | |||
{ | |||
m_input_usage |= (1<<IPT_MV_KBOARD); | |||
m_input_usage |= (1 << IPT_MV_KBOARD); | |||
//Camera keyboard rotation | |||
m_controller->GetKey(KEY_CAM_UP ).BindKeyboard("Up"); | |||
m_controller->GetKey(KEY_CAM_DOWN ).BindKeyboard("Down"); | |||
m_controller->GetKey(KEY_CAM_LEFT ).BindKeyboard("Left"); | |||
m_controller->GetKey(KEY_CAM_UP).BindKeyboard("Up"); | |||
m_controller->GetKey(KEY_CAM_DOWN).BindKeyboard("Down"); | |||
m_controller->GetKey(KEY_CAM_LEFT).BindKeyboard("Left"); | |||
m_controller->GetKey(KEY_CAM_RIGHT).BindKeyboard("Right"); | |||
//Camera keyboard position switch | |||
m_controller->GetKey(KEY_CAM_POS ).BindKeyboard("LeftShift"); | |||
m_controller->GetKey(KEY_CAM_FOV ).BindKeyboard("LeftCtrl"); | |||
m_controller->GetKey(KEY_CAM_POS).BindKeyboard("LeftShift"); | |||
m_controller->GetKey(KEY_CAM_FOV).BindKeyboard("LeftCtrl"); | |||
//Camera unzoom switch | |||
m_controller->GetKey(KEY_CAM_RESET).BindKeyboard("Space"); | |||
@@ -251,7 +388,7 @@ void MeshViewer::Init() | |||
m_controller->GetKey(KEY_F5).BindKeyboard("F5"); | |||
m_controller->GetKey(KEY_ESC).BindKeyboard("Escape"); | |||
} | |||
#endif //NO_NACL_EM_INPUT | |||
#endif //HAS_INPUT | |||
m_camera = new Camera(); | |||
@@ -282,8 +419,8 @@ void MeshViewer::Init() | |||
//TOUKY CHANGE THAT | |||
/* | |||
m_ssetup->Compile("addlight 0.0 position (4 -1 -4) color (.0 .2 .5 1) " | |||
"addlight 0.0 position (8 2 6) color #ffff " | |||
"showgizmo true "); | |||
"addlight 0.0 position (8 2 6) color #ffff " | |||
"showgizmo true "); | |||
*/ | |||
m_ssetup->Startup(); | |||
#endif //NO_SC_SETUP | |||
@@ -295,29 +432,35 @@ void MeshViewer::Init() | |||
} | |||
} | |||
void MeshViewer::TickGame(float seconds) | |||
void MeshViewer::Unprepare() | |||
{ | |||
WorldEntity::TickGame(seconds); | |||
if (m_camera) g_scene->PopCamera(m_camera); | |||
if (m_ssetup) delete m_ssetup; | |||
if (!m_init && g_scene) | |||
{ | |||
Init(); | |||
return; | |||
} | |||
MessageService::Destroy(); | |||
if (!m_init) | |||
return; | |||
//Register all entities | |||
for (Entity* entity : m_entities) | |||
Ticker::Unref(entity); | |||
m_first_tick = true; | |||
m_controller = nullptr; | |||
m_camera = nullptr; | |||
m_ssetup = nullptr; | |||
/** ----- Init is needed ----- **/ | |||
m_init = false; | |||
} | |||
void MeshViewer::Update(float seconds) | |||
{ | |||
//TODO : This should probably be "standard LoL behaviour" | |||
#if NO_NACL_EM_INPUT | |||
#if HAS_INPUT | |||
{ | |||
//Shutdown logic | |||
if (KeyReleased(KEY_ESC)) | |||
Ticker::Shutdown(); | |||
} | |||
#endif //NO_NACL_EM_INPUT | |||
#endif //HAS_INPUT | |||
//Compute render mesh count | |||
float a_j = lol::abs(m_render_max[1]); | |||
@@ -326,9 +469,9 @@ void MeshViewer::TickGame(float seconds) | |||
m_render_max[1] = a_j * ((RATIO_WH * 1.f) / ((i_trans != 0.f)?(i_trans):(RATIO_WH))) - RATIO_HW * .3f; | |||
//Mesh Change | |||
#if NO_NACL_EM_INPUT | |||
#if HAS_INPUT | |||
m_mesh_id = clamp(m_mesh_id + ((int)KeyPressed(KEY_MESH_PREV) - (int)KeyPressed(KEY_MESH_NEXT)), 0, (int)m_meshes.Count() - 1); | |||
#endif //NO_NACL_EM_INPUT | |||
#endif //HAS_INPUT | |||
m_mesh_id1 = damp(m_mesh_id1, (float)m_mesh_id, .2f, seconds); | |||
#if ALL_FEATURES | |||
@@ -352,7 +495,7 @@ void MeshViewer::TickGame(float seconds) | |||
bool is_hsc = false; | |||
vec2 tmpv = vec2::zero; | |||
#if NO_NACL_EM_INPUT | |||
#if HAS_INPUT | |||
is_pos = KeyDown(KEY_CAM_POS) || KeyDown(MSE_CAM_POS); | |||
is_fov = KeyDown(KEY_CAM_FOV) || KeyDown(MSE_CAM_FOV); | |||
@@ -369,7 +512,7 @@ void MeshViewer::TickGame(float seconds) | |||
tmpv += vec2((float)KeyDown(KEY_CAM_UP ) - (float)KeyDown(KEY_CAM_DOWN), | |||
(float)KeyDown(KEY_CAM_RIGHT) - (float)KeyDown(KEY_CAM_LEFT)); | |||
#endif //NO_NACL_EM_INPUT | |||
#endif //HAS_INPUT | |||
//Base data | |||
vec2 rot = (!is_pos && !is_fov)?(tmpv):(vec2(.0f)); rot = vec2(rot.x, -rot.y); | |||
@@ -389,7 +532,7 @@ void MeshViewer::TickGame(float seconds) | |||
m_rot += m_rot_speed * seconds; | |||
#if NO_NACL_EM_INPUT | |||
#if HAS_INPUT | |||
if (m_reset_timer >= 0.f) | |||
m_reset_timer -= seconds; | |||
if (KeyPressed(KEY_CAM_RESET)) | |||
@@ -411,7 +554,7 @@ void MeshViewer::TickGame(float seconds) | |||
m_zoom += m_zoom_speed * seconds; | |||
m_hist_scale += m_hist_scale_speed * seconds; | |||
} | |||
#endif //NO_NACL_EM_INPUT | |||
#endif //HAS_INPUT | |||
//clamp | |||
vec2 rot_mesh = vec2(SmoothClamp(m_rot.x, -ROT_CLAMP, ROT_CLAMP, ROT_CLAMP * .1f), m_rot.y); | |||
@@ -422,13 +565,13 @@ void MeshViewer::TickGame(float seconds) | |||
vec2 hist_scale_mesh = vec2(SmoothClamp(m_hist_scale.x, 0.f, HST_CLAMP, HST_CLAMP * .1f), | |||
SmoothClamp(m_hist_scale.y, 0.f, HST_CLAMP, HST_CLAMP * .1f)); | |||
#if NO_NACL_EM_INPUT | |||
#if HAS_INPUT | |||
if (KeyDown(KEY_CAM_RESET) && m_reset_timer < 0.f) | |||
{ | |||
pos_mesh = vec2::zero; | |||
zoom_mesh = 0.f; | |||
} | |||
#endif //NO_NACL_EM_INPUT | |||
#endif //HAS_INPUT | |||
m_rot_mesh = vec2(damp(m_rot_mesh.x, rot_mesh.x, .2f, seconds), damp(m_rot_mesh.y, rot_mesh.y, .2f, seconds)); | |||
m_pos_mesh = vec2(damp(m_pos_mesh.x, pos_mesh.x, .2f, seconds), damp(m_pos_mesh.y, pos_mesh.y, .2f, seconds)); | |||
@@ -597,7 +740,7 @@ void MeshViewer::TickGame(float seconds) | |||
m_ssetup->m_custom_cmd.Empty(); | |||
#endif //ALL_FEATURES | |||
#if NACL_EM | |||
#if HAS_WEB | |||
/* | |||
if (m_stream_update_time > .0f) | |||
{ | |||
@@ -636,24 +779,23 @@ void MeshViewer::TickGame(float seconds) | |||
#endif //WINDOWS | |||
} | |||
void MeshViewer::TickDraw(float seconds, Scene &scene) | |||
void MeshViewer::Draw(float seconds, Scene &scene) | |||
{ | |||
WorldEntity::TickDraw(seconds, scene); | |||
if (!m_init || !m_first_tick) | |||
return; | |||
//TODO : This should probably be "standard LoL behaviour" | |||
#if NO_NACL_EM_INPUT | |||
#if HAS_INPUT | |||
{ | |||
if (KeyReleased(KEY_F2)) | |||
Video::SetDebugRenderMode((Video::GetDebugRenderMode() + 1) % DebugRenderMode::Max); | |||
else if (KeyReleased(KEY_F1)) | |||
Video::SetDebugRenderMode((Video::GetDebugRenderMode() + DebugRenderMode::Max - 1) % DebugRenderMode::Max); | |||
} | |||
#endif //NO_NACL_EM_INPUT | |||
#endif //HAS_INPUT | |||
#if NO_NACL_EM && WITH_TEXTURE | |||
#if !HAS_WEB && WITH_TEXTURE | |||
if (!m_default_texture) | |||
{ | |||
m_texture_shader = Shader::Create(LOLFX_RESOURCE_NAME(shinymvtexture)); | |||
@@ -662,7 +804,7 @@ void MeshViewer::TickDraw(float seconds, Scene &scene) | |||
} | |||
else if (m_texture && m_default_texture) | |||
m_texture_shader->SetUniform(m_texture_uni, m_default_texture->GetTexture(), 0); | |||
#endif //NO_NACL_EM | |||
#endif //!HAS_WEB && WITH_TEXTURE | |||
g_renderer->SetClearColor(m_ssetup->m_clear_color); | |||
@@ -837,19 +979,3 @@ void MeshViewer::TickDraw(float seconds, Scene &scene) | |||
} | |||
#endif | |||
} | |||
//The basic main : | |||
int main(int argc, char **argv) | |||
{ | |||
System::Init(argc, argv); | |||
Application app("MeshViewer", ivec2((int)DEFAULT_WIDTH, (int)DEFAULT_HEIGHT), 60.0f); | |||
if (argc > 1) | |||
new MeshViewer(argv[1]); | |||
else | |||
new MeshViewer(); | |||
app.Run(); | |||
return EXIT_SUCCESS; | |||
} | |||
@@ -145,7 +145,7 @@ void SceneSetup::Set(SceneSetup::Display const& d, DisplayFlag const& f) | |||
} | |||
//----------------------------------------------------------------------------- | |||
SceneSetupLuaObject::SceneSetupLuaObject(String& name) : LuaObjectDef() | |||
SceneSetupLuaObject::SceneSetupLuaObject(String& name) : LuaObject() | |||
{ | |||
m_setup = new SceneSetup(name); | |||
SceneSetupLuaLoader::RegisterSetup(m_setup); | |||
@@ -273,12 +273,26 @@ SceneSetupLuaLoader::SceneSetupLuaLoader() : LuaLoader() | |||
{ | |||
LuaState* l = GetLuaState(); | |||
LuaObject::Register<SceneSetupLuaObject>(l); | |||
LuaObjectDef::Register<SceneSetupLuaObject>(l); | |||
} | |||
//----------------------------------------------------------------------------- | |||
SceneSetupLuaLoader::~SceneSetupLuaLoader() { } | |||
//----------------------------------------------------------------------------- | |||
static array<SceneSetupLuaObject*> g_instances; | |||
void SceneSetupLuaLoader::Store(LuaObject* obj) | |||
{ | |||
SceneSetupLuaObject* ezm = static_cast<SceneSetupLuaObject*>(obj); | |||
g_instances << ezm; | |||
} | |||
//----------------------------------------------------------------------------- | |||
array<SceneSetupLuaObject*>& SceneSetupLuaLoader::GetInstances() | |||
{ | |||
return g_instances; | |||
} | |||
//----------------------------------------------------------------------------- | |||
void SceneSetupLuaLoader::RegisterSetup(SceneSetup* setup) | |||
{ | |||
@@ -106,7 +106,7 @@ public: | |||
typedef Lolua::VarEnum<SceneSetup::DisplayBase> LuaDisplay; | |||
//----------------------------------------------------------------------------- | |||
class SceneSetupLuaObject : public LuaObjectDef | |||
class SceneSetupLuaObject : public LuaObject | |||
{ | |||
typedef Lolua::VarPtr<SceneSetupLuaObject> LuaSSetupPtr; | |||
public: | |||
@@ -154,6 +154,9 @@ class SceneSetupLuaLoader : public LuaLoader | |||
public: | |||
SceneSetupLuaLoader(); | |||
virtual ~SceneSetupLuaLoader(); | |||
//Virtual Store lua object ------------------------------------------------ | |||
virtual void Store(LuaObject* obj) { } | |||
array<SceneSetupLuaObject*>& GetInstances(); | |||
//------------------------------------------------------------------------- | |||
protected: | |||
@@ -19,11 +19,11 @@ | |||
using namespace lol; | |||
//----------------------------------------------------------------------------- | |||
class DemoObject : public LuaObjectDef | |||
class DemoObject : public LuaObject | |||
{ | |||
typedef Lolua::VarPtr<DemoObject> LuaDemoObjectPtr; | |||
public: | |||
DemoObject() : LuaObjectDef() {} | |||
DemoObject() : LuaObject() {} | |||
virtual ~DemoObject() {} | |||
static DemoObject* New(LuaState* l, int arg_nb) | |||
{ | |||
@@ -103,7 +103,7 @@ public: | |||
LuaState* l = GetLuaState(); | |||
//Registering demo object | |||
LuaObject::Register<DemoObject>(l); | |||
LuaObjectDef::Register<DemoObject>(l); | |||
//Registering function | |||
LuaFunction add_string(l, "GlobalAddString", &GlobalAddString); | |||
@@ -27,7 +27,7 @@ EasyMeshLuaLoader::EasyMeshLuaLoader() : LuaLoader() | |||
LuaState* l = GetLuaState(); | |||
//Registering demo object | |||
LuaObject::Register<EasyMeshLuaObject>(l); | |||
LuaObjectDef::Register<EasyMeshLuaObject>(l); | |||
} | |||
//----------------------------------------------------------------------------- | |||
@@ -37,7 +37,21 @@ EasyMeshLuaLoader::~EasyMeshLuaLoader() | |||
} | |||
//----------------------------------------------------------------------------- | |||
EasyMeshLuaObject::EasyMeshLuaObject() : LuaObjectDef() | |||
static array<EasyMeshLuaObject*> g_instances; | |||
void EasyMeshLuaLoader::Store(LuaObject* obj) | |||
{ | |||
EasyMeshLuaObject* ezm = static_cast<EasyMeshLuaObject*>(obj); | |||
g_instances << ezm; | |||
} | |||
//----------------------------------------------------------------------------- | |||
array<EasyMeshLuaObject*>& EasyMeshLuaLoader::GetInstances() | |||
{ | |||
return g_instances; | |||
} | |||
//----------------------------------------------------------------------------- | |||
EasyMeshLuaObject::EasyMeshLuaObject() : LuaObject() | |||
{ | |||
} | |||
@@ -16,15 +16,7 @@ namespace lol | |||
{ | |||
//----------------------------------------------------------------------------- | |||
class EasyMeshLuaLoader : public LuaLoader | |||
{ | |||
public: | |||
EasyMeshLuaLoader(); | |||
virtual ~EasyMeshLuaLoader(); | |||
}; | |||
//----------------------------------------------------------------------------- | |||
class EasyMeshLuaObject : public LuaObjectDef | |||
class EasyMeshLuaObject : public LuaObject | |||
{ | |||
typedef Lolua::VarPtr<EasyMeshLuaObject> EzMeshPtr; | |||
EasyMesh m_instance; | |||
@@ -650,4 +642,15 @@ public: | |||
}; | |||
//----------------------------------------------------------------------------- | |||
class EasyMeshLuaLoader : public LuaLoader | |||
{ | |||
public: | |||
EasyMeshLuaLoader(); | |||
virtual ~EasyMeshLuaLoader(); | |||
//Virtual Store lua object ------------------------------------------------ | |||
virtual void Store(LuaObject* obj); | |||
array<EasyMeshLuaObject*>& GetInstances(); | |||
}; | |||
} /* namespace lol */ |
@@ -250,6 +250,7 @@ public: | |||
{ | |||
return (int)(m_mouse_axis.Count() + m_joystick_axis.Count()); | |||
} | |||
//Keys -------------------------------------------------------------------- | |||
InputProfile& operator<<(InputProfile::Keyboard const& binding) | |||
{ | |||
m_keys.PushUnique(binding); | |||
@@ -260,6 +261,7 @@ public: | |||
m_keys += bindings; | |||
return *this; | |||
} | |||
//------ | |||
InputProfile& operator<<(InputProfile::MouseKey const& binding) | |||
{ | |||
m_mouse_keys.PushUnique(binding); | |||
@@ -270,16 +272,7 @@ public: | |||
m_mouse_keys += bindings; | |||
return *this; | |||
} | |||
InputProfile& operator<<(InputProfile::MouseAxis const& binding) | |||
{ | |||
m_mouse_axis.PushUnique(binding); | |||
return *this; | |||
} | |||
InputProfile& operator<<(array<InputProfile::MouseAxis> const& bindings) | |||
{ | |||
m_mouse_axis += bindings; | |||
return *this; | |||
} | |||
//------ | |||
InputProfile& operator<<(InputProfile::JoystickKey const& binding) | |||
{ | |||
m_joystick.PushUnique(binding.m_joy); | |||
@@ -293,6 +286,18 @@ public: | |||
m_joystick_keys += bindings; | |||
return *this; | |||
} | |||
//Axis -------------------------------------------------------------------- | |||
InputProfile& operator<<(InputProfile::MouseAxis const& binding) | |||
{ | |||
m_mouse_axis.PushUnique(binding); | |||
return *this; | |||
} | |||
InputProfile& operator<<(array<InputProfile::MouseAxis> const& bindings) | |||
{ | |||
m_mouse_axis += bindings; | |||
return *this; | |||
} | |||
//------ | |||
InputProfile& operator<<(InputProfile::JoystickAxis const& binding) | |||
{ | |||
m_joystick.PushUnique(binding.m_joy); | |||
@@ -306,6 +311,41 @@ public: | |||
m_joystick_axis += bindings; | |||
return *this; | |||
} | |||
//BindingType ------------------------------------------------------------- | |||
struct InputTypeBase : public StructSafeEnum | |||
{ | |||
enum Type | |||
{ | |||
Keyboard = 0, | |||
MouseKey, | |||
JoystickKey, | |||
MouseAxis, | |||
JoystickAxis, | |||
MAX, | |||
}; | |||
protected: | |||
virtual bool BuildEnumMap(map<int64_t, String>& enum_map) { return true; } | |||
}; | |||
typedef SafeEnum<InputTypeBase> InputType; | |||
//Template helper --------------------------------------------------------- | |||
template <typename T, ptrdiff_t BEGIN, ptrdiff_t END> | |||
void AddBindings(InputType const& type, uint64_t joy = 0) | |||
{ | |||
for (ptrdiff_t i = BEGIN; i < END; ++i) | |||
{ | |||
switch (type.ToScalar()) | |||
{ | |||
case InputType::Keyboard:/******/*this << InputProfile::Keyboard/******/(/***/(int)i, T((int)i).ToString()); break; | |||
case InputType::MouseKey:/******/*this << InputProfile::MouseKey/******/(/***/(int)i, T((int)i).ToString()); break; | |||
case InputType::JoystickKey:/***/*this << InputProfile::JoystickKey/***/(joy, (int)i, T((int)i).ToString()); break; | |||
case InputType::MouseAxis:/*****/*this << InputProfile::MouseAxis/*****/(/***/(int)i, T((int)i).ToString()); break; | |||
case InputType::JoystickAxis:/**/*this << InputProfile::JoystickAxis/**/(joy, (int)i, T((int)i).ToString()); break; | |||
} | |||
} | |||
} | |||
private: | |||
array<Keyboard> m_keys; | |||
@@ -315,6 +355,7 @@ private: | |||
array<JoystickKey> m_joystick_keys; | |||
array<JoystickAxis> m_joystick_axis; | |||
}; | |||
typedef InputProfile::InputType InputProfileType; | |||
//----------------------------------------------------------------------------- | |||
//TODO: Add mask|layer system to prevent several controllers from interfering with another. (input overlay in menus) | |||
@@ -97,7 +97,7 @@ InputDeviceInternal* InputDeviceInternal::CreateStandardMouse() | |||
mouse->AddKey(g_name_mouse_key_middle.C()); | |||
mouse->AddKey(g_name_mouse_key_right.C()); | |||
//Added to manage if mouse is in the screen or not. | |||
mouse->AddKey(g_name_mouse_key_inScreen.C()); | |||
mouse->AddKey(g_name_mouse_key_in_screen.C()); | |||
mouse->AddAxis(g_name_mouse_axis_x.C()); | |||
mouse->AddAxis(g_name_mouse_axis_y.C()); | |||
@@ -28,7 +28,7 @@ static String g_name_joystick(const uint64_t num) | |||
const String g_name_mouse_key_left("Left"); | |||
const String g_name_mouse_key_middle("Middle"); | |||
const String g_name_mouse_key_right("Right"); | |||
const String g_name_mouse_key_inScreen("InScreen"); | |||
const String g_name_mouse_key_in_screen("InScreen"); | |||
const String g_name_mouse_axis_x("X"); | |||
const String g_name_mouse_axis_y("Y"); | |||
const String g_name_mouse_axis_xpixel("XPixel"); | |||
@@ -71,20 +71,20 @@ struct ThreadJobTypeBase : public StructSafeEnum | |||
{ | |||
NONE, | |||
WORK_TODO, | |||
WORK_DONE, | |||
WORK_SUCCESSED, | |||
WORK_FAILED, | |||
WORK_FETCHED, | |||
WORK_DONE, | |||
THREAD_STOP | |||
}; | |||
protected: | |||
virtual bool BuildEnumMap(map<int64_t, String>& enum_map) | |||
{ | |||
enum_map[NONE] = "NONE"; | |||
enum_map[WORK_TODO] = "WORK_TODO"; | |||
enum_map[WORK_DONE] = "WORK_DONE"; | |||
enum_map[WORK_FAILED] = "WORK_FAILED"; | |||
enum_map[WORK_FETCHED] = "WORK_FETCHED"; | |||
enum_map[THREAD_STOP] = "THREAD_STOP"; | |||
enum_map[NONE] = "NONE"; | |||
enum_map[WORK_TODO] = "WORK_TODO"; | |||
enum_map[WORK_SUCCESSED] = "WORK_SUCCESSED"; | |||
enum_map[WORK_FAILED] = "WORK_FAILED"; | |||
enum_map[WORK_DONE] = "WORK_DONE"; | |||
enum_map[THREAD_STOP] = "THREAD_STOP"; | |||
return true; | |||
} | |||
}; | |||
@@ -95,9 +95,10 @@ class ThreadJob | |||
{ | |||
friend class BaseThreadManager; | |||
protected: | |||
inline ThreadJob(ThreadJobType type) : m_type(type) {} | |||
public: | |||
inline ThreadJob() : m_type(ThreadJobType::NONE) {} | |||
inline ThreadJob(ThreadJobType type) : m_type(type) {} | |||
virtual ~ThreadJob() {} | |||
ThreadJobType GetJobType() { return m_type; } | |||
@@ -34,7 +34,7 @@ public: | |||
{ } | |||
//Work stuff | |||
bool AddJob(ThreadJob* job); | |||
bool AddWork(ThreadJob* job); | |||
bool GetWorkResult(array<ThreadJob*>& results); | |||
protected: | |||
@@ -42,84 +42,71 @@ protected: | |||
array<ThreadJob*> m_job_result; | |||
}; | |||
//FileUpdateTesterJob --------------------------------------------------------- | |||
class FileUpdateTesterJob : public ThreadJob | |||
{ | |||
public: | |||
FileUpdateTesterJob() | |||
: ThreadJob(ThreadJobType::NONE) { } | |||
FileUpdateTesterJob(String path) | |||
: ThreadJob(ThreadJobType::WORK_TODO) | |||
{ m_path = path; } | |||
String& GetPath() { return m_path; } | |||
bool HasUpdated() { return m_updated; } | |||
void Restart() | |||
{ | |||
SetJobType(ThreadJobType::WORK_TODO); | |||
m_updated = false; | |||
} | |||
protected: | |||
virtual bool DoWork(); | |||
//----------------- | |||
bool m_ready = false; | |||
String m_path = String(); | |||
long int m_time = 0; | |||
bool m_updated = false; | |||
}; | |||
//FileUpdateTester ------------------------------------------------------------ | |||
//Test the files registered and warns when they update | |||
class FileUpdateTester : public BaseThreadManager | |||
{ | |||
typedef BaseThreadManager super; | |||
public: | |||
struct Status | |||
class Status | |||
{ | |||
protected: | |||
mutex m_mutex; | |||
long int m_time = 0; | |||
bool m_updated = false; | |||
public: | |||
void SetTime(long int time) | |||
{ | |||
m_mutex.lock(); | |||
m_time = time; | |||
m_mutex.unlock(); | |||
} | |||
long int GetTime() | |||
{ | |||
m_mutex.lock(); | |||
long int time = m_time; | |||
m_mutex.unlock(); | |||
return m_time; | |||
} | |||
void SetUpdated(bool updated) | |||
{ | |||
m_mutex.lock(); | |||
m_updated = updated; | |||
m_mutex.unlock(); | |||
} | |||
bool HasUpdated() | |||
{ | |||
m_mutex.lock(); | |||
bool updated = m_updated; | |||
m_mutex.unlock(); | |||
return updated; | |||
} | |||
}; | |||
public: | |||
char const *GetName() { return "<FileUpdateTester>"; } | |||
FileUpdateTester() : BaseThreadManager(1) { } | |||
~FileUpdateTester() { } | |||
FileUpdateTester(uint32_t frame_skip = 4) | |||
: BaseThreadManager(1) | |||
{ m_frame_skip = frame_skip; } | |||
virtual ~FileUpdateTester(); | |||
//------------------------------------------------------------------------- | |||
FileUpdateTester::Status* RegisterFile(String const& path); | |||
protected: | |||
void UnregisterFile(String const& path); | |||
public: | |||
void UnregisterFile(FileUpdateTester::Status*& status); | |||
//TODO: Add directories | |||
//FileUpdateTester::Status* RegisterDirectory(String const& path, bool check_files=false); | |||
virtual void TickGame(float seconds); | |||
virtual void TreatResult(ThreadJob* result); | |||
private: | |||
uint32_t m_frame_skip = 4; | |||
uint32_t m_frame_count = 0; | |||
array<ThreadJob*> m_job_done; | |||
map<String, Status*> m_files; | |||
}; | |||
//AsyncImageJob --------------------------------------------------------------- | |||
class AsyncImageJob : public ThreadJob | |||
{ | |||
public: | |||
AsyncImageJob() | |||
: ThreadJob(ThreadJobType::NONE) | |||
{ | |||
m_path = String(); | |||
} | |||
AsyncImageJob(String path) | |||
: ThreadJob(ThreadJobType::WORK_TODO) | |||
{ | |||
m_path = path; | |||
} | |||
String const& GetPath() { return m_path; } | |||
Image const& GetImage() { return m_image; } | |||
protected: | |||
virtual bool DoWork() | |||
{ | |||
return m_image.Load(m_path.C()); | |||
} | |||
String m_path; | |||
Image m_image; | |||
}; | |||
typedef FileUpdateTester::Status FileUpdateStatus; | |||
//AsyncImageLoader ------------------------------------------------------------ | |||
//Load images asynchronously, automatically updating the dummy image | |||
@@ -132,53 +119,15 @@ public: | |||
{ | |||
m_dummy_image.DummyFill(); | |||
} | |||
~AsyncImageLoader() | |||
virtual ~AsyncImageLoader() | |||
{ } | |||
//Returns a dummy image, and start a job to load the image on a thread | |||
Image* Load(const lol::String& path) | |||
{ | |||
//Create a job | |||
AsyncImageJob* job = new AsyncImageJob(path); | |||
//Create a dummy image | |||
Image* image = new Image(m_dummy_image); | |||
//Link the two | |||
m_images[path] = image; | |||
//Add job | |||
AddWork(job); | |||
//return Dummy image | |||
return image; | |||
} | |||
bool CheckStatus(Image* image) | |||
{ | |||
if (m_loaded_images.find(image) != INDEX_NONE) | |||
{ | |||
m_loaded_images.remove_item(image); | |||
return true; | |||
} | |||
return false; | |||
} | |||
Image* Load(const lol::String& path); | |||
bool CheckStatus(Image* image); | |||
protected: | |||
virtual void TreatResult(ThreadJob* result) | |||
{ | |||
AsyncImageJob* job = dynamic_cast<AsyncImageJob*>(result); | |||
ASSERT(job); | |||
//Copy image if work is OK | |||
if (job->GetJobType() != ThreadJobType::WORK_FAILED) | |||
{ | |||
Image* src = m_images[job->GetPath()]; | |||
m_images.remove(job->GetPath()); | |||
src->Copy(job->GetImage()); | |||
m_loaded_images.PushUnique(src); | |||
} | |||
else | |||
{ | |||
Log::Error("AsyncImageJob FAILED. See load image error above.\n"); | |||
} | |||
//Delete all that | |||
delete(result); | |||
} | |||
virtual void TreatResult(ThreadJob* result); | |||
private: | |||
Image m_dummy_image; | |||
@@ -63,8 +63,10 @@ LolImGui::LolImGui() | |||
<< ShaderProgram::Pixel << imgui_pixel; | |||
//Input Setup ------------------------------------------------------------- | |||
for (int i = LolImGuiKey::KEY_START; i < LolImGuiKey::KEY_END; ++i) | |||
m_profile << InputProfile::Keyboard(i, LolImGuiKey(i).ToString()); | |||
InputProfile& ip = m_profile; | |||
ip.AddBindings<LolImGuiKey, LolImGuiKey::KEY_START, LolImGuiKey::KEY_END>(InputProfileType::Keyboard); | |||
//for (int i = LolImGuiKey::KEY_START; i < LolImGuiKey::KEY_END; ++i) | |||
// m_profile << InputProfile::Keyboard(i, LolImGuiKey(i).ToString()); | |||
for (int i = LolImGuiKey::MOUSE_KEY_START; i < LolImGuiKey::MOUSE_KEY_END; ++i) | |||
m_profile << InputProfile::MouseKey(i, LolImGuiKey(i).ToString()); | |||
@@ -96,6 +96,7 @@ class LolImGui : public Entity | |||
enum_map[LeftClick] = g_name_mouse_key_left; | |||
enum_map[RightClick] = g_name_mouse_key_right; | |||
enum_map[MiddleClick] = g_name_mouse_key_middle; | |||
enum_map[Focus] = g_name_mouse_key_in_screen; | |||
return true; | |||
} | |||
@@ -125,8 +126,6 @@ class LolImGui : public Entity | |||
}; | |||
typedef SafeEnum<LolImGuiAxisBase> LolImGuiAxis; | |||
public: | |||
//------------------------------------------------------------------------- | |||
LolImGui(); | |||
@@ -25,6 +25,7 @@ class LuaBaseData | |||
{ | |||
friend class Lolua::Loader; | |||
//PANIC PANIC ------------------------------------------------------------- | |||
static int LuaPanic(LuaState* l) | |||
{ | |||
char const *message = lua_tostring(l, -1); | |||
@@ -33,11 +34,13 @@ class LuaBaseData | |||
return 0; | |||
} | |||
//Exec lua code ----------------------------------------------------------- | |||
static int LuaDoCode(LuaState *l, String const& s) | |||
{ | |||
return luaL_dostring(l, s.C()); | |||
} | |||
//Open a file and exec lua code ------------------------------------------- | |||
static int LuaDoFile(LuaState *l) | |||
{ | |||
if (lua_isnoneornil(l, 1)) | |||
@@ -90,14 +93,51 @@ Loader::Loader() | |||
/* Override dofile() */ | |||
LuaFunction do_file(m_lua_state, "dofile", LuaBaseData::LuaDoFile); | |||
//Store this instance | |||
Loader::Store(m_lua_state, this); | |||
} | |||
//----------------------------------------------------------------------------- | |||
Loader::~Loader() | |||
{ | |||
//Release this instance | |||
Loader::Store(m_lua_state, this); | |||
lua_close(m_lua_state); | |||
} | |||
//Store loader ------------------------------------------------------------ | |||
static array<LuaState*, Lolua::Loader*> g_loaders; | |||
void Loader::Store(LuaState* l, Lolua::Loader* loader) | |||
{ | |||
g_loaders.push(l, loader); | |||
} | |||
void Loader::Release(LuaState* l, Lolua::Loader* loader) | |||
{ | |||
for (ptrdiff_t i = 0; i < g_loaders.count(); ++i) | |||
{ | |||
if (g_loaders[i].m1 == l && g_loaders[i].m2 == loader) | |||
{ | |||
g_loaders.remove(i); | |||
return; | |||
} | |||
} | |||
} | |||
//Store lua object -------------------------------------------------------- | |||
void Loader::StoreObject(LuaState* l, Object* obj) | |||
{ | |||
for (ptrdiff_t i = 0; i < g_loaders.count(); ++i) | |||
{ | |||
if (g_loaders[i].m1 == l) | |||
{ | |||
g_loaders[i].m2->Store(obj); | |||
return; | |||
} | |||
} | |||
} | |||
//----------------------------------------------------------------------------- | |||
bool Loader::ExecLuaFile(String const &lua) | |||
{ | |||
@@ -96,12 +96,12 @@ struct ObjectLib | |||
}; | |||
//----------------------------------------------------------------------------- | |||
class ObjectDef | |||
class Object | |||
{ | |||
public: | |||
ObjectDef() { } | |||
virtual ~ObjectDef() { } | |||
static ObjectDef* New(LuaState* l, int arg_nb) | |||
Object() { } | |||
virtual ~Object() { } | |||
static Object* New(LuaState* l, int arg_nb) | |||
{ | |||
UNUSED(l); | |||
UNUSED(arg_nb); | |||
@@ -114,12 +114,12 @@ public: | |||
//----------------------------------------------------------------------------- | |||
// Class available to link C++ class to Lua methods | |||
//-- | |||
class Object | |||
class ObjectDef | |||
{ | |||
public: | |||
//------------------------------------------------------------------------- | |||
Object() { } | |||
virtual ~Object() { } | |||
ObjectDef() { } | |||
virtual ~ObjectDef() { } | |||
//------------------------------------------------------------------------- | |||
template <typename TLuaClass> | |||
@@ -129,6 +129,7 @@ public: | |||
static const luaL_Reg default_statics[] | |||
{ | |||
{ "New", New<TLuaClass> }, | |||
{ "Store", Store<TLuaClass> }, | |||
{ "__gc", Del<TLuaClass> }, | |||
{ NULL, NULL } | |||
}; | |||
@@ -227,6 +228,7 @@ protected: | |||
} | |||
//------------------------------------------------------------------------- | |||
template <typename TLuaClass> static int Store(LuaState * l); | |||
template <typename TLuaClass> static int Del(LuaState * l); | |||
}; | |||
@@ -305,7 +307,7 @@ protected: | |||
} | |||
virtual void InnerGet(LuaState* l, int& index) | |||
{ | |||
T** obj = static_cast<T**>(luaL_checkudata(l, index++, Object::GetMethodName<T>())); | |||
T** obj = static_cast<T**>(luaL_checkudata(l, index++, ObjectDef::GetMethodName<T>())); | |||
m_value = obj ? *obj : nullptr; | |||
} | |||
void InnerPush(LuaState* l) | |||
@@ -315,20 +317,6 @@ protected: | |||
} | |||
}; | |||
// | |||
// Object member implementations that require VarPtr | |||
// | |||
template <typename TLuaClass> | |||
int Object::Del(LuaState * l) | |||
{ | |||
VarPtr<TLuaClass> obj; | |||
obj.Get(l, 1); | |||
ASSERT(obj()); | |||
delete obj(); | |||
return 0; | |||
} | |||
//----------------------------------------------------------------------------- | |||
/* TODO: FIX THAT TOUKY !! | |||
template<typename T> | |||
@@ -342,7 +330,7 @@ public: | |||
protected: | |||
virtual void InnerGet(LuaState* l, int& index) | |||
{ | |||
T** obj = static_cast<T**>(luaL_testudata(l, index++, Object::GetMethodName<T>())); | |||
T** obj = static_cast<T**>(luaL_testudata(l, index++, ObjectDef::GetMethodName<T>())); | |||
m_value = obj ? *obj : nullptr; | |||
} | |||
}; | |||
@@ -939,6 +927,7 @@ private: | |||
//----------------------------------------------------------------------------- | |||
class Loader | |||
{ | |||
friend class ObjectDef; | |||
public: | |||
Loader(); | |||
virtual ~Loader(); | |||
@@ -965,16 +954,44 @@ public: | |||
protected: | |||
LuaState* GetLuaState(); | |||
static void Store(LuaState* l, Loader* loader); | |||
static void Release(LuaState* l, Loader* loader); | |||
static void StoreObject(LuaState* l, Object* obj); | |||
//Virtual Store lua object ------------------------------------------------ | |||
virtual void Store(Object* obj) { } | |||
private: | |||
LuaState* m_lua_state; | |||
}; | |||
//----------------------------------------------------------------------------- | |||
// ObjectDef member implementations that require VarPtr | |||
template <typename TLuaClass> | |||
int ObjectDef::Store(LuaState * l) | |||
{ | |||
VarPtr<TLuaClass> obj; | |||
obj.Get(l, 1); | |||
ASSERT(obj()); | |||
Loader::StoreObject(l, obj()); | |||
return 0; | |||
} | |||
template <typename TLuaClass> | |||
int ObjectDef::Del(LuaState * l) | |||
{ | |||
VarPtr<TLuaClass> obj; | |||
obj.Get(l, 1); | |||
ASSERT(obj()); | |||
delete obj(); | |||
return 0; | |||
} | |||
} /* namespace Lolua */ | |||
typedef Lolua::Function LuaFunction; | |||
typedef Lolua::Object LuaObject; | |||
typedef Lolua::ObjectDef LuaObjectDef; | |||
typedef Lolua::Object LuaObject; | |||
typedef Lolua::ObjectLib LuaObjectLib; | |||
typedef Lolua::Loader LuaLoader; | |||
typedef Lolua::Var<bool> LuaBool; | |||
@@ -129,7 +129,7 @@ void BaseThreadManager::BaseThreadWork() | |||
else if (*job == ThreadJobType::WORK_TODO) | |||
{ | |||
if (job->DoWork()) | |||
job->SetJobType(ThreadJobType::WORK_DONE); | |||
job->SetJobType(ThreadJobType::WORK_SUCCESSED); | |||
else | |||
job->SetJobType(ThreadJobType::WORK_FAILED); | |||
m_resultqueue.push(job); | |||
@@ -165,8 +165,6 @@ void BaseThreadManager::TickGame(float seconds) | |||
for (int i = 0; i < result.count(); i++) | |||
{ | |||
ThreadJob* job = result[i]; | |||
if (job->GetJobType() == ThreadJobType::WORK_DONE) | |||
job->SetJobType(ThreadJobType::WORK_FETCHED); | |||
TreatResult(job); | |||
} | |||
} | |||
@@ -16,7 +16,7 @@ | |||
using namespace lol; | |||
//DefaultThreadManager -------------------------------------------------------- | |||
bool DefaultThreadManager::AddJob(ThreadJob* job) | |||
bool DefaultThreadManager::AddWork(ThreadJob* job) | |||
{ | |||
return AddWork(job); | |||
} | |||
@@ -28,24 +28,57 @@ bool DefaultThreadManager::GetWorkResult(array<ThreadJob*>& results) | |||
} | |||
//FileUpdateTesterJob --------------------------------------------------------- | |||
bool FileUpdateTesterJob::DoWork() | |||
class FileUpdateTesterJob : public ThreadJob | |||
{ | |||
File f; | |||
f.Open(m_path, FileAccess::Read); | |||
if (!f.IsValid()) | |||
return false; | |||
if (!m_ready) | |||
m_time = f.GetModificationTime(); | |||
else | |||
friend class FileUpdateTester; | |||
public: | |||
FileUpdateTesterJob() | |||
: ThreadJob(ThreadJobType::NONE) { } | |||
FileUpdateTesterJob(String path) | |||
: ThreadJob(ThreadJobType::WORK_TODO) | |||
{ | |||
long int new_time = f.GetModificationTime(); | |||
if (new_time > m_time) | |||
m_updated = true; | |||
m_path = path; | |||
} | |||
return true; | |||
} | |||
String& GetPath() { return m_path; } | |||
bool HasUpdated() { return m_updated; } | |||
void Restart() | |||
{ | |||
SetJobType(ThreadJobType::WORK_TODO); | |||
m_updated = false; | |||
} | |||
protected: | |||
virtual bool DoWork() | |||
{ | |||
File f; | |||
f.Open(m_path, FileAccess::Read); | |||
if (!f.IsValid()) | |||
return false; | |||
if (!m_ready) | |||
m_time = f.GetModificationTime(); | |||
else | |||
{ | |||
long int new_time = f.GetModificationTime(); | |||
if (new_time > m_time) | |||
m_updated = true; | |||
} | |||
return true; | |||
} | |||
//----------------- | |||
bool m_ready = false; | |||
String m_path = String(); | |||
long int m_time = 0; | |||
bool m_updated = false; | |||
}; | |||
//FileUpdateTester ------------------------------------------------------------ | |||
FileUpdateTester::~FileUpdateTester() | |||
{ | |||
ASSERT(!m_files.count(), "Files need to be unregistered before destroying FileUpdateTester"); | |||
} | |||
//File interface -------------------------------------------------------------- | |||
FileUpdateTester::Status* FileUpdateTester::RegisterFile(String const& path) | |||
{ | |||
m_job_dispatch << new FileUpdateTesterJob(path); | |||
@@ -53,26 +86,132 @@ FileUpdateTester::Status* FileUpdateTester::RegisterFile(String const& path) | |||
return m_files[path]; | |||
} | |||
//------------------------------------------------------------------------- | |||
void FileUpdateTester::UnregisterFile(String const& path) | |||
{ | |||
ASSERT(m_files.has_key(path)); | |||
delete m_files[path]; | |||
m_files.remove(path); | |||
} | |||
void FileUpdateTester::UnregisterFile(FileUpdateTester::Status*& status) | |||
{ | |||
ASSERT(status); | |||
array<String> keys = m_files.keys(); | |||
for (String key : keys) | |||
{ | |||
if (m_files[key] == status) | |||
{ | |||
UnregisterFile(key); | |||
status = nullptr; | |||
return; | |||
} | |||
} | |||
ASSERT(false, "Status wasn't found"); | |||
} | |||
//----------------------------------------------------------------------------- | |||
void FileUpdateTester::TickGame(float seconds) | |||
{ | |||
super::TickGame(seconds); | |||
if (!m_job_dispatch.count() && m_job_done.count()) | |||
{ | |||
if (m_frame_count++ < m_frame_skip) | |||
return; | |||
m_frame_count = 0; | |||
array<String> keys = m_files.keys(); | |||
for (String key : keys) | |||
m_files[key]->SetUpdated(false); | |||
m_job_dispatch = m_job_done; | |||
m_job_done.empty(); | |||
} | |||
} | |||
//------------------------------------------------------------------------- | |||
//----------------------------------------------------------------------------- | |||
void FileUpdateTester::TreatResult(ThreadJob* result) | |||
{ | |||
FileUpdateTesterJob* job = static_cast<FileUpdateTesterJob*>(result); | |||
if (job->HasUpdated()) | |||
{ | |||
m_files[job->GetPath()]->m_updated = true; | |||
m_files[job->GetPath()]->SetTime(job->m_time); | |||
m_files[job->GetPath()]->SetUpdated(true); | |||
job->Restart(); | |||
m_job_done << job; | |||
} | |||
} | |||
//AsyncImageJob --------------------------------------------------------------- | |||
class AsyncImageJob : public ThreadJob | |||
{ | |||
public: | |||
AsyncImageJob() | |||
: ThreadJob(ThreadJobType::NONE) | |||
{ | |||
m_path = String(); | |||
} | |||
AsyncImageJob(String path) | |||
: ThreadJob(ThreadJobType::WORK_TODO) | |||
{ | |||
m_path = path; | |||
} | |||
String const& GetPath() { return m_path; } | |||
Image const& GetImage() { return m_image; } | |||
protected: | |||
virtual bool DoWork() | |||
{ | |||
return m_image.Load(m_path.C()); | |||
} | |||
String m_path; | |||
Image m_image; | |||
}; | |||
//----------------------------------------------------------------------------- | |||
Image* AsyncImageLoader::Load(const lol::String& path) | |||
{ | |||
//Create a job | |||
AsyncImageJob* job = new AsyncImageJob(path); | |||
//Create a dummy image | |||
Image* image = new Image(m_dummy_image); | |||
//Link the two | |||
m_images[path] = image; | |||
//Add job | |||
AddWork(job); | |||
//return Dummy image | |||
return image; | |||
} | |||
//----------------------------------------------------------------------------- | |||
bool AsyncImageLoader::CheckStatus(Image* image) | |||
{ | |||
if (m_loaded_images.find(image) != INDEX_NONE) | |||
{ | |||
m_loaded_images.remove_item(image); | |||
return true; | |||
} | |||
return false; | |||
} | |||
//----------------------------------------------------------------------------- | |||
void AsyncImageLoader::TreatResult(ThreadJob* result) | |||
{ | |||
AsyncImageJob* job = dynamic_cast<AsyncImageJob*>(result); | |||
ASSERT(job); | |||
//Copy image if work is OK | |||
if (job->GetJobType() == ThreadJobType::WORK_SUCCESSED) | |||
{ | |||
Image* src = m_images[job->GetPath()]; | |||
m_images.remove(job->GetPath()); | |||
src->Copy(job->GetImage()); | |||
m_loaded_images.PushUnique(src); | |||
} | |||
else | |||
{ | |||
Log::Error("AsyncImageJob FAILED. See load image error above.\n"); | |||
} | |||
//Delete all that | |||
delete(result); | |||
} |