static void renderText(const struct TrackInfo* info, struct sync_track* track, int row, int idx, int x, int y, bool folded) { uint32_t color = (row & 7) ? Emgui_color32(0x4f, 0x4f, 0x4f, 0xff) : Emgui_color32(0x7f, 0x7f, 0x7f, 0xff); if (folded) { if (idx >= 0) Emgui_fill(color, x, y - font_size_half, 8, 8); else Emgui_drawText("-", x, y - font_size_half, color); } else { if (idx >= 0) { char temp[256]; float value = track->keys[idx].value; snprintf(temp, 256, "% .2f", value); Emgui_drawText(temp, x, y - font_size_half, Emgui_color32(255, 255, 255, 255)); } else { Emgui_drawText("---", x, y - font_size_half, color); } } }
static void printRowNumbers(int x, int y, int rowCount, int rowOffset, int rowSpacing, int maskBpm, int endY) { int i; Emgui_setDefaultFont(); if (rowOffset < 0) { y += rowSpacing * -rowOffset; rowOffset = 0; } for (i = 0; i < rowCount; ++i) { char rowText[16]; memset(rowText, 0, sizeof(rowText)); sprintf(rowText, "%05d", rowOffset); if (rowOffset % maskBpm) Emgui_drawText(rowText, x, y, Emgui_color32(0xa0, 0xa0, 0xa0, 0xff)); else Emgui_drawText(rowText, x, y, Emgui_color32(0xf0, 0xf0, 0xf0, 0xff)); y += rowSpacing; rowOffset++; if (y > endY) break; } }
static void renderInterpolation(const struct TrackInfo* info, struct sync_track* track, int size, int idx, int x, int y, bool folded) { int fidx; enum key_type interpolationType; uint32_t color = 0; // This is kinda crappy implementation as we will overdraw this quite a bit but might be fine fidx = idx >= 0 ? idx : -idx - 2; interpolationType = (fidx >= 0) ? track->keys[fidx].type : KEY_STEP; switch (interpolationType) { case KEY_STEP : color = Emgui_color32(0, 0, 0, 255);; 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 (info->viewInfo) Emgui_fill(color, x + (size - 8), y - font_size_half, 2, (info->endSizeY - y) + font_size - 1); }
static int drawConnectionStatus(int posX, int sizeY) { char* conStatus; RemoteConnection_getConnectionStatus(&conStatus); Emgui_drawBorder(Emgui_color32(10, 10, 10, 255), Emgui_color32(10, 10, 10, 255), posX, sizeY - 17, 200, 15); Emgui_drawText(conStatus, posX + 4, sizeY - 15, Emgui_color32(160, 160, 160, 255)); return posX + 200; }
static bool drawColorButton(uint32_t color, int x, int y, int size) { const uint32_t colorFade = Emgui_color32(32, 32, 32, 255); Emgui_fill(color, x, y, size - 8, 8); return Emgui_buttonCoords("", colorFade, x, y, size - 8, 8); }
static int drawNameValue(char* name, int posX, int sizeY, int* value, int low, int high, char* buffer) { int current_value; int text_size = Emgui_getTextSize(name) & 0xffff; Emgui_drawText(name, posX + 4, sizeY - 15, Emgui_color32(160, 160, 160, 255)); current_value = atoi(buffer); if (current_value != *value) { if (buffer[0] != 0) snprintf(buffer, 64, "%d", *value); } Emgui_editBoxXY(posX + text_size + 6, sizeY - 15, 50, 13, 64, buffer); current_value = atoi(buffer); if (current_value != *value) { current_value = eclampi(current_value, low, high); if (buffer[0] != 0) snprintf(buffer, 64, "%d", current_value); *value = current_value; } return text_size + 56; }
static int renderGroupHeader(Group* group, int x, int y, int groupSize, int windowSizeX) { // If the group size is larger than the actual screen we adjust it a bit to make the text more visible if (x + groupSize > windowSizeX) groupSize = windowSizeX - x; drawColorButton(Emgui_color32(127, 127, 127, 255), x + 3, y - colorbar_adjust, groupSize); renderName(group->displayName, x, y - name_adjust, groupSize, group->folded, true); return 0; }
static void drawStatus() { int size = 0; const int sizeY = s_editorData.trackViewInfo.windowSizeY; const int sizeX = s_editorData.trackViewInfo.windowSizeX; const int prevRow = getRowPos(); Emgui_setFont(s_editorData.trackViewInfo.smallFontId); Emgui_fill(Emgui_color32(20, 20, 20, 255), 2, sizeY - 15, sizeX - 3, 13); Emgui_drawBorder(Emgui_color32(10, 10, 10, 255), Emgui_color32(10, 10, 10, 255), 0, sizeY - 17, sizeX - 2, 15); size = drawConnectionStatus(0, sizeY); size += drawCurrentValue(size, sizeY); size += drawNameValue("Row", size, sizeY, &s_editorData.trackViewInfo.rowPos, 0, 20000 - 1, s_currentRow); size += drawNameValue("Start Row", size, sizeY, &s_editorData.trackData.startRow, 0, 10000000, s_startRow); size += drawNameValue("End Row", size, sizeY, &s_editorData.trackData.endRow, 0, 10000000, s_endRow); if (getRowPos() != prevRow) RemoteConnection_sendSetRowCommand(getRowPos()); Emgui_setDefaultFont(); }
void RenderAudio_update(struct TrackData* trackData, int xPos, int yPos, int rowCount, int rowOffset, int rowSpacing, int endY) { uint32_t* fftData = trackData->musicData.fftData; if (!fftData) return; // first calculate the total number of textures we need (we allocate 128 x 1024 textures to be compatible to fairly low-end GPUs) int count = (int)(((float)endY) / (float)TEXTURE_HEIGHT) + 1; if (s_data.textureCount < count) { for (int i = s_data.textureCount; i < count; ++i) { s_data.textureIds[i] = EMGFXBackend_createTexture(0, 128, TEXTURE_HEIGHT, 4); s_data.textureData[i] = malloc(128 * TEXTURE_HEIGHT * 4); } s_data.textureCount = count; } int texturePos = 0; if (rowOffset < 0) { rowOffset = -rowOffset; for (int i = 0; i < rowOffset; ++i) { const int textureIndex = texturePos >> 17; const int textureOffset = texturePos & 0x1ffff; uint32_t* textureDest = &s_data.textureData[textureIndex][textureOffset]; fillColor(textureDest, Emgui_color32(0, 0, 0, 255), rowSpacing); texturePos += 128 * rowSpacing; } yPos += rowSpacing * rowOffset; rowOffset = 0; }
static int drawCurrentValue(int posX, int sizeY) { char valueText[256]; float value = 0.0f; int active_track = 0; int current_row = 0; const char *str = "---"; struct sync_track** tracks = getTracks(); active_track = getActiveTrack(); current_row = getRowPos(); if (tracks) { const struct sync_track* track = tracks[active_track]; int idx = key_idx_floor(track, current_row); if (idx >= 0) { 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 = (float)sync_get_val(track, current_row); } snprintf(valueText, 256, "%f", value); Emgui_drawText(valueText, posX + 4, sizeY - 15, Emgui_color32(160, 160, 160, 255)); Emgui_drawBorder(Emgui_color32(10, 10, 10, 255), Emgui_color32(10, 10, 10, 255), posX, sizeY - 17, 80, 15); Emgui_drawText(str, posX + 85, sizeY - 15, Emgui_color32(160, 160, 160, 255)); Emgui_drawBorder(Emgui_color32(10, 10, 10, 255), Emgui_color32(10, 10, 10, 255), posX + 80, sizeY - 17, 40, 15); return 130; }
int decodeFunc(void* inData) { int a, b, r, g, i; //short waveData[8 * 1024]; unsigned int* fftPtr; unsigned int* fftOutput; float fftData[1024]; //double timeInSec = 0.0; const float maxIntensity = 500 * 2; const int COLOR_STEPS = 255; const int PALETTE_SIZE = 3 * COLOR_STEPS; const int spectrumLength = 1024; ThreadFuncData* threadData = (ThreadFuncData*)inData; unsigned int colors[255 * 3]; int imageHeight = 128; HSTREAM chan = threadData->stream; MusicData* data = threadData->data; float percentDone = 1.0f; float step = 0.0f; mtx_lock(&s_mutex); const int SAMPLING_FREQUENCY = 100; //warning: in TimelineImage this samplingfrequency is assumed to be 100 const double SAMPLING_RESOLUTION = 1.0 / SAMPLING_FREQUENCY; QWORD sampleLength = BASS_ChannelSeconds2Bytes(chan, SAMPLING_RESOLUTION); int numSamples = (int)((double)BASS_ChannelGetLength(chan, BASS_POS_BYTE) / (double)sampleLength); //printf("Num samples %d\n", (int)sampleLength); //printf("Num samples %d\n", numSamples); BASS_ChannelPlay(chan, 0); int j_table[128]; int pj_table[128]; int nj_table[128]; // TODO: Size optimize? data->sampleCount = numSamples; fftPtr = fftOutput = (unsigned int*)malloc(128 * 4 * (numSamples + 1)); //const int spectrumLength = 1024; //const int imageHeight = 256; //var spectrumImage = new Bitmap((int)numSamples, imageHeight); //var volumeImage = new Bitmap((int)numSamples, imageHeight); //s_editorData.waveViewSize = 128; //s_editorData.trackViewInfo.windowSizeX -= s_editorData.waveViewSize; //timeInSec =(DWORD)BASS_ChannelBytes2Seconds(chan, len); //printf(" %u:%02u\n", (int)timeInSec / 60, (int)timeInSec % 60); for (i = 0; i < PALETTE_SIZE; ++i) { a = 255; if (i < PALETTE_SIZE * 0.666f) a = (int)(i * 255 / (PALETTE_SIZE * 0.666f)); b = 0; if (i < PALETTE_SIZE * 0.333f) b = i; else if (i < PALETTE_SIZE * 0.666f) b = -i + 510; r = 0; if (i > PALETTE_SIZE * 0.666f) r = 255; else if (i > PALETTE_SIZE * 0.333f) r = i - 255; g = 0; if (i > PALETTE_SIZE * 0.666f) g = i - 510; colors[i] = Emgui_color32((uint8_t)r, (uint8_t)g, (uint8_t)b, (uint8_t)a); } float f = (float)(spectrumLength / log((float)(imageHeight + 1))); float f2 = (float)((PALETTE_SIZE - 1) / log(maxIntensity + 1)); (void)f2; for (int rowIndex = 0; rowIndex < imageHeight; ++rowIndex) { int j_ = (int)(f * log(rowIndex + 1)); int pj_ = (int)(rowIndex > 0 ? f * log(rowIndex - 1 + 1) : j_); int nj_ = (int)(rowIndex < imageHeight - 1 ? f * log(rowIndex + 1 + 1) : j_); j_table[rowIndex] = j_; pj_table[rowIndex] = pj_; nj_table[rowIndex] = nj_; } step = (float)(99.0f / numSamples); percentDone = 1.0f; for (int sampleIndex = 0; sampleIndex < numSamples; ++sampleIndex) { BASS_ChannelSetPosition(chan, sampleIndex * sampleLength, BASS_POS_BYTE); BASS_ChannelGetData(chan, fftData, BASS_DATA_FFT2048); data->percentDone = (int)(percentDone); //printf("%d/%d\n", sampleIndex, numSamples); for (int rowIndex = 0; rowIndex < imageHeight; ++rowIndex) { //int j_ = (int)(f * log(rowIndex + 1)); //int pj_ = (int)(rowIndex > 0 ? f * log(rowIndex - 1 + 1) : j_); //int nj_ = (int)(rowIndex < imageHeight - 1 ? f * log(rowIndex + 1 + 1) : j_); int j_ = j_table[(imageHeight - rowIndex) - 1]; int pj_ = pj_table[(imageHeight - rowIndex) - 1]; int nj_ = nj_table[(imageHeight - rowIndex) - 1]; //printf("index %d - %d %d %d\n", rowIndex, j_, pj_, nj_); float intensity = 125.0f * 4.0f * fftData[spectrumLength - pj_ - 1] + 750.0f * 4.0f * fftData[spectrumLength - j_ - 1] + 125.0f * 4.0f * fftData[spectrumLength - nj_ - 1]; if (intensity > maxIntensity) intensity = maxIntensity; if (intensity < 0.0f) intensity = 0.0f; int palettePos = (int)(f2 * log(intensity + 1)); *fftOutput++ = colors[palettePos]; } percentDone += step; } BASS_StreamFree(chan); free(threadData); data->percentDone = 100; data->fftData = fftPtr; mtx_unlock(&s_mutex); //printf("thread done\n"); return 1; }
bool TrackView_render(TrackViewInfo* viewInfo, TrackData* trackData) { struct TrackInfo info; int start_track = 0; //viewInfo->startTrack; int x_pos = 128; int end_track = 0; int i = 0; //int track_size; int adjust_top_size; int mid_screen_y ; int y_pos_row, end_row, y_end_border; s_needsUpdate = false; // Calc to position the selection in the ~middle of the screen adjust_top_size = 5 * font_size; mid_screen_y = (viewInfo->windowSizeY / 2) & ~(font_size - 1); y_pos_row = viewInfo->rowPos - (mid_screen_y / font_size); // TODO: Calculate how many channels we can draw given the width end_row = viewInfo->windowSizeY / font_size; y_end_border = viewInfo->windowSizeY - 48; // adjust to have some space at the end of the screen // Shared info for all tracks info.editText = trackData->editText; info.selectLeft = emini(viewInfo->selectStartTrack, viewInfo->selectStopTrack); info.selectRight = emaxi(viewInfo->selectStartTrack, viewInfo->selectStopTrack); info.selectTop = emini(viewInfo->selectStartRow, viewInfo->selectStopRow); info.selectBottom = emaxi(viewInfo->selectStartRow, viewInfo->selectStopRow); info.viewInfo = viewInfo; info.trackData = trackData; info.startY = adjust_top_size; info.startPos = y_pos_row; info.endPos = y_pos_row + end_row; info.endSizeY = y_end_border; info.midPos = mid_screen_y + adjust_top_size; if (trackData->groupCount == 0) return false; x_pos = TrackView_getStartOffset() + -viewInfo->startPixel; printRowNumbers(2, adjust_top_size, end_row, y_pos_row, font_size, trackData->highlightRowStep, y_end_border); Emgui_drawBorder(border_color, border_color, 48, info.startY - font_size * 4, viewInfo->windowSizeX - 80, (info.endSizeY - info.startY) + 40); Emgui_setLayer(1); Emgui_setScissor(48, 0, viewInfo->windowSizeX - 80, viewInfo->windowSizeY); Emgui_setFont(viewInfo->smallFontId); ///sel_track = setActiveTrack(viewInfo, trackData, trackData->activeTrack, x_pos); //if (sel_track != trackData->activeTrack) // TrackData_setActiveTrack(trackData, sel_track); for (i = start_track, end_track = trackData->syncData.num_tracks; i < end_track; ) { Track* track = &trackData->tracks[i]; Group* group = track->group; if (group->trackCount == 1) { int track_size = getTrackSize(viewInfo, track); if ((x_pos + track_size > 0) && (x_pos < viewInfo->windowSizeX)) { // if selected track is less than the first rendered track then we need to reset it to this one Emgui_setFont(info.viewInfo->smallFontId); renderChannel(&info, x_pos, track, false); } x_pos += track_size; ++i; } else { x_pos += renderGroup(group, track, x_pos, &i, info, trackData); } } Emgui_setDefaultFont(); Emgui_fill(Emgui_color32(127, 127, 127, 56), 0, mid_screen_y + adjust_top_size, viewInfo->windowSizeX, font_size + 1); //Emgui_setLayer(1); //drawBookmarks(trackData, 2, adjust_top_size, end_row, y_pos_row, viewInfo->windowSizeX, y_end_border); Emgui_setLayer(0); return s_needsUpdate; }
static int renderChannel(struct TrackInfo* info, int startX, Track* trackData, bool valuesOnly) { int y, y_offset; int text_size = 0; int size = min_track_size; int startPos = info->startPos; const int trackIndex = trackData->index; const int endPos = info->endPos; struct sync_track* track = 0; const uint32_t color = trackData->color; bool folded = false; if (!valuesOnly) { drawFoldButton(startX + 6, info->startY - (font_size + 5), &trackData->folded, trackData->active); folded = trackData->folded; if (info->trackData->syncData.tracks) track = info->trackData->syncData.tracks[trackData->index]; size = renderName(trackData->displayName, startX, info->startY - (font_size * 2), min_track_size, folded, trackData->active); if (folded) { text_size = size; size = track_size_folded; } if (trackData->active) { if (drawColorButton(color, startX + 4, info->startY - colorbar_adjust, size)) { Dialog_showColorPicker(&trackData->color); if (trackData->color != color) s_needsUpdate = true; } } else { Emgui_fill(border_color, startX + 4, info->startY - colorbar_adjust, size - 8, 8); } } Emgui_setDefaultFont(); y_offset = info->startY; folded = valuesOnly ? true : folded; size = valuesOnly ? track_size_folded : size; if (valuesOnly) { Emgui_fill(border_color, startX + size, info->startY - font_size * 4, 2, (info->endSizeY - info->startY) + 40); Emgui_fill(border_color, startX, info->startY - font_size * 4, 2, (info->endSizeY - info->startY) + 40); } else { Emgui_drawBorder(border_color, border_color, startX, info->startY - font_size * 4, size, (info->endSizeY - info->startY) + 40); } // if folded we should skip rendering the rows that are covered by the text if (folded) { int skip_rows = (text_size + font_size * 2) / font_size; if (startPos + skip_rows > 0) { startPos += skip_rows; y_offset += skip_rows * font_size; } } if (startPos < 0) { y_offset = info->startY + (font_size * -startPos); startPos = 0; } y_offset += font_size_half; for (y = startPos; y < endPos; ++y) { int idx = -1; int offset = startX + 6; bool selected; if (track) idx = sync_find_key(track, y); renderInterpolation(info, track, size, idx, offset, y_offset, folded); if (!(trackData->selected && info->viewInfo->rowPos == y && info->editText)) renderText(info, track, y, idx, offset, y_offset, folded); selected = (trackIndex >= info->selectLeft && trackIndex <= info->selectRight) && (y >= info->selectTop && y <= info->selectBottom); if (selected) Emgui_fill(selection_color, startX, y_offset - font_size_half, size, font_size); if (y != 0) { if (TrackData_hasBookmark(info->trackData, y)) Emgui_fill(bookmark_color, startX, y_offset - font_size_half, size, 8); } y_offset += font_size; if (y_offset > (info->endSizeY + font_size_half)) break; } if (!Emgui_hasKeyboardFocus()) { if (trackData->selected) { Emgui_fill(trackData->group->folded ? dark_active_track_color : active_track_color, startX, info->midPos, size, font_size + 1); if (info->editText) Emgui_drawText(info->editText, startX + 2, info->midPos, Emgui_color32(255, 255, 255, 255)); } } Emgui_setFont(info->viewInfo->smallFontId); return size; }