ogl_editor: linux/SDL code for everything
Finish the linux code, should be mostly coherent with win and mac. Update the readme file too. Just SDL basics for creating the window with opengl context, and passing the mouse and keyboard inputs along. Menus are not displayed, but the hotkeys are the same as in Windows. File dialogs use terminal input and color dialog isn't implemented. This is quite straightforward and platform-independent, so should be pretty portable too.
This commit is contained in:
parent
4594187ecb
commit
5248597c58
1
ogl_editor/.gitignore
vendored
1
ogl_editor/.gitignore
vendored
@ -4,3 +4,4 @@ t2-output
|
||||
.tundra*
|
||||
*.swp
|
||||
*.swo
|
||||
.rocket-recents.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
|
||||
|
||||
@ -1,65 +1,257 @@
|
||||
#include "SDL.h"
|
||||
#include <stdio.h>
|
||||
#include <emgui/Emgui.h>
|
||||
#include "Editor.h"
|
||||
#include "Menu.h"
|
||||
|
||||
static SDL_Surface *screen;
|
||||
|
||||
void swapBuffers()
|
||||
{
|
||||
SDL_GL_SwapBuffers();
|
||||
printf("swap\n");
|
||||
}
|
||||
|
||||
void Window_populateRecentList(text_t** files)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 4; i++)
|
||||
if (wcscmp(files[i], "") != 0)
|
||||
wprintf(L"recent: %s\n", files[i]);
|
||||
if (files[i][0] != 0)
|
||||
printf("recent %d: %s\n", i, files[i]);
|
||||
}
|
||||
|
||||
void Window_setTitle(const wchar_t *title)
|
||||
void Window_setTitle(const text_t *title)
|
||||
{
|
||||
char mbyte[32];
|
||||
if (wcstombs(mbyte, title, sizeof(mbyte)) >= sizeof(mbyte))
|
||||
mbyte[sizeof(mbyte) - 1] = 0;
|
||||
SDL_WM_SetCaption(mbyte, NULL);
|
||||
SDL_WM_SetCaption(title, NULL);
|
||||
}
|
||||
|
||||
int Dialog_open(wchar_t* path, int pathSize)
|
||||
int getFilename(text_t *path)
|
||||
{
|
||||
printf("dialog_open() not implemented\n");
|
||||
return 0;
|
||||
#warning TODO retval
|
||||
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_save(wchar_t* path)
|
||||
int Dialog_open(text_t *path)
|
||||
{
|
||||
printf("dialog_save() not implemented\n");
|
||||
return 0;
|
||||
#warning TODO retval
|
||||
printf("Load from: ");
|
||||
return getFilename(path);
|
||||
}
|
||||
|
||||
int Dialog_save(text_t *path)
|
||||
{
|
||||
printf("Save to: ");
|
||||
return getFilename(path);
|
||||
}
|
||||
|
||||
void Dialog_showColorPicker(unsigned int* color)
|
||||
{
|
||||
*color = 0;
|
||||
printf("dialog_save() not implemented\n");
|
||||
printf("dialog_showColorPicker() not implemented\n");
|
||||
}
|
||||
|
||||
int handleKey(SDLKey key)
|
||||
int mapSdlEmKeycode(SDLKey key)
|
||||
{
|
||||
switch (key) {
|
||||
case SDLK_ESCAPE:
|
||||
return 1;
|
||||
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 handleKey(ev->key.keysym.sym);
|
||||
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;
|
||||
|
||||
@ -78,33 +270,93 @@ int doEvents()
|
||||
|
||||
void run(SDL_Surface *screen)
|
||||
{
|
||||
for (;;) {
|
||||
for (;;)
|
||||
{
|
||||
if (doEvents())
|
||||
break;
|
||||
Editor_timedUpdate();
|
||||
printf("frame\n");
|
||||
SDL_Delay(160);
|
||||
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) {
|
||||
if (SDL_Init(SDL_INIT_VIDEO) < 0)
|
||||
{
|
||||
fprintf(stderr, "SDL_Init(): %s\n", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
SDL_Surface *screen = SDL_SetVideoMode(800, 600, 32, SDL_OPENGL | SDL_GL_DOUBLEBUFFER);
|
||||
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();
|
||||
// TODO: Editor_getRecentFiles()
|
||||
|
||||
EMGFXBackend_updateViewPort(800, 600);
|
||||
Editor_setWindowSize(800, 600);
|
||||
Editor_update();
|
||||
|
||||
run(screen);
|
||||
|
||||
saveRecents();
|
||||
|
||||
SDL_Quit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user