From 241937cad2444e323536e3e4b39ec8f299980b4c Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Mon, 29 Oct 2012 21:38:46 +0100 Subject: [PATCH 01/25] Removed dots to match the look of the original editor (dunno if its good or bad) --- ogl_editor/src/TrackView.c | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/ogl_editor/src/TrackView.c b/ogl_editor/src/TrackView.c index f465fd9..9df3d60 100644 --- a/ogl_editor/src/TrackView.c +++ b/ogl_editor/src/TrackView.c @@ -50,7 +50,7 @@ static void printRowNumbers(int x, int y, int rowCount, int rowOffset, int rowSp static void renderChannel(struct sync_track* track, int startX, int startY, int startPos, int endPos) { - uint x, y; + uint y; uint32_t color = Emgui_color32(40, 40, 40, 255); Emgui_drawBorder(color, color, startX, startY - 20, 160, 600); @@ -64,7 +64,7 @@ static void renderChannel(struct sync_track* track, int startX, int startY, int { y_offset = startY + (font_size * -startPos); startPos = 0; - endPos = 40; + //endPos = 40; } y_offset += font_size / 2; @@ -89,26 +89,14 @@ static void renderChannel(struct sync_track* track, int startX, int startY, int } else { - int points[64]; - int* points_ptr = (int*)&points[0]; - - for (x = 0; x < 6; ++x) - { - points_ptr[0] = offset + 0; - points_ptr[1] = y_offset; - points_ptr[2] = offset + 2; - points_ptr[3] = y_offset; - points_ptr[4] = offset + 4; - points_ptr[5] = y_offset; - - points_ptr += 6; - offset += 10; - } + uint32_t color = 0; if (y & 7) - Emgui_drawDots(0x004f4f4f, (int*)&points[0], 18 * 2); + color = Emgui_color32(0x4f, 0x4f, 0x4f, 0xff); else - Emgui_drawDots(0x007f7f7f, (int*)&points[0], 18 * 2); + color = Emgui_color32(0x7f, 0x7f, 0x7f, 0xff); + + Emgui_drawText("---", offset, y_offset - font_size / 2, color); } y_offset += font_size; @@ -136,7 +124,7 @@ static inline int min(int a, int b) } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// +// foo void TrackView_render(const TrackViewInfo* viewInfo, TrackData* trackData) { @@ -146,14 +134,15 @@ void TrackView_render(const TrackViewInfo* viewInfo, TrackData* trackData) // TODO: Calculate how many channels we can draw given the width uint i = 0; //, channel_count = 10; + int end_row = viewInfo->windowSizeY / font_size; - printRowNumbers(2, 42, 40, start_pos + viewInfo->rowPos, font_size, 8); + printRowNumbers(2, 42, end_row - 20, start_pos + viewInfo->rowPos, font_size, 8); if (syncData->num_tracks == 0) { renderChannel(0, 40 + (i * 64), 42, (start_pos + viewInfo->rowPos), - (start_pos + viewInfo->rowPos + 40)); + (start_pos + viewInfo->rowPos + end_row)); uint32_t color = Emgui_color32(127, 127, 127, 56); Emgui_fill(color, 0, 257, 800, font_size + 2); return; @@ -172,6 +161,7 @@ void TrackView_render(const TrackViewInfo* viewInfo, TrackData* trackData) start_track = sel_track - 3; int x_pos = 40; + end_row -= 20; const int end_track = min(start_track + num_tracks, syncData->num_tracks); @@ -179,7 +169,7 @@ void TrackView_render(const TrackViewInfo* viewInfo, TrackData* trackData) { renderChannel(syncData->tracks[i], x_pos, 42, (start_pos + viewInfo->rowPos), - (start_pos + viewInfo->rowPos + 40)); + (start_pos + viewInfo->rowPos + end_row)); if (sel_track == i) { From af042ad66ec755c5691d5e2f0f69303677ac2348 Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Tue, 30 Oct 2012 21:58:56 +0100 Subject: [PATCH 02/25] Proper closing of socket when exiting app --- ogl_editor/src/RemoteConnection.c | 20 +++++++++++--------- ogl_editor/src/RemoteConnection.h | 1 + ogl_editor/src/macosx/RocketView.m | 10 +--------- ogl_editor/src/macosx/delegate.m | 11 +++++++++++ 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/ogl_editor/src/RemoteConnection.c b/ogl_editor/src/RemoteConnection.c index 09c63b9..717bf83 100644 --- a/ogl_editor/src/RemoteConnection.c +++ b/ogl_editor/src/RemoteConnection.c @@ -196,23 +196,14 @@ static SOCKET clientConnect(SOCKET serverSocket, struct sockaddr_in* host) void RemoteConnection_updateListner() { - fd_set fds; - struct timeval timeout; SOCKET clientSocket; struct sockaddr_in client; if (RemoteConnection_connected()) return; - FD_ZERO(&fds); - FD_SET(s_serverSocket, &fds); - - timeout.tv_sec = 0; - timeout.tv_usec = 0; - // look for new clients - //if (select(0, &fds, NULL, NULL, &timeout) > 0) { clientSocket = clientConnect(s_serverSocket, &client); @@ -414,3 +405,14 @@ void RemoteConnection_sendKeyFrames(const char* name, struct sync_track* track) sendSetKeyCommandIndex((uint32_t)track_id, &track->keys[i]); } +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void RemoteConnection_close() +{ + if (RemoteConnection_connected()) + { + closesocket(s_socket); + s_socket = INVALID_SOCKET; + } +} + diff --git a/ogl_editor/src/RemoteConnection.h b/ogl_editor/src/RemoteConnection.h index f23db03..4903da7 100644 --- a/ogl_editor/src/RemoteConnection.h +++ b/ogl_editor/src/RemoteConnection.h @@ -10,6 +10,7 @@ struct sync_track; bool RemoteConnection_createListner(); void RemoteConnection_updateListner(); +void RemoteConnection_close(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Talk with the demo stuff diff --git a/ogl_editor/src/macosx/RocketView.m b/ogl_editor/src/macosx/RocketView.m index 8007964..c249c26 100644 --- a/ogl_editor/src/macosx/RocketView.m +++ b/ogl_editor/src/macosx/RocketView.m @@ -1,5 +1,6 @@ #import "RocketView.h" #include "../Editor.h" +#include "../rlog.h" #include #include @@ -157,14 +158,5 @@ return YES; } -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - --(void) dealloc -{ - Editor_destroy(); - EMGFXBackend_destroy(); - [super dealloc]; -} - @end diff --git a/ogl_editor/src/macosx/delegate.m b/ogl_editor/src/macosx/delegate.m index 21aa4c1..9158b94 100644 --- a/ogl_editor/src/macosx/delegate.m +++ b/ogl_editor/src/macosx/delegate.m @@ -1,6 +1,8 @@ #import "delegate.h" #include "../Editor.h" +#include "../RemoteConnection.h" +#include "rlog.h" @implementation MinimalAppAppDelegate @@ -20,4 +22,13 @@ Editor_menuEvent((int)((NSButton*)sender).tag); } +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (void)applicationWillTerminate:(NSNotification *)aNotification +{ + rlog(R_INFO, "Dealloc\n"); + Editor_destroy(); + RemoteConnection_close(); +} + @end From 7f0f7a09916ee5df14308a06e49d2a0c64b5caa1 Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Tue, 30 Oct 2012 22:07:41 +0100 Subject: [PATCH 03/25] Fixed so demo can disconnect without editor locking up Closes #8 --- ogl_editor/src/RemoteConnection.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ogl_editor/src/RemoteConnection.c b/ogl_editor/src/RemoteConnection.c index 717bf83..2778eef 100644 --- a/ogl_editor/src/RemoteConnection.c +++ b/ogl_editor/src/RemoteConnection.c @@ -248,11 +248,12 @@ bool RemoteConnection_recv(char* buffer, size_t length, int flags) if (!RemoteConnection_connected()) return false; - if ((ret = recv(s_socket, buffer, (int)length, flags)) != (int)length) + ret = recv(s_socket, buffer, (int)length, flags); + + if (ret == 0) { - //rlog(R_INFO, "%d %d\n", ret, length); - //RemoteConnection_disconnect(); - //return false; + RemoteConnection_disconnect(); + return false; } return true; From 624d4fc487c89f8a457c24ae56e5b29ddc9dba55 Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Fri, 2 Nov 2012 22:47:21 +0100 Subject: [PATCH 04/25] Track display behaves much better now --- ogl_editor/src/TrackView.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/ogl_editor/src/TrackView.c b/ogl_editor/src/TrackView.c index 9df3d60..d30e10a 100644 --- a/ogl_editor/src/TrackView.c +++ b/ogl_editor/src/TrackView.c @@ -20,7 +20,7 @@ void TrackView_init() /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static void printRowNumbers(int x, int y, int rowCount, int rowOffset, int rowSpacing, int maskBpm) +static void printRowNumbers(int x, int y, int rowCount, int rowOffset, int rowSpacing, int maskBpm, int endY) { int i; @@ -43,28 +43,30 @@ static void printRowNumbers(int x, int y, int rowCount, int rowOffset, int rowSp y += rowSpacing; rowOffset++; + + if (y > endY) + break; } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static void renderChannel(struct sync_track* track, int startX, int startY, int startPos, int endPos) +static void renderChannel(struct sync_track* track, int startX, int startY, int startPos, int endPos, int endSizeY) { uint y; uint32_t color = Emgui_color32(40, 40, 40, 255); - Emgui_drawBorder(color, color, startX, startY - 20, 160, 600); + Emgui_drawBorder(color, color, startX, startY - font_size, 160, endSizeY); if (track) Emgui_drawText(track->name, startX + 2, startY + 2, Emgui_color32(0xff, 0xff, 0xff, 0xff)); - int y_offset = startY;// + font_size / 2; + int y_offset = startY; if (startPos < 0) { y_offset = startY + (font_size * -startPos); startPos = 0; - //endPos = 40; } y_offset += font_size / 2; @@ -100,6 +102,9 @@ static void renderChannel(struct sync_track* track, int startX, int startY, int } y_offset += font_size; + + if (y_offset > (endSizeY + font_size/2)) + break; } } @@ -128,23 +133,28 @@ static inline int min(int a, int b) void TrackView_render(const TrackViewInfo* viewInfo, TrackData* trackData) { + uint i = 0; struct sync_data* syncData = &trackData->syncData; const int sel_track = trackData->activeTrack; + // Calc to position the selection in the ~middle of the screen + + const int adjust_top_size = 2 * font_size; + const int mid_screen_y = (viewInfo->windowSizeY / 2) & ~(font_size - 1); + const int y_pos_row = viewInfo->rowPos - (mid_screen_y / font_size); + // TODO: Calculate how many channels we can draw given the width - uint i = 0; //, channel_count = 10; int end_row = viewInfo->windowSizeY / font_size; + int y_end_border = viewInfo->windowSizeY - 32; // adjust to have some space at the end of the screen - printRowNumbers(2, 42, end_row - 20, start_pos + viewInfo->rowPos, font_size, 8); + printRowNumbers(2, adjust_top_size, end_row, y_pos_row, font_size, 8, y_end_border); if (syncData->num_tracks == 0) { - renderChannel(0, 40 + (i * 64), 42, - (start_pos + viewInfo->rowPos), - (start_pos + viewInfo->rowPos + end_row)); + renderChannel(0, 40 + (i * 64), adjust_top_size, y_pos_row, y_pos_row + end_row, y_end_border); uint32_t color = Emgui_color32(127, 127, 127, 56); - Emgui_fill(color, 0, 257, 800, font_size + 2); + Emgui_fill(color, 0, mid_screen_y + adjust_top_size, viewInfo->windowSizeX, font_size + 2); return; } @@ -169,7 +179,7 @@ void TrackView_render(const TrackViewInfo* viewInfo, TrackData* trackData) { renderChannel(syncData->tracks[i], x_pos, 42, (start_pos + viewInfo->rowPos), - (start_pos + viewInfo->rowPos + end_row)); + (start_pos + viewInfo->rowPos + end_row), y_end_border); if (sel_track == i) { From dd46b25c723447be5a6278fae66584d4fbbf3a5d Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Fri, 2 Nov 2012 23:10:33 +0100 Subject: [PATCH 05/25] Fixed most issues with strange scrolling Closes #10 --- ogl_editor/src/TrackView.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/ogl_editor/src/TrackView.c b/ogl_editor/src/TrackView.c index d30e10a..6983e86 100644 --- a/ogl_editor/src/TrackView.c +++ b/ogl_editor/src/TrackView.c @@ -10,7 +10,6 @@ #include "../../sync/track.h" const int font_size = 8; -static int start_pos = -27; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -56,10 +55,10 @@ static void renderChannel(struct sync_track* track, int startX, int startY, int uint y; uint32_t color = Emgui_color32(40, 40, 40, 255); - Emgui_drawBorder(color, color, startX, startY - font_size, 160, endSizeY); + Emgui_drawBorder(color, color, startX, startY - font_size * 2, 160, endSizeY); if (track) - Emgui_drawText(track->name, startX + 2, startY + 2, Emgui_color32(0xff, 0xff, 0xff, 0xff)); + Emgui_drawText(track->name, startX + 4, startY - font_size, Emgui_color32(0xff, 0xff, 0xff, 0xff)); int y_offset = startY; @@ -139,7 +138,7 @@ void TrackView_render(const TrackViewInfo* viewInfo, TrackData* trackData) // Calc to position the selection in the ~middle of the screen - const int adjust_top_size = 2 * font_size; + const int adjust_top_size = 3 * font_size; const int mid_screen_y = (viewInfo->windowSizeY / 2) & ~(font_size - 1); const int y_pos_row = viewInfo->rowPos - (mid_screen_y / font_size); @@ -171,29 +170,25 @@ void TrackView_render(const TrackViewInfo* viewInfo, TrackData* trackData) start_track = sel_track - 3; int x_pos = 40; - end_row -= 20; const int end_track = min(start_track + num_tracks, syncData->num_tracks); for (i = start_track; i < end_track; ++i) { - renderChannel(syncData->tracks[i], x_pos, 42, - (start_pos + viewInfo->rowPos), - (start_pos + viewInfo->rowPos + end_row), y_end_border); + renderChannel(syncData->tracks[i], x_pos, adjust_top_size, y_pos_row, y_pos_row + end_row, y_end_border); if (sel_track == i) { - Emgui_fill(Emgui_color32(0xff, 0xff, 0x00, 0x80), x_pos, 257, 160, font_size + 2); + Emgui_fill(Emgui_color32(0xff, 0xff, 0x00, 0x80), x_pos, mid_screen_y + adjust_top_size, 160, font_size + 1); if (trackData->editText) - Emgui_drawText(trackData->editText, x_pos, 257, Emgui_color32(255, 255, 255, 255)); + Emgui_drawText(trackData->editText, x_pos, mid_screen_y + adjust_top_size, Emgui_color32(255, 255, 255, 255)); } x_pos += 160; } uint32_t color = Emgui_color32(127, 127, 127, 56); - - Emgui_fill(color, 0, 257, 800, font_size + 3); + Emgui_fill(color, 0, mid_screen_y + adjust_top_size, viewInfo->windowSizeX, font_size + 1); } From 43332b491cb8220423c18ecfc84f7f31232be2a2 Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Fri, 2 Nov 2012 23:11:01 +0100 Subject: [PATCH 06/25] Last past of screen resizing support Closes #22 --- ogl_editor/src/Editor.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ogl_editor/src/Editor.c b/ogl_editor/src/Editor.c index 7b79bb9..90d8546 100644 --- a/ogl_editor/src/Editor.c +++ b/ogl_editor/src/Editor.c @@ -106,6 +106,7 @@ static void drawStatus() int active_track = getActiveTrack(); const struct sync_track* track = tracks[active_track]; + const int sizeY = s_editorData.trackViewInfo.windowSizeY; int row = s_editorData.trackViewInfo.rowPos; int idx = key_idx_floor(track, row); const char *str = "---"; @@ -123,8 +124,8 @@ static void drawStatus() snprintf(temp, 256, "track %d row %d value %f type %s", active_track, row, sync_get_val(track, row), str); - Emgui_fill(Emgui_color32(0x10, 0x10, 0x10, 0xff), 1, 588, 400, 11); - Emgui_drawText(temp, 3, 590, Emgui_color32(255, 255, 255, 255)); + Emgui_fill(Emgui_color32(0x10, 0x10, 0x10, 0xff), 1, sizeY - 12, 400, 11); + Emgui_drawText(temp, 3, sizeY - 10, Emgui_color32(255, 255, 255, 255)); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -350,6 +351,7 @@ static int processCommands() { RemoteConnection_recv((char*)&newRow, sizeof(int), 0); s_editorData.trackViewInfo.rowPos = htonl(newRow); + rlog(R_INFO, "row from demo %d\n", s_editorData.trackViewInfo.rowPos); ret = 1; break; } From 32552dbd980927c67bdc1a6468c65534365f2a21 Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Sat, 3 Nov 2012 09:42:52 +0100 Subject: [PATCH 07/25] Fixed issue that the editor would get "stuck" if demo exits during playback Closes #29 --- ogl_editor/src/RemoteConnection.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ogl_editor/src/RemoteConnection.c b/ogl_editor/src/RemoteConnection.c index 2778eef..d2f897d 100644 --- a/ogl_editor/src/RemoteConnection.c +++ b/ogl_editor/src/RemoteConnection.c @@ -235,6 +235,8 @@ void RemoteConnection_disconnect() rlog(R_INFO, "disconnect!\n"); + s_paused = true; + memset(s_nameLookup.ids, -1, sizeof(int) * s_nameLookup.count); s_nameLookup.count = 0; } From 2c580d71f507554c32f7e8cb36c2589f687f71aa Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Sat, 3 Nov 2012 10:09:57 +0100 Subject: [PATCH 08/25] Implemented jumping to top row, left/right track --- ogl_editor/src/Editor.c | 15 +++++++++++++-- ogl_editor/src/Editor.h | 1 + ogl_editor/src/macosx/RocketView.m | 3 +++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/ogl_editor/src/Editor.c b/ogl_editor/src/Editor.c index 90d8546..fcd6ead 100644 --- a/ogl_editor/src/Editor.c +++ b/ogl_editor/src/Editor.c @@ -191,6 +191,9 @@ bool Editor_keyDown(int key, int modifiers) if (row < 0) row = 0; + if (modifiers & EDITOR_KEY_COMMAND) + row = 0; + s_editorData.trackViewInfo.rowPos = row; RemoteConnection_sendSetRowCommand(row); @@ -204,6 +207,10 @@ bool Editor_keyDown(int key, int modifiers) if (paused) { int track = getActiveTrack(); track--; + + if (modifiers & EDITOR_KEY_COMMAND) + track = 0; + setActiveTrack(track < 0 ? 0 : track); handled_key = true; @@ -217,9 +224,13 @@ bool Editor_keyDown(int key, int modifiers) if (paused) { int track = getActiveTrack(); track++; + int track_count = getTrackCount(); - if (track >= getTrackCount()) - track = getTrackCount() - 1; + if (track >= track_count) + track = track_count - 1; + + if (modifiers & EDITOR_KEY_COMMAND) + track = track_count - 1; setActiveTrack(track); diff --git a/ogl_editor/src/Editor.h b/ogl_editor/src/Editor.h index 16ed5a7..6ebdac0 100644 --- a/ogl_editor/src/Editor.h +++ b/ogl_editor/src/Editor.h @@ -22,5 +22,6 @@ enum EDITOR_KEY_SHIFT = 1, EDITOR_KEY_ALT = 2, EDITOR_KEY_CTRL = 4, + EDITOR_KEY_COMMAND = 8, }; diff --git a/ogl_editor/src/macosx/RocketView.m b/ogl_editor/src/macosx/RocketView.m index c249c26..5bbdb73 100644 --- a/ogl_editor/src/macosx/RocketView.m +++ b/ogl_editor/src/macosx/RocketView.m @@ -84,6 +84,9 @@ if ([theEvent modifierFlags] & NSControlKeyMask) specialKeys |= EDITOR_KEY_CTRL; + if ([theEvent modifierFlags] & NSCommandKeyMask) + specialKeys |= EDITOR_KEY_COMMAND; + if ([theEvent modifierFlags] & NSNumericPadKeyMask) { switch (keyChar) From afcaf7775d94ff5b3dddb6255cdc9dec107c16ff Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Sat, 3 Nov 2012 12:47:56 +0100 Subject: [PATCH 09/25] Minor cleanup in keyboard handling --- ogl_editor/src/Editor.c | 181 +++++++++++++++++++++++------------------------- 1 file changed, 85 insertions(+), 96 deletions(-) diff --git a/ogl_editor/src/Editor.c b/ogl_editor/src/Editor.c index fcd6ead..8c40fde 100644 --- a/ogl_editor/src/Editor.c +++ b/ogl_editor/src/Editor.c @@ -141,7 +141,6 @@ void Editor_update() Emgui_end(); } - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static char s_editBuffer[512]; @@ -155,87 +154,89 @@ bool Editor_keyDown(int key, int modifiers) int active_track = getActiveTrack(); int row_pos = s_editorData.trackViewInfo.rowPos; + if (key == ' ') + { + // TODO: Don't start playing if we are in edit mode (but space shouldn't be added in edit mode but we still + // shouldn't start playing if we do + + RemoteConnection_sendPauseCommand(!paused); + Editor_update(); + return true; + } + + if (!paused) + return false; + switch (key) { case EMGUI_ARROW_DOWN: { - if (paused) - { - int row = row_pos; + int row = row_pos; - if (modifiers & EDITOR_KEY_ALT) - row += 8; - else - row++; + if (modifiers & EDITOR_KEY_ALT) + row += 8; + else + row++; - s_editorData.trackViewInfo.rowPos = row; + s_editorData.trackViewInfo.rowPos = row; - RemoteConnection_sendSetRowCommand(row); - handled_key = true; - } + RemoteConnection_sendSetRowCommand(row); + handled_key = true; break; } case EMGUI_ARROW_UP: { - if (paused) - { - int row = row_pos; + int row = row_pos; - if (modifiers & EDITOR_KEY_ALT) - row -= 8; - else - row--; + if (modifiers & EDITOR_KEY_ALT) + row -= 8; + else + row--; - if (row < 0) - row = 0; + if (row < 0) + row = 0; - if (modifiers & EDITOR_KEY_COMMAND) - row = 0; + if (modifiers & EDITOR_KEY_COMMAND) + row = 0; - s_editorData.trackViewInfo.rowPos = row; + s_editorData.trackViewInfo.rowPos = row; + + RemoteConnection_sendSetRowCommand(row); + handled_key = true; - RemoteConnection_sendSetRowCommand(row); - handled_key = true; - } break; } case EMGUI_ARROW_LEFT: { - if (paused) - { - int track = getActiveTrack(); track--; + int track = getActiveTrack(); track--; - if (modifiers & EDITOR_KEY_COMMAND) - track = 0; + if (modifiers & EDITOR_KEY_COMMAND) + track = 0; - setActiveTrack(track < 0 ? 0 : track); + setActiveTrack(track < 0 ? 0 : track); - handled_key = true; - } + handled_key = true; break; } case EMGUI_ARROW_RIGHT: { - if (paused) - { - int track = getActiveTrack(); track++; - int track_count = getTrackCount(); + int track = getActiveTrack(); track++; + int track_count = getTrackCount(); - if (track >= track_count) - track = track_count - 1; + if (track >= track_count) + track = track_count - 1; - if (modifiers & EDITOR_KEY_COMMAND) - track = track_count - 1; + if (modifiers & EDITOR_KEY_COMMAND) + track = track_count - 1; - setActiveTrack(track); + setActiveTrack(track); - handled_key = true; - } + handled_key = true; break; } @@ -245,69 +246,57 @@ bool Editor_keyDown(int key, int modifiers) // do edit here - if (paused) + if ((key >= '0' && key <= '9') || key == '.' || key == '-') { - if ((key >= '0' && key <= '9') || key == '.' || key == '-') + if (!is_editing) { - if (!is_editing) - { - memset(s_editBuffer, 0, sizeof(s_editBuffer)); - is_editing = true; - } - - s_editBuffer[strlen(s_editBuffer)] = key; - s_editorData.trackData.editText = s_editBuffer; - - return true; - } - else if (is_editing) - { - struct track_key key; - - key.row = row_pos; - key.value = atof(s_editBuffer); - key.type = 0; - - struct sync_track* track = tracks[active_track]; - const char* track_name = track->name; - - sync_set_key(track, &key); - - rlog(R_INFO, "Setting key %f at %d row %d (name %s)\n", key.value, active_track, key.row, track_name); - - RemoteConnection_sendSetKeyCommand(track_name, &key); - - is_editing = false; - s_editorData.trackData.editText = 0; + memset(s_editBuffer, 0, sizeof(s_editBuffer)); + is_editing = true; } - if (key == 'i') - { - struct sync_track* track = tracks[active_track]; - int row = s_editorData.trackViewInfo.rowPos; + s_editBuffer[strlen(s_editBuffer)] = key; + s_editorData.trackData.editText = s_editBuffer; - int idx = key_idx_floor(track, row); - if (idx < 0) - return false; + return true; + } + else if (is_editing) + { + struct track_key key; - // copy and modify - struct track_key newKey = track->keys[idx]; - newKey.type = ((newKey.type + 1) % KEY_TYPE_COUNT); + key.row = row_pos; + key.value = atof(s_editBuffer); + key.type = 0; - sync_set_key(track, &newKey); + struct sync_track* track = tracks[active_track]; + const char* track_name = track->name; - RemoteConnection_sendSetKeyCommand(track->name, &newKey); + sync_set_key(track, &key); - handled_key = true; - } + rlog(R_INFO, "Setting key %f at %d row %d (name %s)\n", key.value, active_track, key.row, track_name); + + RemoteConnection_sendSetKeyCommand(track_name, &key); + + is_editing = false; + s_editorData.trackData.editText = 0; } - if (key == ' ') + if (key == 'i') { - // TODO: Don't start playing if we are in edit mode (but space shouldn't be added in edit mode but we still - // shouldn't start playing if we do + struct sync_track* track = tracks[active_track]; + int row = s_editorData.trackViewInfo.rowPos; + + int idx = key_idx_floor(track, row); + if (idx < 0) + return false; + + // copy and modify + struct track_key newKey = track->keys[idx]; + newKey.type = ((newKey.type + 1) % KEY_TYPE_COUNT); + + sync_set_key(track, &newKey); + + RemoteConnection_sendSetKeyCommand(track->name, &newKey); - RemoteConnection_sendPauseCommand(!paused); handled_key = true; } From 8a4f94b7494a7937471bcdd9154055920a95b516 Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Sat, 3 Nov 2012 22:25:36 +0100 Subject: [PATCH 10/25] Minor cleanup --- units.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/units.lua b/units.lua index 8a0221a..d1983d0 100644 --- a/units.lua +++ b/units.lua @@ -73,7 +73,8 @@ Program { Env = { CPPPATH = { ".", "ogl_editor/src", - "../emgui/src", "../../../../../emgui/src", + "../emgui/src", + "../../../../../emgui/src", "ogl_editor/External/mxml" }, PROGOPTS = { { "/SUBSYSTEM:WINDOWS", "/DEBUG"; Config = { "win32-*-*", "win64-*-*" } }, From a1aeadfb7adf9700819dc995b24b61bb4ffa3cff Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Sat, 3 Nov 2012 22:26:03 +0100 Subject: [PATCH 11/25] Fixed super annoying bug that sometimes the server socket couldn't get created --- ogl_editor/src/RemoteConnection.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ogl_editor/src/RemoteConnection.c b/ogl_editor/src/RemoteConnection.c index d2f897d..1c5a34c 100644 --- a/ogl_editor/src/RemoteConnection.c +++ b/ogl_editor/src/RemoteConnection.c @@ -228,10 +228,13 @@ void RemoteConnection_disconnect() { #if defined(_WIN32) closesocket(s_socket); + close(s_serverSocket); #else close(s_socket); + close(s_serverSocket); #endif s_socket = INVALID_SOCKET; + s_socket = INVALID_SOCKET; rlog(R_INFO, "disconnect!\n"); From b883f6e8e8042d89ef1e97bdf609640b1636f32c Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Sat, 3 Nov 2012 22:28:13 +0100 Subject: [PATCH 12/25] Implemented new font for track names and also adjusting the track width if the names are too long and center the text if less than min track size Closes #9 --- ogl_editor/src/Editor.c | 73 +++++++++++------ ogl_editor/src/MinecraftiaFont.c | 172 +++++++++++++++++++++++++++++++++++++++ ogl_editor/src/MinecraftiaFont.h | 8 ++ ogl_editor/src/TrackView.c | 44 ++++++++-- ogl_editor/src/TrackView.h | 1 + 5 files changed, 266 insertions(+), 32 deletions(-) create mode 100644 ogl_editor/src/MinecraftiaFont.c create mode 100644 ogl_editor/src/MinecraftiaFont.h diff --git a/ogl_editor/src/Editor.c b/ogl_editor/src/Editor.c index 8c40fde..c449bd4 100644 --- a/ogl_editor/src/Editor.c +++ b/ogl_editor/src/Editor.c @@ -10,6 +10,7 @@ #include "rlog.h" #include "TrackData.h" #include "RemoteConnection.h" +#include "MinecraftiaFont.h" #include "../../sync/sync.h" #include "../../sync/base.h" #include "../../sync/data.h" @@ -62,22 +63,21 @@ static inline int getTrackCount() return s_editorData.trackData.syncData.num_tracks; } -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -//static uint64_t fontIds[2]; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Editor_create() { + int id; Emgui_create("foo"); - //fontIds[0] = Emgui_loadFont("/Users/daniel/Library/Fonts/MicroKnight_v1.0.ttf", 11.0f); - //fontIds[0] = Emgui_loadFont(FONT_PATH "Arial.ttf", 11.0f); - Emgui_setDefaultFont(); - + id = Emgui_loadFontBitmap(g_minecraftiaFont, g_minecraftiaFontSize, EMGUI_FONT_MEMORY, 32, 128, g_minecraftiaFontLayout); memset(&s_editorData, 0, sizeof(s_editorData)); RemoteConnection_createListner(); + + s_editorData.trackViewInfo.smallFontId = id; + + Emgui_setDefaultFont(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -173,15 +173,10 @@ bool Editor_keyDown(int key, int modifiers) { int row = row_pos; - if (modifiers & EDITOR_KEY_ALT) - row += 8; - else - row++; - + row += modifiers & EDITOR_KEY_ALT ? 8 : 1; s_editorData.trackViewInfo.rowPos = row; RemoteConnection_sendSetRowCommand(row); - handled_key = true; break; } @@ -190,15 +185,9 @@ bool Editor_keyDown(int key, int modifiers) { int row = row_pos; - if (modifiers & EDITOR_KEY_ALT) - row -= 8; - else - row--; + row -= modifiers & EDITOR_KEY_ALT ? 8 : 1; - if (row < 0) - row = 0; - - if (modifiers & EDITOR_KEY_COMMAND) + if ((modifiers & EDITOR_KEY_COMMAND) || row < 0) row = 0; s_editorData.trackViewInfo.rowPos = row; @@ -211,7 +200,7 @@ bool Editor_keyDown(int key, int modifiers) case EMGUI_ARROW_LEFT: { - int track = getActiveTrack(); track--; + int track = getActiveTrack() - 1; if (modifiers & EDITOR_KEY_COMMAND) track = 0; @@ -244,7 +233,45 @@ bool Editor_keyDown(int key, int modifiers) default : handled_key = false; break; } - // do edit here + // Handle biasing of values + + if ((key >= '1' && key <= '9') && ((modifiers & EDITOR_KEY_CTRL) || (modifiers & EDITOR_KEY_ALT))) + { + struct sync_track* track = tracks[active_track]; + int row = s_editorData.trackViewInfo.rowPos; + + float bias_value = 0.0f; + + switch (key) + { + case '1' : bias_value = 0.01f; break; + case '2' : bias_value = 0.1f; break; + case '3' : bias_value = 1.0f; break; + case '4' : bias_value = 10.f; break; + case '5' : bias_value = 100.0f; break; + case '6' : bias_value = 1000.0f; break; + case '7' : bias_value = 10000.0f; break; + } + + bias_value = modifiers & EDITOR_KEY_ALT ? -bias_value : bias_value; + + int idx = key_idx_floor(track, row); + if (idx < 0) + return false; + + // copy and modify + struct track_key newKey = track->keys[idx]; + newKey.value += bias_value; + + sync_set_key(track, &newKey); + + RemoteConnection_sendSetKeyCommand(track->name, &newKey); + + Editor_update(); + return true; + } + + // do edit here and biasing here if ((key >= '0' && key <= '9') || key == '.' || key == '-') { diff --git a/ogl_editor/src/MinecraftiaFont.c b/ogl_editor/src/MinecraftiaFont.c new file mode 100644 index 0000000..8fb1d41 --- /dev/null +++ b/ogl_editor/src/MinecraftiaFont.c @@ -0,0 +1,172 @@ +#include +#include "MinecraftiaFont.h" + +int g_minecraftiaFontSize = 713; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +char g_minecraftiaFont[] = +{ + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, + 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x02, 0x2e, 0x02, 0x00, 0x00, 0x02, + 0x90, 0x49, 0x44, 0x41, 0x54, 0x58, 0x85, 0xe5, 0x57, 0xc7, 0x76, 0x03, + 0x21, 0x0c, 0x1c, 0xed, 0xe3, 0xff, 0x7f, 0x79, 0x72, 0x40, 0x65, 0x44, + 0xb1, 0x9d, 0x72, 0x8b, 0x9c, 0xec, 0x62, 0x10, 0x6a, 0x23, 0x09, 0x0c, + 0x00, 0x20, 0x40, 0x92, 0x00, 0x40, 0x1f, 0x13, 0xf4, 0x05, 0xd0, 0x59, + 0x0e, 0xff, 0x04, 0x06, 0x00, 0x18, 0x68, 0x00, 0xe8, 0x6f, 0x73, 0x06, + 0x21, 0x82, 0x70, 0x16, 0xd0, 0x68, 0xb5, 0x32, 0x10, 0xd3, 0xb0, 0x39, + 0x40, 0xcc, 0xe4, 0xce, 0xd8, 0xe1, 0x73, 0x6d, 0x3f, 0x9e, 0x45, 0x93, + 0x3b, 0x92, 0x2c, 0x36, 0x3f, 0x3a, 0xcf, 0xcd, 0xbe, 0xa9, 0xa6, 0xf9, + 0x1d, 0x93, 0x1e, 0x0f, 0xf4, 0xf9, 0x0c, 0x00, 0x81, 0x11, 0xca, 0xc4, + 0x2c, 0x9f, 0xa2, 0x11, 0x30, 0x1a, 0x0d, 0x4c, 0x06, 0x1a, 0x60, 0xcd, + 0x80, 0x50, 0x3a, 0x15, 0xf1, 0x03, 0x14, 0x6a, 0x6d, 0x46, 0x8e, 0x4d, + 0xfb, 0xb7, 0xc9, 0xd4, 0xea, 0x09, 0xd2, 0x14, 0xc9, 0xb9, 0x4a, 0xb8, + 0xc9, 0xe9, 0x96, 0xec, 0x98, 0xba, 0xdd, 0xf6, 0xb2, 0x73, 0xcd, 0x17, + 0xa8, 0xc5, 0x01, 0x00, 0xe3, 0xfb, 0xa0, 0xc2, 0xbf, 0x1b, 0xe8, 0x4a, + 0xd4, 0x4d, 0x42, 0x03, 0x39, 0x5c, 0xb8, 0x5d, 0x84, 0x4c, 0xf1, 0x96, + 0xee, 0x55, 0xbe, 0x3a, 0x3d, 0xa1, 0xbf, 0x63, 0x73, 0xa4, 0x96, 0x8f, + 0x25, 0xe0, 0x6e, 0x3f, 0xf6, 0x94, 0xdb, 0x69, 0xa4, 0x44, 0xa3, 0x4d, + 0x8f, 0x4d, 0x3c, 0xd6, 0x71, 0xe4, 0x97, 0x83, 0x43, 0x18, 0x41, 0xfb, + 0xab, 0x3c, 0x48, 0x31, 0xf4, 0x60, 0x6c, 0xd9, 0x60, 0xa5, 0xbb, 0x72, + 0xa2, 0xf2, 0x40, 0x7b, 0x84, 0x62, 0x7f, 0x7b, 0x22, 0xc7, 0x9e, 0x07, + 0x3d, 0x21, 0x25, 0x06, 0xbb, 0xcd, 0x61, 0x8d, 0x2f, 0x8d, 0xf2, 0xc1, + 0x04, 0x27, 0x81, 0x86, 0x11, 0x56, 0x07, 0x3a, 0x7a, 0x92, 0x03, 0x34, + 0x42, 0x98, 0xa1, 0x26, 0x9b, 0xc2, 0x4a, 0x22, 0x6b, 0xb0, 0xba, 0xbc, + 0x91, 0xe9, 0x15, 0xba, 0x0f, 0x7d, 0xad, 0x49, 0x5b, 0xc8, 0xb4, 0x02, + 0x9d, 0x27, 0xbd, 0xac, 0xf4, 0x2d, 0xbf, 0x1d, 0x85, 0xa8, 0x52, 0x0b, + 0xd0, 0x7e, 0x4c, 0x11, 0x7e, 0x14, 0xd2, 0xbb, 0x35, 0x73, 0x95, 0xe5, + 0x79, 0x4e, 0x59, 0x61, 0x7a, 0x47, 0x5a, 0x9f, 0x68, 0xcf, 0x3c, 0x58, + 0xc2, 0xcb, 0x6b, 0x45, 0x07, 0x8f, 0xe5, 0x13, 0xc4, 0xac, 0x85, 0x80, + 0x51, 0x23, 0x7f, 0x2b, 0x41, 0x53, 0x79, 0xe6, 0x51, 0x1e, 0xbd, 0x41, + 0xc4, 0xd1, 0xf6, 0xbe, 0x8c, 0x83, 0x9e, 0x6e, 0xb7, 0x36, 0xae, 0x7d, + 0x74, 0xa2, 0xd1, 0xbf, 0xca, 0x99, 0xa6, 0xbd, 0x81, 0x90, 0x14, 0xa8, + 0x55, 0x44, 0x4a, 0x7f, 0x6e, 0xf0, 0x95, 0x56, 0xa0, 0x8e, 0x85, 0xec, + 0xcb, 0x79, 0x72, 0x22, 0xfb, 0x7c, 0x1c, 0x94, 0xc9, 0x31, 0xff, 0xc0, + 0x2e, 0xa3, 0x9f, 0x14, 0x8b, 0x00, 0xea, 0x62, 0x7d, 0xb6, 0xc4, 0x69, + 0x27, 0x0d, 0x41, 0x0c, 0x44, 0x95, 0x4b, 0xa5, 0x59, 0x06, 0x6a, 0xb9, + 0x8e, 0x84, 0xc3, 0x75, 0x52, 0xe3, 0x81, 0x99, 0xf0, 0x37, 0xb2, 0xec, + 0x26, 0xeb, 0x02, 0x4b, 0xcc, 0xb3, 0xad, 0xbe, 0xa0, 0x14, 0x67, 0x59, + 0xcd, 0x8b, 0x80, 0xbc, 0x8e, 0x1c, 0xb7, 0xcf, 0x34, 0x65, 0x6c, 0x86, + 0xb1, 0x82, 0xf8, 0x27, 0x54, 0x38, 0xcf, 0x0b, 0xca, 0x94, 0xef, 0x63, + 0xfa, 0x8a, 0xc0, 0xce, 0xc4, 0x92, 0x85, 0xd2, 0xa5, 0x13, 0x30, 0x37, + 0xe5, 0x7c, 0xbc, 0x1f, 0xd0, 0xce, 0x91, 0x6e, 0x1d, 0x78, 0x79, 0xd7, + 0xc5, 0x24, 0xaf, 0x2f, 0x71, 0xc7, 0x11, 0x88, 0xa3, 0x9d, 0x16, 0x4f, + 0xca, 0x6d, 0x97, 0x92, 0xc5, 0xfc, 0x9e, 0x8d, 0xe5, 0x8e, 0x32, 0x57, + 0x74, 0xa4, 0xa5, 0x9d, 0xdb, 0x99, 0x54, 0xf0, 0x3a, 0xd3, 0x2d, 0xf0, + 0x20, 0x03, 0x2b, 0x0a, 0x2f, 0xa9, 0x15, 0xc6, 0x9d, 0x65, 0xe9, 0xd6, + 0xcb, 0x5d, 0x74, 0xe1, 0x8f, 0xd5, 0xf3, 0x56, 0x8d, 0xd7, 0x52, 0xaa, + 0x59, 0xff, 0x47, 0xad, 0xad, 0xb4, 0xa9, 0xa5, 0x5f, 0x1b, 0x28, 0xe6, + 0xa9, 0x67, 0x8c, 0x47, 0x8d, 0xa5, 0xf7, 0x20, 0x8f, 0x2a, 0x6d, 0xec, + 0xf5, 0xab, 0x64, 0xc9, 0x86, 0x3c, 0x86, 0x21, 0x27, 0xaa, 0xb2, 0x65, + 0x8e, 0xac, 0x3d, 0xf8, 0x0d, 0xbd, 0x82, 0x81, 0xea, 0x47, 0xd6, 0x84, + 0x63, 0x40, 0x92, 0x18, 0xf0, 0xfb, 0x49, 0xf0, 0xe7, 0xcd, 0x2c, 0x7e, + 0x5b, 0xb4, 0xcb, 0x0e, 0x85, 0x3b, 0xf6, 0x48, 0x5e, 0x36, 0x5b, 0x28, + 0xea, 0x79, 0xb7, 0xb1, 0x81, 0xa4, 0x02, 0x3e, 0x6d, 0x34, 0x63, 0x9f, + 0x9a, 0x2e, 0x88, 0x63, 0xef, 0x04, 0x48, 0x3b, 0xe7, 0xfd, 0x96, 0xf0, + 0x99, 0x05, 0xbf, 0xb9, 0x34, 0xff, 0x63, 0xfa, 0x02, 0x69, 0x60, 0x73, + 0x1f, 0x6d, 0x77, 0x33, 0x94, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, + 0x44, 0xae, 0x42, 0x60, 0x82 +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// BMFont was used to generate the data (and regexp magic to generate the C layout) + +EmguiFontLayout g_minecraftiaFontLayout[] = +{ + { 32, 60, 50, 3, 1, -1, 11, 5 }, + { 33, 62, 32, 1, 7, 0, 3, 2 }, + { 34, 35, 53, 4, 3, 0, 3, 5 }, + { 35, 31, 0, 5, 7, 0, 3, 6 }, + { 36, 37, 0, 5, 7, 0, 3, 6 }, + { 37, 43, 0, 5, 7, 0, 3, 6 }, + { 38, 49, 0, 5, 7, 0, 3, 6 }, + { 39, 40, 53, 2, 3, 0, 3, 3 }, + { 40, 47, 32, 4, 7, 0, 3, 5 }, + { 41, 42, 32, 4, 7, 0, 3, 5 }, + { 42, 30, 53, 4, 3, 0, 5, 5 }, + { 43, 0, 49, 5, 5, 0, 4, 6 }, + { 44, 62, 40, 1, 3, 0, 8, 2 }, + { 45, 58, 53, 5, 1, 0, 6, 6 }, + { 46, 50, 53, 1, 2, 0, 8, 2 }, + { 47, 42, 8, 5, 7, 0, 3, 6 }, + { 48, 0, 9, 5, 7, 0, 3, 6 }, + { 49, 54, 8, 5, 7, 0, 3, 6 }, + { 50, 0, 17, 5, 7, 0, 3, 6 }, + { 51, 6, 16, 5, 7, 0, 3, 6 }, + { 52, 12, 16, 5, 7, 0, 3, 6 }, + { 53, 18, 16, 5, 7, 0, 3, 6 }, + { 54, 13, 0, 5, 7, 0, 3, 6 }, + { 55, 30, 16, 5, 7, 0, 3, 6 }, + { 56, 36, 16, 5, 7, 0, 3, 6 }, + { 57, 42, 16, 5, 7, 0, 3, 6 }, + { 58, 54, 40, 1, 6, 0, 4, 2 }, + { 59, 24, 40, 1, 7, 0, 4, 2 }, + { 60, 52, 32, 4, 7, 0, 3, 5 }, + { 61, 18, 54, 5, 4, 0, 5, 6 }, + { 62, 5, 41, 4, 7, 0, 3, 5 }, + { 63, 12, 24, 5, 7, 0, 3, 6 }, + { 64, 6, 0, 6, 7, 0, 3, 7 }, + { 65, 18, 24, 5, 7, 0, 3, 6 }, + { 66, 48, 16, 5, 7, 0, 3, 6 }, + { 67, 30, 24, 5, 7, 0, 3, 6 }, + { 68, 36, 24, 5, 7, 0, 3, 6 }, + { 69, 42, 24, 5, 7, 0, 3, 6 }, + { 70, 48, 24, 5, 7, 0, 3, 6 }, + { 71, 54, 24, 5, 7, 0, 3, 6 }, + { 72, 0, 33, 5, 7, 0, 3, 6 }, + { 73, 60, 8, 3, 7, 0, 3, 4 }, + { 74, 24, 24, 5, 7, 0, 3, 6 }, + { 75, 6, 32, 5, 7, 0, 3, 6 }, + { 76, 12, 32, 5, 7, 0, 3, 6 }, + { 77, 18, 32, 5, 7, 0, 3, 6 }, + { 78, 24, 32, 5, 7, 0, 3, 6 }, + { 79, 18, 8, 5, 7, 0, 3, 6 }, + { 80, 6, 24, 5, 7, 0, 3, 6 }, + { 81, 24, 16, 5, 7, 0, 3, 6 }, + { 82, 36, 8, 5, 7, 0, 3, 6 }, + { 83, 30, 8, 5, 7, 0, 3, 6 }, + { 84, 24, 8, 5, 7, 0, 3, 6 }, + { 85, 12, 8, 5, 7, 0, 3, 6 }, + { 86, 55, 0, 5, 7, 0, 3, 6 }, + { 87, 25, 0, 5, 7, 0, 3, 6 }, + { 88, 30, 32, 5, 7, 0, 3, 6 }, + { 89, 36, 32, 5, 7, 0, 3, 6 }, + { 90, 19, 0, 5, 7, 0, 3, 6 }, + { 91, 60, 16, 3, 7, 0, 3, 4 }, + { 92, 6, 8, 5, 7, 0, 3, 6 }, + { 93, 20, 40, 3, 7, 0, 3, 4 }, + { 94, 24, 54, 5, 3, 0, 3, 6 }, + { 95, 52, 53, 5, 1, 0, 9, 6 }, + { 96, 60, 46, 2, 3, 0, 3, 3 }, + { 97, 48, 47, 5, 5, 0, 5, 6 }, + { 98, 48, 8, 5, 7, 0, 3, 6 }, + { 99, 18, 48, 5, 5, 0, 5, 6 }, + { 100, 54, 16, 5, 7, 0, 3, 6 }, + { 101, 56, 40, 5, 5, 0, 5, 6 }, + { 102, 0, 41, 4, 7, 0, 3, 5 }, + { 103, 30, 40, 5, 6, 0, 5, 6 }, + { 104, 0, 25, 5, 7, 0, 3, 6 }, + { 105, 26, 40, 1, 7, 0, 3, 2 }, + { 106, 0, 0, 5, 8, 0, 3, 6 }, + { 107, 57, 32, 4, 7, 0, 3, 5 }, + { 108, 61, 0, 2, 7, 0, 3, 3 }, + { 109, 0, 55, 5, 5, 0, 5, 6 }, + { 110, 6, 55, 5, 5, 0, 5, 6 }, + { 111, 12, 54, 5, 5, 0, 5, 6 }, + { 112, 36, 40, 5, 6, 0, 5, 6 }, + { 113, 42, 40, 5, 6, 0, 5, 6 }, + { 114, 6, 49, 5, 5, 0, 5, 6 }, + { 115, 12, 48, 5, 5, 0, 5, 6 }, + { 116, 60, 24, 3, 7, 0, 3, 4 }, + { 117, 24, 48, 5, 5, 0, 5, 6 }, + { 118, 30, 47, 5, 5, 0, 5, 6 }, + { 119, 36, 47, 5, 5, 0, 5, 6 }, + { 120, 42, 47, 5, 5, 0, 5, 6 }, + { 121, 48, 40, 5, 6, 0, 5, 6 }, + { 122, 54, 47, 5, 5, 0, 5, 6 }, + { 123, 15, 40, 4, 7, 0, 3, 5 }, + { 124, 28, 40, 1, 7, 0, 3, 2 }, + { 125, 10, 40, 4, 7, 0, 3, 5 }, + { 126, 43, 53, 6, 2, 0, 3, 7 }, +}; diff --git a/ogl_editor/src/MinecraftiaFont.h b/ogl_editor/src/MinecraftiaFont.h new file mode 100644 index 0000000..72258ae --- /dev/null +++ b/ogl_editor/src/MinecraftiaFont.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +extern EmguiFontLayout g_minecraftiaFontLayout[]; +extern char g_minecraftiaFont[]; +extern int g_minecraftiaFontSize; + diff --git a/ogl_editor/src/TrackView.c b/ogl_editor/src/TrackView.c index 6983e86..4a2efaf 100644 --- a/ogl_editor/src/TrackView.c +++ b/ogl_editor/src/TrackView.c @@ -10,6 +10,7 @@ #include "../../sync/track.h" const int font_size = 8; +const int min_track_size = 100; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -50,15 +51,38 @@ static void printRowNumbers(int x, int y, int rowCount, int rowOffset, int rowSp /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static void renderChannel(struct sync_track* track, int startX, int startY, int startPos, int endPos, int endSizeY) +static int renderChannel(const TrackViewInfo* viewInfo, struct sync_track* track, + int startX, int startY, int startPos, int endPos, int endSizeY) { uint y; - - uint32_t color = Emgui_color32(40, 40, 40, 255); - Emgui_drawBorder(color, color, startX, startY - font_size * 2, 160, endSizeY); + int size = min_track_size; if (track) - Emgui_drawText(track->name, startX + 4, startY - font_size, Emgui_color32(0xff, 0xff, 0xff, 0xff)); + { + int text_size; + int x_adjust = 0; + + Emgui_setFont(viewInfo->smallFontId); + + text_size = Emgui_getTextSize(track->name) + 4; + + rlog(R_INFO, "t %s size %d\n", track->name, text_size); + + // if text is smaller than min size we center the text + + if (text_size < min_track_size) + x_adjust = (min_track_size - text_size) / 2; + else + size = text_size + 1; + + rlog(R_INFO, "t %s size %d adjust %d\n", track->name, text_size, x_adjust); + + Emgui_drawText(track->name, (startX + 3) + x_adjust, startY - 12, Emgui_color32(0xff, 0xff, 0xff, 0xff)); + Emgui_setDefaultFont(); + } + + uint32_t color = Emgui_color32(40, 40, 40, 255); + Emgui_drawBorder(color, color, startX, startY - font_size * 2, size, endSizeY); int y_offset = startY; @@ -105,6 +129,8 @@ static void renderChannel(struct sync_track* track, int startX, int startY, int if (y_offset > (endSizeY + font_size/2)) break; } + + return size; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -151,7 +177,7 @@ void TrackView_render(const TrackViewInfo* viewInfo, TrackData* trackData) if (syncData->num_tracks == 0) { - renderChannel(0, 40 + (i * 64), adjust_top_size, y_pos_row, y_pos_row + end_row, y_end_border); + renderChannel(0, 0, 40 + (i * 64), adjust_top_size, y_pos_row, y_pos_row + end_row, y_end_border); uint32_t color = Emgui_color32(127, 127, 127, 56); Emgui_fill(color, 0, mid_screen_y + adjust_top_size, viewInfo->windowSizeX, font_size + 2); return; @@ -175,17 +201,17 @@ void TrackView_render(const TrackViewInfo* viewInfo, TrackData* trackData) for (i = start_track; i < end_track; ++i) { - renderChannel(syncData->tracks[i], x_pos, adjust_top_size, y_pos_row, y_pos_row + end_row, y_end_border); + int size = renderChannel(viewInfo, syncData->tracks[i], x_pos, adjust_top_size, y_pos_row, y_pos_row + end_row, y_end_border); if (sel_track == i) { - Emgui_fill(Emgui_color32(0xff, 0xff, 0x00, 0x80), x_pos, mid_screen_y + adjust_top_size, 160, font_size + 1); + Emgui_fill(Emgui_color32(0xff, 0xff, 0x00, 0x80), x_pos, mid_screen_y + adjust_top_size, size, font_size + 1); if (trackData->editText) Emgui_drawText(trackData->editText, x_pos, mid_screen_y + adjust_top_size, Emgui_color32(255, 255, 255, 255)); } - x_pos += 160; + x_pos += size; } uint32_t color = Emgui_color32(127, 127, 127, 56); diff --git a/ogl_editor/src/TrackView.h b/ogl_editor/src/TrackView.h index 1a0cb21..7b8cee0 100644 --- a/ogl_editor/src/TrackView.h +++ b/ogl_editor/src/TrackView.h @@ -11,6 +11,7 @@ typedef struct TrackViewInfo int windowSizeX; int windowSizeY; int rowPos; + int smallFontId; } TrackViewInfo; From 41f793cf923808ef5fb198766483a696a763bd97 Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Sat, 3 Nov 2012 23:22:27 +0100 Subject: [PATCH 13/25] FINALLY fixed super annoying reconnection issue --- ogl_editor/src/RemoteConnection.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/ogl_editor/src/RemoteConnection.c b/ogl_editor/src/RemoteConnection.c index 1c5a34c..4c81ba0 100644 --- a/ogl_editor/src/RemoteConnection.c +++ b/ogl_editor/src/RemoteConnection.c @@ -25,6 +25,7 @@ #include "../../sync/base.h" #include "../../sync/track.h" #include "rlog.h" +#include #ifndef INVALID_SOCKET #define INVALID_SOCKET -1 @@ -138,9 +139,17 @@ bool RemoteConnection_createListner() sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons(1338); + int yes = 1; + if (setsockopt(s_serverSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) + { + perror("setsockopt"); + return false; + } + if (-1 == bind(s_serverSocket, (struct sockaddr *)&sin, sizeof(sin))) { - rlog(R_ERROR, "Unable to create server socket\n"); + perror("bind"); + rlog(R_ERROR, "Unable to bind server socket\n"); return false; } @@ -149,7 +158,7 @@ bool RemoteConnection_createListner() setBlocking(s_serverSocket, false); - rlog(R_INFO, "Creaded listner\n"); + rlog(R_INFO, "Created listner\n"); return true; } @@ -228,13 +237,10 @@ void RemoteConnection_disconnect() { #if defined(_WIN32) closesocket(s_socket); - close(s_serverSocket); #else close(s_socket); - close(s_serverSocket); #endif s_socket = INVALID_SOCKET; - s_socket = INVALID_SOCKET; rlog(R_INFO, "disconnect!\n"); @@ -417,8 +423,14 @@ void RemoteConnection_close() { if (RemoteConnection_connected()) { + rlog(R_INFO, "closing client socket %d\n", s_socket); closesocket(s_socket); s_socket = INVALID_SOCKET; } + + rlog(R_INFO, "closing socket %d\n", s_serverSocket); + + closesocket(s_serverSocket); + s_serverSocket = INVALID_SOCKET; } From 4015d13f405013cde66b7fe9ef7a67f8aa1baa4f Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Sat, 3 Nov 2012 23:23:23 +0100 Subject: [PATCH 14/25] Implemented rendering of interpolation type Closes #14 --- ogl_editor/src/TrackView.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/ogl_editor/src/TrackView.c b/ogl_editor/src/TrackView.c index 4a2efaf..e27f11c 100644 --- a/ogl_editor/src/TrackView.c +++ b/ogl_editor/src/TrackView.c @@ -104,6 +104,27 @@ static int renderChannel(const TrackViewInfo* viewInfo, struct sync_track* track if (track) idx = sync_find_key(track, y); + // This is kinda crappy implementation as we will overdraw this quite a bit but might be fine + + int fidx = idx >= 0 ? idx : -idx - 2; + enum key_type interpolationType = (fidx >= 0) ? track->keys[fidx].type : KEY_STEP; + + uint32_t color = 0; + + switch (interpolationType) + { + case KEY_STEP : color = 0; break; + case KEY_LINEAR : color = Emgui_color32(255, 0, 0, 255); break; + case KEY_SMOOTH : color = Emgui_color32(0, 255, 0, 255); break; + case KEY_RAMP : color = Emgui_color32(0, 0, 255, 255); break; + default: break; + } + + if (viewInfo) + Emgui_fill(color, startX + (size - 4), y_offset - font_size / 2, 2, (endSizeY - y_offset) + font_size - 1); + + // Draw text if we have any + if (idx >= 0) { char temp[256]; @@ -185,7 +206,7 @@ void TrackView_render(const TrackViewInfo* viewInfo, TrackData* trackData) int num_tracks = syncData->num_tracks; - int max_render_tracks = viewInfo->windowSizeX / 128; + int max_render_tracks = viewInfo->windowSizeX / min_track_size; if (num_tracks > max_render_tracks) num_tracks = max_render_tracks; From ca73e5748a4dfbd693092514020c8fad73ce6664 Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Sun, 4 Nov 2012 10:17:49 +0100 Subject: [PATCH 15/25] Made it possible to do selection of rows and tracks (shift + arrow keys) --- ogl_editor/src/Editor.c | 48 ++++++++++++++++++++++++++++++++++---- ogl_editor/src/TrackView.c | 58 +++++++++++++++++----------------------------- ogl_editor/src/TrackView.h | 4 ++++ ogl_editor/src/minmax.h | 22 ++++++++++++++++++ 4 files changed, 90 insertions(+), 42 deletions(-) create mode 100644 ogl_editor/src/minmax.h diff --git a/ogl_editor/src/Editor.c b/ogl_editor/src/Editor.c index c449bd4..0634dc5 100644 --- a/ogl_editor/src/Editor.c +++ b/ogl_editor/src/Editor.c @@ -8,6 +8,7 @@ #include "LoadSave.h" #include "TrackView.h" #include "rlog.h" +#include "minmax.h" #include "TrackData.h" #include "RemoteConnection.h" #include "MinecraftiaFont.h" @@ -149,10 +150,11 @@ static bool is_editing = false; bool Editor_keyDown(int key, int modifiers) { bool handled_key = true; + TrackViewInfo* viewInfo = &s_editorData.trackViewInfo; bool paused = RemoteConnection_isPaused(); struct sync_track** tracks = getTracks(); int active_track = getActiveTrack(); - int row_pos = s_editorData.trackViewInfo.rowPos; + int row_pos = viewInfo->rowPos; if (key == ' ') { @@ -174,7 +176,16 @@ bool Editor_keyDown(int key, int modifiers) int row = row_pos; row += modifiers & EDITOR_KEY_ALT ? 8 : 1; - s_editorData.trackViewInfo.rowPos = row; + viewInfo->rowPos = row; + + if (modifiers & EDITOR_KEY_SHIFT) + { + viewInfo->selectStopRow = row; + break; + } + + viewInfo->selectStartRow = viewInfo->selectStopRow = row; + viewInfo->selectStartTrack = viewInfo->selectStopTrack = active_track; RemoteConnection_sendSetRowCommand(row); @@ -190,7 +201,16 @@ bool Editor_keyDown(int key, int modifiers) if ((modifiers & EDITOR_KEY_COMMAND) || row < 0) row = 0; - s_editorData.trackViewInfo.rowPos = row; + viewInfo->rowPos = row; + + if (modifiers & EDITOR_KEY_SHIFT) + { + viewInfo->selectStopRow = row; + break; + } + + viewInfo->selectStartRow = viewInfo->selectStopRow = row; + viewInfo->selectStartTrack = viewInfo->selectStopTrack = active_track; RemoteConnection_sendSetRowCommand(row); handled_key = true; @@ -207,6 +227,15 @@ bool Editor_keyDown(int key, int modifiers) setActiveTrack(track < 0 ? 0 : track); + if (modifiers & EDITOR_KEY_SHIFT) + { + viewInfo->selectStopTrack = track; + break; + } + + viewInfo->selectStartRow = viewInfo->selectStopRow = row_pos; + viewInfo->selectStartTrack = viewInfo->selectStopTrack = track; + handled_key = true; break; @@ -225,6 +254,15 @@ bool Editor_keyDown(int key, int modifiers) setActiveTrack(track); + if (modifiers & EDITOR_KEY_SHIFT) + { + viewInfo->selectStopTrack = track; + break; + } + + viewInfo->selectStartRow = viewInfo->selectStopRow = row_pos; + viewInfo->selectStartTrack = viewInfo->selectStopTrack = track; + handled_key = true; break; @@ -238,7 +276,7 @@ bool Editor_keyDown(int key, int modifiers) if ((key >= '1' && key <= '9') && ((modifiers & EDITOR_KEY_CTRL) || (modifiers & EDITOR_KEY_ALT))) { struct sync_track* track = tracks[active_track]; - int row = s_editorData.trackViewInfo.rowPos; + int row = viewInfo->rowPos; float bias_value = 0.0f; @@ -310,7 +348,7 @@ bool Editor_keyDown(int key, int modifiers) if (key == 'i') { struct sync_track* track = tracks[active_track]; - int row = s_editorData.trackViewInfo.rowPos; + int row = viewInfo->rowPos; int idx = key_idx_floor(track, row); if (idx < 0) diff --git a/ogl_editor/src/TrackView.c b/ogl_editor/src/TrackView.c index e27f11c..19596e2 100644 --- a/ogl_editor/src/TrackView.c +++ b/ogl_editor/src/TrackView.c @@ -5,6 +5,7 @@ #include #include "TrackData.h" #include "rlog.h" +#include "minmax.h" #include "../../sync/sync.h" #include "../../sync/data.h" #include "../../sync/track.h" @@ -52,7 +53,8 @@ static void printRowNumbers(int x, int y, int rowCount, int rowOffset, int rowSp /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static int renderChannel(const TrackViewInfo* viewInfo, struct sync_track* track, - int startX, int startY, int startPos, int endPos, int endSizeY) + int startX, int startY, int startPos, int endPos, int endSizeY, + int trackId, int selectLeft, int selectRight, int selectTop, int selectBottom) { uint y; int size = min_track_size; @@ -63,11 +65,8 @@ static int renderChannel(const TrackViewInfo* viewInfo, struct sync_track* track int x_adjust = 0; Emgui_setFont(viewInfo->smallFontId); - text_size = Emgui_getTextSize(track->name) + 4; - rlog(R_INFO, "t %s size %d\n", track->name, text_size); - // if text is smaller than min size we center the text if (text_size < min_track_size) @@ -75,8 +74,6 @@ static int renderChannel(const TrackViewInfo* viewInfo, struct sync_track* track else size = text_size + 1; - rlog(R_INFO, "t %s size %d adjust %d\n", track->name, text_size, x_adjust); - Emgui_drawText(track->name, (startX + 3) + x_adjust, startY - 12, Emgui_color32(0xff, 0xff, 0xff, 0xff)); Emgui_setDefaultFont(); } @@ -135,16 +132,15 @@ static int renderChannel(const TrackViewInfo* viewInfo, struct sync_track* track } else { - uint32_t color = 0; - - if (y & 7) - color = Emgui_color32(0x4f, 0x4f, 0x4f, 0xff); - else - color = Emgui_color32(0x7f, 0x7f, 0x7f, 0xff); - + uint32_t color = (y & 7) ? Emgui_color32(0x4f, 0x4f, 0x4f, 0xff) : Emgui_color32(0x7f, 0x7f, 0x7f, 0xff); Emgui_drawText("---", offset, y_offset - font_size / 2, color); } + bool selected = (trackId >= selectLeft && trackId <= selectRight) && (y >= selectTop && y < selectBottom); + + if (selected) + Emgui_fill(Emgui_color32(0x4f, 0x4f, 0x4f, 0x3f), startX, y_offset - font_size/2, size, font_size); + y_offset += font_size; if (y_offset > (endSizeY + font_size/2)) @@ -156,27 +152,6 @@ static int renderChannel(const TrackViewInfo* viewInfo, struct sync_track* track /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -int doMax(int a, int b) -{ - if (b >= a) - return b; - else - return a; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -static inline int min(int a, int b) -{ - if (a < b) - return a; - else - return b; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// foo - void TrackView_render(const TrackViewInfo* viewInfo, TrackData* trackData) { uint i = 0; @@ -198,12 +173,20 @@ void TrackView_render(const TrackViewInfo* viewInfo, TrackData* trackData) if (syncData->num_tracks == 0) { - renderChannel(0, 0, 40 + (i * 64), adjust_top_size, y_pos_row, y_pos_row + end_row, y_end_border); + renderChannel(0, 0, 40 + (i * 64), adjust_top_size, y_pos_row, y_pos_row + end_row, y_end_border, + 0, 0, 0, 0, 0); uint32_t color = Emgui_color32(127, 127, 127, 56); Emgui_fill(color, 0, mid_screen_y + adjust_top_size, viewInfo->windowSizeX, font_size + 2); return; } + int selectLeft = mini(viewInfo->selectStartTrack, viewInfo->selectStopTrack); + int selectRight = maxi(viewInfo->selectStartTrack, viewInfo->selectStopTrack); + int selectTop = mini(viewInfo->selectStartRow, viewInfo->selectStopRow); + int selectBottom = maxi(viewInfo->selectStartRow, viewInfo->selectStopRow); + + rlog(R_INFO, "%d %d %d %d\n", selectLeft, selectRight, selectTop, selectBottom); + int num_tracks = syncData->num_tracks; int max_render_tracks = viewInfo->windowSizeX / min_track_size; @@ -218,11 +201,12 @@ void TrackView_render(const TrackViewInfo* viewInfo, TrackData* trackData) int x_pos = 40; - const int end_track = min(start_track + num_tracks, syncData->num_tracks); + const int end_track = mini(start_track + num_tracks, syncData->num_tracks); for (i = start_track; i < end_track; ++i) { - int size = renderChannel(viewInfo, syncData->tracks[i], x_pos, adjust_top_size, y_pos_row, y_pos_row + end_row, y_end_border); + int size = renderChannel(viewInfo, syncData->tracks[i], x_pos, adjust_top_size, y_pos_row, y_pos_row + end_row, y_end_border, + i, selectLeft, selectRight, selectTop, selectBottom); if (sel_track == i) { diff --git a/ogl_editor/src/TrackView.h b/ogl_editor/src/TrackView.h index 7b8cee0..123fad9 100644 --- a/ogl_editor/src/TrackView.h +++ b/ogl_editor/src/TrackView.h @@ -12,6 +12,10 @@ typedef struct TrackViewInfo int windowSizeY; int rowPos; int smallFontId; + int selectStartTrack; + int selectStopTrack; + int selectStartRow; + int selectStopRow; } TrackViewInfo; diff --git a/ogl_editor/src/minmax.h b/ogl_editor/src/minmax.h new file mode 100644 index 0000000..6e239e6 --- /dev/null +++ b/ogl_editor/src/minmax.h @@ -0,0 +1,22 @@ +#pragma once + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static inline int maxi(int a, int b) +{ + if (a > b) + return a; + + return b; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static inline int mini(int a, int b) +{ + if (a < b) + return a; + + return b; +} + From 82ab8e140ed765cf1c10dce3e23a93738d37004e Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Sun, 4 Nov 2012 10:28:32 +0100 Subject: [PATCH 16/25] Added support to bias a selection of values Closes #20 --- ogl_editor/src/Editor.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/ogl_editor/src/Editor.c b/ogl_editor/src/Editor.c index 0634dc5..543db51 100644 --- a/ogl_editor/src/Editor.c +++ b/ogl_editor/src/Editor.c @@ -275,10 +275,11 @@ bool Editor_keyDown(int key, int modifiers) if ((key >= '1' && key <= '9') && ((modifiers & EDITOR_KEY_CTRL) || (modifiers & EDITOR_KEY_ALT))) { - struct sync_track* track = tracks[active_track]; - int row = viewInfo->rowPos; + struct sync_track** tracks; + int track, row; float bias_value = 0.0f; + tracks = getTracks(); switch (key) { @@ -293,19 +294,32 @@ bool Editor_keyDown(int key, int modifiers) bias_value = modifiers & EDITOR_KEY_ALT ? -bias_value : bias_value; - int idx = key_idx_floor(track, row); - if (idx < 0) - return false; + int selectLeft = mini(viewInfo->selectStartTrack, viewInfo->selectStopTrack); + int selectRight = maxi(viewInfo->selectStartTrack, viewInfo->selectStopTrack); + int selectTop = mini(viewInfo->selectStartRow, viewInfo->selectStopRow); + int selectBottom = maxi(viewInfo->selectStartRow, viewInfo->selectStopRow); - // copy and modify - struct track_key newKey = track->keys[idx]; - newKey.value += bias_value; + for (track = selectLeft; track <= selectRight; ++track) + { + struct sync_track* t = tracks[track]; - sync_set_key(track, &newKey); + for (row = selectTop; row <= selectBottom; ++row) + { + int idx = sync_find_key(t, row); + if (idx < 0) + continue; - RemoteConnection_sendSetKeyCommand(track->name, &newKey); + struct track_key newKey = t->keys[idx]; + newKey.value += bias_value; + + sync_set_key(t, &newKey); + + RemoteConnection_sendSetKeyCommand(t->name, &newKey); + } + } Editor_update(); + return true; } From e08e1189c9b0d5271da579fc5855346a42ccfe18 Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Sun, 4 Nov 2012 12:26:25 +0100 Subject: [PATCH 17/25] Implementd cut/copy and paste of track data Closes #19 --- ogl_editor/src/Editor.c | 163 +++++++++++++++++++++++++++++++++++++++++++-- ogl_editor/src/TrackView.c | 2 - 2 files changed, 158 insertions(+), 7 deletions(-) diff --git a/ogl_editor/src/Editor.c b/ogl_editor/src/Editor.c index 543db51..9fc3125 100644 --- a/ogl_editor/src/Editor.c +++ b/ogl_editor/src/Editor.c @@ -28,13 +28,33 @@ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +typedef struct CopyEntry +{ + int track; + struct track_key keyFrame; +} CopyEntry; + +typedef struct CopyData +{ + CopyEntry* entries; + int bufferWidth; + int bufferHeight; + int count; + +} CopyData; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + typedef struct EditorData { TrackViewInfo trackViewInfo; TrackData trackData; + CopyEntry* copyEntries; + int copyCount; } EditorData; static EditorData s_editorData; +static CopyData s_copyData; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -144,6 +164,81 @@ void Editor_update() /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static void copySelection(int row, int track, int selectLeft, int selectRight, int selectTop, int selectBottom) +{ + CopyEntry* entry = 0; + int copy_count = 0; + struct sync_track** tracks = getTracks(); + + // Count how much we need to copy + + for (track = selectLeft; track <= selectRight; ++track) + { + struct sync_track* t = tracks[track]; + for (row = selectTop; row <= selectBottom; ++row) + { + int idx = sync_find_key(t, row); + if (idx < 0) + continue; + + copy_count++; + } + } + + free(s_copyData.entries); + entry = s_copyData.entries = malloc(sizeof(CopyEntry) * copy_count); + + for (track = selectLeft; track <= selectRight; ++track) + { + struct sync_track* t = tracks[track]; + for (row = selectTop; row <= selectBottom; ++row) + { + int idx = sync_find_key(t, row); + if (idx < 0) + continue; + + entry->track = track - selectLeft; + entry->keyFrame = t->keys[idx]; + entry->keyFrame.row -= selectTop; + entry++; + } + } + + s_copyData.bufferWidth = selectRight - selectLeft + 1; + s_copyData.bufferHeight = selectBottom - selectTop + 1; + s_copyData.count = copy_count; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static void deleteArea(int rowPos, int track, int bufferWidth, int bufferHeight) +{ + int i, j; + const int track_count = getTrackCount(); + struct sync_track** tracks = getTracks(); + + rlog(R_INFO, "rowPos %d track %d bw %d bh %d\n", bufferWidth, bufferHeight); + + for (i = 0; i < bufferWidth; ++i) + { + size_t trackPos = track + i; + if (trackPos >= track_count) + continue; + + size_t trackIndex = trackPos; + struct sync_track* t = tracks[trackIndex]; + + for (j = 0; j < bufferHeight; ++j) + { + int row = rowPos + j; + if (is_key_frame(t, row)) + sync_del_key(t, row); + } + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + static char s_editBuffer[512]; static bool is_editing = false; @@ -156,6 +251,11 @@ bool Editor_keyDown(int key, int modifiers) int active_track = getActiveTrack(); int row_pos = viewInfo->rowPos; + const int selectLeft = mini(viewInfo->selectStartTrack, viewInfo->selectStopTrack); + const int selectRight = maxi(viewInfo->selectStartTrack, viewInfo->selectStopTrack); + const int selectTop = mini(viewInfo->selectStartRow, viewInfo->selectStopRow); + const int selectBottom = maxi(viewInfo->selectStartRow, viewInfo->selectStopRow); + if (key == ' ') { // TODO: Don't start playing if we are in edit mode (but space shouldn't be added in edit mode but we still @@ -271,6 +371,64 @@ bool Editor_keyDown(int key, int modifiers) default : handled_key = false; break; } + // handle copy of tracks/values + + if (key == 'c' && (modifiers & EDITOR_KEY_COMMAND)) + { + copySelection(row_pos, active_track, selectLeft, selectRight, selectTop, selectBottom); + return true; + } + + if (key == 'x' && (modifiers & EDITOR_KEY_COMMAND)) + { + copySelection(row_pos, active_track, selectLeft, selectRight, selectTop, selectBottom); + deleteArea(selectTop, selectLeft, s_copyData.bufferWidth, s_copyData.bufferHeight); + handled_key = true; + } + + // Handle paste of data + + if (key == 'v' && (modifiers & EDITOR_KEY_COMMAND)) + { + const int buffer_width = s_copyData.bufferWidth; + const int buffer_height = s_copyData.bufferHeight; + const int buffer_size = s_copyData.count; + const int track_count = getTrackCount(); + + if (!s_copyData.entries) + return false; + + // First clear the paste area + + deleteArea(row_pos, active_track, buffer_width, buffer_height); + + for (int i = 0; i < buffer_size; ++i) + { + const CopyEntry* ce = &s_copyData.entries[i]; + + assert(ce->track >= 0); + assert(ce->track < buffer_width); + assert(ce->keyFrame.row >= 0); + assert(ce->keyFrame.row < buffer_height); + + size_t trackPos = active_track + ce->track; + if (trackPos < track_count) + { + size_t trackIndex = trackPos; + struct track_key key = ce->keyFrame; + key.row += row_pos; + + rlog(R_INFO, "key.row %d\n", key.row); + + sync_set_key(tracks[trackIndex], &key); + + RemoteConnection_sendSetKeyCommand(tracks[trackIndex]->name, &key); + } + } + + handled_key = true; + } + // Handle biasing of values if ((key >= '1' && key <= '9') && ((modifiers & EDITOR_KEY_CTRL) || (modifiers & EDITOR_KEY_ALT))) @@ -294,11 +452,6 @@ bool Editor_keyDown(int key, int modifiers) bias_value = modifiers & EDITOR_KEY_ALT ? -bias_value : bias_value; - int selectLeft = mini(viewInfo->selectStartTrack, viewInfo->selectStopTrack); - int selectRight = maxi(viewInfo->selectStartTrack, viewInfo->selectStopTrack); - int selectTop = mini(viewInfo->selectStartRow, viewInfo->selectStopRow); - int selectBottom = maxi(viewInfo->selectStartRow, viewInfo->selectStopRow); - for (track = selectLeft; track <= selectRight; ++track) { struct sync_track* t = tracks[track]; diff --git a/ogl_editor/src/TrackView.c b/ogl_editor/src/TrackView.c index 19596e2..96bde11 100644 --- a/ogl_editor/src/TrackView.c +++ b/ogl_editor/src/TrackView.c @@ -185,8 +185,6 @@ void TrackView_render(const TrackViewInfo* viewInfo, TrackData* trackData) int selectTop = mini(viewInfo->selectStartRow, viewInfo->selectStopRow); int selectBottom = maxi(viewInfo->selectStartRow, viewInfo->selectStopRow); - rlog(R_INFO, "%d %d %d %d\n", selectLeft, selectRight, selectTop, selectBottom); - int num_tracks = syncData->num_tracks; int max_render_tracks = viewInfo->windowSizeX / min_track_size; From cb9a027490f591b4a427b6a996d9f7dcee0a7e7e Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Sun, 4 Nov 2012 12:42:38 +0100 Subject: [PATCH 18/25] Fixed text overlap when editing value. Also added pressing esc aborts the edit Closes #12 --- ogl_editor/src/Editor.c | 25 ++++++++++++++++--------- ogl_editor/src/TrackView.c | 14 ++++++++++---- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/ogl_editor/src/Editor.c b/ogl_editor/src/Editor.c index 9fc3125..bf09992 100644 --- a/ogl_editor/src/Editor.c +++ b/ogl_editor/src/Editor.c @@ -493,20 +493,27 @@ bool Editor_keyDown(int key, int modifiers) } else if (is_editing) { - struct track_key key; + // if we press esc we discard the value - key.row = row_pos; - key.value = atof(s_editBuffer); - key.type = 0; + if (key != 27) + { + struct track_key key; - struct sync_track* track = tracks[active_track]; - const char* track_name = track->name; + key.row = row_pos; + key.value = atof(s_editBuffer); + key.type = 0; - sync_set_key(track, &key); + struct sync_track* track = tracks[active_track]; + const char* track_name = track->name; - rlog(R_INFO, "Setting key %f at %d row %d (name %s)\n", key.value, active_track, key.row, track_name); + sync_set_key(track, &key); - RemoteConnection_sendSetKeyCommand(track_name, &key); + rlog(R_INFO, "Setting key %f at %d row %d (name %s)\n", key.value, active_track, key.row, track_name); + + RemoteConnection_sendSetKeyCommand(track_name, &key); + } + + handled_key = true; is_editing = false; s_editorData.trackData.editText = 0; diff --git a/ogl_editor/src/TrackView.c b/ogl_editor/src/TrackView.c index 96bde11..eb77585 100644 --- a/ogl_editor/src/TrackView.c +++ b/ogl_editor/src/TrackView.c @@ -52,7 +52,7 @@ static void printRowNumbers(int x, int y, int rowCount, int rowOffset, int rowSp /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static int renderChannel(const TrackViewInfo* viewInfo, struct sync_track* track, +static int renderChannel(const TrackViewInfo* viewInfo, struct sync_track* track, int editRow, int startX, int startY, int startPos, int endPos, int endSizeY, int trackId, int selectLeft, int selectRight, int selectTop, int selectBottom) { @@ -128,7 +128,8 @@ static int renderChannel(const TrackViewInfo* viewInfo, struct sync_track* track value = track->keys[idx].value; snprintf(temp, 256, "% .2f", value); - Emgui_drawText(temp, offset, y_offset - font_size / 2, Emgui_color32(255, 255, 255, 255)); + if (y != editRow) + Emgui_drawText(temp, offset, y_offset - font_size / 2, Emgui_color32(255, 255, 255, 255)); } else { @@ -173,7 +174,7 @@ void TrackView_render(const TrackViewInfo* viewInfo, TrackData* trackData) if (syncData->num_tracks == 0) { - renderChannel(0, 0, 40 + (i * 64), adjust_top_size, y_pos_row, y_pos_row + end_row, y_end_border, + renderChannel(0, 0, -1, 40 + (i * 64), adjust_top_size, y_pos_row, y_pos_row + end_row, y_end_border, 0, 0, 0, 0, 0); uint32_t color = Emgui_color32(127, 127, 127, 56); Emgui_fill(color, 0, mid_screen_y + adjust_top_size, viewInfo->windowSizeX, font_size + 2); @@ -203,7 +204,12 @@ void TrackView_render(const TrackViewInfo* viewInfo, TrackData* trackData) for (i = start_track; i < end_track; ++i) { - int size = renderChannel(viewInfo, syncData->tracks[i], x_pos, adjust_top_size, y_pos_row, y_pos_row + end_row, y_end_border, + int editRow = -1; + + if (sel_track == i && trackData->editText) + editRow = viewInfo->rowPos; + + int size = renderChannel(viewInfo, syncData->tracks[i], editRow, x_pos, adjust_top_size, y_pos_row, y_pos_row + end_row, y_end_border, i, selectLeft, selectRight, selectTop, selectBottom); if (sel_track == i) From 33e09bd2510f4800ed590eecd1fe311c32e54229 Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Sun, 4 Nov 2012 12:57:34 +0100 Subject: [PATCH 19/25] Fixed so the track data is cleared when loading new one Closes #30 --- ogl_editor/src/loadsave.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ogl_editor/src/loadsave.c b/ogl_editor/src/loadsave.c index 86df494..66b9a60 100644 --- a/ogl_editor/src/loadsave.c +++ b/ogl_editor/src/loadsave.c @@ -2,6 +2,7 @@ #include "Dialog.h" #include "TrackData.h" #include "External/mxml/mxml.h" +#include "RemoteConnection.h" #include "../../sync/data.h" #include #include @@ -55,6 +56,8 @@ static void parseXml(mxml_node_t* rootNode, TrackData* trackData) if (!strcmp("track", element_name)) { + int i; + // TODO: Create the new track/channel here const char* track_name = mxmlElementGetAttr(node, "name"); @@ -62,6 +65,21 @@ static void parseXml(mxml_node_t* rootNode, TrackData* trackData) track_index = TrackData_createGetTrack(trackData, track_name); printf("track_index %d\n", track_index); + struct sync_track* track = trackData->syncData.tracks[track_index]; + + // If we already have this track loaded we delete all the existing keys + + for (i = 0; i < track->num_keys; ++i) + { + int row = track->keys[i].row; + RemoteConnection_sendDeleteKeyCommand(track->name, row); + } + + free(track->keys); + + track->keys = 0; + track->num_keys = 0; + printf("Creating track/channel with name %s\n", track_name); } else if (!strcmp("key", element_name)) From 1db38f6765ea3dc355b58068e711b7bc70d0e2f6 Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Sun, 4 Nov 2012 12:58:08 +0100 Subject: [PATCH 20/25] Demo wasn't told about deleted keys when doing cut'n'paste --- ogl_editor/src/Editor.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ogl_editor/src/Editor.c b/ogl_editor/src/Editor.c index bf09992..ccaadca 100644 --- a/ogl_editor/src/Editor.c +++ b/ogl_editor/src/Editor.c @@ -231,6 +231,9 @@ static void deleteArea(int rowPos, int track, int bufferWidth, int bufferHeight) for (j = 0; j < bufferHeight; ++j) { int row = rowPos + j; + + RemoteConnection_sendDeleteKeyCommand(t->name, row); + if (is_key_frame(t, row)) sync_del_key(t, row); } From c139273f159d7bf9b72f71444549dac4eb2fdc73 Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Sun, 4 Nov 2012 21:06:22 +0100 Subject: [PATCH 21/25] Make sure to use some opts when building for release --- tundra.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tundra.lua b/tundra.lua index 785e61e..d7d0f43 100644 --- a/tundra.lua +++ b/tundra.lua @@ -13,7 +13,8 @@ Build { LIBPATH = { "/usr/lib/gcc/i686-apple-darwin10/4.2.1/x86_64" }, CPPDEFS = { "SDLROCKET_MACOSX" }, CCOPTS = { - { "-g", "-O0" ; Config = { "*-gcc-debug", "*-clang-debug" } } + { "-g", "-O0" ; Config = { "*-gcc-debug", "*-clang-debug" } }, + { "-g", "-O3" ; Config = { "*-clang-release" } } }, CXXOPTS = { { "-g", "-O0"; Config = "macosx-clang-debug" }, From 6af1954d504840b01abfe2afa8182407056d2015 Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Sun, 4 Nov 2012 21:07:09 +0100 Subject: [PATCH 22/25] As the data for SET_ROW can fail because of multiple sends we do a couple of retries to get the correct data --- ogl_editor/src/Editor.c | 29 ++++++++++++++++++++++++----- ogl_editor/src/RemoteConnection.c | 4 ++-- ogl_editor/src/RemoteConnection.h | 2 +- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/ogl_editor/src/Editor.c b/ogl_editor/src/Editor.c index ccaadca..ea3645a 100644 --- a/ogl_editor/src/Editor.c +++ b/ogl_editor/src/Editor.c @@ -217,8 +217,6 @@ static void deleteArea(int rowPos, int track, int bufferWidth, int bufferHeight) const int track_count = getTrackCount(); struct sync_track** tracks = getTracks(); - rlog(R_INFO, "rowPos %d track %d bw %d bh %d\n", bufferWidth, bufferHeight); - for (i = 0; i < bufferWidth; ++i) { size_t trackPos = track + i; @@ -591,10 +589,31 @@ static int processCommands() case SET_ROW: { - RemoteConnection_recv((char*)&newRow, sizeof(int), 0); - s_editorData.trackViewInfo.rowPos = htonl(newRow); - rlog(R_INFO, "row from demo %d\n", s_editorData.trackViewInfo.rowPos); + int i = 0; + ret = RemoteConnection_recv((char*)&newRow, sizeof(int), 0); + + if (ret == -1) + { + // retry to get the data and do it for max of 20 times otherwise disconnect + + for (i = 0; i < 20; ++i) + { + if (RemoteConnection_recv((char*)&newRow, sizeof(int), 0) == 4) + { + s_editorData.trackViewInfo.rowPos = htonl(newRow); + rlog(R_INFO, "row from demo %d\n", s_editorData.trackViewInfo.rowPos); + return 1; + } + } + } + else + { + s_editorData.trackViewInfo.rowPos = htonl(newRow); + rlog(R_INFO, "row from demo %d\n", s_editorData.trackViewInfo.rowPos); + } + ret = 1; + break; } } diff --git a/ogl_editor/src/RemoteConnection.c b/ogl_editor/src/RemoteConnection.c index 4c81ba0..30e2a27 100644 --- a/ogl_editor/src/RemoteConnection.c +++ b/ogl_editor/src/RemoteConnection.c @@ -252,7 +252,7 @@ void RemoteConnection_disconnect() /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool RemoteConnection_recv(char* buffer, size_t length, int flags) +int RemoteConnection_recv(char* buffer, size_t length, int flags) { int ret; @@ -267,7 +267,7 @@ bool RemoteConnection_recv(char* buffer, size_t length, int flags) return false; } - return true; + return ret; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/ogl_editor/src/RemoteConnection.h b/ogl_editor/src/RemoteConnection.h index 4903da7..923cc94 100644 --- a/ogl_editor/src/RemoteConnection.h +++ b/ogl_editor/src/RemoteConnection.h @@ -18,7 +18,7 @@ void RemoteConnection_close(); bool RemoteConnection_isPaused(); bool RemoteConnection_connected(); void RemoteConnection_disconnect(); -bool RemoteConnection_recv(char* buffer, size_t length, int flags); +int RemoteConnection_recv(char* buffer, size_t length, int flags); bool RemoteConnection_send(const char* buffer, size_t length, int flags); bool RemoteConnection_pollRead(); From 56b30807028abb4dd5b553fb8584eb3dea0ad900 Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Tue, 6 Nov 2012 08:01:24 +0100 Subject: [PATCH 23/25] Fixed so status bar is visible even if we don't have any proper track data --- ogl_editor/src/Editor.c | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/ogl_editor/src/Editor.c b/ogl_editor/src/Editor.c index ea3645a..08433e3 100644 --- a/ogl_editor/src/Editor.c +++ b/ogl_editor/src/Editor.c @@ -120,30 +120,37 @@ void Editor_init() static void drawStatus() { char temp[256]; - struct sync_track** tracks = getTracks(); - - if (!tracks) - return; - - int active_track = getActiveTrack(); - const struct sync_track* track = tracks[active_track]; - const int sizeY = s_editorData.trackViewInfo.windowSizeY; - int row = s_editorData.trackViewInfo.rowPos; - int idx = key_idx_floor(track, row); + int active_track = 0; + int current_row = 0; + float value = 0.0f; const char *str = "---"; - if (idx >= 0) + struct sync_track** tracks = getTracks(); + const int sizeY = s_editorData.trackViewInfo.windowSizeY; + + active_track = getActiveTrack(); + current_row = s_editorData.trackViewInfo.rowPos; + + if (tracks) { - switch (track->keys[idx].type) + const struct sync_track* track = tracks[active_track]; + int row = s_editorData.trackViewInfo.rowPos; + int idx = key_idx_floor(track, row); + if (idx >= 0) { - case KEY_STEP: str = "step"; break; - case KEY_LINEAR: str = "linear"; break; - case KEY_SMOOTH: str = "smooth"; break; - case KEY_RAMP: str = "ramp"; break; - default: break; + switch (track->keys[idx].type) + { + case KEY_STEP: str = "step"; break; + case KEY_LINEAR: str = "linear"; break; + case KEY_SMOOTH: str = "smooth"; break; + case KEY_RAMP: str = "ramp"; break; + default: break; + } } + + value = sync_get_val(track, row); } - snprintf(temp, 256, "track %d row %d value %f type %s", active_track, row, sync_get_val(track, row), str); + snprintf(temp, 256, "track %d row %d value %f type %s", active_track, current_row, value, str); Emgui_fill(Emgui_color32(0x10, 0x10, 0x10, 0xff), 1, sizeY - 12, 400, 11); Emgui_drawText(temp, 3, sizeY - 10, Emgui_color32(255, 255, 255, 255)); From 06da6735850288899f439b18b7f8e2483050d209 Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Tue, 6 Nov 2012 08:11:11 +0100 Subject: [PATCH 24/25] Fixed correct handing of mouse position --- ogl_editor/src/macosx/RocketView.m | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ogl_editor/src/macosx/RocketView.m b/ogl_editor/src/macosx/RocketView.m index 5bbdb73..8332e2c 100644 --- a/ogl_editor/src/macosx/RocketView.m +++ b/ogl_editor/src/macosx/RocketView.m @@ -127,8 +127,9 @@ NSWindow* window = [self window]; NSRect originalFrame = [window frame]; NSPoint location = [window mouseLocationOutsideOfEventStream]; + NSRect adjustFrame = [NSWindow contentRectForFrameRect: originalFrame styleMask: NSTitledWindowMask]; - Emgui_setMousePos((int)location.x, (int)originalFrame.size.height - (int)location.y); + Emgui_setMousePos((int)location.x, (int)adjustFrame.size.height - (int)location.y); Editor_update(); } @@ -147,8 +148,9 @@ NSWindow *window = [self window]; NSRect originalFrame = [window frame]; NSPoint location = [window mouseLocationOutsideOfEventStream]; + NSRect adjustFrame = [NSWindow contentRectForFrameRect: originalFrame styleMask: NSTitledWindowMask]; - Emgui_setMousePos((int)location.x, (int)originalFrame.size.height - (int)location.y); + Emgui_setMousePos((int)location.x, (int)adjustFrame.size.height - (int)location.y); Emgui_setMouseLmb(1); Editor_update(); From f11348dafdcaf618ff2167055704f8a52ec077eb Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Tue, 6 Nov 2012 08:11:29 +0100 Subject: [PATCH 25/25] Started with adding some editbox(es) to the status-bar --- ogl_editor/src/Editor.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ogl_editor/src/Editor.c b/ogl_editor/src/Editor.c index 08433e3..2d57679 100644 --- a/ogl_editor/src/Editor.c +++ b/ogl_editor/src/Editor.c @@ -115,6 +115,8 @@ void Editor_init() { } +static char s_numRows[64] = "10000"; + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static void drawStatus() @@ -154,6 +156,7 @@ static void drawStatus() Emgui_fill(Emgui_color32(0x10, 0x10, 0x10, 0xff), 1, sizeY - 12, 400, 11); Emgui_drawText(temp, 3, sizeY - 10, Emgui_color32(255, 255, 255, 255)); + Emgui_editBoxXY(400, sizeY - 14, 100, 12, s_numRows); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////