#define _CRT_SECURE_NO_WARNINGS
#define STB_IMAGE_IMPLEMENTATION
#define SDL_MAIN_USE_CALLBACKS 1
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <stdio.h>
#include <Windows.h>
#include "imgui.h"
#include "imgui_impl_sdl3.h"
#include "imgui_impl_sdlrenderer3.h"
#include "stb_image.h"
static SDL_Window* window = NULL;
static SDL_Renderer* renderer = NULL;
ImGuiIO* pio = NULL;
SDL_Texture* my_texture;
int my_image_width, my_image_height;
bool LoadTextureFromMemory(const void* data, size_t data_size, SDL_Renderer* renderer, SDL_Texture** out_texture, int* out_width, int* out_height)
{
int image_width = 0;
int image_height = 0;
int channels = 4;
unsigned char* image_data = stbi_load_from_memory((const unsigned char*)data, (int)data_size, &image_width, &image_height, NULL, 4);
if (image_data == nullptr)
{
fprintf(stderr, "Failed to load image: %s\n", stbi_failure_reason());
return false;
}
SDL_Surface* surface = SDL_CreateSurfaceFrom(image_width, image_height, SDL_PIXELFORMAT_RGBA32, (void*)image_data, channels * image_width);
if (surface == nullptr)
{
fprintf(stderr, "Failed to create SDL surface: %s\n", SDL_GetError());
return false;
}
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
if (texture == nullptr)
fprintf(stderr, "Failed to create SDL texture: %s\n", SDL_GetError());
*out_texture = texture;
*out_width = image_width;
*out_height = image_height;
SDL_DestroySurface(surface);
stbi_image_free(image_data);
return true;
}
// Open and read a file, then forward to LoadTextureFromMemory()
bool LoadTextureFromFile(const char* file_name, SDL_Renderer* renderer, SDL_Texture** out_texture, int* out_width, int* out_height)
{
FILE* f = fopen(file_name, "rb");
if (f == NULL)
return false;
fseek(f, 0, SEEK_END);
size_t file_size = (size_t)ftell(f);
if (file_size == -1)
return false;
fseek(f, 0, SEEK_SET);
void* file_data = IM_ALLOC(file_size);
fread(file_data, 1, file_size, f);
fclose(f);
bool ret = LoadTextureFromMemory(file_data, file_size, renderer, out_texture, out_width, out_height);
IM_FREE(file_data);
return ret;
}
SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[])
{
SDL_SetAppMetadata("Example Renderer Clear", "1.0", "com.example.renderer-clear");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/clear", 640, 480, 0, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
// (void)io는 의미 없는 명령. just to avoid compiler warning on unused variable
pio = &io;
// io가 SDL_AppIterate()에서 사용되기 때문에 전역 포인터 변수 pio에 대입.
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_ImplSDL3_InitForSDLRenderer(window, renderer);
ImGui_ImplSDLRenderer3_Init(renderer);
// Load our texture after initialising SDL
bool ret = LoadTextureFromFile("palvin.jpg", renderer, &my_texture, &my_image_width, &my_image_height);
IM_ASSERT(ret);
return SDL_APP_CONTINUE;
}
SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event)
{
// 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.
ImGui_ImplSDL3_ProcessEvent(event);
switch (event->type) {
case SDL_EVENT_QUIT:
return SDL_APP_SUCCESS;
case SDL_EVENT_KEY_DOWN:
printf("Key pressed: %s\n", SDL_GetKeyName(event->key.key));
if (event->key.key == SDLK_ESCAPE)
return SDL_APP_SUCCESS;
break;
default:
break;
}
return SDL_APP_CONTINUE;
}
SDL_AppResult SDL_AppIterate(void* appstate)
{
// Start the Dear ImGui frame
ImGui_ImplSDLRenderer3_NewFrame();
ImGui_ImplSDL3_NewFrame();
ImGui::NewFrame();
// Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
{
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / pio->Framerate, pio->Framerate);
ImGui::End();
}
// 윈도우 없이 위치가 고정된 이미지 생성하기.
{
ImGui::Begin("No Window", 0, ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoInputs);
ImGui::SetWindowPos(ImVec2(0, 0));
ImGui::Text("pointer = %p", my_texture);
ImGui::Text("size = %d x %d", my_image_width, my_image_height);
ImGui::Image((ImTextureID)(intptr_t)my_texture, ImVec2((float)my_image_width, (float)my_image_height));
ImGui::End();
}
// Rendering
ImGui::Render();
SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE);
SDL_RenderClear(renderer);
ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData(), renderer);
SDL_RenderPresent(renderer);
return SDL_APP_CONTINUE;
}
void SDL_AppQuit(void* appstate, SDL_AppResult result)
{
// Cleanup
ImGui_ImplSDLRenderer3_Shutdown();
ImGui_ImplSDL3_Shutdown();
ImGui::DestroyContext();
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}