WIP basic UIEditor.

--HG--
branch : dev
This commit is contained in:
Martín Lucas Golini
2018-03-16 02:24:48 -03:00
parent f667f49b79
commit c5de0fb1ff
6 changed files with 422 additions and 3 deletions

View File

@@ -32,6 +32,7 @@ eestrobe*
eeiv*
eehttp-request*
eepp-TextureAtlasEditor*
eepp-UIEditor*
ee.tag
log.log
external_projects.lua

View File

@@ -881,6 +881,32 @@ solution "eepp"
files { "src/thirdparty/imageresampler/*.cpp" }
build_base_cpp_configuration( "imageresampler" )
project "efsw-static"
kind "StaticLib"
language "C++"
set_targetdir("libs/" .. os.get_real() .. "/thirdparty/")
includedirs { "src/thirdparty/efsw/include", "src/thirdparty/efsw/src" }
if os.is("windows") then
osfiles = "src/thirdparty/efsw/src/efsw/platform/win/*.cpp"
else
osfiles = "src/thirdparty/efsw/src/efsw/platform/posix/*.cpp"
end
files { "src/thirdparty/efsw/src/efsw/*.cpp", osfiles }
if os.is("windows") then
excludes { "src/thirdparty/efsw/src/efsw/WatcherKqueue.cpp", "src/thirdparty/efsw/src/efsw/WatcherFSEvents.cpp", "src/thirdparty/efsw/src/efsw/WatcherInotify.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherKqueue.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherInotify.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherFSEvents.cpp" }
elseif os.is("linux") then
excludes { "src/thirdparty/efsw/src/efsw/WatcherKqueue.cpp", "src/thirdparty/efsw/src/efsw/WatcherFSEvents.cpp", "src/thirdparty/efsw/src/efsw/WatcherWin32.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherKqueue.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherWin32.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherFSEvents.cpp" }
elseif os.is("macosx") then
excludes { "src/thirdparty/efsw/src/efsw/WatcherInotify.cpp", "src/thirdparty/efsw/src/efsw/WatcherWin32.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherInotify.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherWin32.cpp" }
elseif os.is("freebsd") then
excludes { "src/thirdparty/efsw/src/efsw/WatcherInotify.cpp", "src/thirdparty/efsw/src/efsw/WatcherWin32.cpp", "src/thirdparty/efsw/src/efsw/WatcherFSEvents.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherInotify.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherWin32.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherFSEvents.cpp" }
end
build_base_cpp_configuration( "efsw" )
project "eepp-main"
kind "StaticLib"
language "C++"
@@ -967,6 +993,19 @@ solution "eepp"
files { "src/tools/mapeditor/*.cpp" }
build_link_configuration( "eepp-MapEditor", true )
project "eepp-uieditor"
set_kind()
language "C++"
includedirs { "src/thirdparty/efsw/include" }
if not os.is("windows") and not os.is("haiku") then
links { "pthread" }
end
links { "efsw-static" }
files { "src/tools/uieditor/*.cpp" }
build_link_configuration( "eepp-UIEditor", true )
if os.isfile("external_projects.lua") then
dofile("external_projects.lua")
end

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.5.0, 2018-02-04T04:26:21. -->
<!-- Written by QtCreator 4.5.0, 2018-03-16T02:22:39. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
@@ -72,7 +72,7 @@
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{6d057187-158a-4883-8d5b-d470a6b6b025}</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">10</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">15</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">../../make/linux</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
@@ -1365,6 +1365,62 @@
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.15">
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">0</value>
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">0</value>
<value type="int">1</value>
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
<value type="int">11</value>
<value type="int">12</value>
<value type="int">13</value>
<value type="int">14</value>
</valuelist>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Arguments"></value>
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Executable">%{buildDir}../../../bin/eepp-UIEditor-debug</value>
<value type="bool" key="ProjectExplorer.CustomExecutableRunConfiguration.UseTerminal">false</value>
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.WorkingDirectory">%{buildDir}../../../bin/</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Run %{buildDir}../../../bin/eepp-UIEditor-debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">eeuieditor-debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">true</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">false</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.2">
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
@@ -1813,7 +1869,7 @@
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">15</value>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">16</value>
</valuemap>
</data>
<data>

View File

@@ -1,3 +1,4 @@
../../src/tools/uieditor/uieditor.cpp
../../include/eepp/scene.hpp
../../include/eepp/scene/actions/close.hpp
../../include/eepp/scene/event.hpp

View File

@@ -2,3 +2,4 @@
../../include/
../../src/thirdparty
../../include/eepp/thirdparty
../../src/thirdparty/efsw/include

View File

@@ -0,0 +1,321 @@
#include <eepp/ee.hpp>
#include <efsw/efsw.hpp>
EE::Window::Window * window = NULL;
UIMessageBox * MsgBox = NULL;
efsw::FileWatcher * fileWatcher = NULL;
UITheme * theme = NULL;
UIWidget * uiContainer = NULL;
UIWinMenu * uiWinMenu = NULL;
DirectoryPack * directoryPack = NULL;
UISceneNode * uiSceneNode = NULL;
std::string currentLayout;
bool updateLayout = false;
Clock waitClock;
efsw::WatchID watch = 0;
class UpdateListener : public efsw::FileWatchListener
{
public:
UpdateListener() {}
void handleFileAction( efsw::WatchID watchid, const std::string& dir, const std::string& filename, efsw::Action action, std::string oldFilename = "" )
{
if ( action == efsw::Actions::Modified ) {
std::cout << "DIR (" << dir << ") FILE (" << filename << ") has event Modified" << std::endl;
if ( dir + filename == currentLayout )
{
updateLayout = true;
waitClock.restart();
}
}
}
};
UpdateListener * listener = NULL;
static bool isImage( const std::string& path ) {
std::string mPath = path;
if ( path.size() >= 4 )
{
std::string File = mPath.substr( mPath.find_last_of("/\\") + 1 );
std::string Ext = File.substr( File.find_last_of(".") + 1 );
String::toLowerInPlace( Ext );
if ( Ext == "png" || Ext == "tga" || Ext == "bmp" || Ext == "jpg" || Ext == "gif" || Ext == "jpeg" || Ext == "dds" || Ext == "psd" || Ext == "hdr" || Ext == "pic" || Ext == "pvr" || Ext == "pkm" )
return true;
}
return false;
}
static bool isFont( const std::string& path ) {
std::string mPath = path;
if ( path.size() >= 4 )
{
std::string File = mPath.substr( mPath.find_last_of("/\\") + 1 );
std::string Ext = File.substr( File.find_last_of(".") + 1 );
String::toLowerInPlace( Ext );
if ( Ext == "ttf" || Ext == "otf" || Ext == "wolff" )
return true;
}
return false;
}
static void loadImage( std::string path )
{
std::string filename( FileSystem::fileRemoveExtension( FileSystem::fileNameFromPath( path ) ) );
GlobalTextureAtlas::instance()->add( TextureFactory::instance()->loadFromFile( path ), filename );
}
static void loadFont( std::string path )
{
std::string filename( FileSystem::fileRemoveExtension( FileSystem::fileNameFromPath( path ) ) );
FontTrueType * font = FontTrueType::New( filename );
font->loadFromFile( path );
}
static void loadImagesFromFolder( std::string folderPath )
{
std::vector<std::string> files = FileSystem::filesGetInPath( folderPath );
FileSystem::dirPathAddSlashAtEnd( folderPath );
for ( auto it = files.begin(); it != files.end(); ++it )
{
if ( isImage( *it ) )
{
loadImage( folderPath + (*it) );
}
}
}
static void loadFontsFromFolder( std::string folderPath )
{
std::vector<std::string> files = FileSystem::filesGetInPath( folderPath );
FileSystem::dirPathAddSlashAtEnd( folderPath );
for ( auto it = files.begin(); it != files.end(); ++it )
{
if ( isFont( *it ) )
{
loadFont( folderPath + (*it) );
}
}
}
static void loadLayoutFromFile( std::string file )
{
if ( watch != 0 )
{
fileWatcher->removeWatch( watch );
}
std::string folder( FileSystem::fileRemoveFileName( file ) );
watch = fileWatcher->addWatch( folder, listener );
Float pd = PixelDensity::getPixelDensity();
uiContainer->childsCloseAll();
PixelDensity::setPixelDensity(1);
uiSceneNode->loadLayoutFromFile( file, uiContainer );
PixelDensity::setPixelDensity(pd);
currentLayout = file;
}
static void refreshLayout() {
if ( !currentLayout.empty() && FileSystem::fileExists( currentLayout ) && uiContainer != NULL ) {
loadLayoutFromFile( currentLayout );
}
updateLayout = false;
}
bool onCloseRequestCallback( EE::Window::Window * w ) {
MsgBox = UIMessageBox::New( MSGBOX_OKCANCEL, "Do you really want to close the current file?\nAll changes will be lost." );
MsgBox->addEventListener( Event::MsgBoxConfirmClick, cb::Make1<void, const Event*>( []( const Event * event ) { window->close(); } ) );
MsgBox->addEventListener( Event::OnClose, cb::Make1<void, const Event*>( []( const Event * event ) { MsgBox = NULL; } ) );
MsgBox->setTitle( "Close Editor?" );
MsgBox->center();
MsgBox->show();
return false;
}
void mainLoop() {
window->getInput()->update();
if ( window->getInput()->isKeyUp( KEY_ESCAPE ) && NULL == MsgBox && onCloseRequestCallback( window ) ) {
window->close();
}
if ( updateLayout && waitClock.getElapsedTime().asMilliseconds() > 250.f ) {
refreshLayout();
}
SceneManager::instance()->update();
if ( SceneManager::instance()->getUISceneNode()->invalidated() ) {
window->clear();
SceneManager::instance()->draw();
window->display();
} else {
Sys::sleep( Milliseconds(8) );
}
}
void resizeCb(EE::Window::Window * window)
{
Float scaleW = (Float)window->getSize().getWidth() / (Float)uiContainer->getSize().getWidth();
Float scaleH = (Float)window->getSize().getHeight() / (Float)uiContainer->getSize().getHeight();
uiContainer->setScale( scaleW < scaleH ? scaleW : scaleH );
uiContainer->center();
}
void imagePathOpen( const Event * Event ) {
UICommonDialog * CDL = reinterpret_cast<UICommonDialog*> ( Event->getNode() );
loadImagesFromFolder( CDL->getFullPath() );
}
void fontPathOpen( const Event * Event ) {
UICommonDialog * CDL = reinterpret_cast<UICommonDialog*> ( Event->getNode() );
loadFontsFromFolder( CDL->getFullPath() );
}
void layoutOpen( const Event * Event ) {
UICommonDialog * CDL = reinterpret_cast<UICommonDialog*> ( Event->getNode() );
Float pd = PixelDensity::getPixelDensity();
PixelDensity::setPixelDensity(1);
uiSceneNode->loadLayoutFromFile( CDL->getFullPath(), uiContainer );
PixelDensity::setPixelDensity(pd);
}
void fileMenuClick( const Event * Event ) {
if ( !Event->getNode()->isType( UI_TYPE_MENUITEM ) )
return;
const String& txt = reinterpret_cast<UIMenuItem*> ( Event->getNode() )->getText();
if ( "Open..." == txt ) {
UICommonDialog * TGDialog = UICommonDialog::New( UI_CDL_DEFAULT_FLAGS, "*.xml" );
TGDialog->setWinFlags( UI_WIN_DEFAULT_FLAGS | UI_WIN_MAXIMIZE_BUTTON | UI_WIN_MODAL );
TGDialog->setTitle( "Open layout..." );
TGDialog->addEventListener( Event::OpenFile, cb::Make1( layoutOpen ) );
TGDialog->center();
TGDialog->show();
} else if ( "Close" == txt ) {
currentLayout = "";
uiContainer->childsCloseAll();
} else if ( "Quit" == txt ) {
onCloseRequestCallback( window );
} else if ( "Load images from path..." == txt ) {
UICommonDialog * TGDialog = UICommonDialog::New( UI_CDL_DEFAULT_FLAGS | CDL_FLAG_ALLOW_FOLDER_SELECT );
TGDialog->setWinFlags( UI_WIN_DEFAULT_FLAGS | UI_WIN_MAXIMIZE_BUTTON | UI_WIN_MODAL );
TGDialog->setTitle( "Open images from folder..." );
TGDialog->addEventListener( Event::OpenFile, cb::Make1( imagePathOpen ) );
TGDialog->center();
TGDialog->show();
} else if ( "Load fonts from path..." == txt ) {
UICommonDialog * TGDialog = UICommonDialog::New( UI_CDL_DEFAULT_FLAGS | CDL_FLAG_ALLOW_FOLDER_SELECT );
TGDialog->setWinFlags( UI_WIN_DEFAULT_FLAGS | UI_WIN_MAXIMIZE_BUTTON | UI_WIN_MODAL );
TGDialog->setTitle( "Open fonts from folder..." );
TGDialog->addEventListener( Event::OpenFile, cb::Make1( fontPathOpen ) );
TGDialog->center();
TGDialog->show();
}
}
EE_MAIN_FUNC int main (int argc, char * argv []) {
directoryPack = eeNew( DirectoryPack, () );
directoryPack->create( Sys::getProcessPath() );
fileWatcher = new efsw::FileWatcher();
listener = new UpdateListener();
fileWatcher->watch();
Display * currentDisplay = Engine::instance()->getDisplayManager()->getDisplayIndex(0);
Float pixelDensity = 1;
DisplayMode currentMode = currentDisplay->getCurrentMode();
Uint32 width = eemin( currentMode.Width, (Uint32)( 1280 * pixelDensity ) );
Uint32 height = eemin( currentMode.Height, (Uint32)( 720 * pixelDensity ) );
window = Engine::instance()->createWindow( WindowSettings( width, height, "eepp - UI Editor", WindowStyle::Default, WindowBackend::Default, 32, "assets/icon/ee.png" ), ContextSettings( true, GLv_default, true, 24, 1, 0, false ) );
if ( window->isOpen() ) {
window->setCloseRequestCallback( cb::Make1( onCloseRequestCallback ) );
uiSceneNode = UISceneNode::New();
SceneManager::instance()->add( uiSceneNode );
uiSceneNode->enableDrawInvalidation();
{
std::string pd;
if ( PixelDensity::getPixelDensity() >= 1.5f ) pd = "1.5x";
else if ( PixelDensity::getPixelDensity() >= 2.f ) pd = "2x";
TextureAtlasLoader tgl( "assets/ui/uitheme" + pd + ".eta" );
theme = UITheme::loadFromTextureAtlas( UIThemeDefault::New( "uitheme" + pd, "uitheme" + pd ), TextureAtlasManager::instance()->getByName( "uitheme" + pd ) );
FontTrueType * font = FontTrueType::New( "NotoSans-Regular", "assets/fonts/NotoSans-Regular.ttf" );
UIThemeManager::instance()->setDefaultEffectsEnabled( true )->setDefaultTheme( theme )->setDefaultFont( font )->add( theme );
}
uiContainer = UIWidget::New();
uiContainer->setId( "appContainer" )->setSize( 1200, 1920 );
uiContainer->clipDisable();
uiWinMenu = UIWinMenu::New();
UIPopUpMenu * uiPopMenu = UIPopUpMenu::New();
uiPopMenu->add( "Open...", theme->getIconByName( "document-open" ) );
uiPopMenu->addSeparator();
uiPopMenu->add( "Close", theme->getIconByName( "document-close" ) );
uiPopMenu->addSeparator();
uiPopMenu->add( "Quit", theme->getIconByName( "quit" ) );
uiWinMenu->addMenuButton( "File", uiPopMenu );
uiPopMenu->addEventListener( Event::OnItemClicked, cb::Make1( fileMenuClick ) );
UIPopUpMenu * uiResourceMenu = UIPopUpMenu::New();
uiResourceMenu->add( "Load images from path...", theme->getIconByName( "document-open" ) );
uiResourceMenu->addSeparator();
uiResourceMenu->add( "Load fonts from path...", theme->getIconByName( "document-open" ) );
uiWinMenu->addMenuButton( "Resources", uiResourceMenu );
uiResourceMenu->addEventListener( Event::OnItemClicked, cb::Make1( fileMenuClick ) );
resizeCb( window );
window->pushResizeCallback( cb::Make1( resizeCb ) );
window->runMainLoop( &mainLoop );
}
eeSAFE_DELETE( directoryPack );
Engine::destroySingleton();
MemoryManager::showResults();
delete fileWatcher;
delete listener;
return EXIT_SUCCESS;
}