diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b313b9..28552c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,18 +67,22 @@ if( IMJSCHEMA_BUILD_EXECUTABLES) set(srcFiles example.cpp ) # all the source files for this library set(PublicLinkedTargets "" ) set(PrivateLinkedTargets ImJSchema::ImJSchema SDL2::SDL2 nlohmann_json::nlohmann_json imguiLib) - - #myproject_set_project_warnings(ImJSchema TRUE "" "" "" "") - + add_executable( ${outName} ${srcFiles} ) + target_link_libraries( ${outName} PUBLIC ${PublicLinkedTargets} ) + target_link_libraries( ${outName} PRIVATE ${PrivateLinkedTargets} ) #------------------------------------------------------------------------------- - + set(outName schenity) # name of the library + set(srcFiles schenity.cpp ) # all the source files for this library + set(PublicLinkedTargets "" ) + set(PrivateLinkedTargets ImJSchema::ImJSchema SDL2::SDL2 nlohmann_json::nlohmann_json imguiLib) add_executable( ${outName} ${srcFiles} ) - target_link_libraries( ${outName} PUBLIC ${PublicLinkedTargets} ) target_link_libraries( ${outName} PRIVATE ${PrivateLinkedTargets} ) + #------------------------------------------------------------------------------- ################################################################################ + enable_testing() add_subdirectory(test) endif() diff --git a/conanfile.txt b/conanfile.txt index 6ab26f1..440c752 100644 --- a/conanfile.txt +++ b/conanfile.txt @@ -2,6 +2,7 @@ sdl/2.26.1 nlohmann_json/3.9.1 catch2/3.3.2 +imgui/1.90-docking [options] sdl:shared=False @@ -9,3 +10,5 @@ sdl:shared=False [generators] cmake_find_package +[imports] +./res, * -> imgui_src @ root_package=imgui diff --git a/include/ImJSchema/detail/json_utils.h b/include/ImJSchema/detail/json_utils.h index 6c71a72..2663b9b 100644 --- a/include/ImJSchema/detail/json_utils.h +++ b/include/ImJSchema/detail/json_utils.h @@ -8,6 +8,73 @@ namespace ImJSchema { using json = nlohmann::json; +/** + * @brief jsonExpandAllReferences + * @param J + * + * Given a json object that has a property named, ref, which is + * a string that represents a path to an object in defsRoot + * + # eg: +"items": { + "name" : "Hello", + "defaultValue" : "World", + "$ref": "#/$defs/positiveInteger" +} + +// defs +{ + "$defs": { + "positiveInteger": { + "type": "integer", + "exclusiveMinimum": 0, + "defaultValue" : "Hello" + } + } +} + +Copies the values from defs which are not in the original object +{ + "items": { + "name" : "Hello", + "defaultValue" : "World", + "type": "integer", + "exclusiveMinimum": 0 + } +} +*/ +inline void jsonExpandAllReferences(json & J, json const & defs, std::string ref= "$ref"); +inline void jsonExpandAllReferences(json & J, std::string ref= "$ref"); + +/** + * @brief jsonFindPath + * @param path + * @param obj + * @return + * + * Returns a pointer to a json object that exists in obj based on its path. + * + * eg: + * a path looks like: "objName/array/0" + * + * { + * "objName" : { + * "array" : ["first" , "second" ] + * } + * } + */ +inline json * jsonFindPath(std::string_view const path, json & obj); +inline json const* jsonFindPath(std::string_view const path, json const & obj); + + +/** + * @brief doIfKeyExists + * @param K + * @param J + * @param C + * + * Executes the callable if a key, K, exists in J + */ template void doIfKeyExists(json::object_t::key_type const &K, jsonObject & J, Callable_type && C) { @@ -18,6 +85,16 @@ void doIfKeyExists(json::object_t::key_type const &K, jsonObject & J, Callable_t } +/** + * @brief JValue + * @param J + * @param key + * @param default_value + * @return + * + * Returns the ValueType, if the key, exists in J and is the same type as ValueType, If not, + * returns the default value + */ template ValueType JValue(json const & J, json::object_t::key_type const & key, const ValueType& default_value) { @@ -58,8 +135,10 @@ ValueType JValue(json const & J, json::object_t::key_type const & key, const Val } } + + template -inline T * _jsonFindPath(std::string_view path, T & obj); +inline T * _jsonFindPath(std::string_view const path, T & obj); /** * @brief jsonFindPath @@ -69,49 +148,18 @@ inline T * _jsonFindPath(std::string_view path, T & obj); * * Given a path in a json object. Returns a pointer to the json object */ -inline json const* jsonFindPath(std::string_view path, json const & obj) +inline json const* jsonFindPath(std::string_view const path, json const & obj) { return _jsonFindPath(path, obj); } -inline json * jsonFindPath(std::string_view path, json & obj) +inline json * jsonFindPath(std::string_view const path, json & obj) { return _jsonFindPath(path, obj); } -/** - * @brief jsonExpandDef - * @param J - * - * Given a json object that has a property named, ref, which is - * a string that represents a path to an object in defsRoot - # eg: -"items": { - "name" : "Hello", - "defaultValue" : "World", - "$ref": "#/$defs/positiveInteger" -} -// defsRoot -{ - "$defs": { - "positiveInteger": { - "type": "integer", - "exclusiveMinimum": 0, - "defaultValue" : "Hello" - } - } -} -Copies the values from defsRoot which are not in the original object -{ - "items": { - "name" : "Hello", - "defaultValue" : "World", - "type": "integer", - "exclusiveMinimum": 0 - } -} -*/ +//=============== Private Functions ====================== /** * @brief jsonExpandDefs @@ -205,7 +253,15 @@ inline void _jsonExpandReference(json & J, json const & defs, std::string ref = } -inline void jsonExpandAllReferences(json & J, json const & defs, std::string ref= "$ref") +/** + * @brief jsonExpandAllReferences + * @param J + * @param defs + * @param ref + * + * Recursive fuction which expands ALL definitions + */ +inline void jsonExpandAllReferences(json & J, json const & defs, std::string ref) { if(J.is_array()) { @@ -224,15 +280,17 @@ inline void jsonExpandAllReferences(json & J, json const & defs, std::string ref } } -inline void jsonExpandAllReferences(json & J, std::string ref= "$ref") +inline void jsonExpandAllReferences(json & J, std::string ref) { jsonExpandAllReferences(J, J, ref); } -//=============== Private Functions ====================== + + + template -inline T * _jsonFindPath(std::string_view path, T & obj) +inline T * _jsonFindPath(std::string_view const path, T & obj) { // path == "grandParent/parent/child" if(path.empty()) diff --git a/schenity.cpp b/schenity.cpp new file mode 100644 index 0000000..c32709d --- /dev/null +++ b/schenity.cpp @@ -0,0 +1,256 @@ +// Dear ImGui: standalone example application for SDL2 + SDL_Renderer +// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.) +// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. +// Read online: https://github.com/ocornut/imgui/tree/master/docs + +// Important to understand: SDL_Renderer is an _optional_ component of SDL2. +// For a multi-platform app consider using e.g. SDL+DirectX on Windows and SDL+OpenGL on Linux/OSX. + +#define IMGUI_DEFINE_MATH_OPERATORS +#include "imgui.h" + + + +#include <../res/bindings/imgui_impl_sdl2.h> +#include <../res/bindings/imgui_impl_sdlrenderer2.h> + +#include +#include +#include +#if !SDL_VERSION_ATLEAST(2,0,17) +#error This backend requires SDL 2.0.17+ because of SDL_RenderGeometry() function +#endif + +#include +#include +#include +#include + +namespace IJS = ImJSchema; + + + +bool BeginFullScreen(const char* name, bool* p_open = nullptr, ImGuiWindowFlags _flags = 0) +{ + static bool use_work_area = true; + static ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings | _flags; + + // We demonstrate using the full viewport area or the work area (without menu-bars, task-bars etc.) + // Based on your use case you may want one or the other. + const ImGuiViewport* viewport = ImGui::GetMainViewport(); + ImGui::SetNextWindowPos( use_work_area ? viewport->WorkPos : viewport->Pos); + ImGui::SetNextWindowSize(use_work_area ? viewport->WorkSize : viewport->Size); + + return ImGui::Begin(name, p_open, flags); +} + +ImJSchema::json _value; +ImJSchema::json _cache; +ImJSchema::json _schema = ImJSchema::json::parse( + R"foo({ + "$defs": { + "normalized_number": { + "type" : "number", + "maximum": 1.0, + "minimum": 0.0, + "default": 0.0, + "ui:widget" : "slider" + } + }, + "ui:order" : ["albedo", "metallic", "roughness", "emissive", "emissiveFactor", "unlit"], + "description" : "Execute using \n\n schenity schema.json", + "properties" : { + "metallic" : { "$ref": "#/$defs/normalized_number" }, + "roughness" : { "$ref": "#/$defs/normalized_number" }, + "albedo" : { "type" : "string", "ui:widget" : "color" }, + "emissive" : { "type" : "string", "ui:widget" : "color" }, + "emissiveFactor" : { + "type" : "number", + "minimum" : 0.0, + "ui:speed" : 0.01, + "ui:widget" : "drag" + }, + "unlit" : { + "type" : "boolean" + } + }, + "type": "object" +})foo" +); + +int runApp() +{ + BeginFullScreen("Object"); + + int ret = 255; + + auto width = ImGui::GetContentRegionAvail().x / 2; + + ImVec2 ButtonSize = {width,100}; + + + if(IJS::drawSchemaWidget("object", + _value, + _schema, + _cache)) + { + // dont do anything when the user + // changes values + } + auto height = ImGui::GetContentRegionAvail().y; + ImGui::Dummy({5,height-ButtonSize.y}); + + if( ImGui::Button("Cancel", ButtonSize) ) + { + ret = 1; + } + ImGui::SameLine(); + if( ImGui::Button("Confirm", ButtonSize) ) + { + std::cout << _value.dump(); + ret = 0; + } + ImGui::End(); + + return ret; +} + + + +int main(int argc, char** argv) +{ + if(argc==2) + { + std::string inputFile= argv[1]; + if( std::filesystem::exists(inputFile)) + { + std::ifstream in(inputFile); + auto cpy = _schema; + + try + { + in >> _schema; + IJS::jsonExpandAllReferences(_schema); + } catch( std::exception & E) + { + _schema = cpy; + _schema["description"] = std::string("Error parsing json: ") + E.what(); + } + + } + } + + // Setup SDL + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) + { + printf("Error: %s\n", SDL_GetError()); + return -1; + } + +// From 2.0.18: Enable native IME. +#ifdef SDL_HINT_IME_SHOW_UI + SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1"); +#endif + + int windowWidth = 64*8; + int windowHeight = 64*10; + + // Create window with SDL_Renderer graphics context + SDL_WindowFlags window_flags = static_cast(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI ); + SDL_Window* window = SDL_CreateWindow("schenity: Like Zenity, but with Schemas", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, windowWidth, windowHeight, window_flags); + SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); + + if (renderer == nullptr) + { + SDL_Log("Error creating SDL_Renderer!"); + return 0; + } + //SDL_RendererInfo info; + //SDL_GetRendererInfo(renderer, &info); + //SDL_Log("Current SDL_Renderer: %s", info.name); + + // Setup Dear ImGui context + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); (void)io; + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + + // Setup Dear ImGui style + ImGui::StyleColorsDark(); + //ImGui::StyleColorsLight(); + + // Setup Platform/Renderer backends + ImGui_ImplSDL2_InitForSDLRenderer(window, renderer); + ImGui_ImplSDLRenderer2_Init(renderer); + + // Load Fonts + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering. + // - Read 'docs/FONTS.md' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! + //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != nullptr); + + // Our state + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); + + + // Main loop + bool done = false; + int returnValue=0; + + while (!done) + { + // Poll and handle events (inputs, window resize, etc.) + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. + SDL_Event event; + while (SDL_PollEvent(&event)) + { + ImGui_ImplSDL2_ProcessEvent(&event); + if (event.type == SDL_QUIT) + done = true; + if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window)) + done = true; + } + + // Start the Dear ImGui frame + ImGui_ImplSDLRenderer2_NewFrame(); + ImGui_ImplSDL2_NewFrame(); + ImGui::NewFrame(); + + returnValue = runApp(); + if(returnValue != 255) + done = true; + + // Rendering + ImGui::Render(); + SDL_RenderSetScale(renderer, io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y); + SDL_SetRenderDrawColor(renderer, static_cast(clear_color.x * 255), static_cast(clear_color.y * 255), static_cast(clear_color.z * 255), static_cast(clear_color.w * 255)); + SDL_RenderClear(renderer); + ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData()); + SDL_RenderPresent(renderer); + } + // Cleanup + ImGui_ImplSDLRenderer2_Shutdown(); + ImGui_ImplSDL2_Shutdown(); + ImGui::DestroyContext(); + + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); + + return returnValue; +} + diff --git a/share/01_basic_object.json b/share/01_basic_object.json new file mode 100644 index 0000000..d2ca0a0 --- /dev/null +++ b/share/01_basic_object.json @@ -0,0 +1,8 @@ +{ + "type": "object", + "properties" : { + "number" : { "type" : "number"}, + "bool" : { "type" : "boolean"}, + "string" : { "type" : "string"} + } +} diff --git a/share/02_basic_array.json b/share/02_basic_array.json new file mode 100644 index 0000000..3b875f3 --- /dev/null +++ b/share/02_basic_array.json @@ -0,0 +1,6 @@ +{ + "type": "array", + "items" : { + "type" : "number" + } +} diff --git a/share/03_descriptions.json b/share/03_descriptions.json new file mode 100644 index 0000000..1ba94b2 --- /dev/null +++ b/share/03_descriptions.json @@ -0,0 +1,26 @@ +{ + "description" : "Each schema object can have a \"description\" property to display visible text", + "type": "object", + "ui:order" : ["name", "age", "imguiAwesome", "object"], + "properties" : { + "name" : { + "type" : "string", + "description" : "Please enter the name wish to be called" + }, + "age" : { + "type" : "number", + "description" : "The age you will be at the end of this year" + }, + "imguiAwesome" : { + "type" : "boolean", + "description" : "Check this box if you think ImGui is awesome." + }, + "object" : { + "type" : "object", + "description" : "Objects within an object type will show up as a Collapsable header", + "properties" : { + "number" : { "type" : "number"} + } + } + } +} diff --git a/share/04_ordering.json b/share/04_ordering.json new file mode 100644 index 0000000..0e2d94e --- /dev/null +++ b/share/04_ordering.json @@ -0,0 +1,11 @@ +{ + "type": "object", + "description" : "By default, properties in an object will be displayed in alphabetical order. You can set the order the widgets appear by setting the ui:order property. If you do not list the widget, it will not show up in the list", + "ui:order" : ["b", "c", "a"], + "properties": { + "a": { "type": "string", "ui:help" : "Hover over the label to show this tooltip"}, + "b": { "type": "string" }, + "c": { "type": "string" }, + "d": { "type": "string" } + } +} diff --git a/share/05_titles.json b/share/05_titles.json new file mode 100644 index 0000000..83712ff --- /dev/null +++ b/share/05_titles.json @@ -0,0 +1,33 @@ +{ + "description" : "Each schema object can have a \"title\". This value will show up as the label ", + "type": "object", + "ui:order" : ["name", "age", "imguiAwesome", "array", "object"], + "properties" : { + "name" : { + "type" : "string", + "title" : "Name" + }, + "age" : { + "type" : "number", + "title" : "Age" + }, + "imguiAwesome" : { + "type" : "boolean", + "title" : "Is ImGui Awesome?" + }, + "object" : { + "type" : "object", + "title" : "Super Special Object", + "properties" : { + "number" : { "type" : "number"} + } + }, + "array" : { + "type" : "array", + "title" : "Super Special Array", + "items" : { + "type" : "number" + } + } + } +} diff --git a/share/06_help.json b/share/06_help.json new file mode 100644 index 0000000..d321e87 --- /dev/null +++ b/share/06_help.json @@ -0,0 +1,29 @@ +{ + "description" : "You can use the \"ui:help\" : \"tool tip text\" to show tooltip. Hover over the object label", + "type": "object", + "ui:order" : ["name", "age", "imguiAwesome", "object"], + "properties" : { + "name" : { + "type" : "string", + "title" : "Name", + "ui:help" : "Please enter the name wish to be called" + }, + "age" : { + "type" : "number", + "title" : "Age", + "ui:help" : "The age you will be at the end of this year" + }, + "imguiAwesome" : { + "type" : "boolean", + "title" : "Is ImGui Awesome?", + "ui:help" : "Check this box if you think ImGui is awesome." + }, + "object" : { + "type" : "object", + "ui:help" : "Objects within an object type will show up as a Collapsable header", + "properties" : { + "number" : { "type" : "number"} + } + } + } +} diff --git a/share/07_number_widgets.json b/share/07_number_widgets.json new file mode 100644 index 0000000..b39fd89 --- /dev/null +++ b/share/07_number_widgets.json @@ -0,0 +1,54 @@ +{ + "type": "object", + "properties": { + "float": { + "type": "number", + "default": 0.0, + "ui:step": 1, + "ui:step_fast": 10, + "description" : "Default floating point number. if ui:step is not provided, the increment buttons will not show. Default ui:step_fast is 10x ui:step" + }, + "float_slider": { + "type": "number", + "default": 0.0, + "maximum": 10.0, + "minimum": 0.0, + "ui:widget": "slider", + "description" : "Slider widgets require both a minimum and maximum property to be set. Will default to drag widget if either of these are not provided" + }, + "float_drag": { + "type": "number", + "default": 0.0, + "maximum": 1.0, + "minimum": 0.0, + "ui:speed": 0.0010000000474974513, + "ui:widget": "drag", + "description" : "Drag widgets" + }, + "int": { + "type": "integer", + "default": 0, + "ui:step": 1, + "ui:step_fast": 10, + "description" : "Integer widgets can be used as well, by setting the type to \"integer\"" + }, + "int_drag": { + "type": "integer", + "default": 0, + "maximum": 10, + "minimum": 0, + "ui:step": 1, + "ui:step_fast": 10, + "ui:widget": "drag" + }, + "int_slider": { + "type": "integer", + "default": 0, + "maximum": 10, + "minimum": 0, + "ui:step": 1, + "ui:step_fast": 10, + "ui:widget": "slider" + } + } +} diff --git a/share/08_boolean_widgets.json b/share/08_boolean_widgets.json new file mode 100644 index 0000000..b9bcce7 --- /dev/null +++ b/share/08_boolean_widgets.json @@ -0,0 +1,32 @@ +{ + "description" : "Boolean widgets. This object makes use of the \"ui:column_size\" property.", + "ui:column_size" : 50, + "type": "object", + "properties": { + "checkbox": { + "type": "boolean", + "default": false, + "title" : "Check Box", + "description" : "The default is checkbox" + }, + "enabledisable": { + "type": "boolean", + "default": false, + "ui:widget": "enabledisable", + "title" : "Enable/Disable", + "description" : "But there are also different styles. See Enumerated Types for an alternative method" + }, + "truefalse": { + "type": "boolean", + "default": false, + "ui:widget": "truefalse", + "title" : "True/False" + }, + "yesno": { + "type": "boolean", + "default": true, + "ui:widget": "yesno", + "title" : "Yes/No" + } + } +} diff --git a/share/09_string_widgets.json b/share/09_string_widgets.json new file mode 100644 index 0000000..f91678c --- /dev/null +++ b/share/09_string_widgets.json @@ -0,0 +1,24 @@ +{ + "type": "object", + "ui:order" : ["basic", "textarea", "color", "color_picker"], + "properties": { + "basic": { + "type": "string" + }, + "color": { + "type": "string", + "ui:widget": "color" + }, + "color_picker": { + "type": "string", + "ui:widget": "color_picker" + }, + "textarea": { + "type": "string", + "ui:options": { + "rows": 5 + }, + "ui:widget": "textarea" + } + } +} diff --git a/share/10_array_widgets.json b/share/10_array_widgets.json new file mode 100644 index 0000000..e57cbab --- /dev/null +++ b/share/10_array_widgets.json @@ -0,0 +1,46 @@ +{ + "type": "object", + "ui:order" : ["fixed_length", "varying_size", "color_array", "color_array_alpha"], + "properties": { + "fixed_length": { + "type": "array", + "items" : { + "type": "string", + "default": "hello world" + }, + "minItems" : 3, + "maxItems" : 3, + "title" : "Fixed Length Array", + "description" : "You can set the number of items in the array using the minItems and maxItems properties" + }, + "varying_size": { + "type": "array", + "items" : { + "type": "string", + "default": "hello world" + }, + "title" : "Varying Length Array", + "description" : "If you dont set the minItems/maxItems, you can grow or shrink the array using the buttons." + }, + "color_array": { + "type": "array", + "items" : { + "type": "number" + }, + "minItems" : 3, + "ui:widget" : "color", + "title" : "Color Array", + "description" : "Must have items set to number. If minItems==3" + }, + "color_array_alpha": { + "type": "array", + "items" : { + "type": "number" + }, + "minItems" : 4, + "ui:widget" : "color", + "title" : "Color Array Alpha", + "description" : "Must have items set to number. Requires minItems==4" + } + } +} diff --git a/share/11_object_widgets.json b/share/11_object_widgets.json new file mode 100644 index 0000000..d024cf9 --- /dev/null +++ b/share/11_object_widgets.json @@ -0,0 +1,43 @@ +{ + "type": "object", + "ui:order" : ["regular", "header", "collapsing"], + "properties": { + "regular": { + "type": "object", + "title" : "Regular Object", + "ui:label_width" : 0.25, + "ui:label_width_fixed" : false, + "properties" : + { + "string" : { "type" : "string" }, + "number" : { "type" : "number" }, + "boolean" : { "type" : "boolean" } + }, + "description" : "This is a regular object type. If ui:label_width_fixed is true, then ui:label_width is a value in pixels" + }, + "header": { + "type": "object", + "title" : "Header Widget", + "ui:widget" : "header", + "properties" : + { + "string" : { "type" : "string" }, + "number" : { "type" : "number" }, + "boolean" : { "type" : "boolean" } + }, + "description" : "Objects with ui:widget=header, will show up as headers" + }, + "collapsing": { + "type": "object", + "title" : "Collapsing Widget", + "ui:widget" : "collapsing", + "properties" : + { + "string" : { "type" : "string" }, + "number" : { "type" : "number" }, + "boolean" : { "type" : "boolean" } + }, + "description" : "Objects with ui:widget=collapsing, will show up as collapsable headers" + } + } +} diff --git a/share/12_constants.json b/share/12_constants.json new file mode 100644 index 0000000..f234a62 --- /dev/null +++ b/share/12_constants.json @@ -0,0 +1,14 @@ +{ + "type": "object", + "description" : "You can hide constant values in the form by setting the 'default', 'ui:hidden', and 'ui:disabled' properties.", + "properties": { + "constant_value": { + "type": "string", + "default" : "This is the default value", + "ui:hidden" : true, + "ui:disabled" : true + }, + "b": { "type": "string" }, + "c": { "type": "string" } + } +} diff --git a/share/13_enumerated.json b/share/13_enumerated.json new file mode 100644 index 0000000..29f50fc --- /dev/null +++ b/share/13_enumerated.json @@ -0,0 +1,44 @@ +{ + "type": "object", + "description" : "Enumerated types allow you to choose from one option. It requires the \"enum\" property. Additinally, if provided, the \"enumNames\" property will be used for displaying", + "properties": { + "strings": { + "type": "string", + "enum" : ["wiz", "src", "war"] + }, + "strings_with_names": { + "type": "string", + "title" : "String with Names", + "default" : "rogue", + "description" : "When using \"ui:widget\" : \"buttons\", You can set \"ui:options/columns\" to be a number to set the total number of columns for the buttons ", + "enum" : ["wiz", "sorc", "war", "fight", "barb", "art", "rogue", "monk", "pal"], + "enumNames" : ["Wizard", "Sorcerer", "Warlock", "Fighter", "Barbarian", "Artificer", "Rogue", "Monk", "Paladin"], + "ui:widget" : "button", + "ui:options" : { + "columns" : 3 + } + }, + "numbers": { + "type": "number", + "title" : "Numbers", + "enum" : [1,2,3] + }, + "numbers_with_names": { + "type": "number", + "title" : "Numbers With Names", + "enum" : [1,2,3], + "enumNames" : ["first", "second", "third"] + }, + "booleans": { + "type": "boolean", + "title" : "boolean", + "enum" : [false, true] + }, + "booleans_with_names": { + "type": "boolean", + "title" : "Boolean with Names", + "enum" : [false, true], + "enumNames" : ["False", "True"] + } + } +} diff --git a/share/14_references.json b/share/14_references.json new file mode 100644 index 0000000..1cfec98 --- /dev/null +++ b/share/14_references.json @@ -0,0 +1,33 @@ +{ + "$defs": { + "number": { + "default": 0.75, + "type": "number" + }, + "normalized": { + "maximum": 1.0, + "minimum": 0.0, + "default": 0.33, + "ui:widget" : "slider" + }, + "enum_list" : ["Hello", "this", "is", "a", "list"] + }, + "description" : "References allow you to reuse parts of your schema.\n\nThe drawSchemaWidget( ) function does not natively support the $ref property.\n\nIf you have a schema object, J, you can use the jsonExpandAllReferences(J) function\nto expand the references before you pass it into the drawSchemaWidget()", + "ui:order" : ["single_ref", "multi_ref", "enum_list"], + "properties" : { + "single_ref" : { + "description" : "The $ref string property points to a path within the JSON document", + "$ref": "#/$defs/number" + }, + "multi_ref" : { + "description" : "You can also use multiple references as a string array. Earlier items are overridden by later values in the array", + "$ref": ["#/$defs/number", "#/$defs/normalized"] + }, + "enum_list" : { + "description" : "Any property can set as a reference to a definition", + "type" : "string", + "enum" : { "$ref" : "#/$defs/enum_list"} + } + }, + "type": "object" +} diff --git a/share/15_DnD.json b/share/15_DnD.json new file mode 100644 index 0000000..c8dd557 --- /dev/null +++ b/share/15_DnD.json @@ -0,0 +1,58 @@ +{ + "$defs" : { + "class_list" : ["Wizard", "Sorcerer", "Warlock", "Fighter", "Barbarian", "Artificer", "Rogue", "Monk", "Paladin"], + "race_list" : ["Human", "Dwarf", "Elf", "Halfling"], + "stat" : { + "type" : "integer", + "ui:step" : 1, + "minimum" : 1, + "maximum" : 20, + "default" : 10 + }, + "character" : { + "type" : "object", + "ui:order" : ["name", "race", "class", "alignment_1", "alignment_2", "stats"], + "properties" : { + "name" : {"type" : "string"}, + "race" : { + "type" : "string", + "enum" : { "$ref" : "#/$defs/race_list" } + }, + "class" : { + "type" : "string", + "enum" : { "$ref" : "#/$defs/class_list" } + }, + "alignment_1" : { + "type" : "string", + "enum" : ["Lawful", "Neutral", "Chaotic"], + "ui:widget" : "button" + }, + "alignment_2" : { + "type" : "string", + "enum" : ["Good", "Neutral", "Evil"], + "ui:widget" : "button" + }, + "stats" : { + "type" : "object", + "properties" : { + "str" : { "$ref" : "#/$defs/stat" }, + "con" : { "$ref" : "#/$defs/stat" }, + "dex" : { "$ref" : "#/$defs/stat" }, + "int" : { "$ref" : "#/$defs/stat" }, + "wis" : { "$ref" : "#/$defs/stat" }, + "cha" : { "$ref" : "#/$defs/stat" } + } + } + } + } + }, + "type": "object", + "properties": { + "party" : { + "type" : "array", + "items" : { + "$ref" : "#/$defs/character" + } + } + } +} diff --git a/share/16_PBR.json b/share/16_PBR.json new file mode 100644 index 0000000..6cb2725 --- /dev/null +++ b/share/16_PBR.json @@ -0,0 +1,28 @@ +{ + "$defs": { + "normalized_number": { + "type" : "number", + "maximum": 1.0, + "minimum": 0.0, + "default": 0.0, + "ui:widget" : "slider" + } + }, + "ui:order" : ["albedo", "metallic", "roughness", "emissive", "emissiveFactor", "unlit"], + "properties" : { + "metallic" : { "$ref": "#/$defs/normalized_number" }, + "roughness" : { "$ref": "#/$defs/normalized_number" }, + "albedo" : { "type" : "string", "ui:widget" : "color" }, + "emissive" : { "type" : "string", "ui:widget" : "color" }, + "emissiveFactor" : { + "type" : "number", + "minimum" : 0.0, + "ui:speed" : 0.01, + "ui:widget" : "drag" + }, + "unlit" : { + "type" : "boolean" + } + }, + "type": "object" +} diff --git a/share/imgui.ini b/share/imgui.ini new file mode 100644 index 0000000..4a5c201 --- /dev/null +++ b/share/imgui.ini @@ -0,0 +1,5 @@ +[Window][Debug##Default] +Pos=60,60 +Size=400,400 +Collapsed=0 + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e429a28..1a5f50b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -13,7 +13,7 @@ get_filename_component(folder_name ${CMAKE_CURRENT_SOURCE_DIR} NAME) string(REPLACE " " "_" folder_name ${folder_name}) -enable_testing() + find_package(Threads REQUIRED) diff --git a/test/unit-parse.cpp b/test/unit-parse.cpp index d3bd3d4..4e453da 100644 --- a/test/unit-parse.cpp +++ b/test/unit-parse.cpp @@ -1,9 +1,6 @@ #include #include -#include -#include - #include "ImJSchema/detail/json_utils.h"