prosperon/source/engine/editor/editor.c

1030 lines
23 KiB
C
Raw Normal View History

2023-01-12 17:41:54 -06:00
void editor_init(){}
#ifdef GOOGLE
2022-08-15 16:38:21 -05:00
#include "editor.h"
#include "ed_project.h"
2022-06-21 12:48:19 -05:00
2022-08-14 14:19:36 -05:00
#include "2dphysics.h"
2021-11-30 21:29:18 -06:00
#include "camera.h"
2022-08-14 14:19:36 -05:00
#include "config.h"
#include "datastream.h"
#include "debug.h"
#include "debugdraw.h"
2021-11-30 21:29:18 -06:00
#include "editorstate.h"
2022-08-14 14:19:36 -05:00
#include "gameobject.h"
2021-11-30 21:29:18 -06:00
#include "input.h"
#include "level.h"
2022-08-14 14:19:36 -05:00
#include "math.h"
#include "openglrender.h"
#include "resources.h"
#include "script.h"
#include "shader.h"
#include "sound.h"
2021-11-30 21:29:18 -06:00
#include "sprite.h"
2022-08-14 14:19:36 -05:00
#include "texture.h"
#include "vec.h"
#include "window.h"
2022-01-21 11:26:22 -06:00
#include <chipmunk/chipmunk.h>
2021-11-30 21:29:18 -06:00
#include <ctype.h>
2022-08-14 14:19:36 -05:00
#include <dirent.h>
#include <stdio.h>
2022-07-03 00:43:42 -05:00
#include <stdlib.h>
#include "nuke.h"
2022-12-28 16:50:54 -06:00
#include "texture.h"
2022-07-03 00:43:42 -05:00
2022-08-24 12:24:21 -05:00
#include "log.h"
2022-07-03 00:43:42 -05:00
#include "ftw.h"
2022-02-07 08:50:34 -06:00
2022-12-23 13:48:29 -06:00
extern struct nk_context *ctx;
2021-11-30 21:29:18 -06:00
#include <stb_ds.h>
2022-08-14 14:19:36 -05:00
#define ASSET_TEXT_BUF 1024 * 1024 /* 1 MB buffer for editing text files */
2022-06-21 12:48:19 -05:00
2022-08-14 14:19:36 -05:00
struct gameproject *cur_project = NULL;
struct vec *projects = NULL;
2021-11-30 21:29:18 -06:00
static char setpath[MAXPATH];
2022-12-19 12:16:51 -06:00
2021-11-30 21:29:18 -06:00
// Menus
// TODO: Pack this into a bitfield
2022-08-14 14:19:36 -05:00
static struct editorVars editor = {0};
2021-11-30 21:29:18 -06:00
// Lighting effect flags
static bool renderAO = true;
static bool renderDynamicShadows = true;
// Debug render modes
static int renderGizmos = false;
static int showGrid = true;
static int debugDrawPhysics = false;
2021-11-30 21:29:18 -06:00
2022-08-19 11:25:08 -05:00
const char *allowed_extensions[] = {"jpg", "png", "rb", "wav", "mp3", };
void text_ed_cb(GLFWwindow *win, unsigned int codepoint);
void asset_srch_cb(GLFWwindow *win, unsigned int codepoint)
{
YughInfo("Pushed %d.", codepoint);
2022-08-19 11:25:08 -05:00
}
2021-11-30 21:29:18 -06:00
static const char *editor_filename = "editor.ini";
2022-08-25 15:48:15 -05:00
static struct {
2022-08-14 14:19:36 -05:00
char *key;
struct fileasset *value;
2022-08-25 15:48:15 -05:00
} *assets = NULL;
2022-02-07 08:50:34 -06:00
2022-08-19 11:25:08 -05:00
static char asset_search_buffer[100] = {'\0'};
2021-11-30 21:29:18 -06:00
struct fileasset *selected_asset;
static int selected_index = -1;
2022-08-18 08:50:03 -05:00
int show_desktop = 0;
2022-08-19 11:25:08 -05:00
int tex_view = 0;
2021-11-30 21:29:18 -06:00
static int grid1_width = 1;
static int grid1_span = 100;
static int grid2_width = 3;
static int grid2_span = 1000;
static int grid1_draw = true;
static int grid2_draw = true;
2021-11-30 21:29:18 -06:00
static float tex_scale = 1.f;
2022-08-14 14:19:36 -05:00
static struct TexAnimation tex_gui_anim = {0};
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
char current_level[MAXNAME] = {'\0'};
char levelname[MAXNAME] = {'\0'};
2021-11-30 21:29:18 -06:00
static struct vec *levels = NULL;
static const int ASSET_WIN_SIZE = 512;
2022-08-14 14:19:36 -05:00
static const char *get_extension(const char *filepath) {
return strrchr(filepath, '.');
2021-11-30 21:29:18 -06:00
}
2022-08-24 12:24:21 -05:00
size_t asset_side_size(struct fileasset *asset) {
if (asset->type == ASSET_TYPE_IMAGE)
return sizeof(struct Texture);
return 0;
}
2022-08-25 15:48:15 -05:00
void save_asset(struct fileasset *asset) {
if (asset == NULL) {
2022-08-24 12:24:21 -05:00
YughWarn("No asset to save.", 0);
return;
}
2022-08-25 15:48:15 -05:00
if (asset->type != ASSET_TYPE_IMAGE) return;
2022-08-24 12:24:21 -05:00
2022-08-25 15:48:15 -05:00
FILE *f = res_open(str_replace_ext(asset->filename, EXT_ASSET), "w");
fwrite(asset->data, asset_side_size(asset), 1, f);
2022-08-24 12:24:21 -05:00
fclose(f);
}
2022-08-25 15:48:15 -05:00
void load_asset(struct fileasset *asset) {
if (asset == NULL) {
2022-08-24 12:24:21 -05:00
YughWarn("No asset to load.", 0);
return;
}
2022-08-25 15:48:15 -05:00
if (asset->type != ASSET_TYPE_IMAGE)
return;
2022-08-24 12:24:21 -05:00
2022-08-25 15:48:15 -05:00
if (asset->data == NULL)
asset->data = malloc(asset_side_size(asset));
2022-08-24 12:24:21 -05:00
2022-08-25 15:48:15 -05:00
FILE *f = res_open(str_replace_ext(asset->filename, EXT_ASSET), "r");
2022-08-24 12:24:21 -05:00
if (f == NULL)
return;
2022-08-25 15:48:15 -05:00
struct Texture tex;
struct Texture *asset_tex = asset->data;
fread(&tex, asset_side_size(asset), 1, f);
asset_tex->opts = tex.opts;
asset_tex->anim = tex.anim;
2022-08-24 12:24:21 -05:00
fclose(f);
}
2022-08-25 15:48:15 -05:00
static int check_if_resource(const char *fpath, const struct stat *sb, int typeflag) {
if (typeflag != FTW_F)
return 0;
const char *ext = get_extension(fpath);
if (ext && is_allowed_extension(ext)) {
struct fileasset *newasset = calloc(1, sizeof(struct fileasset));
newasset->searched = true;
if (!strcmp(ext+1, "png") || !strcmp(ext+1, "jpg"))
newasset->type = ASSET_TYPE_IMAGE;
else if (!strcmp(ext+1, "rb"))
newasset->type = ASSET_TYPE_TEXT;
else if (!strcmp(ext+1, "wav") || !strcmp(ext+1, "mp3"))
newasset->type = ASSET_TYPE_SOUND;
else
newasset->type = ASSET_TYPE_NULL;
newasset->filename = strdup(fpath);
shput(assets, newasset->filename, newasset);
}
return 0;
}
static void print_files_in_directory(const char *dirpath) {
struct fileasset *n = NULL;
for (int i = 0; i < shlen(assets); i++) {
free(assets[i].key);
free(assets[i].value);
}
shfree(assets);
ftw(dirpath, check_if_resource, 10);
}
static void get_all_files() { print_files_in_directory("."); }
2022-08-14 14:19:36 -05:00
static int *compute_prefix_function(const char *str) {
int str_len = strlen(str);
int *pi = (int *)malloc(sizeof(int) * str_len);
pi[0] = 0;
int k = 0;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
for (int q = 2; q < str_len; q++) {
while (k > 0 && str[k + 1] != str[q])
k = pi[k];
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
if (str[k + 1] == str[q])
k += 1;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
pi[q] = k;
}
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
return pi;
2021-11-30 21:29:18 -06:00
}
2022-08-14 14:19:36 -05:00
static bool kmp_match(const char *search, const char *text, int *pi) {
int s_len = strlen(search);
int t_len = strlen(text);
// int *pi = compute_prefix_function(search);
int q = 0;
bool found = false;
2022-06-21 12:48:19 -05:00
2022-08-14 14:19:36 -05:00
for (int i = 0; i < t_len; i++) {
while (q > 0 && search[q + 1] != text[i])
q = pi[q];
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
if (search[q + 1] == text[i])
q += 1;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
if (q == s_len) {
q = pi[q];
found = true;
goto end;
2021-11-30 21:29:18 -06:00
}
2022-08-14 14:19:36 -05:00
}
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
end:
return found;
2021-11-30 21:29:18 -06:00
}
2022-08-19 11:25:08 -05:00
void filter_asset_srch()
{
if (asset_search_buffer[0] == '\0') {
for (int i = 0; i < shlen(assets); i++)
assets[i].value->searched = true;
} else {
for (int i = 0; i < shlen(assets); i++)
assets[i].value->searched = (strstr(assets[i].value->filename, asset_search_buffer) == NULL) ? false : true;
}
2021-11-30 21:29:18 -06:00
}
2022-08-19 11:25:08 -05:00
void filter_autoindent()
2021-11-30 21:29:18 -06:00
{
2022-08-14 14:19:36 -05:00
}
2021-11-30 21:29:18 -06:00
2022-08-19 11:25:08 -05:00
2022-08-14 14:19:36 -05:00
void editor_save() {
FILE *feditor = fopen(editor_filename, "w+");
fwrite(&editor, sizeof(editor), 1, feditor);
fclose(feditor);
}
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
static void edit_input_cb(GLFWwindow *w, int key, int scancode, int action, int mods) {
2022-08-19 11:25:08 -05:00
if (editor_wantkeyboard()) {
if (editor.asset_srch & NK_EDIT_ACTIVE) {
filter_asset_srch();
}
if ((editor.text_ed & NK_EDIT_ACTIVE) && key == GLFW_KEY_ENTER) {
filter_autoindent();
}
return;
}
2021-11-30 21:29:18 -06:00
2022-08-18 08:50:03 -05:00
if (action == GLFW_RELEASE) {
switch(key) {
case GLFW_KEY_TAB:
show_desktop = 0;
break;
}
2022-08-14 14:19:36 -05:00
return;
2022-08-18 08:50:03 -05:00
}
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
switch (key) {
case GLFW_KEY_ESCAPE:
quit();
2022-08-14 14:19:36 -05:00
//editor_save_projects();
editor_save();
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_1:
renderMode = LIT;
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_2:
renderMode = UNLIT;
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_3:
renderMode = WIREFRAME;
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_4:
renderMode = DIRSHADOWMAP;
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_5:
renderGizmos = !renderGizmos;
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_6:
debugDrawPhysics = !debugDrawPhysics;
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_7:
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_8:
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_9:
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_0:
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_T:
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_F2:
2022-08-15 16:38:21 -05:00
NEGATE(editor.assets.show);
2022-08-14 14:19:36 -05:00
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_F3:
2022-08-15 16:38:21 -05:00
NEGATE(editor.stats.show);
2022-08-14 14:19:36 -05:00
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_F4:
2022-08-15 16:38:21 -05:00
NEGATE(editor.hierarchy.show);
2022-08-14 14:19:36 -05:00
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_F5:
2022-08-14 14:19:36 -05:00
break;
2022-08-05 14:23:39 -05:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_F6:
2022-08-15 16:38:21 -05:00
NEGATE(editor.gamesettings.show);
2022-08-14 14:19:36 -05:00
break;
2022-06-21 12:48:19 -05:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_F7:
2022-08-15 16:38:21 -05:00
NEGATE(editor.viewmode.show);
2022-08-14 14:19:36 -05:00
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_F8:
NEGATE(editor.debug.show);
2022-08-14 14:19:36 -05:00
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_F9:
2022-08-15 16:38:21 -05:00
NEGATE(editor.export.show);
2022-08-14 14:19:36 -05:00
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_F10:
2022-08-15 16:38:21 -05:00
NEGATE(editor.level.show);
2022-08-14 14:19:36 -05:00
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_F11:
window_togglefullscreen(mainwin);
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_GRAVE_ACCENT:
2022-08-15 16:38:21 -05:00
NEGATE(editor.repl.show);
2022-08-14 14:19:36 -05:00
break;
2022-06-21 23:16:14 -05:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_K:
showGrid = !showGrid;
break;
case GLFW_KEY_DELETE:
break;
2022-06-21 23:16:14 -05:00
2022-08-14 14:19:36 -05:00
case GLFW_KEY_F:
/*
if (selectedobject != NULL) {
cam_goto_object(&camera, &selectedobject->transform);
}
*/
break;
2022-08-18 08:50:03 -05:00
case GLFW_KEY_TAB:
show_desktop = 1;
break;
2022-08-14 14:19:36 -05:00
}
}
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
static void edit_mouse_cb(GLFWwindow *w, int button, int action, int mods) {
if (editor_wantkeyboard())
return;
if (action == GLFW_PRESS) {
switch (button) {
case GLFW_MOUSE_BUTTON_RIGHT:
cursor_hide();
break;
case GLFW_MOUSE_BUTTON_MIDDLE:
/*
glBindFramebuffer(GL_FRAMEBUFFER, debugColorPickBO);
int mx = 0;
int my = 0;
SDL_GetMouseState(&mx, &my);
unsigned char data[4];
glReadPixels(mx, SCREEN_HEIGHT - my, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
int pickID = data[0] + data[1]*256 + data[2]*256*256;
snprintf(objectName, 200, "Object %d", pickID);
pickGameObject(pickID);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
*/
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
pickGameObject(-1);
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
break;
2021-11-30 21:29:18 -06:00
}
2022-08-14 14:19:36 -05:00
} else if (action == GLFW_RELEASE) {
switch (button) {
case GLFW_MOUSE_BUTTON_RIGHT:
cursor_show();
break;
2022-06-21 23:16:14 -05:00
}
2022-08-14 14:19:36 -05:00
}
}
2021-11-30 21:29:18 -06:00
void editor_init(struct window *window) {
2022-08-18 08:50:03 -05:00
levels = vec_make(MAXPATH, 10);
get_levels();
2022-08-14 14:19:36 -05:00
editor_load_projects();
2022-08-15 16:38:21 -05:00
findPrefabs();
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
FILE *feditor = fopen(editor_filename, "r");
if (feditor == NULL) {
editor_save();
} else {
fread(&editor, sizeof(editor), 1, feditor);
fclose(feditor);
}
2022-06-21 23:16:14 -05:00
2022-08-14 14:19:36 -05:00
nuke_init(window);
window->nuke_gui = editor_render;
2022-08-15 16:38:21 -05:00
window_makefullscreen(window);
2022-08-14 14:19:36 -05:00
glfwSetKeyCallback(window->window, edit_input_cb);
glfwSetMouseButtonCallback(window->window, edit_mouse_cb);
2022-08-15 16:38:21 -05:00
2022-08-19 11:25:08 -05:00
//glfwSetCharCallback(window->window, text_ed_cb);
//glfwSetCharCallback(window->window, asset_srch_cb);
2022-08-25 15:48:15 -05:00
get_all_files();
2022-06-21 23:16:14 -05:00
}
2021-11-30 21:29:18 -06:00
2022-08-19 11:25:08 -05:00
int editor_wantkeyboard() {
if (editor.text_ed & NK_EDIT_ACTIVE)
return 1;
2021-11-30 21:29:18 -06:00
2022-08-19 11:25:08 -05:00
if (editor.asset_srch & NK_EDIT_ACTIVE)
return 1;
return 0;
}
const int nuk_std = NK_WINDOW_BORDER | NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE | NK_WINDOW_TITLE;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
const struct nk_rect nk_rect_std = {250, 250, 250, 250};
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
void editor_project_gui() {
/* Grid, etc */
if (grid1_draw)
draw_grid(grid1_width, grid1_span);
if (grid2_draw)
draw_grid(grid2_width, grid2_span);
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
if (debugDrawPhysics) {
// for (int i = 0; i < number_of_gameobjects(); i++)
// phys2d_dbgdrawcircle(objects[i]->circle);
}
2022-06-22 09:34:43 -05:00
2022-08-15 16:38:21 -05:00
/*
2022-08-14 14:19:36 -05:00
if (nk_menu_begin_label(ctx, "Windows", NK_TEXT_LEFT, nk_vec2(100, 200))) {
2022-08-14 18:10:29 -05:00
nk_layout_row_dynamic(ctx, 25, 1);
2021-11-30 21:29:18 -06:00
2022-08-15 16:38:21 -05:00
nk_checkbox_label(ctx, "Resources", &editor.assets.show);
nk_checkbox_label(ctx, "Hierarchy", &editor.hierarchy.show);
nk_checkbox_label(ctx, "Lighting F5", &editor.lighting.show);
nk_checkbox_label(ctx, "Game Settings F6", &editor.gamesettings.show);
nk_checkbox_label(ctx, "View F7", &editor.viewmode.show);
nk_checkbox_label(ctx, "Debug F8", &editor.debug.show);
nk_checkbox_label(ctx, "Export F9", &editor.export.show);
nk_checkbox_label(ctx, "Level F10", &editor.level.show);
nk_checkbox_label(ctx, "REPL", &editor.repl.show);
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
nk_menu_end(ctx);
2021-11-30 21:29:18 -06:00
}
2022-08-15 16:38:21 -05:00
*/
NK_MENU_START(level)
2022-08-28 22:34:33 -05:00
nuke_nel(1);
nuke_labelf("Current level: %s", current_level[0] == '\0' ? "No level loaded." : current_level);
2022-08-28 22:34:33 -05:00
nuke_nel(3);
2022-12-23 13:48:29 -06:00
if (nuke_btn("New")) {
2022-08-14 14:19:36 -05:00
new_level();
current_level[0] = '\0';
}
2021-11-30 21:29:18 -06:00
2022-12-23 13:48:29 -06:00
if (nuke_btn("Save")) {
2022-11-20 14:37:17 -06:00
if (strlen(current_level) == 0) {
YughWarn("Can't save level that has no name.");
} else {
save_level(current_level);
get_levels();
}
2022-08-14 14:19:36 -05:00
}
2021-11-30 21:29:18 -06:00
2022-12-23 13:48:29 -06:00
if (nuke_btn("Save as")) {
2022-11-20 14:37:17 -06:00
if (strlen(current_level) == 0) {
YughWarn("Can't save level that has no name.");
} else {
strcpy(current_level, levelname);
strncat(current_level, EXT_LEVEL, 10);
2022-11-20 14:37:17 -06:00
save_level(current_level);
levelname[0] = '\0';
get_levels();
}
2022-08-14 14:19:36 -05:00
}
2022-08-28 22:34:33 -05:00
nuke_nel(1);
2022-08-15 16:38:21 -05:00
nk_edit_string_zero_terminated(ctx, NK_EDIT_SIMPLE, levelname, MAXNAME - 1, nk_filter_default);
2022-06-22 09:34:43 -05:00
2022-08-28 22:34:33 -05:00
2022-08-15 16:38:21 -05:00
vec_walk(levels, editor_level_btn);
NK_MENU_END()
2022-06-22 09:34:43 -05:00
2022-08-25 15:48:15 -05:00
NK_MENU_START(export)
nuke_nel(2);
if (nuke_btn("Bake")) {
2021-11-30 21:29:18 -06:00
}
if (nuke_btn("Build")) {
2021-11-30 21:29:18 -06:00
}
2022-08-25 15:48:15 -05:00
NK_MENU_END()
2022-08-14 14:19:36 -05:00
2022-08-15 16:38:21 -05:00
NK_MENU_START(gamesettings)
2022-08-14 18:10:29 -05:00
nk_layout_row_dynamic(ctx,25,1);
2022-08-14 14:19:36 -05:00
// nk_edit_string_zero_terminated(ctx, NK_EDIT_SIMPLE, cur_project->name,
// 126, nk_filter_default);
2022-12-23 13:48:29 -06:00
if (nuke_push_tree_id("Physics", 0)) {
nuke_prop_float("2d Gravity", -5000.f, &phys2d_gravity, 0.f, 1.f, 0.1f);
2023-01-10 17:23:11 -06:00
//phys2d_apply();
2022-08-14 14:19:36 -05:00
nk_tree_pop(ctx);
}
2021-11-30 21:29:18 -06:00
2022-12-23 13:48:29 -06:00
if (nuke_push_tree_id("Quality", 0)) {
2022-08-14 14:19:36 -05:00
nk_tree_pop(ctx);
2021-11-30 21:29:18 -06:00
}
2022-08-14 14:19:36 -05:00
2022-08-15 16:38:21 -05:00
NK_MENU_END()
NK_MENU_START(stats)
nuke_labelf("FPS: %2.4f", 1.f / deltaT);
nuke_labelf("Triangles rendered: %llu", triCount);
2022-08-15 16:38:21 -05:00
NK_MENU_END()
2021-11-30 21:29:18 -06:00
2022-08-15 16:38:21 -05:00
NK_MENU_START(repl)
2022-06-22 09:34:43 -05:00
2022-12-19 12:16:51 -06:00
nk_layout_row_dynamic(ctx, 300, 1);
nk_edit_string_zero_terminated(ctx, NK_EDIT_MULTILINE|NK_EDIT_READ_ONLY|NK_EDIT_GOTO_END_ON_ACTIVATE, lastlog, ERROR_BUFFER, NULL);
2022-12-19 09:12:34 -06:00
static char buffer[512] = {'\0'};
nk_layout_row_dynamic(ctx, 25, 2);
2022-12-19 12:16:51 -06:00
nk_flags active = nk_edit_string_zero_terminated(ctx, NK_EDIT_BOX | NK_EDIT_SIG_ENTER|NK_EDIT_AUTO_SELECT, buffer, 512-1, nk_filter_ascii);
2022-12-19 09:12:34 -06:00
if (active & NK_EDIT_COMMITED || nuke_btn("Submit")) {
char bigbuf[1024];
snprintf(bigbuf, 1024, "(loginfo %s)", buffer);
script_run(bigbuf);
2022-08-14 14:19:36 -05:00
buffer[0] = '\0';
2021-11-30 21:29:18 -06:00
}
2022-08-15 16:38:21 -05:00
NK_MENU_END()
2022-08-14 14:19:36 -05:00
2022-08-15 16:38:21 -05:00
NK_MENU_START(hierarchy)
nuke_nel(1);
2021-11-30 21:29:18 -06:00
if (nuke_btn("New Object")) {
2022-08-14 14:19:36 -05:00
MakeGameobject();
2022-06-22 09:34:43 -05:00
}
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
obj_gui_hierarchy(selectedobject);
2021-11-30 21:29:18 -06:00
2022-08-15 16:38:21 -05:00
NK_MENU_END()
2021-11-30 21:29:18 -06:00
2022-08-18 08:50:03 -05:00
NK_FORCE(simulate)
nuke_nel(2);
2022-08-14 14:19:36 -05:00
if (physOn) {
if (nuke_btn("Pause"))
2022-08-14 14:19:36 -05:00
game_pause();
2021-11-30 21:29:18 -06:00
if (nuke_btn("Stop"))
2022-08-14 14:19:36 -05:00
game_stop();
} else {
if (nuke_btn("Play"))
2022-08-14 14:19:36 -05:00
game_start();
}
2021-11-30 21:29:18 -06:00
2022-08-18 08:50:03 -05:00
NK_FORCE_END()
2021-11-30 21:29:18 -06:00
2022-08-18 08:50:03 -05:00
NK_FORCE(prefab)
2022-08-28 22:34:33 -05:00
nuke_nel(1);
2022-08-14 18:10:29 -05:00
2022-08-15 16:38:21 -05:00
vec_walk(prefabs, editor_prefab_btn);
NK_FORCE_END()
2022-08-14 14:19:36 -05:00
2022-08-15 16:38:21 -05:00
NK_MENU_START(assets)
2022-08-28 22:34:33 -05:00
nuke_nel(1);
2022-08-19 11:25:08 -05:00
editor.asset_srch = nk_edit_string_zero_terminated(ctx, NK_EDIT_SIMPLE, asset_search_buffer, 100, nk_filter_ascii);
2022-08-14 14:19:36 -05:00
2022-12-23 13:48:29 -06:00
if (nuke_btn("Reload all files"))
2022-08-14 14:19:36 -05:00
get_all_files();
2021-11-30 21:29:18 -06:00
2022-08-19 11:25:08 -05:00
2022-08-14 14:19:36 -05:00
for (int i = 0; i < shlen(assets); i++) {
if (!assets[i].value->searched)
continue;
2021-11-30 21:29:18 -06:00
2022-12-23 13:48:29 -06:00
if (nuke_btn(assets[i].key))
2022-08-25 15:48:15 -05:00
editor_selectasset_str(assets[i].key);
2022-08-14 14:19:36 -05:00
}
2022-06-21 12:48:19 -05:00
2022-08-15 16:38:21 -05:00
NK_MENU_END()
2022-06-22 09:34:43 -05:00
2022-08-14 14:19:36 -05:00
if (selected_asset)
editor_asset_gui(selected_asset);
2022-06-22 09:34:43 -05:00
2022-08-15 16:38:21 -05:00
NK_MENU_START(debug)
nuke_nel(1);
if (nk_tree_push(ctx, NK_TREE_NODE, "Debug Draws", NK_MINIMIZED)) {
nuke_checkbox("Gizmos", &renderGizmos);
nuke_checkbox("Grid", &showGrid);
nuke_checkbox("Physics", &debugDrawPhysics);
nk_tree_pop(ctx);
}
2022-06-21 12:48:19 -05:00
if (nuke_btn("Reload Shaders")) {
2022-08-14 14:19:36 -05:00
shader_compile_all();
2021-11-30 21:29:18 -06:00
}
nuke_property_int("Grid 1 Span", 1, &grid1_span, 500, 1);
nuke_checkbox("Draw", &grid1_draw);
2021-11-30 21:29:18 -06:00
nuke_property_int("Grid 2 Span", 10, &grid2_span, 1000, 1);
nuke_checkbox("Draw", &grid2_draw);
2021-11-30 21:29:18 -06:00
nuke_property_float("Grid Opacity", 0.f, &gridOpacity, 1.f, 0.01f, 0.01f);
nuke_property_float("Small unit", 0.5f, &smallGridUnit, 5.f, 0.1f, 0.1f);
nuke_property_float("Big unit", 10.f, &bigGridUnit, 50.f, 1.f, 0.1f);
nuke_property_float("Small thickness", 1.f, &gridSmallThickness, 10.f, 0.1f, 0.1f);
nuke_property_float("Big thickness", 1.f, &gridBigThickness, 10.f, 0.1f, 0.1f);
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
static struct nk_colorf smgrd;
static struct nk_colorf lgrd;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
nk_color_pick(ctx, &smgrd, NK_RGBA);
nk_color_pick(ctx, &lgrd, NK_RGBA);
2021-11-30 21:29:18 -06:00
NK_MENU_END()
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
startobjectgui:
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
if (selectedobject) {
2023-01-03 17:13:31 -06:00
cpVect pos = cpBodyGetPosition(selectedobject->body);
draw_point(pos.x, pos.y, 5);
2021-11-30 21:29:18 -06:00
2022-08-15 16:38:21 -05:00
NK_FORCE(gameobject)
2021-11-30 21:29:18 -06:00
nuke_nel(3);
2021-11-30 21:29:18 -06:00
if (nuke_btn("Save"))
2022-08-14 14:19:36 -05:00
gameobject_saveprefab(selectedobject);
2021-11-30 21:29:18 -06:00
if (nuke_btn("Del")) {
2022-08-14 14:19:36 -05:00
gameobject_delete(selected_index);
pickGameObject(-1);
nk_end(ctx);
goto startobjectgui;
}
2021-11-30 21:29:18 -06:00
2022-12-23 13:48:29 -06:00
if (selectedobject->editor.prefabSync && nuke_btn("Revert"))
2022-08-14 14:19:36 -05:00
gameobject_revertprefab(selectedobject);
2021-11-30 21:29:18 -06:00
nuke_label("Name");
2022-08-15 16:38:21 -05:00
nk_edit_string_zero_terminated(ctx, NK_EDIT_SIMPLE, selectedobject->editor.mname, 50, nk_filter_ascii);
2021-11-30 21:29:18 -06:00
nuke_label("Prefab");
2022-08-15 16:38:21 -05:00
nk_edit_string_zero_terminated(ctx, NK_EDIT_SIMPLE, selectedobject->editor.prefabName, 50, nk_filter_ascii);
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
object_gui(selectedobject);
2021-11-30 21:29:18 -06:00
2022-08-25 15:48:15 -05:00
// nuke_label("Components");
nuke_nel(3);
2023-01-03 17:13:31 -06:00
for (int i = 0; i < gameobject_ncomponents(selectedobject); i++) {
if (nuke_btn(selectedobject->components[i].ref->name)) {
gameobject_addcomponent(selectedobject, &selectedobject->components[i]);
2022-08-25 15:48:15 -05:00
}
}
2022-08-15 16:38:21 -05:00
NK_FORCE_END()
2021-11-30 21:29:18 -06:00
2022-08-25 15:48:15 -05:00
/*
2022-08-15 16:38:21 -05:00
NK_FORCE(components)
nuke_nel(1);
2022-08-14 14:19:36 -05:00
for (int i = 0; i < ncomponent; i++) {
if (nuke_btn(components[i].name)) {
2022-08-14 14:19:36 -05:00
gameobject_addcomponent(selectedobject, &components[i]);
}
2021-11-30 21:29:18 -06:00
}
2022-08-15 16:38:21 -05:00
NK_FORCE_END()
2022-08-25 15:48:15 -05:00
*/
2022-08-15 16:38:21 -05:00
}
2021-11-30 21:29:18 -06:00
}
2022-08-14 14:19:36 -05:00
void editor_render() { editor_project_gui(); }
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
void pickGameObject(int pickID) {
2022-08-26 09:19:17 -05:00
if (pickID >= 0 && pickID < arrlen(gameobjects)) {
2022-08-14 14:19:36 -05:00
selected_index = pickID;
2022-08-26 09:19:17 -05:00
selectedobject = &gameobjects[pickID];
2022-08-14 14:19:36 -05:00
} else {
selected_index = -1;
selectedobject = NULL;
}
2021-11-30 21:29:18 -06:00
}
2022-08-14 14:19:36 -05:00
int is_allowed_extension(const char *ext) {
2022-08-18 08:50:03 -05:00
for (size_t i = 0; i < sizeof(allowed_extensions) / sizeof(allowed_extensions[0]); i++) {
2022-08-14 14:19:36 -05:00
if (!strcmp(ext + 1, allowed_extensions[i]))
return true;
}
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
return false;
2021-11-30 21:29:18 -06:00
}
2022-08-14 14:19:36 -05:00
void editor_level_btn(char *level) {
if (nuke_btn(level)) {
2022-08-14 14:19:36 -05:00
load_level(level);
strcpy(current_level, level);
}
2021-11-30 21:29:18 -06:00
}
2022-08-25 15:48:15 -05:00
struct fileasset *asset_from_path(const char *p)
{
return shget(assets, p);
}
2022-08-24 12:24:21 -05:00
2022-08-25 15:48:15 -05:00
void editor_selectasset_str(const char *path) {
struct fileasset *asset = asset_from_path(path);
2022-08-24 12:24:21 -05:00
2021-11-30 21:29:18 -06:00
2022-08-25 15:48:15 -05:00
FILE *fasset;
switch (asset->type) {
case ASSET_TYPE_IMAGE:
if (asset->data == NULL) {
asset->data = texture_loadfromfile(path);
load_asset(asset);
}
2023-01-02 07:55:26 -06:00
//else
//tex_pull(asset->data);
2022-08-25 15:48:15 -05:00
2023-01-02 07:55:26 -06:00
struct Texture *tex = asset->data;
tex_gui_anim.anim = &tex->anim;
2022-08-25 15:48:15 -05:00
tex_anim_set(&tex_gui_anim);
anim_setframe(&tex_gui_anim, 0);
2023-01-02 07:55:26 -06:00
float tex_scale = (float) ASSET_WIN_SIZE / (float)tex_gui_anim.anim->tex->width;
2022-08-25 15:48:15 -05:00
if (tex_scale >= 10.f) {
tex_scale = 10.f;
}
break;
case ASSET_TYPE_TEXT:
fasset = fopen(asset->filename, "rb");
fseek(fasset, 0, SEEK_END);
long length = ftell(fasset);
fseek(fasset, 0, SEEK_SET);
asset->data = malloc(ASSET_TEXT_BUF);
fread(asset->data, 1, length, fasset);
fclose(fasset);
break;
case ASSET_TYPE_SOUND:
break;
default:
break;
}
load_asset(asset);
if (selected_asset != NULL)
save_asset(selected_asset);
selected_asset = asset;
2021-11-30 21:29:18 -06:00
}
2022-08-14 14:19:36 -05:00
void editor_asset_tex_gui(struct Texture *tex) {
2022-08-19 11:25:08 -05:00
nuke_labelf("%dx%d", tex->width, tex->height);
nuke_prop_float("Zoom", 0.01f, &tex_scale, 10.f, 0.1f, 0.01f);
int old_sprite = tex->opts.sprite;
2021-11-30 21:29:18 -06:00
2022-08-19 11:25:08 -05:00
nuke_checkbox("Sprite", &tex->opts.sprite);
2021-11-30 21:29:18 -06:00
2023-01-02 07:55:26 -06:00
//if (old_sprite != tex->opts.sprite)
//tex_gpu_load(tex);
2021-11-30 21:29:18 -06:00
2022-08-25 15:48:15 -05:00
nuke_nel(4);
2022-08-19 11:25:08 -05:00
nuke_radio_btn("Raw", &tex_view, 0);
nuke_radio_btn("View 1", &tex_view, 1);
nuke_radio_btn("View 2", &tex_view, 2);
2021-11-30 21:29:18 -06:00
2022-08-19 11:25:08 -05:00
nuke_checkbox("Animation", &tex->opts.animation);
2021-11-30 21:29:18 -06:00
2022-08-25 15:48:15 -05:00
2022-08-19 11:25:08 -05:00
if (tex->opts.animation) {
2023-01-02 07:55:26 -06:00
/*
2022-08-19 11:25:08 -05:00
int old_frames = tex->anim.frames;
int old_ms = tex->anim.ms;
2021-11-30 21:29:18 -06:00
2022-08-25 15:48:15 -05:00
nuke_nel(2);
2022-08-19 11:25:08 -05:00
nuke_property_int("Frames", 1, &tex->anim.frames, 20, 1);
nuke_property_int("FPS", 1, &tex->anim.ms, 24, 1);
2021-11-30 21:29:18 -06:00
2022-08-19 11:25:08 -05:00
if (tex_gui_anim.playing) {
if (nuke_btn("Pause"))
anim_pause(&tex_gui_anim);
if (tex_gui_anim.playing && nuke_btn("Stop"))
anim_stop(&tex_gui_anim);
} else {
2022-08-25 15:48:15 -05:00
nuke_nel(3);
2022-08-19 11:25:08 -05:00
if (nuke_btn("Play"))
anim_play(&tex_gui_anim);
2021-11-30 21:29:18 -06:00
2022-08-19 11:25:08 -05:00
if (nuke_btn("Bkwd"))
anim_bkwd(&tex_gui_anim);
2022-06-22 09:34:43 -05:00
2022-08-19 11:25:08 -05:00
if (nuke_btn("Fwd"))
anim_fwd(&tex_gui_anim);
}
2021-11-30 21:29:18 -06:00
2022-08-25 15:48:15 -05:00
nuke_nel(1);
2022-08-19 11:25:08 -05:00
nuke_labelf("Frame %d/%d", tex_gui_anim.frame+1, tex_gui_anim.tex->anim.frames);
2021-11-30 21:29:18 -06:00
2022-08-19 11:25:08 -05:00
if (old_frames != tex->anim.frames || old_ms != tex->anim.ms)
tex_anim_set(&tex_gui_anim);
2022-12-30 13:31:06 -06:00
nk_layout_row_static(ctx, tex->height*tex_scale*(tex_gui_anim.st.t1-tex_gui_anim.st.t0), tex->width*tex_scale*(tex_gui_anim.st.s1 - tex_gui_anim.st.s0), 1);
2022-08-22 08:55:54 -05:00
struct nk_rect r;
2022-12-30 13:31:06 -06:00
r.x = tex_gui_anim.st.s0*tex->width;
r.y = tex_gui_anim.st.t0*tex->height;
r.w = st_s_w(tex_gui_anim.st)*tex->width;
r.h = st_s_h(tex_gui_anim.st)*tex->height;
2022-08-22 08:55:54 -05:00
nk_image(ctx, nk_subimage_id(tex->id, tex->width, tex->height, r));
2023-01-02 07:55:26 -06:00
*/
2022-08-22 08:55:54 -05:00
} else {
2022-08-19 11:25:08 -05:00
nk_layout_row_static(ctx, tex->height*tex_scale, tex->width*tex_scale, 1);
nk_image(ctx, nk_image_id(tex->id));
2022-08-22 08:55:54 -05:00
}
2022-08-19 11:25:08 -05:00
}
void text_ed_cb(GLFWwindow *win, unsigned int codepoint)
{
YughInfo("Pressed button %d", codepoint);
2022-08-19 11:25:08 -05:00
if (editor.text_ed & NK_EDIT_ACTIVE) {
if (codepoint == '\n') {
YughInfo("Hit newline.");
2022-08-19 11:25:08 -05:00
}
}
2021-11-30 21:29:18 -06:00
}
2022-08-14 14:19:36 -05:00
void editor_asset_text_gui(char *text) {
2022-08-19 11:25:08 -05:00
nk_layout_row_dynamic(ctx, 600, 1);
editor.text_ed = nk_edit_string_zero_terminated(ctx, NK_EDIT_BOX, text, ASSET_TEXT_BUF, nk_filter_ascii);
nuke_nel(4);
if (nuke_btn("Save")) {
2022-08-19 11:25:08 -05:00
FILE *f = fopen(selected_asset->filename, "wd");
size_t len = strlen(text);
fwrite(text, len, 1, f);
fclose(f);
}
/* TODO: Nicer formatting for text input. Auto indent. */
2021-11-30 21:29:18 -06:00
}
2022-08-25 15:48:15 -05:00
void editor_asset_sound_gui(struct wav *wav)
{
}
2022-08-14 14:19:36 -05:00
void editor_asset_gui(struct fileasset *asset) {
2021-11-30 21:29:18 -06:00
2022-08-19 11:25:08 -05:00
NK_FORCE(asset)
2021-11-30 21:29:18 -06:00
2022-08-18 08:50:03 -05:00
nuke_nel(2);
2022-08-14 14:19:36 -05:00
nk_labelf(ctx, NK_TEXT_LEFT, "%s", selected_asset->filename);
2021-11-30 21:29:18 -06:00
2022-12-23 13:48:29 -06:00
if (nuke_btn("Close"))
2022-08-14 14:19:36 -05:00
selected_asset = NULL;
2021-11-30 21:29:18 -06:00
2022-08-18 08:50:03 -05:00
nuke_nel(1);
2022-08-14 14:19:36 -05:00
switch (asset->type) {
case ASSET_TYPE_NULL:
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case ASSET_TYPE_IMAGE:
2022-08-18 08:50:03 -05:00
editor_asset_tex_gui(asset->data);
2022-08-14 14:19:36 -05:00
break;
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
case ASSET_TYPE_TEXT:
2022-08-18 08:50:03 -05:00
editor_asset_text_gui(asset->data);
2022-08-14 14:19:36 -05:00
break;
2022-08-25 15:48:15 -05:00
case ASSET_TYPE_SOUND:
editor_asset_sound_gui(asset->data);
break;
2022-08-14 14:19:36 -05:00
}
2021-11-30 21:29:18 -06:00
2022-08-19 11:25:08 -05:00
NK_FORCE_END()
2021-11-30 21:29:18 -06:00
}
2022-08-14 14:19:36 -05:00
void editor_makenewobject() {}
2021-11-30 21:29:18 -06:00
2022-11-19 17:13:57 -06:00
int obj_gui_hierarchy(struct gameobject *selected) {
2021-11-30 21:29:18 -06:00
2022-08-26 09:19:17 -05:00
for (int i = 0; i < arrlen(gameobjects); i++) {
2022-11-19 17:13:57 -06:00
struct gameobject *go = &gameobjects[i];
2022-08-12 14:03:56 -05:00
2022-08-14 14:19:36 -05:00
if (nk_select_label(ctx, go->editor.mname, NK_TEXT_LEFT, go == selected)) {
if (go != selected)
pickGameObject(i);
2021-11-30 21:29:18 -06:00
}
2022-08-14 14:19:36 -05:00
}
2021-11-30 21:29:18 -06:00
2022-08-14 14:19:36 -05:00
return 0;
2021-11-30 21:29:18 -06:00
}
2022-08-14 14:19:36 -05:00
void get_levels() { fill_extensions(levels, DATA_PATH, EXT_LEVEL); }
2022-06-22 09:34:43 -05:00
2022-08-14 14:19:36 -05:00
void editor_prefab_btn(char *prefab) {
2022-12-23 13:48:29 -06:00
if (nuke_btn(prefab)) {
YughInfo("Making prefab '%s'.", prefab);
2022-08-14 14:19:36 -05:00
gameobject_makefromprefab(prefab);
}
2022-06-22 09:34:43 -05:00
}
2022-08-14 14:19:36 -05:00
void game_start() { physOn = 1; }
void game_resume() { physOn = 1; }
void game_stop() { physOn = 0; }
void game_pause() { physOn = 0; }
void sprite_gui(struct sprite *sprite) {
2022-08-17 00:01:51 -05:00
nuke_nel(2);
//nk_labelf(ctx, NK_TEXT_LEFT, "Path %s", tex_get_path(sprite->tex));
2022-08-17 00:01:51 -05:00
2022-08-14 14:19:36 -05:00
2022-12-23 13:48:29 -06:00
if (nuke_btn("Load texture") && selected_asset != NULL) {
2022-08-14 14:19:36 -05:00
sprite_loadtex(sprite, selected_asset->filename);
}
2022-08-14 14:19:36 -05:00
if (sprite->tex != NULL) {
//nk_labelf(ctx, NK_TEXT_LEFT, "%s", tex_get_path(sprite->tex));
nk_labelf(ctx, NK_TEXT_LEFT, "%dx%d", sprite->tex->width, sprite->tex->height);
2022-08-24 12:24:21 -05:00
nk_layout_row_static(ctx, sprite->tex->height, sprite->tex->width, 1);
if (nk_button_image(ctx, nk_image_id(sprite->tex->id)))
editor_selectasset_str(tex_get_path(sprite->tex));
2022-08-14 14:19:36 -05:00
}
2022-12-23 13:48:29 -06:00
nuke_property_float2("Sprite Position", -1.f, sprite->pos, 0.f, 0.01f, 0.01f);
2022-08-14 14:19:36 -05:00
2022-08-17 00:01:51 -05:00
nuke_nel(3);
2022-12-23 13:48:29 -06:00
if (nuke_btn("C")) {
2022-08-14 14:19:36 -05:00
sprite->pos[0] = -0.5f;
sprite->pos[1] = -0.5f;
}
2022-12-23 13:48:29 -06:00
if (nuke_btn("U")) {
2022-08-14 14:19:36 -05:00
sprite->pos[0] = -0.5f;
sprite->pos[1] = -1.f;
}
2022-12-23 13:48:29 -06:00
if (nuke_btn("D")) {
2022-08-14 14:19:36 -05:00
sprite->pos[0] = -0.5f;
sprite->pos[1] = 0.f;
}
2022-08-24 12:24:21 -05:00
}
2023-01-12 17:41:54 -06:00
#endif