merged master

This commit is contained in:
Mikulas Florek 2015-03-12 19:50:37 +01:00
commit 87bd91c636
25 changed files with 640 additions and 415 deletions

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Mikulas Florek
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -134,7 +134,7 @@
</ImportGroup>
<ProjectExtensions>
<VisualStudio>
<UserProperties MocDir=".\..\..\..\tmp\render_test" UicDir=".\..\..\..\tmp\render_test\GeneratedFiles" RccDir=".\..\..\..\tmp\render_test\GeneratedFiles" lupdateOptions="" lupdateOnBuild="0" lreleaseOptions="" Qt5Version_x0020_Win32="5.3. msvc2013" MocOptions="" />
<UserProperties MocDir=".\..\..\..\tmp\render_test" UicDir=".\..\..\..\tmp\render_test\GeneratedFiles" RccDir=".\..\..\..\tmp\render_test\GeneratedFiles" lupdateOptions="" lupdateOnBuild="0" lreleaseOptions="" Qt5Version_x0020_Win32="$(DefaultQtVersion)" MocOptions="" />
</VisualStudio>
</ProjectExtensions>
</Project>

View file

@ -221,7 +221,6 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\script\base_script.h" />
<ClInclude Include="..\..\..\src\script\script_system.h" />
<ClInclude Include="..\..\..\src\script\script_visitor.h" />
</ItemGroup>

View file

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClInclude Include="..\..\..\src\script\base_script.h" />
<ClInclude Include="..\..\..\src\script\script_system.h" />
<ClInclude Include="..\..\..\src\script\script_visitor.h" />
</ItemGroup>

View file

@ -58,6 +58,7 @@ namespace Lumix
void operator =(const Path& rhs);
void operator =(const char* rhs);
void operator =(const string& rhs);
bool operator ==(const Path& rhs) const { return m_data->m_id == rhs.m_data->m_id; }
~Path();

View file

@ -62,7 +62,7 @@ namespace Lumix
serializer.deserialize("template_name", name, sizeof(name), "");
m_name = name;
serializer.deserialize("entity", m_entity.index, -1);
m_entity.universe = m_editor.getEngine().getUniverse();
m_entity.universe = m_editor.getUniverse();
}
@ -152,7 +152,7 @@ namespace Lumix
{
serializer.deserialize("template_name_hash", m_template_name_hash, 0);
serializer.deserialize("entity", m_entity.index, -1);
m_entity.universe = m_editor.getEngine().getUniverse();
m_entity.universe = m_editor.getUniverse();
serializer.deserialize("position_x", m_position.x, 0);
serializer.deserialize("position_y", m_position.y, 0);
serializer.deserialize("position_z", m_position.z, 0);
@ -168,7 +168,7 @@ namespace Lumix
int instance_index = m_entity_system.m_instances.find(m_template_name_hash);
if (instance_index >= 0)
{
m_entity = m_entity_system.m_editor.getEngine().getUniverse()->createEntity();
m_entity = m_entity_system.m_editor.getUniverse()->createEntity();
m_entity.setPosition(m_position);
m_entity.setRotation(m_rotation);
@ -233,7 +233,7 @@ namespace Lumix
{
editor.universeCreated().bind<EntityTemplateSystemImpl, &EntityTemplateSystemImpl::onUniverseCreated>(this);
editor.universeDestroyed().bind<EntityTemplateSystemImpl, &EntityTemplateSystemImpl::onUniverseDestroyed>(this);
setUniverse(editor.getEngine().getUniverse());
setUniverse(editor.getUniverse());
editor.registerEditorCommandCreator("create_entity_template_instance", &EntityTemplateSystemImpl::createCreateInstanceCommand);
editor.registerEditorCommandCreator("create_entity_template", &EntityTemplateSystemImpl::createCreateTemplateCommand);
}
@ -283,7 +283,7 @@ namespace Lumix
{
m_instances.clear();
m_template_names.clear();
setUniverse(m_editor.getEngine().getUniverse());
setUniverse(m_editor.getUniverse());
}

View file

@ -86,7 +86,7 @@ class SetEntityNameCommand : public IEditorCommand
serializer.deserialize("name", name, sizeof(name), "");
m_new_name = name;
serializer.deserialize("entity", m_entity.index, 0);
m_entity.universe = m_editor.getEngine().getUniverse();
m_entity.universe = m_editor.getUniverse();
m_old_name = m_entity.getName();
}
@ -177,7 +177,7 @@ class PasteEntityCommand : public IEditorCommand
serializer.deserialize("pos_y", m_position.y, 0);
serializer.deserialize("pos_z", m_position.z, 0);
serializer.deserialize("entity", m_entity.index, 0);
m_entity.universe = m_editor.getEngine().getUniverse();
m_entity.universe = m_editor.getUniverse();
int size;
serializer.deserialize("size", size, 0);
serializer.deserializeArrayBegin("data");
@ -199,7 +199,7 @@ class PasteEntityCommand : public IEditorCommand
{
cmps[i].scene->destroyComponent(cmps[i]);
}
m_editor.getEngine().getUniverse()->destroyEntity(m_entity);
m_editor.getUniverse()->destroyEntity(m_entity);
m_entity = Entity::INVALID;
}
@ -291,7 +291,7 @@ class MoveEntityCommand : public IEditorCommand
for (int i = 0; i < m_entities.size(); ++i)
{
serializer.deserializeArrayItem(m_entities[i].index, 0);
m_entities[i].universe = m_editor.getEngine().getUniverse();
m_entities[i].universe = m_editor.getUniverse();
serializer.deserializeArrayItem(m_new_positions[i].x, 0);
serializer.deserializeArrayItem(m_new_positions[i].y, 0);
serializer.deserializeArrayItem(m_new_positions[i].z, 0);
@ -411,7 +411,7 @@ class RemoveArrayPropertyItemCommand : public IEditorCommand
serializer.deserialize("entity_index", m_component.entity.index, 0);
serializer.deserialize("component_index", m_component.index, 0);
serializer.deserialize("component_type", m_component.type, 0);
m_component.entity.universe = m_editor.getEngine().getUniverse();
m_component.entity.universe = m_editor.getUniverse();
m_component.scene = m_editor.getEngine().getSceneByComponentType(m_component.type);
uint32_t property_name_hash;
serializer.deserialize("property_name_hash", property_name_hash, 0);
@ -593,7 +593,7 @@ class SetPropertyCommand : public IEditorCommand
serializer.deserialize("entity_index", m_component.entity.index, 0);
serializer.deserialize("component_index", m_component.index, 0);
serializer.deserialize("component_type", m_component.type, 0);
m_component.entity.universe = m_editor.getEngine().getUniverse();
m_component.entity.universe = m_editor.getUniverse();
m_component.scene = m_editor.getEngine().getSceneByComponentType(m_component.type);
serializer.deserializeArrayBegin("data");
m_new_value.clear();
@ -763,7 +763,7 @@ struct WorldEditorImpl : public WorldEditor
{
Entity& entity = m_entities.pushEmpty();
serializer.deserializeArrayItem(entity.index, 0);
entity.universe = m_editor.getEngine().getUniverse();
entity.universe = m_editor.getUniverse();
}
serializer.deserializeArrayEnd();
}
@ -872,7 +872,7 @@ struct WorldEditorImpl : public WorldEditor
for (int i = 0; i < count; ++i)
{
serializer.deserializeArrayItem(m_entities[i].index, 0);
m_entities[i].universe = m_editor.getEngine().getUniverse();
m_entities[i].universe = m_editor.getUniverse();
serializer.deserializeArrayItem(m_positons_rotations[i].m_position.x, 0);
serializer.deserializeArrayItem(m_positons_rotations[i].m_position.y, 0);
serializer.deserializeArrayItem(m_positons_rotations[i].m_position.z, 0);
@ -929,7 +929,7 @@ struct WorldEditorImpl : public WorldEditor
InputBlob blob(m_old_values);
for (int i = 0; i < m_entities.size(); ++i)
{
Entity new_entity = m_editor.getEngine().getUniverse()->createEntity();
Entity new_entity = m_editor.getUniverse()->createEntity();
new_entity.setPosition(m_positons_rotations[i].m_position);
new_entity.setRotation(m_positons_rotations[i].m_rotation);
int cmps_count;
@ -1018,7 +1018,7 @@ struct WorldEditorImpl : public WorldEditor
serializer.deserialize("entity", m_component.entity.index, 0);
serializer.deserialize("component", m_component.index, 0);
serializer.deserialize("component_type", m_component.type, 0);
m_component.entity.universe = m_editor.getEngine().getUniverse();
m_component.entity.universe = m_editor.getUniverse();
m_component.scene = m_editor.getEngine().getSceneByComponentType(m_component.type);
}
@ -1140,7 +1140,7 @@ struct WorldEditorImpl : public WorldEditor
virtual void execute() override
{
m_entity = m_editor.getEngine().getUniverse()->createEntity();
m_entity = m_editor.getUniverse()->createEntity();
m_entity.setPosition(m_position);
m_editor.selectEntities(&m_entity, 1);
}
@ -1164,7 +1164,7 @@ struct WorldEditorImpl : public WorldEditor
virtual void undo() override
{
m_editor.getEngine().getUniverse()->destroyEntity(m_entity);
m_editor.getUniverse()->destroyEntity(m_entity);
}
@ -1206,6 +1206,12 @@ struct WorldEditorImpl : public WorldEditor
}
virtual Universe* getUniverse() override
{
return m_engine->getUniverse();
}
virtual Engine& getEngine() override
{
return *m_engine;
@ -1755,6 +1761,12 @@ struct WorldEditorImpl : public WorldEditor
}
virtual bool isGameMode() const override
{
return m_is_game_mode;
}
virtual void toggleGameMode() override
{
if (m_is_game_mode)
@ -2196,6 +2208,7 @@ struct WorldEditorImpl : public WorldEditor
, m_universe_destroyed(m_allocator)
, m_universe_created(m_allocator)
, m_universe_loaded(m_allocator)
, m_game_mode_toggled(m_allocator)
, m_selected_entities(m_allocator)
, m_editor_icons(m_allocator)
, m_plugins(m_allocator)
@ -2725,6 +2738,7 @@ struct WorldEditorImpl : public WorldEditor
DelegateList<void()> m_universe_loaded;
DelegateList<void(const Array<Entity>&)> m_entity_selected;
DelegateList<void(const Entity&, const char*)> m_entity_name_set;
DelegateList<void(bool)> m_game_mode_toggled;
FS::FileSystem* m_file_system;
FS::TCPFileServer m_tpc_file_server;
@ -2772,7 +2786,7 @@ void WorldEditor::destroy(WorldEditor* editor)
void PasteEntityCommand::execute()
{
InputBlob blob(m_blob.getData(), m_blob.getSize());
Entity new_entity = m_editor.getEngine().getUniverse()->createEntity();
Entity new_entity = m_editor.getUniverse()->createEntity();
new_entity.setPosition(m_position);
int32_t count;
blob.read(count);

View file

@ -62,6 +62,7 @@ namespace Lumix
virtual IPropertyDescriptor* getProperty(const char* component_type, const char* property_name) = 0;
virtual void executeCommand(IEditorCommand* command) = 0;
virtual Engine& getEngine() = 0;
virtual Universe* getUniverse() = 0;
virtual IAllocator& getAllocator() = 0;
virtual void render(IRenderDevice& render_device) = 0;
virtual void renderIcons(IRenderDevice& render_device) = 0;
@ -126,6 +127,7 @@ namespace Lumix
virtual bool executeUndoStack(const Path& path) = 0;
virtual bool runTest(const Path& undo_stack_path, const Path& result_universe_path) = 0;
virtual void registerEditorCommandCreator(const char* command_type, EditorCommandCreator) = 0;
virtual bool isGameMode() const = 0;
protected:
virtual ~WorldEditor() {}

View file

@ -1,6 +1,5 @@
#include "script_system.h"
#include <Windows.h>
#include "base_script.h"
#include "core/iallocator.h"
#include "core/crc32.h"
#include "core/fs/file_system.h"
@ -18,13 +17,17 @@ static const uint32_t SCRIPT_HASH = crc32("script");
namespace Lumix
{
typedef BaseScript* (*CreateScriptFunction)();
typedef void (*DestroyScriptFunction)(BaseScript* script);
class ScriptSystemImpl;
class ScriptSceneImpl : public ScriptScene
{
public:
typedef void (*InitFunction)(ScriptScene*);
typedef void (*UpdateFunction)(float);
typedef void (*DoneFunction)();
typedef void (*SerializeFunction)(OutputBlob&);
typedef void (*DeserializeFunction)(InputBlob&);
public:
ScriptSceneImpl(ScriptSystemImpl& system, Engine& engine, Universe& universe)
: m_universe(universe)
@ -32,15 +35,19 @@ namespace Lumix
, m_system(system)
, m_allocator(engine.getAllocator())
, m_paths(m_allocator)
, m_running_scripts(m_allocator)
, m_script_entities(m_allocator)
, m_script_renamed(m_allocator)
, m_module(NULL)
, m_done_function(NULL)
, m_deserialize_function(NULL)
, m_serialize_function(NULL)
, m_update_function(NULL)
{
}
~ScriptSceneImpl()
{
stopAll();
}
@ -55,7 +62,6 @@ namespace Lumix
void deserialize(InputBlob& serializer) override
{
stopAll();
int32_t count;
serializer.read(count);
m_script_entities.resize(count);
@ -73,137 +79,149 @@ namespace Lumix
m_universe.addComponent(entity, SCRIPT_HASH, this, i);
}
}
runAll();
}
void update(float dt)
virtual void serializeScripts(OutputBlob& blob) override
{
for (int i = 0; i < m_running_scripts.size(); ++i)
if (m_serialize_function)
{
m_running_scripts[i].m_script_object->update(dt);
m_serialize_function(blob);
}
}
virtual void deserializeScripts(InputBlob& blob) override
{
if (m_deserialize_function)
{
m_deserialize_function(blob);
}
}
void update(float time_delta) override
{
if (m_is_compiling)
{
return;
}
if (m_update_function)
{
m_update_function(time_delta);
}
}
virtual const Lumix::Path& getScriptPath(Component cmp) override
{
return m_paths[cmp.index];
}
void getScriptPath(Component cmp, string& str) override
{
str = m_paths[cmp.index];
}
virtual DelegateList<void(const Path&, const Path&)>& scriptRenamed() override
{
return m_script_renamed;
}
void setScriptPath(Component cmp, const string& str) override
{
m_paths[cmp.index] = string(str.c_str(), m_allocator);
stopScript(cmp.index);
if (!runScript(cmp.index))
{
g_log_warning.log("script") << "Could not run script " << str;
}
Lumix::Path old_path = m_paths[cmp.index];
m_paths[cmp.index] = str.c_str();
m_script_renamed.invoke(old_path, m_paths[cmp.index]);
}
void getDll(const char* script_path, char* dll_path, char* full_path, int max_length)
virtual Component getNextScript(const Component& cmp) override
{
copyString(dll_path, max_length, script_path);
int32_t len = (int32_t)strlen(script_path);
if (len > 4)
for (int i = cmp.index + 1; i < m_script_entities.size(); ++i)
{
copyString(dll_path + len - 4, 5, ".dll");
if (m_script_entities[i] != -1)
{
return Component(Entity(&m_universe, m_script_entities[i]), SCRIPT_HASH, this, i);
}
}
copyString(full_path, max_length, m_engine.getBasePath());
catCString(full_path, max_length, "\\");
catCString(full_path, max_length, dll_path);
return Component::INVALID;
}
virtual Component getFirstScript() override
{
for (int i = 0; i < m_script_entities.size(); ++i)
{
if (m_script_entities[i] != -1)
{
return Component(Entity(&m_universe, m_script_entities[i]), SCRIPT_HASH, this, i);
}
}
return Component::INVALID;
}
void getScriptDefaultPath(Entity e, char* path, char* full_path, int length, const char* ext)
{
char tmp[30];
toCString(e.index, tmp, 30);
copyString(full_path, length, m_engine.getBasePath());
catCString(full_path, length, "\\scripts\\e");
catCString(full_path, length, "e");
catCString(full_path, length, tmp);
catCString(full_path, length, ".");
catCString(full_path, length, ext);
copyString(path, length, "scripts\\e");
copyString(path, length, "e");
catCString(path, length, tmp);
catCString(path, length, ".");
catCString(path, length, ext);
}
virtual void beforeScriptCompiled(const Lumix::Path& path) override
virtual void afterScriptCompiled() override
{
for (int i = 0; i < m_paths.size(); ++i)
if (!m_module)
{
if (m_paths[i] == path.c_str())
const char* library_path = "scripts/Debug/main.dll";
m_module = LoadLibrary(library_path);
if (!m_module)
{
stopScript(i);
}
}
}
virtual void afterScriptCompiled(const Lumix::Path& path) override
{
for (int i = 0; i < m_paths.size(); ++i)
{
if (m_paths[i] == path.c_str())
{
runScript(i);
}
}
}
void stopScript(int index)
{
int entity_idx = m_script_entities[index];
for (int i = 0; i < m_running_scripts.size(); ++i)
{
if (m_running_scripts[i].m_entity_idx == entity_idx)
{
DestroyScriptFunction f = (DestroyScriptFunction)GetProcAddress(m_running_scripts[i].m_lib, "destroyScript");
f(m_running_scripts[i].m_script_object);
BOOL b = FreeLibrary(m_running_scripts[i].m_lib);
ASSERT(b == TRUE);
m_running_scripts.eraseFast(i);
g_log_error.log("script") << "Could not load " << library_path;
return;
}
m_update_function = (UpdateFunction)GetProcAddress(m_module, "update");
m_done_function = (DoneFunction)GetProcAddress(m_module, "done");
m_serialize_function = (SerializeFunction)GetProcAddress(m_module, "serialize");
m_deserialize_function = (DeserializeFunction)GetProcAddress(m_module, "deserialize");
InitFunction init_function = (InitFunction)GetProcAddress(m_module, "init");
if (!m_update_function || !init_function)
{
g_log_error.log("script") << "Script interface in " << library_path << " is not complete";
}
if (init_function)
{
init_function(this);
}
}
m_is_compiling = false;
}
bool runScript(int i)
virtual void beforeScriptCompiled() override
{
char path[LUMIX_MAX_PATH];
char full_path[LUMIX_MAX_PATH];
getDll(m_paths[i].c_str(), path, full_path, LUMIX_MAX_PATH);
HMODULE h = LoadLibrary(full_path);
if (h)
m_is_compiling = true;
if (m_done_function)
{
CreateScriptFunction f = (CreateScriptFunction)GetProcAddress(h, TEXT("createScript"));
BaseScript* script = f();
if (!f)
{
g_log_warning.log("script") << "failed to create script " << m_paths[i].c_str();
FreeLibrary(h);
}
else
{
RunningScript running_script;
running_script.m_script_object = script;
running_script.m_entity_idx = m_script_entities[i];
running_script.m_lib = h;
m_running_scripts.push(running_script);
script->create(*this, Entity(&m_universe, running_script.m_entity_idx));
return true;
}
m_done_function();
}
return false;
FreeLibrary(m_module);
m_module = NULL;
}
@ -219,64 +237,11 @@ namespace Lumix
Component cmp = m_universe.addComponent(entity, SCRIPT_HASH, this, m_script_entities.size() - 1);
m_universe.componentCreated().invoke(cmp);
runScript(m_paths.size() - 1);
return cmp;
}
void runAll()
{
char path[MAX_PATH];
char full_path[MAX_PATH];
for (int i = 0; i < m_script_entities.size(); ++i)
{
if(m_script_entities[i] != -1)
{
Entity e(&m_universe, m_script_entities[i]);
getDll(m_paths[i].c_str(), path, full_path, MAX_PATH);
HMODULE h = LoadLibrary(full_path);
if (h)
{
CreateScriptFunction f = (CreateScriptFunction)GetProcAddress(h, TEXT("createScript"));
BaseScript* script = f();
if (!f)
{
g_log_warning.log("script") << "failed to create script " << m_paths[i].c_str();
FreeLibrary(h);
}
else
{
RunningScript running_script;
running_script.m_entity_idx = e.index;
running_script.m_lib = h;
running_script.m_script_object = script;
m_running_scripts.push(running_script);
script->create(*this, e);
}
}
else
{
g_log_warning.log("script") << "failed to load script " << m_paths[i].c_str();
}
}
}
}
void stopAll()
{
for (int i = 0; i < m_running_scripts.size(); ++i)
{
DestroyScriptFunction f = (DestroyScriptFunction)GetProcAddress(m_running_scripts[i].m_lib, "destroyScript");
f(m_running_scripts[i].m_script_object);
BOOL b = FreeLibrary(m_running_scripts[i].m_lib);
ASSERT(b == TRUE);
}
m_running_scripts.clear();
}
void serialize(OutputBlob& serializer) override
{
serializer.write((int32_t)m_script_entities.size());
@ -310,21 +275,20 @@ namespace Lumix
return m_engine;
}
struct RunningScript
{
BaseScript* m_script_object;
HMODULE m_lib;
int m_entity_idx;
};
IAllocator& m_allocator;
Array<RunningScript> m_running_scripts;
Array<int32_t> m_script_entities;
Array<Path> m_paths;
Universe& m_universe;
Engine& m_engine;
ScriptSystemImpl& m_system;
HMODULE m_module;
UpdateFunction m_update_function;
DoneFunction m_done_function;
SerializeFunction m_serialize_function;
DeserializeFunction m_deserialize_function;
bool m_is_compiling;
DelegateList<void(const Path&, const Path&)> m_script_renamed;
};
class ScriptSystemImpl : public IPlugin
@ -333,6 +297,7 @@ namespace Lumix
Engine& m_engine;
BaseProxyAllocator m_allocator;
ScriptSystemImpl(Engine& engine)
: m_engine(engine)
, m_allocator(engine.getAllocator())
@ -357,7 +322,7 @@ namespace Lumix
if (m_engine.getWorldEditor())
{
IAllocator& allocator = m_engine.getWorldEditor()->getAllocator();
m_engine.getWorldEditor()->registerProperty("script", allocator.newObject<FilePropertyDescriptor<ScriptSceneImpl> >("source", &ScriptSceneImpl::getScriptPath, &ScriptSceneImpl::setScriptPath, "Script (*.cpp)", allocator));
m_engine.getWorldEditor()->registerProperty("script", allocator.newObject<FilePropertyDescriptor<ScriptSceneImpl> >("source", (void (ScriptSceneImpl::*)(Component, string&))&ScriptSceneImpl::getScriptPath, &ScriptSceneImpl::setScriptPath, "Script (*.cpp)", allocator));
}
return true;
}
@ -380,8 +345,7 @@ namespace Lumix
{
return m_system;
}
extern "C" IPlugin* createPlugin(Engine& engine)
{

View file

@ -19,10 +19,19 @@ class LUMIX_SCRIPT_API ScriptScene : public IScene
{
public:
virtual void getScriptPath(Component cmp, string& str) = 0;
virtual const Lumix::Path& getScriptPath(Component cmp) = 0;
virtual void setScriptPath(Component cmp, const string& str) = 0;
virtual void beforeScriptCompiled(const Lumix::Path& path) = 0;
virtual void afterScriptCompiled(const Lumix::Path& path) = 0;
virtual void serializeScripts(OutputBlob& blob) = 0;
virtual void deserializeScripts(InputBlob& blob) = 0;
virtual void beforeScriptCompiled() = 0;
virtual void afterScriptCompiled() = 0;
virtual DelegateList<void(const Path&, const Path&)>& scriptRenamed() = 0;
virtual Component getFirstScript() = 0;
virtual Component getNextScript(const Component& cmp) = 0;
virtual Engine& getEngine() = 0;
};

View file

@ -17,7 +17,7 @@ AnimationEditor::AnimationEditor(PropertyView& property_view)
: m_property_view(property_view)
{
m_animator = new Animator;
m_graph_path = "untitled";
m_graph_path = "tmp/untitled";
setWindowTitle("Animation editor");
setObjectName("animationEditor");

View file

@ -483,7 +483,7 @@ bool Animator::compile(const QString& base_path, const QString& path)
QProcess* process = new QProcess;
QStringList list;
list << "/C";
list << QString("%1/tmp/compile.bat %2").arg(base_path, file.fileName());
list << QString("%1/tmp/compile.bat %1/%2").arg(base_path).arg(file.fileName());
process->start("cmd.exe", list);
m_library.unload();
process->connect(process, (void (QProcess::*)(int))&QProcess::finished, [process, this, info](int exit_code){

View file

@ -142,8 +142,7 @@ void AssetBrowser::onFileChanged(const QString& path)
QFileInfo info(path);
if (info.suffix() == "cpp")
{
auto path = info.filePath().toLatin1();
m_compiler->compile(Lumix::Path(path.data()));
m_compiler->onScriptChanged(info.fileName().toLatin1().data());
}
else if(info.suffix() == "blend@")
{

View file

@ -56,8 +56,8 @@ class SetParentEditorCommand : public Lumix::IEditorCommand
{
serializer.deserialize("parent", m_new_parent.index, 0);
serializer.deserialize("child", m_child.index, 0);
m_new_parent.universe = m_editor.getEngine().getUniverse();
m_child.universe = m_editor.getEngine().getUniverse();
m_new_parent.universe = m_editor.getUniverse();
m_child.universe = m_editor.getUniverse();
m_old_parent = m_hierarchy.getParent(m_child);
}
@ -600,7 +600,7 @@ void EntityList::setWorldEditor(Lumix::WorldEditor& editor)
editor.universeCreated().bind<EntityList, &EntityList::onUniverseCreated>(this);
editor.universeDestroyed().bind<EntityList, &EntityList::onUniverseDestroyed>(this);
editor.universeLoaded().bind<EntityList, &EntityList::onUniverseLoaded>(this);
m_universe = editor.getEngine().getUniverse();
m_universe = editor.getUniverse();
m_model->setEngine(editor.getEngine());
m_model->setUniverse(m_universe);
m_filter->setSourceModel(m_model);
@ -648,14 +648,14 @@ void EntityList::onEntitySelected(const Lumix::Array<Lumix::Entity>& entities)
void EntityList::onUniverseCreated()
{
m_universe = m_editor->getEngine().getUniverse();
m_universe = m_editor->getUniverse();
m_model->setUniverse(m_universe);
}
void EntityList::onUniverseLoaded()
{
m_universe = m_editor->getEngine().getUniverse();
m_universe = m_editor->getUniverse();
m_model->setUniverse(m_universe);
if (m_is_update_enabled)
{

View file

@ -5,13 +5,15 @@
#include "editor/world_editor.h"
#include "engine/engine.h"
#include "graphics/pipeline.h"
#include "mainwindow.h"
#include <QMouseEvent>
GameView::GameView(QWidget* parent) :
QDockWidget(parent),
m_ui(new Ui::GameView)
GameView::GameView(MainWindow& parent)
: QDockWidget(&parent)
, m_ui(new Ui::GameView)
, m_main_window(parent)
{
m_ui->setupUi(this);
m_pipeline = NULL;
@ -86,6 +88,6 @@ void GameView::keyPressEvent(QKeyEvent* event)
void GameView::on_playButton_clicked()
{
m_editor->toggleGameMode();
m_main_window.on_actionGame_mode_triggered();
}

View file

@ -4,6 +4,9 @@
#include <QDockWidget>
class MainWindow;
namespace Lumix
{
class WorldEditor;
@ -20,7 +23,7 @@ class GameView : public QDockWidget
Q_OBJECT
public:
explicit GameView(QWidget* parent = NULL);
explicit GameView(MainWindow& parent);
virtual ~GameView();
QWidget* getContentWidget() const;
@ -40,5 +43,6 @@ private:
Ui::GameView* m_ui;
Lumix::PipelineInstance* m_pipeline;
Lumix::WorldEditor* m_editor;
MainWindow& m_main_window;
};

View file

@ -78,7 +78,7 @@ void InsertMeshCommand::undo()
{
cmps[i].scene->destroyComponent(cmps[i]);
}
m_editor.getEngine().getUniverse()->destroyEntity(m_entity);
m_editor.getUniverse()->destroyEntity(m_entity);
m_entity = Lumix::Entity::INVALID;
}

View file

@ -17,6 +17,7 @@
#include "property_view.h"
#include "sceneview.h"
#include "scripts/scriptcompilerwidget.h"
#include "scripts/scriptcompiler.h"
#include "profilerui.h"
#include <qcombobox.h>
#include <qdir.h>
@ -40,7 +41,7 @@ MainWindow::MainWindow(QWidget* parent) :
m_animation_editor = new AnimationEditor(*m_property_view);
m_skeleton_view = new SkeletonView();
m_scene_view = new SceneView;
m_game_view = new GameView;
m_game_view = new GameView(*this);
m_asset_browser = new AssetBrowser;
m_script_compiler_ui = new ScriptCompilerWidget;
m_file_server_ui = new FileServerWidget;
@ -49,6 +50,9 @@ MainWindow::MainWindow(QWidget* parent) :
m_notifications = Notifications::create(*this);
m_entity_list = new EntityList(NULL);
m_toggle_game_mode_after_compile = false;
connect(m_script_compiler_ui->getCompiler(), &ScriptCompiler::compiled, this, &MainWindow::onScriptCompiled);
QSettings settings("Lumix", "QtEditor");
bool geometry_restored = restoreGeometry(settings.value("mainWindowGeometry").toByteArray());
@ -220,7 +224,6 @@ MainWindow::~MainWindow()
delete m_skeleton_view;
delete m_scene_view;
delete m_property_view;
delete m_game_view;
delete m_asset_browser;
delete m_script_compiler_ui;
delete m_file_server_ui;
@ -362,9 +365,26 @@ void MainWindow::on_actionPolygon_Mode_changed()
m_world_editor->setWireframe(m_ui->actionPolygon_Mode->isChecked());
}
void MainWindow::onScriptCompiled()
{
if (m_toggle_game_mode_after_compile)
{
m_world_editor->toggleGameMode();
}
m_toggle_game_mode_after_compile = false;
}
void MainWindow::on_actionGame_mode_triggered()
{
m_world_editor->toggleGameMode();
if (!m_world_editor->isGameMode())
{
m_script_compiler_ui->getCompiler()->compileAllModules();
m_toggle_game_mode_after_compile = true;
}
else
{
m_world_editor->toggleGameMode();
}
}
void MainWindow::on_actionLook_at_selected_entity_triggered()

View file

@ -31,7 +31,11 @@ public:
signals:
void resized(const QSize& size);
public slots:
void on_actionGame_mode_triggered();
private slots:
void onScriptCompiled();
void on_actionLog_triggered();
void on_actionOpen_triggered();
void on_actionSave_As_triggered();
@ -45,10 +49,8 @@ private slots:
void on_actionScene_View_triggered();
void on_actionAnimation_Editor_triggered();
void on_actionSkeleton_View_triggered();
virtual void closeEvent(QCloseEvent* event) override;
void on_actionProfiler_triggered();
void on_actionPolygon_Mode_changed();
void on_actionGame_mode_triggered();
void on_actionLook_at_selected_entity_triggered();
void on_actionNew_triggered();
void on_actionSave_triggered();
@ -82,6 +84,7 @@ private:
private:
virtual void resizeEvent(QResizeEvent* event) override;
virtual void closeEvent(QCloseEvent* event) override;
void fillRecentFiles();
void onUniverseLoaded();
void addEditorDock(Qt::DockWidgetArea area, QDockWidget* widget, void (MainWindow::*callback)());
@ -109,5 +112,6 @@ private:
class QComboBox* m_layout_combobox;
QList<QString> m_recent_files;
QList<DockInfo> m_dock_infos;
bool m_toggle_game_mode_after_compile;
};

View file

@ -413,7 +413,7 @@ void PropertyView::setWorldEditor(Lumix::WorldEditor& editor)
m_world_editor->entitySelected().bind<PropertyView, &PropertyView::onEntitySelected>(this);
m_world_editor->universeCreated().bind<PropertyView, &PropertyView::onUniverseCreated>(this);
m_world_editor->universeDestroyed().bind<PropertyView, &PropertyView::onUniverseDestroyed>(this);
if (m_world_editor->getEngine().getUniverse())
if (m_world_editor->getUniverse())
{
onUniverseCreated();
}
@ -422,13 +422,13 @@ void PropertyView::setWorldEditor(Lumix::WorldEditor& editor)
void PropertyView::onUniverseCreated()
{
m_world_editor->getEngine().getUniverse()->entityMoved().bind<PropertyView, &PropertyView::onEntityPosition>(this);
m_world_editor->getUniverse()->entityMoved().bind<PropertyView, &PropertyView::onEntityPosition>(this);
}
void PropertyView::onUniverseDestroyed()
{
m_world_editor->getEngine().getUniverse()->entityMoved().unbind<PropertyView, &PropertyView::onEntityPosition>(this);
m_world_editor->getUniverse()->entityMoved().unbind<PropertyView, &PropertyView::onEntityPosition>(this);
}
@ -884,8 +884,12 @@ ScriptComponentPlugin::ScriptComponentPlugin(Lumix::WorldEditor& editor, ScriptC
, m_compiler(compiler)
, m_status_item(NULL)
{
connect(&m_compiler, &ScriptCompiler::compiled, [this](const Lumix::Path&, uint32_t status){
setScriptStatus(status == 0 ? ScriptCompiler::SUCCESS : ScriptCompiler::FAILURE);
connect(&m_compiler, &ScriptCompiler::compiled, [this](const QString& module_name){
QFileInfo info(m_world_editor.getUniversePath().c_str());
if (module_name == info.baseName())
{
setScriptStatus(m_compiler.getStatus(module_name));
}
});
}
@ -909,7 +913,7 @@ void ScriptComponentPlugin::createEditor(QTreeWidgetItem* component_item, const
compile_button->connect(compile_button, &QPushButton::clicked, this, [this, component](){
Lumix::string path(m_world_editor.getAllocator());
static_cast<Lumix::ScriptScene*>(component.scene)->getScriptPath(component, path);
m_compiler.compile(Lumix::Path(path.c_str()));
m_compiler.onScriptChanged(path.c_str());
});
QTreeWidgetItem* status_item = new QTreeWidgetItem(QStringList() << "Status");
@ -917,7 +921,8 @@ void ScriptComponentPlugin::createEditor(QTreeWidgetItem* component_item, const
component_item->addChild(status_item);
Lumix::string path(m_world_editor.getAllocator());
static_cast<Lumix::ScriptScene*>(component.scene)->getScriptPath(component, path);
switch (m_compiler.getStatus(Lumix::Path(path.c_str())))
QFileInfo info(m_world_editor.getUniversePath().c_str());
switch (m_compiler.getStatus(info.baseName()))
{
case ScriptCompiler::SUCCESS:
status_item->setText(1, "Compiled");

View file

@ -16,155 +16,194 @@ ScriptCompiler::ScriptCompiler(QObject* parent)
}
void ScriptCompiler::compileAll()
void ScriptCompiler::onScriptRenamed(const Lumix::Path& old_path, const Lumix::Path& new_path)
{
QDirIterator dirIt(QString(m_base_path.c_str()) + "/scripts/", QDirIterator::Subdirectories);
while (dirIt.hasNext())
for (auto iter = m_modules.begin(), end = m_modules.end(); iter != end; ++iter)
{
dirIt.next();
if (QFileInfo(dirIt.filePath()).isFile())
Module& module = *iter;
for (int i = 0; module.m_scripts.size(); ++i)
{
if (QFileInfo(dirIt.filePath()).suffix() == "cpp")
if (module.m_scripts[i] == old_path)
{
compile(Lumix::Path(dirIt.filePath().toLatin1().data()));
module.m_scripts[i] = new_path;
break;
}
}
}
}
void ScriptCompiler::addScript(const QString& module_name, const Lumix::Path& path)
{
if (m_modules.find(module_name) == m_modules.end())
{
m_modules.insert(module_name, Module(module_name));
}
m_modules[module_name].m_scripts.push_back(path);
m_modules[module_name].m_status = UNKNOWN;
}
void ScriptCompiler::removeScript(const Lumix::Path& path)
{
for (auto iter = m_modules.begin(), end = m_modules.end(); iter != end; ++iter)
{
Module& module = *iter;
for (int i = 0; module.m_scripts.size(); ++i)
{
if (module.m_scripts[i] == path)
{
module.m_scripts.removeAt(i);
module.m_status = UNKNOWN;
break;
}
}
}
}
void ScriptCompiler::destroyModule(const QString& module_name)
{
if (m_modules.contains(module_name))
{
m_modules[module_name].m_status = UNKNOWN;
m_modules[module_name].m_scripts.clear();
}
}
void ScriptCompiler::compileAllModules()
{
for (auto iter = m_modules.begin(), end = m_modules.end(); iter != end; ++iter)
{
Module& module = *iter;
compileModule(module.m_module_name);
}
}
void ScriptCompiler::compileModule(const QString& module_name)
{
if (!m_modules.contains(module_name))
{
return;
}
Module& module = m_modules[module_name];
Lumix::OutputBlob* out_blob = m_editor->getAllocator().newObject<Lumix::OutputBlob>(m_editor->getAllocator());
Lumix::ScriptScene* scene = static_cast<Lumix::ScriptScene*>(m_editor->getEngine().getScene(crc32("script")));
if (m_editor->isGameMode())
{
scene->serializeScripts(*out_blob);
}
scene->beforeScriptCompiled();
module.m_status = NOT_COMPILED;
QString sources = QString(" <ClCompile Include=\"%1.cpp\"/>\n").arg(module.m_module_name);
for (int i = 0; i < module.m_scripts.size(); ++i)
{
sources += QString(" <ClCompile Include=\"%1\"/>\n").arg(module.m_scripts[i].c_str());
}
QFile file(QString("scripts/%1.vcxproj").arg(module.m_module_name));
file.open(QIODevice::Text | QIODevice::WriteOnly);
file.write(QString(
"<Project DefaultTargets=\"Build\" ToolsVersion=\"12.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
" <ItemGroup>\n"
" <ProjectConfiguration Include = \"Debug|Win32\">\n"
" <Configuration>Debug</Configuration>\n"
" <Platform>Win32</Platform>\n"
" </ProjectConfiguration>\n"
" <ProjectConfiguration Include = \"Release|Win32\">\n"
" <Configuration>Release</Configuration>\n"
" <Platform>Win32</Platform>\n"
" </ProjectConfiguration>\n"
" </ItemGroup>\n"
" <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.default.props\"/>\n"
" <PropertyGroup>\n"
" <ConfigurationType>DynamicLibrary</ConfigurationType>\n"
" <PlatformToolset>v120</PlatformToolset>\n"
" </PropertyGroup>\n"
" <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\"/>\n"
" <ItemDefinitionGroup>\n"
" <ClCompile>\n"
" <AdditionalIncludeDirectories>%1\\src</AdditionalIncludeDirectories>\n"
" </ClCompile>\n"
" <Link>\n"
" <AdditionalDependencies>core.lib;engine.lib;physics.lib</AdditionalDependencies>\n"
" <AdditionalLibraryDirectories>%1\\bin\\win32_debug</AdditionalLibraryDirectories>\n"
" <GenerateDebugInformation>false</GenerateDebugInformation>"
" </Link>\n"
" </ItemDefinitionGroup>\n"
" <ItemGroup>\n").arg(m_sources_path).toLatin1().data());
file.write(sources.toLatin1().data());
file.write(
" </ItemGroup>\n"
" <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Targets\"/>\n"
"</Project>\n");
file.close();
QProcess* process = new QProcess;
process->connect(process, (void (QProcess::*)(int))&QProcess::finished, [module_name, out_blob, scene, this, process](int exit_code){
process->deleteLater();
m_modules[module_name].m_log = process->readAll();
m_modules[module_name].m_status = exit_code == 0 ? SUCCESS : FAILURE;
emitCompiled(module_name);
scene->afterScriptCompiled();
if (m_editor->isGameMode())
{
Lumix::InputBlob blob(*out_blob);
scene->deserializeScripts(blob);
m_editor->getAllocator().deleteObject(out_blob);
}
});
QStringList list;
list << "/C";
list << QString("%1/scripts/compile_all.bat %2").arg(m_editor->getBasePath()).arg(file.fileName());
process->start("cmd.exe", list);
}
ScriptCompiler::Status ScriptCompiler::getStatus(const QString& module_name)
{
return m_modules[module_name].m_status;
}
QString ScriptCompiler::getLog(const QString& module_name)
{
return m_modules[module_name].m_log;
}
void ScriptCompiler::onScriptChanged(const QString& path)
{
for (auto iter = m_modules.begin(), end = m_modules.end(); iter != end; ++iter)
{
Module& module = *iter;
for (int i = 0; i < module.m_scripts.size(); ++i)
{
if (module.m_scripts[i] == path)
{
compileModule(module.m_module_name);
break;
}
}
}
}
void ScriptCompiler::setWorldEditor(Lumix::WorldEditor& editor)
{
m_editor = &editor;
}
void ScriptCompiler::compile(const Lumix::Path& path)
void ScriptCompiler::onGameModeToggled(bool was_game_mode)
{
if (m_editor)
if (!was_game_mode)
{
Lumix::ScriptScene* scene = static_cast<Lumix::ScriptScene*>(m_editor->getEngine().getScene(crc32("script")));
scene->beforeScriptCompiled(path);
}
ProcessInfo process;
Lumix::Path rel_path;
if(strncmp(path.c_str(), m_base_path.c_str(), m_base_path.length()) == 0)
{
rel_path = path.c_str() + m_base_path.length() + 1;
}
else
{
rel_path = path;
}
process.m_path = rel_path;
process.m_process = new QProcess();
m_processes.push_back(process);
QStringList list;
char cmd_line[255];
sprintf(cmd_line, "%s\\scripts\\compile.bat %s\\%s", m_base_path.c_str(), m_base_path.c_str(), rel_path.c_str());
list.push_back("/C");
list.push_back(cmd_line);
connect(process.m_process, (void (QProcess::*)(int))&QProcess::finished, this, &ScriptCompiler::compilerFinish);
process.m_process->start("cmd.exe", list);
}
void ScriptCompiler::compilerFinish(int exitCode)
{
QProcess* process = static_cast<QProcess*>(QObject::sender());
QString s = process->readAll();
process->deleteLater();
while(process->waitForReadyRead())
{
s += process->readAll();
}
for(int i = 0; i < m_processes.size(); ++i)
{
if(m_processes[i].m_process == process)
{
uint32_t hash = crc32(m_processes[i].m_path.c_str());
m_log[hash] = s.toLatin1().data();
m_status[hash] = exitCode == 0 ? SUCCESS : FAILURE;
QString msg;
if(exitCode == 0)
{
msg.sprintf("Script %s compiled successfully", m_processes[i].m_path.c_str());
}
else
{
msg.sprintf("Script %s failed to compile", m_processes[i].m_path.c_str());
Lumix::g_log_error.log("script") << "Script " << m_processes[i].m_path.c_str() << " failed to compile";
}
emit compiled(Lumix::Path(m_processes[i].m_path.c_str()), exitCode);
emit messageLogged(msg);
if (m_editor)
{
Lumix::ScriptScene* scene = static_cast<Lumix::ScriptScene*>(m_editor->getEngine().getScene(crc32("script")));
scene->afterScriptCompiled(m_processes[i].m_path);
}
m_processes.removeAt(i);
break;
}
QFileInfo info(m_editor->getUniversePath().c_str());
compileModule(info.baseName());
}
}
ScriptCompiler::Status ScriptCompiler::getStatus(const Lumix::Path& path)
{
uint32_t hash;
if(strncmp(path.c_str(), m_base_path.c_str(), m_base_path.length()) == 0)
{
hash = crc32(path.c_str() + m_base_path.length() + 1);
}
else
{
hash = crc32(path.c_str());
}
QMap<uint32_t, Status>::iterator iter = m_status.find(hash);
return iter == m_status.end() ? UNKNOWN : iter.value();
}
void ScriptCompiler::checkFinished()
{
for(int i = m_processes.size() - 1; i >= 0; --i)
{
ProcessInfo& process = m_processes[i];
if(process.m_process->state() == QProcess::NotRunning)
{
uint32_t hash = crc32(process.m_path.c_str());
m_status[hash] = process.m_process->exitCode() == 0 ? SUCCESS : FAILURE;
QString s;
while(process.m_process->waitForReadyRead())
{
s += process.m_process->readAll();
}
m_log[hash] = s.toLatin1().data();
delete process.m_process;
m_processes.remove(i);
}
}
if (m_processes.empty())
{
Lumix::g_log_info.log("script") << "All scripts processed";
}
}
QString ScriptCompiler::getLog(const Lumix::Path& path)
{
uint32_t hash;
if(strncmp(path.c_str(), m_base_path.c_str(), m_base_path.length()) == 0)
{
hash = crc32(path.c_str() + m_base_path.length() + 1);
}
else
{
hash = crc32(path.c_str());
}
return m_log[hash];
}

View file

@ -3,8 +3,10 @@
#include <QMap>
#include <QObject>
#include <QString>
#include <QVector>
#include "core/array.h"
#include "core/blob.h"
#include "core/delegate_list.h"
#include "core/path.h"
#include "core/string.h"
@ -25,23 +27,24 @@ public:
FAILURE
};
class Module;
public:
explicit ScriptCompiler(QObject* parent = NULL);
void compile(const Lumix::Path& path);
void compileAll();
void setBasePath(const Lumix::Path& path) { m_base_path = path; }
void checkFinished();
bool isEmpty() const { return m_processes.empty(); }
Status getStatus(const Lumix::Path& path);
QString getLog(const Lumix::Path& path);
void compileModule(const QString& module_name);
void compileAllModules();
Status getStatus(const QString& module_name);
QString getLog(const QString& module_name);
void setWorldEditor(Lumix::WorldEditor& editor);
void addScript(const QString& module_name, const Lumix::Path& path);
void onScriptRenamed(const Lumix::Path& old_path, const Lumix::Path& new_path);
void removeScript(const Lumix::Path& path);
void destroyModule(const QString& module_name);
void setSourcesPath(const QString& path) { m_sources_path = path; }
void onScriptChanged(const QString& path);
signals:
void messageLogged(const QString& message);
void compiled(const Lumix::Path&, uint32_t);
public slots:
void compilerFinish(int exitCode);
void compiled(const QString&);
private:
struct ProcessInfo
@ -51,9 +54,25 @@ private:
};
private:
Lumix::Path m_base_path;
QVector<ProcessInfo> m_processes;
QMap<uint32_t, Status> m_status;
QMap<uint32_t, QString> m_log;
void emitCompiled(const QString& module_name) { emit compiled(module_name); }
void onGameModeToggled(bool was_game_mode);
private:
Lumix::WorldEditor* m_editor;
QMap<QString, Module> m_modules;
QString m_sources_path;
};
class ScriptCompiler::Module
{
public:
Module(const QString& name) : m_module_name(name) {}
Module() { Q_ASSERT(false); }
public:
QVector<Lumix::Path> m_scripts;
Status m_status;
QString m_log;
QString m_module_name;
};

View file

@ -1,55 +1,182 @@
#include "scriptcompilerwidget.h"
#include "ui_scriptcompilerwidget.h"
#include <qfilesystemmodel.h>
#include "scriptcompiler.h"
#include "editor/world_editor.h"
#include "engine/engine.h"
#include "ui_scriptcompilerwidget.h"
#include "scriptcompiler.h"
#include "script/script_system.h"
#include <qdesktopservices.h>
#include <qfiledialog.h>
#include <qfilesystemmodel.h>
#include <qprocess.h>
#include <qsettings.h>
ScriptCompilerWidget::ScriptCompilerWidget(QWidget* parent) :
QDockWidget(parent),
m_ui(new Ui::ScriptCompilerWidget)
static const unsigned int SCRIPT_HASH = crc32("script");
ScriptCompilerWidget::ScriptCompilerWidget(QWidget* parent)
: QDockWidget(parent)
, m_ui(new Ui::ScriptCompilerWidget)
, m_universe(NULL)
{
m_ui->setupUi(this);
m_model = new QFileSystemModel;
m_model->setRootPath(QDir::currentPath() + "/scripts/");
m_base_path = QDir::currentPath().toLatin1().data();
QStringList filters;
filters << "*.cpp";
m_model->setNameFilterDisables(false);
m_model->setNameFilters(filters);
m_ui->scriptListView->setModel(m_model);
m_ui->scriptListView->setRootIndex(m_model->index(QDir::currentPath() + "/scripts/"));
m_compiler = new ScriptCompiler;
connect(m_compiler, SIGNAL(messageLogged(const QString&)), this, SLOT(logMessage(const QString&)));
QByteArray base_path = m_base_path.toLatin1();
m_compiler->setBasePath(Lumix::Path(base_path.data()));
m_compiler->compileAll();
connect(m_compiler, &ScriptCompiler::compiled, [this](const QString& module_name){
m_ui->compilerOutputView->setText(m_compiler->getLog(module_name));
});
connect(m_ui->scriptListWidget, &QListWidget::itemDoubleClicked, [this](QListWidgetItem * item) {
QProcess* process = new QProcess;
process->start(QString("cmd.exe /C %1/scripts/edit_in_vs.bat %2").arg(m_editor->getBasePath()).arg(item->text()));
process->connect(process, (void (QProcess::*)(int))&QProcess::finished, [process](int) {
process->deleteLater();
});
});
QSettings settings("Lumix", "QtEditor");
m_compiler->setSourcesPath(settings.value("engineSourceCodePath").toString());
m_ui->engineSourcePathEdit->setText(settings.value("engineSourceCodePath").toString());
connect(m_ui->engineSourceBrowseButton, &QPushButton::clicked, [this]() {
m_ui->engineSourcePathEdit->setText(QFileDialog::getExistingDirectory());
m_compiler->setSourcesPath(m_ui->engineSourcePathEdit->text());
QSettings settings("Lumix", "QtEditor");
settings.setValue("engineSourceCodePath", m_ui->engineSourcePathEdit->text());
});
connect(m_ui->engineSourcePathEdit, &QLineEdit::editingFinished, [this](){
m_compiler->setSourcesPath(m_ui->engineSourcePathEdit->text());
QSettings settings("Lumix", "QtEditor");
settings.setValue("engineSourceCodePath", m_ui->engineSourcePathEdit->text());
});
}
ScriptCompilerWidget::~ScriptCompilerWidget()
{
m_editor->universeCreated().unbind<ScriptCompilerWidget, &ScriptCompilerWidget::onUniverseCreated>(this);
m_editor->universeDestroyed().unbind<ScriptCompilerWidget, &ScriptCompilerWidget::onUniverseDestroyed>(this);
m_editor->universeLoaded().unbind<ScriptCompilerWidget, &ScriptCompilerWidget::onUniverseLoaded>(this);
delete m_compiler;
delete m_ui;
delete m_model;
}
void ScriptCompilerWidget::setWorldEditor(Lumix::WorldEditor& editor)
{
m_compiler->setWorldEditor(editor);
m_editor = &editor;
setUniverse(m_editor->getUniverse());
m_editor->universeCreated().bind<ScriptCompilerWidget, &ScriptCompilerWidget::onUniverseCreated>(this);
m_editor->universeDestroyed().bind<ScriptCompilerWidget, &ScriptCompilerWidget::onUniverseDestroyed>(this);
m_editor->universeLoaded().bind<ScriptCompilerWidget, &ScriptCompilerWidget::onUniverseLoaded>(this);
}
void ScriptCompilerWidget::logMessage(const QString& message)
void ScriptCompilerWidget::onUniverseCreated()
{
m_ui->logView->addItem(message);
setUniverse(m_editor->getUniverse());
}
void ScriptCompilerWidget::on_scriptListView_clicked(const QModelIndex &index)
void ScriptCompilerWidget::onUniverseLoaded()
{
QString path = m_model->filePath(index);
QString c = m_compiler->getLog(Lumix::Path(path.toLatin1().data()));
m_ui->compilerOutputView->setText(c);
Lumix::ScriptScene* scene = static_cast<Lumix::ScriptScene*>(m_editor->getEngine().getScene(crc32("script")));
Lumix::Component script = scene->getFirstScript();
QFileInfo info(m_editor->getUniversePath().c_str());
while(script.isValid())
{
const Lumix::Path& path = scene->getScriptPath(script);
m_compiler->addScript(info.baseName(), path);
m_ui->scriptListWidget->addItem(path.c_str());
script = scene->getNextScript(script);
}
}
void ScriptCompilerWidget::onUniverseDestroyed()
{
setUniverse(NULL);
}
void ScriptCompilerWidget::on_compileAllButton_clicked()
{
m_compiler->compileAll();
m_compiler->compileAllModules();
}
void ScriptCompilerWidget::on_openInVSButton_clicked()
{
QProcess* process = new QProcess;
QFileInfo info(m_editor->getUniversePath().c_str());
process->start(QString("cmd.exe /C %1/scripts/open_in_vs.bat %2.vcxproj").arg(m_editor->getBasePath()).arg(info.baseName()));
process->connect(process, (void (QProcess::*)(int))&QProcess::finished, [process](int) {
process->deleteLater();
});
}
void ScriptCompilerWidget::onComponentCreated(const Lumix::Component& component)
{
if (component.type == SCRIPT_HASH)
{
QFileInfo info(m_editor->getUniversePath().c_str());
Lumix::ScriptScene* scene = static_cast<Lumix::ScriptScene*>(m_editor->getEngine().getScene(crc32("script")));
const Lumix::Path& path = scene->getScriptPath(component);
m_compiler->addScript(info.baseName(), path);
m_ui->scriptListWidget->addItem(path.c_str());
}
}
void ScriptCompilerWidget::onComponentDestroyed(const Lumix::Component& component)
{
if (component.type == SCRIPT_HASH)
{
Lumix::ScriptScene* scene = static_cast<Lumix::ScriptScene*>(m_editor->getEngine().getScene(crc32("script")));
const Lumix::Path& path = scene->getScriptPath(component);
m_compiler->removeScript(path);
for (int i = 0; i < m_ui->scriptListWidget->count(); ++i)
{
if (m_ui->scriptListWidget->item(i)->text() == path.c_str())
{
delete m_ui->scriptListWidget->takeItem(i);
break;
}
}
}
}
void ScriptCompilerWidget::onScriptRenamed(const Lumix::Path& old_path, const Lumix::Path& new_path)
{
m_compiler->onScriptRenamed(old_path, new_path);
for (int i = 0; i < m_ui->scriptListWidget->count(); ++i)
{
if (m_ui->scriptListWidget->item(i)->text() == old_path.c_str())
{
m_ui->scriptListWidget->item(i)->setText(new_path.c_str());
break;
}
}
}
void ScriptCompilerWidget::setUniverse(Lumix::Universe* universe)
{
if (universe)
{
Lumix::ScriptScene* scene = static_cast<Lumix::ScriptScene*>(m_editor->getEngine().getScene(crc32("script")));
scene->scriptRenamed().bind<ScriptCompilerWidget, &ScriptCompilerWidget::onScriptRenamed>(this);
universe->componentCreated().bind<ScriptCompilerWidget, &ScriptCompilerWidget::onComponentCreated>(this);
universe->componentDestroyed().bind<ScriptCompilerWidget, &ScriptCompilerWidget::onComponentDestroyed>(this);
ASSERT(!scene->getFirstScript().isValid());
}
else
{
m_ui->scriptListWidget->clear();
m_compiler->destroyModule(QFileInfo(m_editor->getUniversePath().c_str()).baseName());
}
m_universe = universe;
}

View file

@ -10,6 +10,9 @@ namespace Ui
namespace Lumix
{
struct Component;
class Path;
class Universe;
class WorldEditor;
}
@ -24,16 +27,25 @@ public:
~ScriptCompilerWidget();
ScriptCompiler* getCompiler() const { return m_compiler; }
void setWorldEditor(Lumix::WorldEditor& editor);
void setUniverse(Lumix::Universe* universe);
private:
void onUniverseCreated();
void onUniverseDestroyed();
void onUniverseLoaded();
void onComponentCreated(const Lumix::Component&);
void onComponentDestroyed(const Lumix::Component&);
void onScriptRenamed(const Lumix::Path& old_path, const Lumix::Path& new_path);
private slots:
void on_scriptListView_clicked(const QModelIndex &index);
void logMessage(const QString& message);
void on_compileAllButton_clicked();
void on_openInVSButton_clicked();
private:
Ui::ScriptCompilerWidget* m_ui;
class QFileSystemModel* m_model;
ScriptCompiler* m_compiler;
QString m_base_path;
Lumix::WorldEditor* m_editor;
Lumix::Universe* m_universe;
};

View file

@ -42,33 +42,7 @@
</widget>
</item>
<item>
<widget class="QListView" name="scriptListView"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Log</string>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="logView"/>
<widget class="QListWidget" name="scriptListWidget"/>
</item>
</layout>
</widget>
@ -132,17 +106,28 @@
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<widget class="QPushButton" name="openInVSButton">
<property name="text">
<string>Open In VS</string>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>478</width>
<height>20</height>
</size>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Engine source</string>
</property>
</spacer>
</widget>
</item>
<item>
<widget class="QLineEdit" name="engineSourcePathEdit"/>
</item>
<item>
<widget class="QPushButton" name="engineSourceBrowseButton">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</widget>