From 1e0324be3aee1de197320ee2aa153ca446c330b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sat, 4 Jul 2020 03:04:44 -0300 Subject: [PATCH] WIP. --- include/eepp/ui/abstract/model.hpp | 91 + .../eepp/ui/abstract/modeleditingdelegate.hpp | 48 + include/eepp/ui/abstract/modelindex.hpp | 42 + include/eepp/ui/abstract/modelselection.hpp | 70 + include/eepp/ui/uiabstractview.hpp | 74 + premake4.lua | 4 +- premake5.lua | 1710 ++++++++--------- projects/android-project/app/jni/eepp.mk | 2 +- projects/linux/ee.creator.user | 2 +- projects/linux/ee.files | 13 + src/eepp/ui/abstract/model.cpp | 42 + src/eepp/ui/abstract/modelselection.cpp | 62 + src/eepp/ui/uiabstractview.cpp | 59 + 13 files changed, 1360 insertions(+), 859 deletions(-) create mode 100644 include/eepp/ui/abstract/model.hpp create mode 100644 include/eepp/ui/abstract/modeleditingdelegate.hpp create mode 100644 include/eepp/ui/abstract/modelindex.hpp create mode 100644 include/eepp/ui/abstract/modelselection.hpp create mode 100644 include/eepp/ui/uiabstractview.hpp create mode 100644 src/eepp/ui/abstract/model.cpp create mode 100644 src/eepp/ui/abstract/modelselection.cpp create mode 100644 src/eepp/ui/uiabstractview.cpp diff --git a/include/eepp/ui/abstract/model.hpp b/include/eepp/ui/abstract/model.hpp new file mode 100644 index 000000000..33a814d44 --- /dev/null +++ b/include/eepp/ui/abstract/model.hpp @@ -0,0 +1,91 @@ +#ifndef EE_UI_MODEL_MODEL_HPP +#define EE_UI_MODEL_MODEL_HPP + +#include +#include +#include +#include + +namespace EE { namespace UI { +class UIAbstractView; +}} // namespace EE::UI + +namespace EE { namespace UI { namespace Abstract { + +enum class SortOrder { None, Ascending, Descending }; + +class Variant; + +class EE_API Model { + public: + enum UpdateFlag { + DontInvalidateIndexes = 0, + InvalidateAllIndexes = 1 << 0, + }; + + enum class Role { + Display, + Sort, + Custom, + ForegroundColor, + BackgroundColor, + Icon, + Font, + DragData, + TextAlignment, + }; + + virtual ~Model(){}; + + virtual int rowCount( const ModelIndex& = ModelIndex() ) const = 0; + virtual int columnCount( const ModelIndex& = ModelIndex() ) const = 0; + virtual std::string columnName( int ) const { return {}; } + virtual Variant data( const ModelIndex&, Role = Role::Display ) const = 0; + virtual void update() = 0; + virtual ModelIndex parentIndex( const ModelIndex& ) const { return {}; } + virtual ModelIndex index( int row, int column = 0, const ModelIndex& = ModelIndex() ) const { + return createIndex( row, column ); + } + virtual ModelIndex sibling( int row, int column, const ModelIndex& parent ) const; + virtual void setData( const ModelIndex&, const Variant& ) {} + virtual int treeColumn() const { return 0; } + virtual bool acceptsDrag( const ModelIndex&, const std::string& dataType ); + + virtual bool isColumnSortable( int /*columnIndex*/ ) const { return true; } + + virtual std::string dragDataType() const { return {}; } + + bool isValid( const ModelIndex& index ) const { + auto parentIndex = this->parentIndex( index ); + return index.row() >= 0 && index.row() < rowCount( parentIndex ) && index.column() >= 0 && + index.column() < columnCount( parentIndex ); + } + + virtual int keyColumn() const { return -1; } + virtual SortOrder sortOrder() const { return SortOrder::None; } + virtual void setKeyColumnAndSortOrder( int, SortOrder ) {} + + void registerView( UIAbstractView* ); + void unregisterView( UIAbstractView* ); + + std::function onUpdate; + + protected: + Model(){}; + + void forEachView( std::function ); + void didUpdate( unsigned flags = UpdateFlag::InvalidateAllIndexes ); + + ModelIndex createIndex( int row, int column, const void* data = nullptr ) const; + + private: + std::unordered_set mViews; +}; + +inline ModelIndex ModelIndex::parent() const { + return mModel ? mModel->parentIndex( *this ) : ModelIndex(); +} + +}}} // namespace EE::UI::Abstract + +#endif // EE_UI_MODEL_MODEL_HPP diff --git a/include/eepp/ui/abstract/modeleditingdelegate.hpp b/include/eepp/ui/abstract/modeleditingdelegate.hpp new file mode 100644 index 000000000..dbf2ec4dd --- /dev/null +++ b/include/eepp/ui/abstract/modeleditingdelegate.hpp @@ -0,0 +1,48 @@ +#ifndef EE_UI_MODELEDITINGDELEGATE_HPP +#define EE_UI_MODELEDITINGDELEGATE_HPP + +#include +#include +#include + +namespace EE { namespace UI { namespace Abstract { + +class EE_API ModelEditingDelegate { + public: + virtual ~ModelEditingDelegate() {} + + void bind( std::shared_ptr model, const ModelIndex& index ) { + if ( mModel.get() == model.get() && mIndex == index ) + return; + mModel = model; + mIndex = index; + mWidget = createWidget(); + } + + UIWidget* getWidget() { return mWidget; } + UIWidget* getWidget() const { return mWidget; } + + std::function onCommit; + + virtual Variant value() const = 0; + virtual void setValue( const Variant& ) = 0; + virtual void willBeginEditing() {} + + protected: + ModelEditingDelegate() {} + + virtual UIWidget* createWidget() = 0; + + void commit() { + if ( onCommit ) + onCommit(); + } + + std::shared_ptr mModel; + ModelIndex mIndex; + UIWidget* mWidget; +}; + +}}} // namespace EE::UI::Abstract + +#endif // MODELEDITINGDELEGATE_HPP diff --git a/include/eepp/ui/abstract/modelindex.hpp b/include/eepp/ui/abstract/modelindex.hpp new file mode 100644 index 000000000..14b86a4b5 --- /dev/null +++ b/include/eepp/ui/abstract/modelindex.hpp @@ -0,0 +1,42 @@ +#ifndef EE_UI_MODEL_MODELINDEX_HPP +#define EE_UI_MODEL_MODELINDEX_HPP + +#include + +namespace EE { namespace UI { namespace Abstract { + +class Model; + +class EE_API ModelIndex { + public: + ModelIndex() {} + + bool isValid() const { return mRow != -1 && mColumn != -1; } + + const Int64& row() const { return mRow; } + const Int64& column() const { return mColumn; } + void* data() const { return mData; } + ModelIndex parent() const; + bool hasParent() const { return parent().isValid(); } + + bool operator==( const ModelIndex& other ) const { + return mModel == other.mModel && mRow == other.mRow && mColumn == other.mColumn && + mData == other.mData; + } + + bool operator!=( const ModelIndex& other ) const { return !( *this == other ); } + + protected: + friend class Model; + const Model* mModel{nullptr}; + Int64 mRow{-1}; + Int64 mColumn{-1}; + void* mData{nullptr}; + + ModelIndex( const Model& model, int row, int column, void* internalData ) : + mModel( &model ), mRow( row ), mColumn( column ), mData( internalData ) {} +}; + +}}} // namespace EE::UI::Model + +#endif // EE_UI_MODEL_MODELINDEX_HPP diff --git a/include/eepp/ui/abstract/modelselection.hpp b/include/eepp/ui/abstract/modelselection.hpp new file mode 100644 index 000000000..5b87d55f5 --- /dev/null +++ b/include/eepp/ui/abstract/modelselection.hpp @@ -0,0 +1,70 @@ +#ifndef EE_UI_MODEL_MODELSELECTION_HPP +#define EE_UI_MODEL_MODELSELECTION_HPP + +#include +#include +#include +#include + +namespace EE { namespace UI { +class UIAbstractView; +}} // namespace EE::UI + +namespace EE { namespace UI { namespace Abstract { + +class EE_API ModelSelection { + public: + ModelSelection( UIAbstractView* view ) : mView( view ) {} + + int size() const { return mIndexes.size(); } + bool isEmpty() const { return mIndexes.empty(); } + bool contains( const ModelIndex& index ) const { + return std::find( mIndexes.begin(), mIndexes.end(), index ) != mIndexes.end(); + } + bool containsRow( int row ) const { + for ( auto& index : mIndexes ) { + if ( index.row() == row ) + return true; + } + return false; + } + + void set( const ModelIndex& ); + void add( const ModelIndex& ); + void toggle( const ModelIndex& ); + bool remove( const ModelIndex& ); + void clear(); + + template void forEachIndex( Callback callback ) { + for ( auto& index : indexes() ) + callback( index ); + } + + template void forEachIndex( Callback callback ) const { + for ( auto& index : indexes() ) + callback( index ); + } + + std::vector indexes() const { + std::vector selectedIndexes; + for ( auto& index : mIndexes ) + selectedIndexes.push_back( index ); + return selectedIndexes; + } + + ModelIndex first() const { + if ( mIndexes.empty() ) + return {}; + return *mIndexes.begin(); + } + + void removeMatching( std::function ); + + protected: + UIAbstractView* mView; + std::vector mIndexes; +}; + +}}} // namespace EE::UI::Abstract + +#endif // EE_UI_MODEL_MODELSELECTION_HPP diff --git a/include/eepp/ui/uiabstractview.hpp b/include/eepp/ui/uiabstractview.hpp new file mode 100644 index 000000000..b13bbcbaa --- /dev/null +++ b/include/eepp/ui/uiabstractview.hpp @@ -0,0 +1,74 @@ +#ifndef EE_UI_UIABSTRACTVIEW_HPP +#define EE_UI_UIABSTRACTVIEW_HPP + +#include +#include +#include +#include +#include + +using namespace EE::UI::Abstract; + +namespace EE { namespace UI { + +class EE_API UIAbstractView : public UIWidget { + public: + void set_model( std::shared_ptr ); + Model* model() { return m_model.get(); } + const Model* model() const { return m_model.get(); } + + ModelSelection& selection() { return m_selection; } + const ModelSelection& selection() const { return m_selection; } + virtual void select_all() = 0; + + bool is_editable() const { return m_editable; } + void set_editable( bool editable ) { m_editable = editable; } + + virtual void didUpdateModel( unsigned flags ); + virtual void didUpdateSelection(); + + virtual Vector2i content_rect( const ModelIndex& ) const { return {}; } + virtual ModelIndex index_at_event_position( const Vector2i& ) const = 0; + + void set_activates_on_selection( bool b ) { m_activates_on_selection = b; } + bool activates_on_selection() const { return m_activates_on_selection; } + + std::function on_selection_change; + std::function on_activation; + std::function on_selection; + std::function on_drop; + + //std::function( const ModelIndex& )> aid_create_editing_delegate; + + void notifySelectionChange(); + + protected: + UIAbstractView(); + + virtual ~UIAbstractView(); + + virtual void did_scroll(); + void set_hovered_index( const ModelIndex& ); + void activate( const ModelIndex& ); + void activate_selected(); + + bool m_editable{false}; + ModelIndex m_edit_index; + UIWidget* m_edit_widget; + Vector2i m_edit_widget_content_rect; + + Vector2i m_left_mousedown_position; + bool m_might_drag{false}; + + ModelIndex m_hovered_index; + + private: + std::shared_ptr m_model; + std::unique_ptr m_editing_delegate; + ModelSelection m_selection; + bool m_activates_on_selection{false}; +}; + +}} // namespace EE::UI + +#endif // EE_UI_UIABSTRACTVIEW_HPP diff --git a/premake4.lua b/premake4.lua index 595a8ad55..c54c0060e 100644 --- a/premake4.lua +++ b/premake4.lua @@ -433,7 +433,7 @@ function build_link_configuration( package_name, use_ee_icon ) end fix_shared_lib_linking_path( package_name, "libeepp-debug" ) - + if not os.is_real("emscripten") then targetname ( package_name .. "-debug" .. extension ) else @@ -748,7 +748,7 @@ function build_eepp( build_name ) "src/eepp/scene/*.cpp", "src/eepp/scene/actions/*.cpp", "src/eepp/ui/*.cpp", - "src/eepp/ui/actions/*.cpp", + "src/eepp/ui/abstract/*.cpp", "src/eepp/ui/css/*.cpp", "src/eepp/ui/doc/*.cpp", "src/eepp/ui/tools/*.cpp", diff --git a/premake5.lua b/premake5.lua index cebee0a06..484a0abfa 100644 --- a/premake5.lua +++ b/premake5.lua @@ -1,855 +1,855 @@ -newoption { trigger = "with-openssl", description = "Enables OpenSSL support ( and disables mbedtls backend )." } -newoption { trigger = "with-dynamic-freetype", description = "Dynamic link against freetype." } -newoption { trigger = "with-static-eepp", description = "Force to build the demos and tests with eepp compiled statically" } -newoption { trigger = "with-static-backend", description = "It will try to compile the library with a static backend (only for gcc and mingw).\n\t\t\t\tThe backend should be placed in libs/your_platform/libYourBackend.a" } -newoption { trigger = "with-gles2", description = "Compile with GLES2 support" } -newoption { trigger = "with-gles1", description = "Compile with GLES1 support" } -newoption { trigger = "with-mojoal", description = "Compile with mojoAL as OpenAL implementation instead of using openal-soft (requires SDL2 backend)" } -newoption { trigger = "use-frameworks", description = "In macOS it will try to link the external libraries from its frameworks. For example, instead of linking against SDL2 it will link against SDL2.framework." } -newoption { trigger = "windows-vc-build", description = "This is used to build the framework in Visual Studio downloading its external dependencies and making them available to the VS project without having to install them manually." } -newoption { - trigger = "with-backend", - description = "Select the backend to use for window and input handling.\n\t\t\tIf no backend is selected or if the selected is not installed the script will search for a backend present in the system, and will use it.", - allowed = { - { "SDL2", "SDL2" }, - } -} - -function print_table( table_ref ) - for _, value in pairs( table_ref ) do - print(value) - end -end - -function table_length(T) - local count = 0 - for _ in pairs(T) do count = count + 1 end - return count -end - -function multiple_insert( parent_table, insert_table ) - for _, value in pairs( insert_table ) do - table.insert( parent_table, value ) - end -end - -function os_findlib( name ) - if os.istarget("macosx") and ( is_xcode() or _OPTIONS["use-frameworks"] ) then - local path = "/Library/Frameworks/" .. name .. ".framework" - - if os.isdir( path ) then - return path - end - end - - return os.findlib( name ) -end - -function get_backend_link_name( name ) - if os.istarget("macosx") and ( is_xcode() or _OPTIONS["use-frameworks"] ) then - local fname = name .. ".framework" - - if os_findlib( name ) then -- Search for the framework - return fname - end - end - - return name -end - -function string.starts(String,Start) - if ( _ACTION ) then - return string.sub(String,1,string.len(Start))==Start - end - - return false -end - -function is_vs() - return ( string.starts(_ACTION,"vs") ) -end - -function is_xcode() - return ( string.starts(_ACTION,"xcode") ) -end - -function set_kind() - if os.istarget("macosx") then - kind("ConsoleApp") - else - kind("WindowedApp") - end -end - -link_list = { } -os_links = { } -backends = { } -static_backends = { } -backend_selected = false -remote_sdl2_version = "SDL2-2.0.12" -remote_sdl2_devel_src_url = "https://libsdl.org/release/SDL2-2.0.12.zip" -remote_sdl2_devel_vc_url = "https://www.libsdl.org/release/SDL2-devel-2.0.12-VC.zip" - -function incdirs( dirs ) - if is_xcode() then - sysincludedirs { dirs } - end - includedirs { dirs } -end - -function download_and_extract_sdl(sdl_url) - print("Downloading: " .. sdl_url) - local dest_dir = "src/thirdparty/" - local local_file = dest_dir .. remote_sdl2_version .. ".zip" - local result_str, response_code = http.download(sdl_url, local_file) - if response_code == 200 then - print("Downloaded successfully to: " .. local_file) - zip.extract(local_file, dest_dir) - print("Extracted " .. local_file .. " into " .. dest_dir) - else - print("Failed to download: " .. sdl_url) - exit(1) - end -end - -function download_and_extract_dependencies() - if not os.isdir("src/thirdparty/" .. remote_sdl2_version) then - if _OPTIONS["windows-vc-build"] then - download_and_extract_sdl(remote_sdl2_devel_vc_url) - elseif os.istarget("ios") then - download_and_extract_sdl(remote_sdl2_devel_src_url) - end - end -end - -function build_base_configuration( package_name ) - incdirs { "src/thirdparty/zlib" } - - set_ios_config() - set_xcode_config() - - filter "not system:windows" - buildoptions{ "-fPIC" } - - filter "configurations:debug*" - targetname ( package_name .. "-debug" ) - - filter "configurations:release*" - targetname ( package_name ) - - filter "action:not vs*" - cdialect "gnu99" - buildoptions { "-Wall" } - - filter "action:vs*" - incdirs { "src/thirdparty/libzip/vs" } -end - -function build_base_cpp_configuration( package_name ) - if not os.istarget("windows") then - buildoptions{ "-fPIC" } - end - - set_ios_config() - set_xcode_config() - - filter "action:not vs*" - buildoptions { "-Wall" } - - filter "configurations:debug*" - defines { "DEBUG" } - symbols "On" - targetname ( package_name .. "-debug" ) - - filter "configurations:release*" - optimize "Speed" - targetname ( package_name ) -end - -function build_link_configuration( package_name, use_ee_icon ) - incdirs { "include" } - local extension = ""; - - if package_name == "eepp" then - defines { "EE_EXPORTS" } - elseif package_name == "eepp-static" then - defines { "EE_STATIC" } - end - - if package_name ~= "eepp" and package_name ~= "eepp-static" then - if not _OPTIONS["with-static-eepp"] then - links { "eepp-shared" } - else - links { "eepp-static" } - defines { "EE_STATIC" } - add_static_links() - links { link_list } - end - end - - set_ios_config() - set_xcode_config() - - filter { "system:windows", "action:not vs*" } - if ( true == use_ee_icon ) then - linkoptions { "../../bin/assets/icon/ee.res" } - end - - filter { "system:windows", "action:vs*" } - files { "bin/assets/icon/ee.rc", "bin/assets/icon/ee.ico" } - vpaths { ['Resources/*'] = { "ee.rc", "ee.ico" } } - - filter "action:not vs*" - cppdialect "C++14" - buildoptions { "-Wall" } - - filter { "configurations:debug*", "action:not vs*" } - buildoptions{ "-Wno-long-long" } - - filter { "configurations:release*", "action:not vs*" } - buildoptions { "-fno-strict-aliasing -ffast-math" } - - filter { "configurations:release*", "action:not vs*", "system:not macosx" } - buildoptions { "-s" } - - filter "configurations:debug*" - defines { "DEBUG", "EE_DEBUG", "EE_MEMORY_MANAGER" } - targetname ( package_name .. "-debug" .. extension ) - - filter "configurations:release*" - defines { "NDEBUG" } - targetname ( package_name .. extension ) - - filter { "system:windows", "action:not vs*" } - linkoptions { "-static-libgcc", "-static-libstdc++" } - - filter { "system:windows", "action:vs*" } - if table.contains( backends, "SDL2" ) then - links { "SDL2", "SDL2main" } - end - - filter { "options:windows-vc-build", "system:windows", "platforms:x86" } - syslibdirs { "src/thirdparty/" .. remote_sdl2_version .."/lib/x86" } - - filter { "options:windows-vc-build", "system:windows", "platforms:x86_64" } - syslibdirs { "src/thirdparty/" .. remote_sdl2_version .."/lib/x64" } - - filter "system:emscripten" - targetname ( package_name .. extension ) - linkoptions{ "-O2 -s TOTAL_MEMORY=67108864 -s ASM_JS=1 -s VERBOSE=1 -s DISABLE_EXCEPTION_CATCHING=0 -s USE_SDL=2 -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s ERROR_ON_MISSING_LIBRARIES=0 -s FULL_ES3=1 -s \"BINARYEN_TRAP_MODE='clamp'\"" } - buildoptions { "-fno-strict-aliasing -O2 -s USE_SDL=2 -s PRECISE_F32=1 -s ENVIRONMENT=web" } - - if _OPTIONS["with-gles1"] and ( not _OPTIONS["with-gles2"] or _OPTIONS["force-gles1"] ) then - linkoptions{ "-s LEGACY_GL_EMULATION=1" } - end - - if _OPTIONS["with-gles2"] and not _OPTIONS["force-gles1"] then - linkoptions{ "-s FULL_ES2=1" } - end -end - -function generate_os_links() - if os.istarget("linux") then - multiple_insert( os_links, { "rt", "pthread", "X11", "GL", "Xcursor" } ) - - if _OPTIONS["with-static-eepp"] then - table.insert( os_links, "dl" ) - end - elseif os.istarget("windows") then - multiple_insert( os_links, { "opengl32", "glu32", "gdi32", "ws2_32", "winmm", "ole32" } ) - elseif os.istarget("mingw32") then - multiple_insert( os_links, { "opengl32", "glu32", "gdi32", "ws2_32", "winmm", "ole32" } ) - elseif os.istarget("macosx") then - multiple_insert( os_links, { "OpenGL.framework", "CoreFoundation.framework" } ) - elseif os.istarget("bsd") then - multiple_insert( os_links, { "rt", "pthread", "X11", "GL", "Xcursor" } ) - elseif os.istarget("haiku") then - multiple_insert( os_links, { "GL", "network" } ) - elseif os.istarget("ios") then - multiple_insert( os_links, { "OpenGLES.framework", "AudioToolbox.framework", "CoreAudio.framework", "Foundation.framework", "CoreFoundation.framework", "UIKit.framework", "QuartzCore.framework", "CoreGraphics.framework", "CoreMotion.framework", "AVFoundation.framework", "GameController.framework" } ) - elseif os.istarget("android") then - multiple_insert( os_links, { "GLESv1_CM", "GLESv2", "log" } ) - end - - if not _OPTIONS["with-mojoal"] then - if os.istarget("linux") or os.istarget("bsd") or os.istarget("haiku") or os.istarget("emscripten") then - multiple_insert( os_links, { "openal" } ) - elseif os.istarget("windows") or os.istarget("mingw32") then - multiple_insert( os_links, { "OpenAL32" } ) - elseif os.istarget("macosx") or os.istarget("ios") then - multiple_insert( os_links, { "OpenAL.framework" } ) - end - end -end - -function parse_args() - if _OPTIONS["with-gles2"] then - defines { "EE_GLES2", "SOIL_GLES2" } - end - - if _OPTIONS["with-gles1"] then - defines { "EE_GLES1", "SOIL_GLES1" } - end -end - -function add_static_links() - -- The linking order DOES matter - -- Expose the symbols that need one static library AFTER adding that static lib - - -- Add static backends - if next(static_backends) ~= nil then - for _, value in pairs( static_backends ) do - linkoptions { value } - end - end - - if not _OPTIONS["with-dynamic-freetype"] then - links { "freetype-static" } - end - - links { "SOIL2-static", - "chipmunk-static", - "libzip-static", - "jpeg-compressor-static", - "zlib-static", - "imageresampler-static", - "pugixml-static", - "vorbis-static" - } - - if _OPTIONS["with-mojoal"] then - links { "mojoal-static"} - end - - if not _OPTIONS["with-openssl"] then - links { "mbedtls-static" } - end - - if not os.istarget("haiku") and not os.istarget("ios") and not os.istarget("android") and not os.istarget("emscripten") then - links{ "glew-static" } - end -end - -function can_add_static_backend( name ) - if _OPTIONS["with-static-backend"] then - return true - end - return false -end - -function insert_static_backend( name ) - table.insert( static_backends, "../../libs/" .. os.target() .. "/lib" .. name .. ".a" ) -end - -function add_sdl2() - print("Using SDL2 backend"); - if not can_add_static_backend("SDL2") then - table.insert( link_list, get_backend_link_name( "SDL2" ) ) - else - print("Using static backend") - insert_static_backend( "SDL2" ) - end - - table.insert( backends, "SDL2" ) -end - -function set_xcode_config() - if is_xcode() or _OPTIONS["use-frameworks"] then - linkoptions { "-F /Library/Frameworks" } - incdirs { "/Library/Frameworks/SDL2.framework/Headers" } - defines { "EE_SDL2_FROM_ROOTPATH" } - end -end - -function set_ios_config() - if os.istarget("ios") then - local toolchainpath = os.getenv("TOOLCHAINPATH") - local iosversion = os.getenv("IOSVERSION") - local sysroot_path = os.getenv("SYSROOTPATH") - - if nil == os.getenv("TOOLCHAINPATH") then - toolchainpath = os.outputof("xcrun -find -sdk iphonesimulator clang") - end - - if nil == os.getenv("IOSVERSION") then - iosversion = os.outputof("xcrun --sdk iphonesimulator --show-sdk-version") - end - - if nil == os.getenv("SYSROOTPATH") then - local platform_path = os.outputof("xcrun --sdk iphonesimulator --show-sdk-platform-path") - sysroot_path = platform_path .. "/Developer/SDKs/iPhoneSimulator" .. iosversion .. ".sdk/" - end - - local framework_path = sysroot_path .. "/System/Library/Frameworks" - local framework_libs_path = framework_path .. "/usr/lib" - local sysroot_ver = " -miphoneos-version-min=9.0 -isysroot " .. sysroot_path - - buildoptions { sysroot_ver .. " -I" .. sysroot_path .. "/usr/include" } - linkoptions { sysroot_ver } - libdirs { framework_libs_path } - linkoptions { " -F" .. framework_path .. " -L" .. framework_libs_path .. " -isysroot " .. sysroot_path } - includedirs { "src/thirdparty/" .. remote_sdl2_version .. "/include" } - end -end - -function backend_is( name, libname ) - if not _OPTIONS["with-backend"] then - _OPTIONS["with-backend"] = "SDL2" - end - - if next(backends) == nil then - backends = string.explode(_OPTIONS["with-backend"],",") - end - - local backend_sel = table.contains( backends, name ) - - local ret_val = os_findlib( libname ) and backend_sel - - if os.istarget("mingw32") or os.istarget("emscripten") then - ret_val = backend_sel - end - - if ret_val then - backend_selected = true - end - - return ret_val -end - -function select_backend() - if backend_is("SDL2", "SDL2") then - print("Selected SDL2") - add_sdl2() - end - - -- If the selected backend is not present, try to find one present - if not backend_selected then - if os_findlib("SDL2", "SDL2") then - add_sdl2() - else - print("ERROR: Couldnt find any backend. Forced SDL2.") - add_sdl2() - end - end -end - -function check_ssl_support() - if _OPTIONS["with-openssl"] then - if os.istarget("windows") then - table.insert( link_list, get_backend_link_name( "libssl" ) ) - table.insert( link_list, get_backend_link_name( "libcrypto" ) ) - else - table.insert( link_list, get_backend_link_name( "ssl" ) ) - table.insert( link_list, get_backend_link_name( "crypto" ) ) - end - - files { "src/eepp/network/ssl/backend/openssl/*.cpp" } - - defines { "EE_OPENSSL" } - else - files { "src/eepp/network/ssl/backend/mbedtls/*.cpp" } - - defines { "EE_MBEDTLS" } - end - - defines { "EE_SSL_SUPPORT" } -end - -function build_eepp( build_name ) - files { "src/eepp/core/*.cpp", - "src/eepp/math/*.cpp", - "src/eepp/system/*.cpp", - "src/eepp/audio/*.cpp", - "src/eepp/graphics/*.cpp", - "src/eepp/graphics/renderer/*.cpp", - "src/eepp/window/*.cpp", - "src/eepp/network/*.cpp", - "src/eepp/network/ssl/*.cpp", - "src/eepp/network/http/*.cpp", - "src/eepp/scene/*.cpp", - "src/eepp/scene/actions/*.cpp", - "src/eepp/ui/*.cpp", - "src/eepp/ui/actions/*.cpp", - "src/eepp/ui/css/*.cpp", - "src/eepp/ui/doc/*.cpp", - "src/eepp/ui/tools/*.cpp", - "src/eepp/physics/*.cpp", - "src/eepp/physics/constraints/*.cpp", - "src/eepp/maps/*.cpp", - "src/eepp/maps/mapeditor/*.cpp" - } - - incdirs { "include", - "src", - "src/thirdparty", - "include/eepp/thirdparty", - "src/thirdparty/freetype2/include", - "src/thirdparty/zlib", - "src/thirdparty/libogg/include", - "src/thirdparty/libvorbis/include", - "src/thirdparty/mbedtls/include" - } - - add_static_links() - check_ssl_support() - - if table.contains( backends, "SDL2" ) then - files { "src/eepp/window/backend/SDL2/*.cpp" } - defines { "EE_BACKEND_SDL_ACTIVE", "EE_SDL_VERSION_2" } - end - - multiple_insert( link_list, os_links ) - - links { link_list } - - build_link_configuration( build_name ) - - filter "options:use-frameworks" - defines { "EE_USE_FRAMEWORKS" } - - filter { "system:macosx", "action:xcode* or options:use-frameworks" } - libdirs { "/System/Library/Frameworks", "/Library/Frameworks" } - - filter "system:windows" - files { "src/eepp/system/platform/win/*.cpp" } - files { "src/eepp/network/platform/win/*.cpp" } - - filter "system:not windows" - files { "src/eepp/system/platform/posix/*.cpp" } - files { "src/eepp/network/platform/unix/*.cpp" } - - filter "options:with-mojoal" - defines( "AL_LIBTYPE_STATIC" ) - incdirs { "src/thirdparty/mojoAL" } - - filter "options:windows-vc-build" - incdirs { "src/thirdparty/" .. remote_sdl2_version .. "/include" } - - filter "action:vs*" - incdirs { "src/thirdparty/libzip/vs" } - - filter "action:not vs*" - cppdialect "C++14" - - filter "options:with-dynamic-freetype" - if not os.istarget("ios") and os_findlib("freetype") then - table.insert( link_list, get_backend_link_name( "freetype" ) ) - end -end - -workspace "eepp" - targetdir("./bin/") - if os.istarget("ios") then - configurations { "debug-x64", "debug-arm64", "release-x64", "release-arm64" } - platforms { "x86_64", "arm64" } - else - configurations { "debug", "release" } - platforms { "x86_64", "x86" } - end - rtti "On" - download_and_extract_dependencies() - select_backend() - generate_os_links() - parse_args() - location("./make/" .. os.target() .. "/") - objdir("obj/" .. os.target() .. "/") - - filter "platforms:x86" - architecture "x86" - - filter "platforms:arm64 or configurations:debug-arm64 or configurations:release-arm64" - architecture "arm64" - - filter "platforms:x86_64 or configurations:debug-x64 or configurations:release-x64" - architecture "x86_64" - - filter "system:macosx" - defines { "GL_SILENCE_DEPRECATION" } - - filter "configurations:debug*" - defines { "DEBUG" } - symbols "On" - filter "configurations:release*" - optimize "Speed" - - filter { "system:windows", "action:vs*" } - flags { "MultiProcessorCompile" } - - project "SOIL2-static" - kind "StaticLib" - language "C" - targetdir("libs/" .. os.target() .. "/thirdparty/") - files { "src/thirdparty/SOIL2/src/SOIL2/*.c" } - incdirs { "src/thirdparty/SOIL2" } - build_base_configuration( "SOIL2" ) - - project "glew-static" - kind "StaticLib" - language "C" - defines { "GLEW_NO_GLU", "GLEW_STATIC" } - targetdir("libs/" .. os.target() .. "/thirdparty/") - files { "src/thirdparty/glew/*.c" } - incdirs { "include/thirdparty/glew" } - build_base_configuration( "glew" ) - - project "mbedtls-static" - kind "StaticLib" - language "C" - targetdir("libs/" .. os.target() .. "/thirdparty/") - incdirs { "src/thirdparty/mbedtls/include/" } - files { "src/thirdparty/mbedtls/library/*.c" } - build_base_cpp_configuration( "mbedtls" ) - - project "vorbis-static" - kind "StaticLib" - language "C" - targetdir("libs/" .. os.target() .. "/thirdparty/") - incdirs { "src/thirdparty/libvorbis/lib/", "src/thirdparty/libogg/include", "src/thirdparty/libvorbis/include" } - files { "src/thirdparty/libogg/**.c", "src/thirdparty/libvorbis/**.c" } - build_base_cpp_configuration( "vorbis" ) - - project "pugixml-static" - kind "StaticLib" - language "C++" - targetdir("libs/" .. os.target() .. "/thirdparty/") - files { "src/thirdparty/pugixml/*.cpp" } - build_base_cpp_configuration( "pugixml" ) - - project "zlib-static" - kind "StaticLib" - language "C" - targetdir("libs/" .. os.target() .. "/thirdparty/") - files { "src/thirdparty/zlib/*.c" } - build_base_configuration( "zlib" ) - - project "libzip-static" - kind "StaticLib" - language "C" - targetdir("libs/" .. os.target() .. "/thirdparty/") - files { "src/thirdparty/libzip/*.c" } - incdirs { "src/thirdparty/zlib" } - build_base_configuration( "libzip" ) - - project "freetype-static" - kind "StaticLib" - language "C" - targetdir("libs/" .. os.target() .. "/thirdparty/") - defines { "FT2_BUILD_LIBRARY" } - files { "src/thirdparty/freetype2/src/**.c" } - incdirs { "src/thirdparty/freetype2/include" } - build_base_configuration( "freetype" ) - - project "chipmunk-static" - kind "StaticLib" - targetdir("libs/" .. os.target() .. "/thirdparty/") - files { "src/thirdparty/chipmunk/*.c", "src/thirdparty/chipmunk/constraints/*.c" } - incdirs { "include/eepp/thirdparty/chipmunk" } - build_base_configuration( "chipmunk" ) - filter "action:vs*" - language "C++" - buildoptions { "/TP" } - filter "action:not vs*" - language "C" - - project "jpeg-compressor-static" - kind "StaticLib" - language "C++" - targetdir("libs/" .. os.target() .. "/thirdparty/") - files { "src/thirdparty/jpeg-compressor/*.cpp" } - build_base_cpp_configuration( "jpeg-compressor" ) - - project "imageresampler-static" - kind "StaticLib" - language "C++" - targetdir("libs/" .. os.target() .. "/thirdparty/") - files { "src/thirdparty/imageresampler/*.cpp" } - build_base_cpp_configuration( "imageresampler" ) - - project "mojoal-static" - kind "StaticLib" - language "C" - targetdir("libs/" .. os.target() .. "/thirdparty/") - incdirs { "include/eepp/thirdparty/mojoAL" } - defines( "AL_LIBTYPE_STATIC" ) - files { "src/thirdparty/mojoAL/*.c" } - build_base_cpp_configuration( "mojoal" ) - filter "options:windows-vc-build" - incdirs { "src/thirdparty/" .. remote_sdl2_version .. "/include" } - - project "efsw-static" - kind "StaticLib" - language "C++" - targetdir("libs/" .. os.target() .. "/thirdparty/") - incdirs { "src/thirdparty/efsw/include", "src/thirdparty/efsw/src" } - files { "src/thirdparty/efsw/src/efsw/*.cpp" } - build_base_cpp_configuration( "efsw" ) - filter "system:windows" - files { "src/thirdparty/efsw/src/efsw/platform/win/*.cpp" } - 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" - } - filter "system:linux" - 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" - } - filter "system:macosx or system:ios" - 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" - } - filter "system:bsd" - 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" - } - filter "system:not windows" - files { "src/thirdparty/efsw/src/efsw/platform/posix/*.cpp" } - - -- Library - project "eepp-main" - kind "StaticLib" - language "C++" - targetdir("libs/" .. os.target() .. "/") - files { "src/eepp/main/eepp_main.cpp" } - - project "eepp-static" - kind "StaticLib" - language "C++" - targetdir("libs/" .. os.target() .. "/") - build_eepp( "eepp-static" ) - - project "eepp-shared" - kind "SharedLib" - language "C++" - targetdir("libs/" .. os.target() .. "/") - build_eepp( "eepp" ) - - -- Examples - project "eepp-external-shader" - set_kind() - language "C++" - files { "src/examples/external_shader/*.cpp" } - build_link_configuration( "eepp-external-shader", true ) - - project "eepp-empty-window" - set_kind() - language "C++" - files { "src/examples/empty_window/*.cpp" } - build_link_configuration( "eepp-empty-window", true ) - - project "eepp-sound" - kind "ConsoleApp" - language "C++" - files { "src/examples/sound/*.cpp" } - build_link_configuration( "eepp-sound", true ) - - project "eepp-sprites" - set_kind() - language "C++" - files { "src/examples/sprites/*.cpp" } - build_link_configuration( "eepp-sprites", true ) - - project "eepp-fonts" - set_kind() - language "C++" - files { "src/examples/fonts/*.cpp" } - build_link_configuration( "eepp-fonts", true ) - - project "eepp-vbo-fbo-batch" - set_kind() - language "C++" - files { "src/examples/vbo_fbo_batch/*.cpp" } - build_link_configuration( "eepp-vbo-fbo-batch", true ) - - project "eepp-physics" - set_kind() - language "C++" - files { "src/examples/physics/*.cpp" } - build_link_configuration( "eepp-physics", true ) - - project "eepp-http-request" - kind "ConsoleApp" - language "C++" - files { "src/examples/http_request/*.cpp" } - incdirs { "src/thirdparty" } - build_link_configuration( "eepp-http-request", true ) - - project "eepp-ui-hello-world" - set_kind() - language "C++" - files { "src/examples/ui_hello_world/*.cpp" } - incdirs { "src/thirdparty" } - build_link_configuration( "eepp-ui-hello-world", true ) - - -- Tools - project "eepp-textureatlaseditor" - set_kind() - language "C++" - files { "src/tools/textureatlaseditor/*.cpp" } - build_link_configuration( "eepp-TextureAtlasEditor", true ) - - project "eepp-mapeditor" - set_kind() - language "C++" - files { "src/tools/mapeditor/*.cpp" } - build_link_configuration( "eepp-MapEditor", true ) - - project "eepp-uieditor" - set_kind() - language "C++" - incdirs { "src/thirdparty/efsw/include", "src/thirdparty" } - links { "efsw-static", "pugixml-static" } - files { "src/tools/uieditor/*.cpp" } - build_link_configuration( "eepp-UIEditor", true ) - filter "system:macosx" - links { "CoreFoundation.framework", "CoreServices.framework" } - filter { "system:not windows", "system:not haiku" } - links { "pthread" } - - project "ecode" - set_kind() - language "C++" - files { "src/tools/codeeditor/*.cpp" } - incdirs { "src/thirdparty" } - build_link_configuration( "ecode", true ) - - project "eepp-texturepacker" - kind "ConsoleApp" - language "C++" - incdirs { "src/thirdparty" } - files { "src/tools/texturepacker/*.cpp" } - build_link_configuration( "eepp-TexturePacker", true ) - - -- Tests - project "eepp-test" - set_kind() - language "C++" - files { "src/tests/test_all/*.cpp" } - build_link_configuration( "eepp-test", true ) - - project "eepp-ui-perf-test" - set_kind() - language "C++" - files { "src/tests/ui_perf_test/*.cpp" } - includedirs { "src/thirdparty" } - build_link_configuration( "eepp-ui-perf-test", true ) - -if os.isfile("external_projects.lua") then - dofile("external_projects.lua") -end +newoption { trigger = "with-openssl", description = "Enables OpenSSL support ( and disables mbedtls backend )." } +newoption { trigger = "with-dynamic-freetype", description = "Dynamic link against freetype." } +newoption { trigger = "with-static-eepp", description = "Force to build the demos and tests with eepp compiled statically" } +newoption { trigger = "with-static-backend", description = "It will try to compile the library with a static backend (only for gcc and mingw).\n\t\t\t\tThe backend should be placed in libs/your_platform/libYourBackend.a" } +newoption { trigger = "with-gles2", description = "Compile with GLES2 support" } +newoption { trigger = "with-gles1", description = "Compile with GLES1 support" } +newoption { trigger = "with-mojoal", description = "Compile with mojoAL as OpenAL implementation instead of using openal-soft (requires SDL2 backend)" } +newoption { trigger = "use-frameworks", description = "In macOS it will try to link the external libraries from its frameworks. For example, instead of linking against SDL2 it will link against SDL2.framework." } +newoption { trigger = "windows-vc-build", description = "This is used to build the framework in Visual Studio downloading its external dependencies and making them available to the VS project without having to install them manually." } +newoption { + trigger = "with-backend", + description = "Select the backend to use for window and input handling.\n\t\t\tIf no backend is selected or if the selected is not installed the script will search for a backend present in the system, and will use it.", + allowed = { + { "SDL2", "SDL2" }, + } +} + +function print_table( table_ref ) + for _, value in pairs( table_ref ) do + print(value) + end +end + +function table_length(T) + local count = 0 + for _ in pairs(T) do count = count + 1 end + return count +end + +function multiple_insert( parent_table, insert_table ) + for _, value in pairs( insert_table ) do + table.insert( parent_table, value ) + end +end + +function os_findlib( name ) + if os.istarget("macosx") and ( is_xcode() or _OPTIONS["use-frameworks"] ) then + local path = "/Library/Frameworks/" .. name .. ".framework" + + if os.isdir( path ) then + return path + end + end + + return os.findlib( name ) +end + +function get_backend_link_name( name ) + if os.istarget("macosx") and ( is_xcode() or _OPTIONS["use-frameworks"] ) then + local fname = name .. ".framework" + + if os_findlib( name ) then -- Search for the framework + return fname + end + end + + return name +end + +function string.starts(String,Start) + if ( _ACTION ) then + return string.sub(String,1,string.len(Start))==Start + end + + return false +end + +function is_vs() + return ( string.starts(_ACTION,"vs") ) +end + +function is_xcode() + return ( string.starts(_ACTION,"xcode") ) +end + +function set_kind() + if os.istarget("macosx") then + kind("ConsoleApp") + else + kind("WindowedApp") + end +end + +link_list = { } +os_links = { } +backends = { } +static_backends = { } +backend_selected = false +remote_sdl2_version = "SDL2-2.0.12" +remote_sdl2_devel_src_url = "https://libsdl.org/release/SDL2-2.0.12.zip" +remote_sdl2_devel_vc_url = "https://www.libsdl.org/release/SDL2-devel-2.0.12-VC.zip" + +function incdirs( dirs ) + if is_xcode() then + sysincludedirs { dirs } + end + includedirs { dirs } +end + +function download_and_extract_sdl(sdl_url) + print("Downloading: " .. sdl_url) + local dest_dir = "src/thirdparty/" + local local_file = dest_dir .. remote_sdl2_version .. ".zip" + local result_str, response_code = http.download(sdl_url, local_file) + if response_code == 200 then + print("Downloaded successfully to: " .. local_file) + zip.extract(local_file, dest_dir) + print("Extracted " .. local_file .. " into " .. dest_dir) + else + print("Failed to download: " .. sdl_url) + exit(1) + end +end + +function download_and_extract_dependencies() + if not os.isdir("src/thirdparty/" .. remote_sdl2_version) then + if _OPTIONS["windows-vc-build"] then + download_and_extract_sdl(remote_sdl2_devel_vc_url) + elseif os.istarget("ios") then + download_and_extract_sdl(remote_sdl2_devel_src_url) + end + end +end + +function build_base_configuration( package_name ) + incdirs { "src/thirdparty/zlib" } + + set_ios_config() + set_xcode_config() + + filter "not system:windows" + buildoptions{ "-fPIC" } + + filter "configurations:debug*" + targetname ( package_name .. "-debug" ) + + filter "configurations:release*" + targetname ( package_name ) + + filter "action:not vs*" + cdialect "gnu99" + buildoptions { "-Wall" } + + filter "action:vs*" + incdirs { "src/thirdparty/libzip/vs" } +end + +function build_base_cpp_configuration( package_name ) + if not os.istarget("windows") then + buildoptions{ "-fPIC" } + end + + set_ios_config() + set_xcode_config() + + filter "action:not vs*" + buildoptions { "-Wall" } + + filter "configurations:debug*" + defines { "DEBUG" } + symbols "On" + targetname ( package_name .. "-debug" ) + + filter "configurations:release*" + optimize "Speed" + targetname ( package_name ) +end + +function build_link_configuration( package_name, use_ee_icon ) + incdirs { "include" } + local extension = ""; + + if package_name == "eepp" then + defines { "EE_EXPORTS" } + elseif package_name == "eepp-static" then + defines { "EE_STATIC" } + end + + if package_name ~= "eepp" and package_name ~= "eepp-static" then + if not _OPTIONS["with-static-eepp"] then + links { "eepp-shared" } + else + links { "eepp-static" } + defines { "EE_STATIC" } + add_static_links() + links { link_list } + end + end + + set_ios_config() + set_xcode_config() + + filter { "system:windows", "action:not vs*" } + if ( true == use_ee_icon ) then + linkoptions { "../../bin/assets/icon/ee.res" } + end + + filter { "system:windows", "action:vs*" } + files { "bin/assets/icon/ee.rc", "bin/assets/icon/ee.ico" } + vpaths { ['Resources/*'] = { "ee.rc", "ee.ico" } } + + filter "action:not vs*" + cppdialect "C++14" + buildoptions { "-Wall" } + + filter { "configurations:debug*", "action:not vs*" } + buildoptions{ "-Wno-long-long" } + + filter { "configurations:release*", "action:not vs*" } + buildoptions { "-fno-strict-aliasing -ffast-math" } + + filter { "configurations:release*", "action:not vs*", "system:not macosx" } + buildoptions { "-s" } + + filter "configurations:debug*" + defines { "DEBUG", "EE_DEBUG", "EE_MEMORY_MANAGER" } + targetname ( package_name .. "-debug" .. extension ) + + filter "configurations:release*" + defines { "NDEBUG" } + targetname ( package_name .. extension ) + + filter { "system:windows", "action:not vs*" } + linkoptions { "-static-libgcc", "-static-libstdc++" } + + filter { "system:windows", "action:vs*" } + if table.contains( backends, "SDL2" ) then + links { "SDL2", "SDL2main" } + end + + filter { "options:windows-vc-build", "system:windows", "platforms:x86" } + syslibdirs { "src/thirdparty/" .. remote_sdl2_version .."/lib/x86" } + + filter { "options:windows-vc-build", "system:windows", "platforms:x86_64" } + syslibdirs { "src/thirdparty/" .. remote_sdl2_version .."/lib/x64" } + + filter "system:emscripten" + targetname ( package_name .. extension ) + linkoptions{ "-O2 -s TOTAL_MEMORY=67108864 -s ASM_JS=1 -s VERBOSE=1 -s DISABLE_EXCEPTION_CATCHING=0 -s USE_SDL=2 -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s ERROR_ON_MISSING_LIBRARIES=0 -s FULL_ES3=1 -s \"BINARYEN_TRAP_MODE='clamp'\"" } + buildoptions { "-fno-strict-aliasing -O2 -s USE_SDL=2 -s PRECISE_F32=1 -s ENVIRONMENT=web" } + + if _OPTIONS["with-gles1"] and ( not _OPTIONS["with-gles2"] or _OPTIONS["force-gles1"] ) then + linkoptions{ "-s LEGACY_GL_EMULATION=1" } + end + + if _OPTIONS["with-gles2"] and not _OPTIONS["force-gles1"] then + linkoptions{ "-s FULL_ES2=1" } + end +end + +function generate_os_links() + if os.istarget("linux") then + multiple_insert( os_links, { "rt", "pthread", "X11", "GL", "Xcursor" } ) + + if _OPTIONS["with-static-eepp"] then + table.insert( os_links, "dl" ) + end + elseif os.istarget("windows") then + multiple_insert( os_links, { "opengl32", "glu32", "gdi32", "ws2_32", "winmm", "ole32" } ) + elseif os.istarget("mingw32") then + multiple_insert( os_links, { "opengl32", "glu32", "gdi32", "ws2_32", "winmm", "ole32" } ) + elseif os.istarget("macosx") then + multiple_insert( os_links, { "OpenGL.framework", "CoreFoundation.framework" } ) + elseif os.istarget("bsd") then + multiple_insert( os_links, { "rt", "pthread", "X11", "GL", "Xcursor" } ) + elseif os.istarget("haiku") then + multiple_insert( os_links, { "GL", "network" } ) + elseif os.istarget("ios") then + multiple_insert( os_links, { "OpenGLES.framework", "AudioToolbox.framework", "CoreAudio.framework", "Foundation.framework", "CoreFoundation.framework", "UIKit.framework", "QuartzCore.framework", "CoreGraphics.framework", "CoreMotion.framework", "AVFoundation.framework", "GameController.framework" } ) + elseif os.istarget("android") then + multiple_insert( os_links, { "GLESv1_CM", "GLESv2", "log" } ) + end + + if not _OPTIONS["with-mojoal"] then + if os.istarget("linux") or os.istarget("bsd") or os.istarget("haiku") or os.istarget("emscripten") then + multiple_insert( os_links, { "openal" } ) + elseif os.istarget("windows") or os.istarget("mingw32") then + multiple_insert( os_links, { "OpenAL32" } ) + elseif os.istarget("macosx") or os.istarget("ios") then + multiple_insert( os_links, { "OpenAL.framework" } ) + end + end +end + +function parse_args() + if _OPTIONS["with-gles2"] then + defines { "EE_GLES2", "SOIL_GLES2" } + end + + if _OPTIONS["with-gles1"] then + defines { "EE_GLES1", "SOIL_GLES1" } + end +end + +function add_static_links() + -- The linking order DOES matter + -- Expose the symbols that need one static library AFTER adding that static lib + + -- Add static backends + if next(static_backends) ~= nil then + for _, value in pairs( static_backends ) do + linkoptions { value } + end + end + + if not _OPTIONS["with-dynamic-freetype"] then + links { "freetype-static" } + end + + links { "SOIL2-static", + "chipmunk-static", + "libzip-static", + "jpeg-compressor-static", + "zlib-static", + "imageresampler-static", + "pugixml-static", + "vorbis-static" + } + + if _OPTIONS["with-mojoal"] then + links { "mojoal-static"} + end + + if not _OPTIONS["with-openssl"] then + links { "mbedtls-static" } + end + + if not os.istarget("haiku") and not os.istarget("ios") and not os.istarget("android") and not os.istarget("emscripten") then + links{ "glew-static" } + end +end + +function can_add_static_backend( name ) + if _OPTIONS["with-static-backend"] then + return true + end + return false +end + +function insert_static_backend( name ) + table.insert( static_backends, "../../libs/" .. os.target() .. "/lib" .. name .. ".a" ) +end + +function add_sdl2() + print("Using SDL2 backend"); + if not can_add_static_backend("SDL2") then + table.insert( link_list, get_backend_link_name( "SDL2" ) ) + else + print("Using static backend") + insert_static_backend( "SDL2" ) + end + + table.insert( backends, "SDL2" ) +end + +function set_xcode_config() + if is_xcode() or _OPTIONS["use-frameworks"] then + linkoptions { "-F /Library/Frameworks" } + incdirs { "/Library/Frameworks/SDL2.framework/Headers" } + defines { "EE_SDL2_FROM_ROOTPATH" } + end +end + +function set_ios_config() + if os.istarget("ios") then + local toolchainpath = os.getenv("TOOLCHAINPATH") + local iosversion = os.getenv("IOSVERSION") + local sysroot_path = os.getenv("SYSROOTPATH") + + if nil == os.getenv("TOOLCHAINPATH") then + toolchainpath = os.outputof("xcrun -find -sdk iphonesimulator clang") + end + + if nil == os.getenv("IOSVERSION") then + iosversion = os.outputof("xcrun --sdk iphonesimulator --show-sdk-version") + end + + if nil == os.getenv("SYSROOTPATH") then + local platform_path = os.outputof("xcrun --sdk iphonesimulator --show-sdk-platform-path") + sysroot_path = platform_path .. "/Developer/SDKs/iPhoneSimulator" .. iosversion .. ".sdk/" + end + + local framework_path = sysroot_path .. "/System/Library/Frameworks" + local framework_libs_path = framework_path .. "/usr/lib" + local sysroot_ver = " -miphoneos-version-min=9.0 -isysroot " .. sysroot_path + + buildoptions { sysroot_ver .. " -I" .. sysroot_path .. "/usr/include" } + linkoptions { sysroot_ver } + libdirs { framework_libs_path } + linkoptions { " -F" .. framework_path .. " -L" .. framework_libs_path .. " -isysroot " .. sysroot_path } + includedirs { "src/thirdparty/" .. remote_sdl2_version .. "/include" } + end +end + +function backend_is( name, libname ) + if not _OPTIONS["with-backend"] then + _OPTIONS["with-backend"] = "SDL2" + end + + if next(backends) == nil then + backends = string.explode(_OPTIONS["with-backend"],",") + end + + local backend_sel = table.contains( backends, name ) + + local ret_val = os_findlib( libname ) and backend_sel + + if os.istarget("mingw32") or os.istarget("emscripten") then + ret_val = backend_sel + end + + if ret_val then + backend_selected = true + end + + return ret_val +end + +function select_backend() + if backend_is("SDL2", "SDL2") then + print("Selected SDL2") + add_sdl2() + end + + -- If the selected backend is not present, try to find one present + if not backend_selected then + if os_findlib("SDL2", "SDL2") then + add_sdl2() + else + print("ERROR: Couldnt find any backend. Forced SDL2.") + add_sdl2() + end + end +end + +function check_ssl_support() + if _OPTIONS["with-openssl"] then + if os.istarget("windows") then + table.insert( link_list, get_backend_link_name( "libssl" ) ) + table.insert( link_list, get_backend_link_name( "libcrypto" ) ) + else + table.insert( link_list, get_backend_link_name( "ssl" ) ) + table.insert( link_list, get_backend_link_name( "crypto" ) ) + end + + files { "src/eepp/network/ssl/backend/openssl/*.cpp" } + + defines { "EE_OPENSSL" } + else + files { "src/eepp/network/ssl/backend/mbedtls/*.cpp" } + + defines { "EE_MBEDTLS" } + end + + defines { "EE_SSL_SUPPORT" } +end + +function build_eepp( build_name ) + files { "src/eepp/core/*.cpp", + "src/eepp/math/*.cpp", + "src/eepp/system/*.cpp", + "src/eepp/audio/*.cpp", + "src/eepp/graphics/*.cpp", + "src/eepp/graphics/renderer/*.cpp", + "src/eepp/window/*.cpp", + "src/eepp/network/*.cpp", + "src/eepp/network/ssl/*.cpp", + "src/eepp/network/http/*.cpp", + "src/eepp/scene/*.cpp", + "src/eepp/scene/actions/*.cpp", + "src/eepp/ui/*.cpp", + "src/eepp/ui/abstract/*.cpp", + "src/eepp/ui/css/*.cpp", + "src/eepp/ui/doc/*.cpp", + "src/eepp/ui/tools/*.cpp", + "src/eepp/physics/*.cpp", + "src/eepp/physics/constraints/*.cpp", + "src/eepp/maps/*.cpp", + "src/eepp/maps/mapeditor/*.cpp" + } + + incdirs { "include", + "src", + "src/thirdparty", + "include/eepp/thirdparty", + "src/thirdparty/freetype2/include", + "src/thirdparty/zlib", + "src/thirdparty/libogg/include", + "src/thirdparty/libvorbis/include", + "src/thirdparty/mbedtls/include" + } + + add_static_links() + check_ssl_support() + + if table.contains( backends, "SDL2" ) then + files { "src/eepp/window/backend/SDL2/*.cpp" } + defines { "EE_BACKEND_SDL_ACTIVE", "EE_SDL_VERSION_2" } + end + + multiple_insert( link_list, os_links ) + + links { link_list } + + build_link_configuration( build_name ) + + filter "options:use-frameworks" + defines { "EE_USE_FRAMEWORKS" } + + filter { "system:macosx", "action:xcode* or options:use-frameworks" } + libdirs { "/System/Library/Frameworks", "/Library/Frameworks" } + + filter "system:windows" + files { "src/eepp/system/platform/win/*.cpp" } + files { "src/eepp/network/platform/win/*.cpp" } + + filter "system:not windows" + files { "src/eepp/system/platform/posix/*.cpp" } + files { "src/eepp/network/platform/unix/*.cpp" } + + filter "options:with-mojoal" + defines( "AL_LIBTYPE_STATIC" ) + incdirs { "src/thirdparty/mojoAL" } + + filter "options:windows-vc-build" + incdirs { "src/thirdparty/" .. remote_sdl2_version .. "/include" } + + filter "action:vs*" + incdirs { "src/thirdparty/libzip/vs" } + + filter "action:not vs*" + cppdialect "C++14" + + filter "options:with-dynamic-freetype" + if not os.istarget("ios") and os_findlib("freetype") then + table.insert( link_list, get_backend_link_name( "freetype" ) ) + end +end + +workspace "eepp" + targetdir("./bin/") + if os.istarget("ios") then + configurations { "debug-x64", "debug-arm64", "release-x64", "release-arm64" } + platforms { "x86_64", "arm64" } + else + configurations { "debug", "release" } + platforms { "x86_64", "x86" } + end + rtti "On" + download_and_extract_dependencies() + select_backend() + generate_os_links() + parse_args() + location("./make/" .. os.target() .. "/") + objdir("obj/" .. os.target() .. "/") + + filter "platforms:x86" + architecture "x86" + + filter "platforms:arm64 or configurations:debug-arm64 or configurations:release-arm64" + architecture "arm64" + + filter "platforms:x86_64 or configurations:debug-x64 or configurations:release-x64" + architecture "x86_64" + + filter "system:macosx" + defines { "GL_SILENCE_DEPRECATION" } + + filter "configurations:debug*" + defines { "DEBUG" } + symbols "On" + filter "configurations:release*" + optimize "Speed" + + filter { "system:windows", "action:vs*" } + flags { "MultiProcessorCompile" } + + project "SOIL2-static" + kind "StaticLib" + language "C" + targetdir("libs/" .. os.target() .. "/thirdparty/") + files { "src/thirdparty/SOIL2/src/SOIL2/*.c" } + incdirs { "src/thirdparty/SOIL2" } + build_base_configuration( "SOIL2" ) + + project "glew-static" + kind "StaticLib" + language "C" + defines { "GLEW_NO_GLU", "GLEW_STATIC" } + targetdir("libs/" .. os.target() .. "/thirdparty/") + files { "src/thirdparty/glew/*.c" } + incdirs { "include/thirdparty/glew" } + build_base_configuration( "glew" ) + + project "mbedtls-static" + kind "StaticLib" + language "C" + targetdir("libs/" .. os.target() .. "/thirdparty/") + incdirs { "src/thirdparty/mbedtls/include/" } + files { "src/thirdparty/mbedtls/library/*.c" } + build_base_cpp_configuration( "mbedtls" ) + + project "vorbis-static" + kind "StaticLib" + language "C" + targetdir("libs/" .. os.target() .. "/thirdparty/") + incdirs { "src/thirdparty/libvorbis/lib/", "src/thirdparty/libogg/include", "src/thirdparty/libvorbis/include" } + files { "src/thirdparty/libogg/**.c", "src/thirdparty/libvorbis/**.c" } + build_base_cpp_configuration( "vorbis" ) + + project "pugixml-static" + kind "StaticLib" + language "C++" + targetdir("libs/" .. os.target() .. "/thirdparty/") + files { "src/thirdparty/pugixml/*.cpp" } + build_base_cpp_configuration( "pugixml" ) + + project "zlib-static" + kind "StaticLib" + language "C" + targetdir("libs/" .. os.target() .. "/thirdparty/") + files { "src/thirdparty/zlib/*.c" } + build_base_configuration( "zlib" ) + + project "libzip-static" + kind "StaticLib" + language "C" + targetdir("libs/" .. os.target() .. "/thirdparty/") + files { "src/thirdparty/libzip/*.c" } + incdirs { "src/thirdparty/zlib" } + build_base_configuration( "libzip" ) + + project "freetype-static" + kind "StaticLib" + language "C" + targetdir("libs/" .. os.target() .. "/thirdparty/") + defines { "FT2_BUILD_LIBRARY" } + files { "src/thirdparty/freetype2/src/**.c" } + incdirs { "src/thirdparty/freetype2/include" } + build_base_configuration( "freetype" ) + + project "chipmunk-static" + kind "StaticLib" + targetdir("libs/" .. os.target() .. "/thirdparty/") + files { "src/thirdparty/chipmunk/*.c", "src/thirdparty/chipmunk/constraints/*.c" } + incdirs { "include/eepp/thirdparty/chipmunk" } + build_base_configuration( "chipmunk" ) + filter "action:vs*" + language "C++" + buildoptions { "/TP" } + filter "action:not vs*" + language "C" + + project "jpeg-compressor-static" + kind "StaticLib" + language "C++" + targetdir("libs/" .. os.target() .. "/thirdparty/") + files { "src/thirdparty/jpeg-compressor/*.cpp" } + build_base_cpp_configuration( "jpeg-compressor" ) + + project "imageresampler-static" + kind "StaticLib" + language "C++" + targetdir("libs/" .. os.target() .. "/thirdparty/") + files { "src/thirdparty/imageresampler/*.cpp" } + build_base_cpp_configuration( "imageresampler" ) + + project "mojoal-static" + kind "StaticLib" + language "C" + targetdir("libs/" .. os.target() .. "/thirdparty/") + incdirs { "include/eepp/thirdparty/mojoAL" } + defines( "AL_LIBTYPE_STATIC" ) + files { "src/thirdparty/mojoAL/*.c" } + build_base_cpp_configuration( "mojoal" ) + filter "options:windows-vc-build" + incdirs { "src/thirdparty/" .. remote_sdl2_version .. "/include" } + + project "efsw-static" + kind "StaticLib" + language "C++" + targetdir("libs/" .. os.target() .. "/thirdparty/") + incdirs { "src/thirdparty/efsw/include", "src/thirdparty/efsw/src" } + files { "src/thirdparty/efsw/src/efsw/*.cpp" } + build_base_cpp_configuration( "efsw" ) + filter "system:windows" + files { "src/thirdparty/efsw/src/efsw/platform/win/*.cpp" } + 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" + } + filter "system:linux" + 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" + } + filter "system:macosx or system:ios" + 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" + } + filter "system:bsd" + 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" + } + filter "system:not windows" + files { "src/thirdparty/efsw/src/efsw/platform/posix/*.cpp" } + + -- Library + project "eepp-main" + kind "StaticLib" + language "C++" + targetdir("libs/" .. os.target() .. "/") + files { "src/eepp/main/eepp_main.cpp" } + + project "eepp-static" + kind "StaticLib" + language "C++" + targetdir("libs/" .. os.target() .. "/") + build_eepp( "eepp-static" ) + + project "eepp-shared" + kind "SharedLib" + language "C++" + targetdir("libs/" .. os.target() .. "/") + build_eepp( "eepp" ) + + -- Examples + project "eepp-external-shader" + set_kind() + language "C++" + files { "src/examples/external_shader/*.cpp" } + build_link_configuration( "eepp-external-shader", true ) + + project "eepp-empty-window" + set_kind() + language "C++" + files { "src/examples/empty_window/*.cpp" } + build_link_configuration( "eepp-empty-window", true ) + + project "eepp-sound" + kind "ConsoleApp" + language "C++" + files { "src/examples/sound/*.cpp" } + build_link_configuration( "eepp-sound", true ) + + project "eepp-sprites" + set_kind() + language "C++" + files { "src/examples/sprites/*.cpp" } + build_link_configuration( "eepp-sprites", true ) + + project "eepp-fonts" + set_kind() + language "C++" + files { "src/examples/fonts/*.cpp" } + build_link_configuration( "eepp-fonts", true ) + + project "eepp-vbo-fbo-batch" + set_kind() + language "C++" + files { "src/examples/vbo_fbo_batch/*.cpp" } + build_link_configuration( "eepp-vbo-fbo-batch", true ) + + project "eepp-physics" + set_kind() + language "C++" + files { "src/examples/physics/*.cpp" } + build_link_configuration( "eepp-physics", true ) + + project "eepp-http-request" + kind "ConsoleApp" + language "C++" + files { "src/examples/http_request/*.cpp" } + incdirs { "src/thirdparty" } + build_link_configuration( "eepp-http-request", true ) + + project "eepp-ui-hello-world" + set_kind() + language "C++" + files { "src/examples/ui_hello_world/*.cpp" } + incdirs { "src/thirdparty" } + build_link_configuration( "eepp-ui-hello-world", true ) + + -- Tools + project "eepp-textureatlaseditor" + set_kind() + language "C++" + files { "src/tools/textureatlaseditor/*.cpp" } + build_link_configuration( "eepp-TextureAtlasEditor", true ) + + project "eepp-mapeditor" + set_kind() + language "C++" + files { "src/tools/mapeditor/*.cpp" } + build_link_configuration( "eepp-MapEditor", true ) + + project "eepp-uieditor" + set_kind() + language "C++" + incdirs { "src/thirdparty/efsw/include", "src/thirdparty" } + links { "efsw-static", "pugixml-static" } + files { "src/tools/uieditor/*.cpp" } + build_link_configuration( "eepp-UIEditor", true ) + filter "system:macosx" + links { "CoreFoundation.framework", "CoreServices.framework" } + filter { "system:not windows", "system:not haiku" } + links { "pthread" } + + project "ecode" + set_kind() + language "C++" + files { "src/tools/codeeditor/*.cpp" } + incdirs { "src/thirdparty" } + build_link_configuration( "ecode", true ) + + project "eepp-texturepacker" + kind "ConsoleApp" + language "C++" + incdirs { "src/thirdparty" } + files { "src/tools/texturepacker/*.cpp" } + build_link_configuration( "eepp-TexturePacker", true ) + + -- Tests + project "eepp-test" + set_kind() + language "C++" + files { "src/tests/test_all/*.cpp" } + build_link_configuration( "eepp-test", true ) + + project "eepp-ui-perf-test" + set_kind() + language "C++" + files { "src/tests/ui_perf_test/*.cpp" } + includedirs { "src/thirdparty" } + build_link_configuration( "eepp-ui-perf-test", true ) + +if os.isfile("external_projects.lua") then + dofile("external_projects.lua") +end diff --git a/projects/android-project/app/jni/eepp.mk b/projects/android-project/app/jni/eepp.mk index 793e6d5e0..c59cb45d1 100644 --- a/projects/android-project/app/jni/eepp.mk +++ b/projects/android-project/app/jni/eepp.mk @@ -82,7 +82,7 @@ CODE_SRCS := \ ui/*.cpp \ ui/css/*.cpp \ ui/doc/*.cpp \ - ui/actions/*.cpp \ + ui/model/*.cpp \ ui/tools/*.cpp \ maps/*.cpp \ maps/mapeditor/*.cpp diff --git a/projects/linux/ee.creator.user b/projects/linux/ee.creator.user index 057dfcf17..0381c8ad0 100644 --- a/projects/linux/ee.creator.user +++ b/projects/linux/ee.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/projects/linux/ee.files b/projects/linux/ee.files index 9cad74458..eebb8abc6 100644 --- a/projects/linux/ee.files +++ b/projects/linux/ee.files @@ -294,8 +294,12 @@ ../../include/eepp/thirdparty/chipmunk/cpSpatialIndex.h ../../include/eepp/thirdparty/chipmunk/cpVect.h ../../include/eepp/thirdparty/PlusCallback/callback.hpp +../../include/eepp/ui/abstract/model.hpp ../../include/eepp/ui/base.hpp ../../include/eepp/ui.hpp +../../include/eepp/ui/abstract/modeleditingdelegate.hpp +../../include/eepp/ui/abstract/modelindex.hpp +../../include/eepp/ui/abstract/modelselection.hpp ../../include/eepp/ui/border.hpp ../../include/eepp/ui/css/animationdefinition.hpp ../../include/eepp/ui/css/drawableimageparser.hpp @@ -331,9 +335,13 @@ ../../include/eepp/ui/doc/undostack.hpp ../../include/eepp/ui/keyboardshortcut.hpp ../../include/eepp/ui/marginmove/scale.hpp +../../include/eepp/ui/abstract/model.hpp +../../include/eepp/ui/abstract/modelindex.hpp +../../include/eepp/ui/abstract/modelselection.hpp ../../include/eepp/ui/tools/textureatlaseditor.hpp ../../include/eepp/ui/tools/uicodeeditorsplitter.hpp ../../include/eepp/ui/tools/uicolorpicker.hpp +../../include/eepp/ui/uiabstractview.hpp ../../include/eepp/ui/uibackgrounddrawable.hpp ../../include/eepp/ui/uiborderdrawable.hpp ../../include/eepp/ui/uicheckbox.hpp @@ -754,6 +762,8 @@ ../../src/eepp/system/translator.cpp ../../src/eepp/system/virtualfilesystem.cpp ../../src/eepp/system/zip.cpp +../../src/eepp/ui/abstract/model.cpp +../../src/eepp/ui/abstract/modelselection.cpp ../../src/eepp/ui/border.cpp ../../src/eepp/ui/css/animationdefinition.cpp ../../src/eepp/ui/css/drawableimageparser.cpp @@ -784,6 +794,8 @@ ../../src/eepp/ui/doc/textdocument.cpp ../../src/eepp/ui/doc/undostack.cpp ../../src/eepp/ui/keyboardshortcut.cpp +../../src/eepp/ui/abstract/model.cpp +../../src/eepp/ui/abstract/modelselection.cpp ../../src/eepp/ui/tools/textureatlaseditor.cpp ../../src/eepp/ui/tools/textureatlasnew.cpp ../../src/eepp/ui/tools/textureatlasnew.hpp @@ -791,6 +803,7 @@ ../../src/eepp/ui/tools/textureatlastextureregioneditor.hpp ../../src/eepp/ui/tools/uicodeeditorsplitter.cpp ../../src/eepp/ui/tools/uicolorpicker.cpp +../../src/eepp/ui/uiabstractview.cpp ../../src/eepp/ui/uibackgrounddrawable.cpp ../../src/eepp/ui/uiborderdrawable.cpp ../../src/eepp/ui/uicheckbox.cpp diff --git a/src/eepp/ui/abstract/model.cpp b/src/eepp/ui/abstract/model.cpp new file mode 100644 index 000000000..279ed4042 --- /dev/null +++ b/src/eepp/ui/abstract/model.cpp @@ -0,0 +1,42 @@ +#include +#include + +namespace EE { namespace UI { namespace Abstract { + +void Model::didUpdate( unsigned flags ) { + if ( onUpdate ) + onUpdate(); + forEachView( [&]( UIAbstractView* view ) { view->didUpdateModel( flags ); } ); +} + +void Model::forEachView( std::function callback ) { + for ( auto view : mViews ) + callback( view ); +} + +void Model::unregisterView( UIAbstractView* view ) { + mViews.erase( view ); +} + +void Model::registerView( UIAbstractView* view ) { + mViews.insert( view ); +} + +ModelIndex Model::createIndex( int row, int column, const void* data ) const { + return ModelIndex( *this, row, column, const_cast( data ) ); +} + +ModelIndex Model::sibling( int row, int column, const ModelIndex& parent ) const { + if ( !parent.isValid() ) + return index( row, column, {} ); + int rowCount = this->rowCount( parent ); + if ( row < 0 || row > rowCount ) + return {}; + return index( row, column, parent ); +} + +bool Model::acceptsDrag( const ModelIndex&, const std::string& dataType ) { + return false; +} + +}}} // namespace EE::UI::Abstract diff --git a/src/eepp/ui/abstract/modelselection.cpp b/src/eepp/ui/abstract/modelselection.cpp new file mode 100644 index 000000000..d273a5fb7 --- /dev/null +++ b/src/eepp/ui/abstract/modelselection.cpp @@ -0,0 +1,62 @@ +#include +#include +#include + +namespace EE { namespace UI { namespace Abstract { + +void ModelSelection::removeMatching( std::function filter ) { + std::vector::iterator> toRemove; + for ( auto it = mIndexes.begin(); it != mIndexes.end(); it++ ) { + if ( filter( *it ) ) + toRemove.push_back( it ); + } + for ( auto& index : toRemove ) + mIndexes.erase( index ); +} + +void ModelSelection::set( const ModelIndex& index ) { + eeASSERT( index.isValid() ); + if ( mIndexes.size() == 1 && contains( index ) ) + return; + mIndexes.clear(); + mIndexes.push_back( index ); + mView->notifySelectionChange(); +} + +void ModelSelection::add( const ModelIndex& index ) { + eeASSERT( index.isValid() ); + auto contains = std::find( mIndexes.begin(), mIndexes.end(), index ); + if ( contains == mIndexes.end() ) + return; + mIndexes.push_back( index ); + mView->notifySelectionChange(); +} + +void ModelSelection::toggle( const ModelIndex& index ) { + eeASSERT( index.isValid() ); + auto contains = std::find( mIndexes.begin(), mIndexes.end(), index ); + if ( contains != mIndexes.end() ) + mIndexes.erase( contains ); + else + mIndexes.push_back( index ); + mView->notifySelectionChange(); +} + +bool ModelSelection::remove( const ModelIndex& index ) { + eeASSERT( index.isValid() ); + auto contains = std::find( mIndexes.begin(), mIndexes.end(), index ); + if ( contains == mIndexes.end() ) + return false; + mIndexes.erase( contains ); + mView->notifySelectionChange(); + return true; +} + +void ModelSelection::clear() { + if ( mIndexes.empty() ) + return; + mIndexes.clear(); + mView->notifySelectionChange(); +} + +}}} // namespace EE::UI::Abstract diff --git a/src/eepp/ui/uiabstractview.cpp b/src/eepp/ui/uiabstractview.cpp new file mode 100644 index 000000000..4a463d1c9 --- /dev/null +++ b/src/eepp/ui/uiabstractview.cpp @@ -0,0 +1,59 @@ +#include +#include +#include + +using namespace EE::Scene; +using namespace EE::Window; + +namespace EE { namespace UI { + +UIAbstractView::UIAbstractView() : m_selection( this ) {} + +UIAbstractView::~UIAbstractView() {} + +void UIAbstractView::set_model( std::shared_ptr model ) { + if ( model.get() == m_model.get() ) + return; + if ( m_model ) + m_model->unregisterView( this ); + m_model = model; + if ( m_model ) + m_model->registerView( this ); + didUpdateModel( Model::InvalidateAllIndexes ); +} + +void UIAbstractView::didUpdateModel( unsigned flags ) { + m_hovered_index = {}; + if ( !model() || ( flags & Model::InvalidateAllIndexes ) ) { + selection().clear(); + } else { + selection().removeMatching( [this]( auto& index ) { return !model()->isValid( index ); } ); + } +} + +void UIAbstractView::didUpdateSelection() { + if ( model() && on_selection && selection().first().isValid() ) + on_selection( selection().first() ); +} + +void UIAbstractView::did_scroll() {} + +void UIAbstractView::activate( const ModelIndex& index ) { + if ( on_activation ) + on_activation( index ); +} + +void UIAbstractView::activate_selected() { + if ( !on_activation ) + return; + + selection().forEachIndex( [this]( auto& index ) { on_activation( index ); } ); +} + +void UIAbstractView::notifySelectionChange() { + didUpdateSelection(); + if ( on_selection_change ) + on_selection_change(); +} + +}} // namespace EE::UI