diff --git a/ogl_editor/.gitignore b/ogl_editor/.gitignore index b02033c..25a8437 100644 --- a/ogl_editor/.gitignore +++ b/ogl_editor/.gitignore @@ -1,3 +1,7 @@ tags tundra-output +t2-output .tundra* +*.swp +*.swo +.rocket-recents.txt diff --git a/ogl_editor/emgui/src/Emgui.c b/ogl_editor/emgui/src/Emgui.c index c21c947..2fbb6f0 100644 --- a/ogl_editor/emgui/src/Emgui.c +++ b/ogl_editor/emgui/src/Emgui.c @@ -1,8 +1,8 @@ -#include "emgui.h" -#include "emgui_internal.h" +#include "Emgui.h" +#include "Emgui_internal.h" #include "memory/LinearAllocator.h" #include "GFXBackend.h" -#include "MicroKnightFont.h" +#include "MicroknightFont.h" #include "External/stb_truetype.h" #include "External/stb_image.h" #include diff --git a/ogl_editor/emgui/src/Emgui_internal.h b/ogl_editor/emgui/src/Emgui_internal.h index 082f94e..a7cd8c7 100644 --- a/ogl_editor/emgui/src/Emgui_internal.h +++ b/ogl_editor/emgui/src/Emgui_internal.h @@ -1,8 +1,8 @@ #ifndef EMGUI_INTERNAL_H_ #define EMGUI_INTERNAL_H_ -#include -#include "emgui_internal.h" +#include +#include "Emgui_internal.h" #include "External/stb_truetype.h" /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/ogl_editor/emgui/src/GFXBackends/OpenGLBackend.c b/ogl_editor/emgui/src/GFXBackends/OpenGLBackend.c index ed47b56..2a01365 100644 --- a/ogl_editor/emgui/src/GFXBackends/OpenGLBackend.c +++ b/ogl_editor/emgui/src/GFXBackends/OpenGLBackend.c @@ -1,8 +1,10 @@ #include "../GFXBackend.h" -#include "../emgui_internal.h" +#include "../Emgui_internal.h" #if defined(__APPLE__) #include #include +#elif defined(EMGUI_UNIX) +#include #else #define WIN32_LEAN_AND_MEAN #include diff --git a/ogl_editor/linux-build.sh b/ogl_editor/linux-build.sh new file mode 100755 index 0000000..9d1f51f --- /dev/null +++ b/ogl_editor/linux-build.sh @@ -0,0 +1 @@ +tundra linux-gcc-release diff --git a/ogl_editor/readme.txt b/ogl_editor/readme.txt index 120a12b..2097b76 100644 --- a/ogl_editor/readme.txt +++ b/ogl_editor/readme.txt @@ -22,6 +22,8 @@ Daniel Collin can be contacted at daniel aat collin dot com Latest version of this program should be availible at https://github.com/emoon/rocket +The SDL-based linux support is written by Konsta 'sooda' Hölttä at https://github.com/sooda/rocket + Motivation ---------- @@ -37,7 +39,7 @@ Features: * Folding support for both groups and tracks. Something I found annoying in the old editor was that you had to scroll around quite a bit to get to channel you wanted. Now with folding you use the screen space better. * Faster navigation: Can jump between key values, jump in step of 8 and also with bookmarks. * Other features such as using more of the keyboard for biasing of values (see key layout below) -* Trackpad support (OS X only, mouse wheel on Windows) to scroll around (can only be used with biasing) +* Trackpad support (OS X only, mouse wheel elsewhere) to scroll around (can only be used with biasing) * Cross platform. Read more about the code in the next section. * Navigation while play-backing. It's now possible to jump forward/backward when playing the demo (demo "scratching") * Fast way to insert a interpolated value by just pressing return on an empty row. @@ -47,14 +49,14 @@ Source Code Now uses a UI system called 'Emgui' which is an intermediate mode UI that was developed at the same time as the editor. Emui uses OpenGL as the rendering API for the UI making it possible to port to many platforms but using a diffrent backend is also very possible. -The code is written in C and has currently been compiled with clang on Mac and Visual Studio 2012 (Express) on Windows. -I have tried to keep the code as platform independent as possible and platform files are (mostly) in the src/macosx and src/windows directories. +The code is written in C and has currently been compiled with clang on Mac, Visual Studio 2012 (Express) on Windows, and gcc on Linux. +I have tried to keep the code as platform independent as possible and platform files are (mostly) in the src/macosx, src/windows and src/linux directories. Some parts of the code could need some cleanup but should hopefully be quite easy to follow and understand. Building the code ----------------- -Both Mac and Windows version uses the Tundra build system (https://github.com/deplinenoise/tundra) so in order to build the code you need a tundra executable for your OS +All Mac, Windows and Linux versions use the Tundra build system (https://github.com/deplinenoise/tundra) so in order to build the code you need a tundra executable for your OS I have made two of the available here for your convenience if you don't want to build the code yourself. Mac: https://dl.dropbox.com/u/5205843/tundra-mac.zip @@ -75,6 +77,11 @@ In that case run the "vsvars32.bat" included with Visual Studio from a command p If you want to build from command line that works just as fine as well (just set vsvars32 (as seen above) and run "tundra win32-msvc-debug" for the debug build. +Linux +----- + +Almost like in Mac, use the supplied linux-build.sh file. No project files are generated - Tundra builds the editor straight away. + Tips & tricks ------------- @@ -138,7 +145,7 @@ Cmd+E - Remote export --------------------------------------------------------------------------------- -Windows: +Windows and Linux: Editing: 0-9 - Edit value diff --git a/ogl_editor/src/Dialog.h b/ogl_editor/src/Dialog.h index b1ed861..52fa956 100644 --- a/ogl_editor/src/Dialog.h +++ b/ogl_editor/src/Dialog.h @@ -1,6 +1,6 @@ #pragma once -#include +#include int Dialog_open(text_t* dest); int Dialog_save(text_t* dest); diff --git a/ogl_editor/src/Editor.c b/ogl_editor/src/Editor.c index bcc295b..3893c29 100644 --- a/ogl_editor/src/Editor.c +++ b/ogl_editor/src/Editor.c @@ -5,7 +5,7 @@ #include #include "Menu.h" #include "Dialog.h" -#include "LoadSave.h" +#include "loadsave.h" #include "TrackView.h" #include "rlog.h" #include "minmax.h" @@ -17,7 +17,7 @@ #include "../../sync/sync.h" #include "../../sync/base.h" #include "../../sync/data.h" -#include +#include static void updateNeedsSaving(); @@ -772,6 +772,9 @@ static int processCommands() // find track serverIndex = TrackData_createGetTrack(&s_editorData.trackData, trackName); + // if it's the first one we get, select it too + if (serverIndex == 0) + setActiveTrack(0); // setup remap and send the keyframes to the demo RemoteConnection_mapTrackName(trackName); diff --git a/ogl_editor/src/Editor.h b/ogl_editor/src/Editor.h index c6f5363..dc79e07 100644 --- a/ogl_editor/src/Editor.h +++ b/ogl_editor/src/Editor.h @@ -1,6 +1,6 @@ #pragma once -#include +#include /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/ogl_editor/src/Menu.c b/ogl_editor/src/Menu.c index 7851f78..f626f6d 100644 --- a/ogl_editor/src/Menu.c +++ b/ogl_editor/src/Menu.c @@ -1,5 +1,5 @@ #include "Menu.h" -#include +#include /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/ogl_editor/src/MinecraftiaFont.c b/ogl_editor/src/MinecraftiaFont.c index 6a254f7..8bb3c5f 100644 --- a/ogl_editor/src/MinecraftiaFont.c +++ b/ogl_editor/src/MinecraftiaFont.c @@ -1,4 +1,4 @@ -#include +#include #include "MinecraftiaFont.h" int g_minecraftiaFontSize = 713; diff --git a/ogl_editor/src/MinecraftiaFont.h b/ogl_editor/src/MinecraftiaFont.h index d591859..16b7b78 100644 --- a/ogl_editor/src/MinecraftiaFont.h +++ b/ogl_editor/src/MinecraftiaFont.h @@ -1,6 +1,6 @@ #pragma once -#include +#include extern EmguiFontLayout g_minecraftiaFontLayout[]; extern char g_minecraftiaFont[]; diff --git a/ogl_editor/src/RemoteConnection.h b/ogl_editor/src/RemoteConnection.h index 1dcb30f..8b32d0c 100644 --- a/ogl_editor/src/RemoteConnection.h +++ b/ogl_editor/src/RemoteConnection.h @@ -1,6 +1,6 @@ #pragma once -#include +#include struct track_key; struct sync_track; diff --git a/ogl_editor/src/TrackData.h b/ogl_editor/src/TrackData.h index bd2c4da..5d085f8 100644 --- a/ogl_editor/src/TrackData.h +++ b/ogl_editor/src/TrackData.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include "../../sync/data.h" /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/ogl_editor/src/TrackView.c b/ogl_editor/src/TrackView.c index 1668861..526c47a 100644 --- a/ogl_editor/src/TrackView.c +++ b/ogl_editor/src/TrackView.c @@ -1,5 +1,5 @@ -#include "trackview.h" -#include +#include "TrackView.h" +#include #include #include #include @@ -14,7 +14,7 @@ #if defined(__APPLE__) #include #include -#else +#elif !defined(EMGUI_UNIX) #define WIN32_LEAN_AND_MEAN #include #include diff --git a/ogl_editor/src/TrackView.h b/ogl_editor/src/TrackView.h index 51b85bc..57f3544 100644 --- a/ogl_editor/src/TrackView.h +++ b/ogl_editor/src/TrackView.h @@ -1,6 +1,6 @@ #pragma once -#include +#include /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/ogl_editor/src/Window.h b/ogl_editor/src/Window.h index 784e738..069c732 100644 --- a/ogl_editor/src/Window.h +++ b/ogl_editor/src/Window.h @@ -1,6 +1,6 @@ #pragma once -#include +#include /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/ogl_editor/src/linux/main.c b/ogl_editor/src/linux/main.c new file mode 100644 index 0000000..7efc239 --- /dev/null +++ b/ogl_editor/src/linux/main.c @@ -0,0 +1,362 @@ +#include "SDL.h" +#include +#include +#include "Editor.h" +#include "Menu.h" + +static SDL_Surface *screen; + +void swapBuffers() +{ + SDL_GL_SwapBuffers(); +} + +void Window_populateRecentList(text_t** files) +{ + int i; + for (i = 0; i < 4; i++) + if (files[i][0] != 0) + printf("recent %d: %s\n", i, files[i]); +} + +void Window_setTitle(const text_t *title) +{ + SDL_WM_SetCaption(title, NULL); +} + +int getFilename(text_t *path) +{ + fgets(path, 512, stdin); + if (path[0] == 0) + { + printf("Aborted\n"); + return 0; + } + else + { + if (path[0] != 0 && path[strlen(path) - 1] == '\n') + path[strlen(path) - 1] = 0; // cut newline + return 1; + } +} + +int Dialog_open(text_t *path) +{ + printf("Load from: "); + return getFilename(path); +} + +int Dialog_save(text_t *path) +{ + printf("Save to: "); + return getFilename(path); +} + +void Dialog_showColorPicker(unsigned int* color) +{ + printf("dialog_showColorPicker() not implemented\n"); +} + +int mapSdlEmKeycode(SDLKey key) +{ + switch (key) + { + case SDLK_LEFT: return EMGUI_KEY_ARROW_LEFT; + case SDLK_RIGHT: return EMGUI_KEY_ARROW_RIGHT; + case SDLK_UP: return EMGUI_KEY_ARROW_UP; + case SDLK_DOWN: return EMGUI_KEY_ARROW_DOWN; + case SDLK_RETURN: return EMGUI_KEY_ENTER; + case SDLK_ESCAPE: return EMGUI_KEY_ESC; + case SDLK_TAB: return EMGUI_KEY_TAB; + case SDLK_BACKSPACE: return EMGUI_KEY_BACKSPACE; + case SDLK_SPACE: return EMGUI_KEY_SPACE; + default: return key >= ' ' && key <= 127 ? key : 0; + } +} + +static int modifiers; + +int getModifiers() +{ + return modifiers; +} + +void updateModifier(int mask, int flag) +{ + modifiers = (modifiers & ~mask) | (flag ? mask : 0); +} + +int updateModifiers(SDLMod mod) +{ + updateModifier(EMGUI_KEY_SHIFT, !!(mod & (KMOD_LSHIFT | KMOD_RSHIFT))); + updateModifier(EMGUI_KEY_CTRL, !!(mod & (KMOD_LCTRL | KMOD_RCTRL))); + updateModifier(EMGUI_KEY_ALT, !!(mod & (KMOD_LALT | KMOD_RALT))); + return getModifiers(); +} + +int updateModifierPress(SDLKey key, int state) +{ + switch (key) + { + case SDLK_LSHIFT: updateModifier(EMGUI_KEY_SHIFT, state); return 0; + case SDLK_RSHIFT: updateModifier(EMGUI_KEY_SHIFT, state); return 0; + case SDLK_LCTRL: updateModifier(EMGUI_KEY_CTRL, state); return 0; + case SDLK_RCTRL: updateModifier(EMGUI_KEY_CTRL, state); return 0; + case SDLK_LALT: updateModifier(EMGUI_KEY_ALT, state); return 0; + case SDLK_RALT: updateModifier(EMGUI_KEY_ALT, state); return 0; + default: return 1; + } +} + +int checkMenu(int key, int mod, const MenuDescriptor *item) +{ + for (; item->name; item++) + { + if (key == item->key && mod == item->winMod) + { + printf("Menuevent %d %s\n", item->id, item->name); + if (key== EMGUI_KEY_TAB || + key== EMGUI_KEY_ENTER || + key== EDITOR_MENU_DELETE_KEY) + { + Emgui_sendKeyinput(key, getModifiers()); + } + Editor_menuEvent(item->id); + return 0; + } + } + return 1; +} + +int checkRecent(int key, int mod) +{ + if (mod == EMGUI_KEY_CTRL && key >= '1' && key <= '4') { + printf("Load recent %d\n", key - '1'); + Editor_menuEvent(EDITOR_MENU_RECENT_FILE_0 + key - '1'); + return 0; + } + return 1; +} + +int sendMenu(int key, int mod) +{ + if (!checkMenu(key, mod, g_fileMenu)) + return 0; + if (!checkMenu(key, mod, g_editMenu)) + return 0; + if (!checkMenu(key, mod, g_viewMenu)) + return 0; + if (!checkRecent(key, mod)) + return 0; + return 1; +} + +void sendKey(int key, int modifiers) +{ + Emgui_sendKeyinput(key, modifiers); + Editor_keyDown(key, -1, modifiers); + Editor_update(); +} + +// sdl keycodes used only internally, mapped to emgui items in the very beginning +void updateKey(SDL_keysym *sym) +{ + int keycode = mapSdlEmKeycode(sym->sym); + int modifiers = updateModifiers(sym->mod); + + if (!keycode) + { + if (updateModifierPress(sym->sym, 1)) + printf("bad key\n"); + } + else + { + if (sendMenu(keycode, modifiers)) + sendKey(keycode, modifiers); + } +} + +int handleKeyDown(SDL_KeyboardEvent *ev) +{ + updateKey(&ev->keysym); + return 0; +} + +void handleKeyUp(SDL_KeyboardEvent *ev) +{ + updateModifierPress(ev->keysym.sym, 0); +} + +void handleMouseMotion(SDL_MouseMotionEvent *ev) +{ + Emgui_setMouseLmb(!!(ev->state & SDL_BUTTON_LMASK)); + Emgui_setMousePos(ev->x, ev->y); + Editor_update(); +} + +void handleMouseButton(SDL_MouseButtonEvent *ev) +{ + switch (ev->button) + { + case SDL_BUTTON_LEFT: + Emgui_setMouseLmb(ev->state == SDL_PRESSED); + Editor_update(); + break; + case SDL_BUTTON_WHEELUP: + case SDL_BUTTON_WHEELDOWN: + if (ev->state == SDL_PRESSED) + { + float dir = ev->button == SDL_BUTTON_WHEELDOWN ? 1.0f : -1.0f; + Editor_scroll(0.0f, dir, getModifiers()); + Editor_update(); + } + break; + default: + break; + } +} + +void resize(int w, int h) +{ + screen = SDL_SetVideoMode(w, h, 32, + SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_RESIZABLE); + EMGFXBackend_updateViewPort(w, h); + Editor_setWindowSize(w, h); + Editor_update(); +} + +int handleEvent(SDL_Event *ev) +{ + switch (ev->type) + { + case SDL_QUIT: + return 1; + case SDL_KEYDOWN: + return handleKeyDown(&ev->key); + case SDL_KEYUP: + handleKeyUp(&ev->key); + break; + case SDL_MOUSEMOTION: + handleMouseMotion(&ev->motion); + break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + handleMouseButton(&ev->button); + break; + case SDL_ACTIVEEVENT: + case SDL_VIDEOEXPOSE: + Editor_update(); + break; + case SDL_VIDEORESIZE: + resize(ev->resize.w, ev->resize.h); + break; + default: + printf("Unknown SDL event %d\n", ev->type); + } + return 0; + +} + +int doEvents() +{ + SDL_Event ev; + int quit = 0; + + while (SDL_PollEvent(&ev)) // SDL_WaitEvent() + quit |= handleEvent(&ev); + + return quit; +} + +void run(SDL_Surface *screen) +{ + for (;;) + { + if (doEvents()) + break; + Editor_timedUpdate(); + SDL_Delay(16); + } +} + +// this just in working directory +#define RECENTS_FILE ".rocket-recents.txt" + +void saveRecents() +{ + int i; + text_t **recents = Editor_getRecentFiles(); + + FILE *fh = fopen(RECENTS_FILE, "w"); + if (!fh) + return; + + for (i = 0; i < 4; i++) + fprintf(fh, "%s\n", recents[i]); + + fclose(fh); +} + +void loadRecents() +{ + int i; + text_t **recents = Editor_getRecentFiles(); + + FILE *fh = fopen(RECENTS_FILE, "r"); + if (!fh) + return; + + printf("Recent files:\n"); + for (i = 0; i < 4; i++) { + fgets(recents[i], 2048, fh); // size looked up in Editor.c + + if (strlen(recents[i]) < 2 || + recents[i][strlen(recents[i]) - 1] != '\n') { + recents[i][0] = 0; + break; // eof or too long line + } + + recents[i][strlen(recents[i]) - 1] = 0; // strip newline + printf("%d: %s\n", i, recents[i]); + fprintf(fh, "%s\n", recents[i]); + } + + printf("total %d\n", i); + for (; i < 4; i++) // clear the rest if less than 4 recents + recents[i][0] = 0; + fclose(fh); +} + +int main(int argc, char *argv[]) +{ + if (SDL_Init(SDL_INIT_VIDEO) < 0) + { + fprintf(stderr, "SDL_Init(): %s\n", SDL_GetError()); + return 1; + } + + SDL_EnableKeyRepeat(200, 20); + screen = SDL_SetVideoMode(800, 600, 32, + SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_RESIZABLE); + + if (!screen) + { + fprintf(stderr, "SDL_SetVideoMode(): %s\n", SDL_GetError()); + return 1; + } + + loadRecents(); + + EMGFXBackend_create(); + Editor_create(); + EMGFXBackend_updateViewPort(800, 600); + Editor_setWindowSize(800, 600); + Editor_update(); + + run(screen); + + saveRecents(); + + SDL_Quit(); + return 0; +} diff --git a/ogl_editor/src/loadsave.c b/ogl_editor/src/loadsave.c index 91fc899..66c89d3 100644 --- a/ogl_editor/src/loadsave.c +++ b/ogl_editor/src/loadsave.c @@ -1,4 +1,4 @@ -#include "LoadSave.h" +#include "loadsave.h" #include "Dialog.h" #include "TrackData.h" #include "../external/mxml/mxml.h" @@ -6,7 +6,7 @@ #include "../../sync/data.h" #include #include -#include +#include /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -21,6 +21,7 @@ static void parseXml(mxml_node_t* rootNode, TrackData* trackData) mxml_node_t* node = rootNode; free(trackData->bookmarks); + trackData->bookmarks = NULL; trackData->bookmarkCount = 0; trackData->highlightRowStep = 8; diff --git a/ogl_editor/src/loadsave.h b/ogl_editor/src/loadsave.h index f91b8ac..1c3a4f0 100644 --- a/ogl_editor/src/loadsave.h +++ b/ogl_editor/src/loadsave.h @@ -1,6 +1,6 @@ #pragma once -#include +#include struct TrackData; diff --git a/ogl_editor/src/minmax.h b/ogl_editor/src/minmax.h index cf3651b..fd6caf1 100644 --- a/ogl_editor/src/minmax.h +++ b/ogl_editor/src/minmax.h @@ -1,6 +1,6 @@ #pragma once -#include +#include /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/ogl_editor/tundra.lua b/ogl_editor/tundra.lua index 6f35cbc..235d028 100644 --- a/ogl_editor/tundra.lua +++ b/ogl_editor/tundra.lua @@ -24,11 +24,24 @@ local win32 = { }, } +local linux = { + Env = { + CPPDEFS = { "EMGUI_UNIX" }, + CCOPTS = { + "-I.", + "`sdl-config --cflags`", + { "-O0", "-g"; Config = "*-*-debug" }, + { "-O2"; Config = "*-*-release" }, + }, + }, +} + Build { Units = "units.lua", Configs = { Config { Name = "macosx-clang", DefaultOnHost = "macosx", Inherit = macosx, Tools = { "clang-osx" } }, Config { Name = "win32-msvc", DefaultOnHost = { "windows" }, Inherit = win32, Tools = { "msvc" } }, + Config { Name = "linux-gcc", DefaultOnHost = { "linux" }, Inherit = linux, Tools = { "gcc" } }, }, } diff --git a/ogl_editor/units.lua b/ogl_editor/units.lua index 93de4a4..5b10d26 100644 --- a/ogl_editor/units.lua +++ b/ogl_editor/units.lua @@ -107,7 +107,10 @@ Program { Depends = { "sync", "mxml", "emgui" }, - Libs = { { "wsock32.lib", "opengl32.lib", "glu32.lib", "kernel32.lib", "user32.lib", "gdi32.lib", "Comdlg32.lib", "Advapi32.lib" ; Config = "win32-*-*" } }, + Libs = { + { "wsock32.lib", "opengl32.lib", "glu32.lib", "kernel32.lib", "user32.lib", "gdi32.lib", "Comdlg32.lib", "Advapi32.lib" ; Config = "win32-*-*" }, + { "GL", "SDL", "m"; Config = "linux-*-*" } + }, Frameworks = { "Cocoa", "OpenGL", "Carbon" },