diff --git a/scripts/gen_build.py b/scripts/gen_build.py index b0ca50a..d863979 100644 --- a/scripts/gen_build.py +++ b/scripts/gen_build.py @@ -32,7 +32,9 @@ with pl.project("game"): # project wide settings pl.set_output_directory("../out") - pl.add_link_directories("../out") + pl.add_link_directories( + "../out", + "../../pilotlight/out") pl.add_include_directories( "../src", "../extensions", @@ -141,6 +143,7 @@ with pl.project("game"): pl.add_source_files("../src/app.c") pl.set_output_binary("template_app") + pl.add_dynamic_link_libraries("pl_unity_ext", "pl_platform_ext") # only needed if using functions directly # default config with pl.configuration("debug"): diff --git a/src/app.c b/src/app.c index bb185d1..22579bc 100644 --- a/src/app.c +++ b/src/app.c @@ -82,9 +82,6 @@ Index of this file: #include "pl_stats_ext.h" #include "pl_console_ext.h" -// out extension -#include "pl_example_ext.h" - //----------------------------------------------------------------------------- // [SECTION] structs //----------------------------------------------------------------------------- @@ -116,7 +113,6 @@ const plStatsI* gptStats = NULL; const plMemoryI* gptMemory = NULL; const plLogI* gptLog = NULL; const plConsoleI* gptConsole = NULL; -const plExampleI* gptExample = NULL; #define PL_ALLOC(x) gptMemory->tracked_realloc(NULL, (x), __FILE__, __LINE__) #define PL_REALLOC(x, y) gptMemory->tracked_realloc((x), (y), __FILE__, __LINE__) @@ -150,7 +146,6 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plAppData* ptAppData) gptMemory = pl_get_api_latest(ptApiRegistry, plMemoryI); gptLog = pl_get_api_latest(ptApiRegistry, plLogI); gptConsole = pl_get_api_latest(ptApiRegistry, plConsoleI); - gptExample = pl_get_api_latest(ptApiRegistry, plExampleI); return ptAppData; } @@ -165,7 +160,7 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plAppData* ptAppData) // * fourth argument indicates if the extension is reloadable (should we check for changes and reload if changed) ptExtensionRegistry->add_path("../../pl-template/out"); ptExtensionRegistry->load("pl_unity_ext", NULL, NULL, false); - ptExtensionRegistry->load("pl_platform_ext", NULL, NULL, false); // provides the file API used by the drawing ext + ptExtensionRegistry->load("pl_platform_ext", "pl_load_platform_ext", "pl_unload_platform_ext", false); // provides the file API used by the drawing ext ptExtensionRegistry->load("pl_example_ext", NULL, NULL, true); // load required apis @@ -183,11 +178,6 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plAppData* ptAppData) gptLog = pl_get_api_latest(ptApiRegistry, plLogI); gptConsole = pl_get_api_latest(ptApiRegistry, plConsoleI); - // out extension - gptExample = pl_get_api_latest(ptApiRegistry, plExampleI); - - gptExample->print_to_console("Hello from example extension"); - // this path is taken only during first load, so we // allocate app memory here ptAppData = PL_ALLOC(sizeof(plAppData)); @@ -198,7 +188,7 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plAppData* ptAppData) // use window API to create a window plWindowDesc tWindowDesc = { - .pcTitle = "Template App", + .pcTitle = "Example Basic 3", .iXPos = 200, .iYPos = 200, .uWidth = 600, @@ -242,7 +232,7 @@ pl_app_shutdown(plAppData* ptAppData) //----------------------------------------------------------------------------- PL_EXPORT void -pl_app_resize(plAppData* ptAppData) +pl_app_resize(plWindow* ptWindow, plAppData* ptAppData) { gptStarter->resize(); } @@ -282,6 +272,16 @@ pl_app_update(plAppData* ptAppData) (plVec2){200.0f}, (plVec2){100.0f, 200.0f}, (plDrawSolidOptions){.uColor = PL_COLOR_32_RGBA(0.0f, 0.5f, 1.0f, 0.5f)}); + plVec2 points[5] = { + (plVec2){100.0f, 100.0f}, + (plVec2){500.0f, 100.0f}, + (plVec2){500.0f, 300.0f}, + (plVec2){300.0f, 500.0f}, + (plVec2){100.0f, 300.0f}, + }; + gptDraw->add_convex_polygon_filled(ptBGLayer, points, sizeof(points)/sizeof(points[0]), (plDrawSolidOptions){.uColor = PL_COLOR_32_RGBA(1.0f, 0.25f, 0.25f, 0.5f)}); + gptDraw->add_polygon(ptBGLayer, points, sizeof(points)/sizeof(points[0]), (plDrawLineOptions){.fThickness = 30.0f, .uColor = PL_COLOR_32_RGBA(1.0f, 1.0f, 1.0f, 0.5f)}); + gptProfile->end_sample(0); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~UI & Screen Log API~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/app_direct.c b/src/app_direct.c new file mode 100644 index 0000000..05569da --- /dev/null +++ b/src/app_direct.c @@ -0,0 +1,287 @@ +/* + example_basic_2.c + - demonstrates loading APIs + - demonstrates loading extensions + - demonstrates hot reloading + - demonstrates starter extension + - demonstrates basic drawing extension (2D) + - demonstrates basic screen log extension + - demonstrates basic console extension + - demonstrates basic UI extension +*/ + +/* +Index of this file: +// [SECTION] quick notes +// [SECTION] includes +// [SECTION] structs +// [SECTION] apis +// [SECTION] pl_app_load +// [SECTION] pl_app_shutdown +// [SECTION] pl_app_resize +// [SECTION] pl_app_update +*/ + +//----------------------------------------------------------------------------- +// [SECTION] quick notes +//----------------------------------------------------------------------------- + +/* + This example is the first to introduce extensions. Extensions are just + shared libraries that export a "load" and "unload" function. The default + being: + + * void pl_load_ext (plApiRegistryI*, bool reload) + * void pl_unload_ext(plApiRegistryI*, bool reload) + + This example is also the first to introduce the "starter" extension. This + extension acts a bit as a helper extension to remove some common boilerplate + but is also just useful in general for most applications only needing to use + UI, plotting, drawing, etc. Or even to just experiment with the lower level + graphics extension in an isolated manner. Later examples will gradually peel + away at this extension and others. For this example, we will just demonstrate + some of the smaller helpful extensions. These include: + + * log + * profile + * stat + * console + * screen log + * ui + + This will be very light introductions with later examples going into more + detail. Feel free to open the header file for the extension for more + information and functionality. +*/ + +//----------------------------------------------------------------------------- +// [SECTION] includes +//----------------------------------------------------------------------------- + +#include // malloc, free +#include // memset +#include "pl.h" + +#include "pl_unity_ext.h" // for loading extension directly to not need api structs + +#define PL_MATH_INCLUDE_FUNCTIONS // required to expose some of the color helpers +#include "pl_math.h" + +// extensions +#include "pl_draw_ext.h" +#include "pl_starter_ext.h" +#include "pl_ui_ext.h" +#include "pl_screen_log_ext.h" +#include "pl_profile_ext.h" +#include "pl_log_ext.h" +#include "pl_stats_ext.h" +#include "pl_console_ext.h" +#include "pl_platform_ext.h" + +//----------------------------------------------------------------------------- +// [SECTION] structs +//----------------------------------------------------------------------------- + +typedef struct _plAppData +{ + // window + plWindow* ptWindow; + + // log channel + uint64_t uExampleLogChannel; + + // console variable + bool bShowHelpWindow; +} plAppData; + +//----------------------------------------------------------------------------- +// [SECTION] apis +//----------------------------------------------------------------------------- + +plApiRegistryI* gptApiRegistry = NULL; + +#define PL_ALLOC(x) pl_memory_tracked_realloc(NULL, (x), __FILE__, __LINE__) +#define PL_REALLOC(x, y) pl_memory_tracked_realloc((x), (y), __FILE__, __LINE__) +#define PL_FREE(x) pl_memory_tracked_realloc((x), 0, __FILE__, __LINE__) + +//----------------------------------------------------------------------------- +// [SECTION] pl_app_load +//----------------------------------------------------------------------------- + +PL_EXPORT void* +pl_app_load(plApiRegistryI* ptApiRegistry, plAppData* ptAppData) +{ + gptApiRegistry = ptApiRegistry; // saving for cleanup later + + // retrieve extension registry + const plExtensionRegistryI* ptExtensionRegistry = pl_get_api_latest(ptApiRegistry, plExtensionRegistryI); + + // load extensions + pl_load_ext(ptApiRegistry, false); + pl_load_platform_ext(ptApiRegistry, false); + + // this path is taken only during first load, so we + // allocate app memory here + ptAppData = PL_ALLOC(sizeof(plAppData)); + memset(ptAppData, 0, sizeof(plAppData)); + + // default values + ptAppData->bShowHelpWindow = true; + + // use window API to create a window + plWindowDesc tWindowDesc = { + .pcTitle = "Example Basic 2", + .iXPos = 200, + .iYPos = 200, + .uWidth = 600, + .uHeight = 600, + }; + pl_window_create(tWindowDesc, &ptAppData->ptWindow); + pl_window_show(ptAppData->ptWindow); + + // initialize the starter API (handles alot of boilerplate) + plStarterInit tStarterInit = { + .tFlags = PL_STARTER_FLAGS_ALL_EXTENSIONS, + .ptWindow = ptAppData->ptWindow + }; + pl_starter_initialize(tStarterInit); + pl_starter_finalize(); + + // add a log channel + ptAppData->uExampleLogChannel = pl_log_add_channel("Example 2", (plLogExtChannelInit){.tType = PL_LOG_CHANNEL_TYPE_BUFFER}); + + // add a console variable + pl_console_add_toggle_variable("a.HelpWindow", &ptAppData->bShowHelpWindow, "toggle help window", PL_CONSOLE_VARIABLE_FLAGS_NONE); + + // return app memory + return ptAppData; +} + +//----------------------------------------------------------------------------- +// [SECTION] pl_app_shutdown +//----------------------------------------------------------------------------- + +PL_EXPORT void +pl_app_shutdown(plAppData* ptAppData) +{ + pl_starter_cleanup(); + pl_window_destroy(ptAppData->ptWindow); + + // unload extensions + pl_load_ext(gptApiRegistry, false); + pl_load_platform_ext(gptApiRegistry, false); + PL_FREE(ptAppData); +} + +//----------------------------------------------------------------------------- +// [SECTION] pl_app_resize +//----------------------------------------------------------------------------- + +PL_EXPORT void +pl_app_resize(plWindow* ptWindow, plAppData* ptAppData) +{ + pl_starter_resize(); +} + +//----------------------------------------------------------------------------- +// [SECTION] pl_app_update +//----------------------------------------------------------------------------- + +PL_EXPORT void +pl_app_update(plAppData* ptAppData) +{ + // this needs to be the first call when using the starter + // extension. You must return if it returns false (usually a swapchain recreation). + if(!pl_starter_begin_frame()) + return; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~stats API~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // rather than have to lookup the counter every frame, its best to "store" it + // like this. To update it, just deference it and set the value. + static double* pdExample2Counter = NULL; + if(!pdExample2Counter) + pdExample2Counter = pl_stats_get_counter("example 2 counter"); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~drawing & profile API~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + pl_profile_begin_sample(0, "example drawing"); + + plDrawLayer2D* ptFGLayer = pl_starter_get_foreground_layer(); + pl_draw_add_line(ptFGLayer, + (plVec2){0.0f, 0.0f}, + (plVec2){500.0f, 500.0f}, (plDrawLineOptions){ .fThickness = 1.0f, .uColor = PL_COLOR_32_MAGENTA}); + + plDrawLayer2D* ptBGLayer = pl_starter_get_background_layer(); + pl_draw_add_triangle_filled(ptBGLayer, + (plVec2){50.0f, 100.0f}, + (plVec2){200.0f}, + (plVec2){100.0f, 200.0f}, (plDrawSolidOptions){.uColor = PL_COLOR_32_RGBA(0.0f, 0.5f, 1.0f, 0.5f)}); + + plVec2 points[5] = { + (plVec2){100.0f, 100.0f}, + (plVec2){500.0f, 100.0f}, + (plVec2){500.0f, 300.0f}, + (plVec2){300.0f, 500.0f}, + (plVec2){100.0f, 300.0f}, + }; + pl_draw_add_convex_polygon_filled(ptBGLayer, points, sizeof(points)/sizeof(points[0]), (plDrawSolidOptions){.uColor = PL_COLOR_32_RGBA(1.0f, 0.25f, 0.25f, 0.5f)}); + pl_draw_add_polygon(ptBGLayer, points, sizeof(points)/sizeof(points[0]), (plDrawLineOptions){.fThickness = 30.0f, .uColor = PL_COLOR_32_RGBA(1.0f, 1.0f, 1.0f, 0.5f)}); + + pl_profile_end_sample(0); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~UI & Screen Log API~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // creating a window + if(ptAppData->bShowHelpWindow) + { + if(pl_ui_begin_window("Help", NULL, PL_UI_WINDOW_FLAGS_AUTO_SIZE | PL_UI_WINDOW_FLAGS_NO_COLLAPSE)) + { + pl_ui_layout_static(0.0f, 500.0f, 1); + pl_ui_text("Press F1 to bring up console."); + pl_ui_text("Look for t.StatsTool (we added a stat)"); + pl_ui_text("Look for t.LogTool (we added a log channel)"); + pl_ui_text("Look for t.ProfileTool"); + pl_ui_text("Look for t.MemoryAllocationTool and look for example 2!"); + pl_ui_text("Look for a.HelpWindow (console variable we added)"); + pl_ui_end_window(); + } + } + + // creating another window + if(pl_ui_begin_window("Pilot Light", NULL, PL_UI_WINDOW_FLAGS_NONE)) + { + pl_ui_text("Pilot Light %s", PILOT_LIGHT_VERSION_STRING); + + if(pl_ui_button("Log")) + { + pl_log_trace(ptAppData->uExampleLogChannel, "Log"); + pl_log_debug(ptAppData->uExampleLogChannel, "Log"); + pl_log_info(ptAppData->uExampleLogChannel, "Log"); + pl_log_warn(ptAppData->uExampleLogChannel, "Log"); + pl_log_error(ptAppData->uExampleLogChannel, "Log"); + pl_log_fatal(ptAppData->uExampleLogChannel, "Log"); + } + + static int iCounter = 0; + pl_ui_slider_int("Stat Counter Example", &iCounter, -10, 10, 0); + *pdExample2Counter = iCounter; // setting our stat variable + + pl_ui_layout_row_begin(PL_UI_LAYOUT_ROW_TYPE_DYNAMIC, 0.0f, 2); // got to pl_ui_ext.h to see layout systems + + pl_ui_layout_row_push(0.3f); + if(pl_ui_button("Log To Screen")) + pl_screen_log_add_message(5.0, "Cool Message!"); + + pl_ui_layout_row_push(0.3f); + if(pl_ui_button("Big Log To Screen")) + pl_screen_log_add_message_ex(0, 5, PL_COLOR_32_GREEN, 3.0f, "%s", "Bigger & Greener!"); + + pl_ui_layout_row_end(); + + pl_ui_end_window(); + } + + // must be the last function called when using the starter extension + pl_starter_end_frame(); +}