static void biasSelection(float value) { int track, row; struct sync_track** tracks = getTracks(); TrackViewInfo* viewInfo = getTrackViewInfo(); 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); // If we have no selection and no currenty key bias the previous key if (selectLeft == selectRight && selectTop == selectBottom) { int idx; struct sync_track* track; struct sync_track** tracks = getTracks(); if (!tracks || !tracks[getActiveTrack()]->keys) return; track = tracks[getActiveTrack()]; idx = sync_find_key(track, getRowPos()); if (idx < 0) { idx = -idx - 1; selectTop = selectBottom = track->keys[emaxi(idx - 1, 0)].row; } } Commands_beginMulti("biasSelection"); for (track = selectLeft; track <= selectRight; ++track) { struct sync_track* t = tracks[track]; for (row = selectTop; row <= selectBottom; ++row) { struct track_key newKey; int idx = sync_find_key(t, row); if (idx < 0) continue; newKey = t->keys[idx]; newKey.value += value; Commands_updateKey(track, &newKey); } } Commands_endMulti(); updateNeedsSaving(); }
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 execUpdateKey(void* userData) { struct UpdateKeyData* data = (struct UpdateKeyData*)userData; struct sync_track* t = s_syncTracks[data->track]; int idx = sync_find_key(t, data->key.row); data->oldKey = t->keys[idx]; sync_set_key(t, &data->key); RemoteConnection_sendSetKeyCommand(t->name, &data->key); }
static void execDeleteKey(void* userData) { struct DeleteKeyData* data = (struct DeleteKeyData*)userData; struct sync_track* t = s_syncTracks[data->track]; int idx = sync_find_key(t, data->row); data->oldKey = t->keys[idx]; sync_del_key(t, data->row); RemoteConnection_sendDeleteKeyCommand(t->name, data->row); }
static void endEditing() { const char* track_name; struct track_key key; struct sync_track* track; int row_pos = getRowPos(); int active_track = getActiveTrack(); if (!is_editing || !getTracks()) return; track = getTracks()[active_track]; if (strcmp(s_editBuffer, "")) { key.row = row_pos; key.value = (float)atof(s_editBuffer); key.type = 0; if (track->num_keys > 0) { int idx = sync_find_key(track, getRowPos()); if (idx > 0) { // exact match, keep current type key.type = track->keys[emaxi(idx, 0)].type; } else { // no match, grab type from previous key if (idx < 0) idx = -idx - 1; key.type = track->keys[emaxi(idx - 1, 0)].type; } } track_name = track->name; Commands_addOrUpdateKey(active_track, &key); updateNeedsSaving(); } is_editing = false; s_editorData.trackData.editText = 0; }
int sync_del_key(struct sync_track *t, int pos) { void *tmp; int idx = sync_find_key(t, pos); assert(idx >= 0); memmove(t->keys + idx, t->keys + idx + 1, sizeof(struct track_key) * (t->num_keys - idx - 1)); assert(t->keys); tmp = realloc(t->keys, sizeof(struct track_key) * (t->num_keys - 1)); if (t->num_keys != 1 && !tmp) return -1; t->num_keys--; t->keys = tmp; return 0; }
static void onPrevNextKey(bool prevKey, enum Selection selection) { struct sync_track* track; struct sync_track** tracks = getTracks(); TrackViewInfo* viewInfo = getTrackViewInfo(); if (!tracks || !tracks[getActiveTrack()]->keys) return; track = tracks[getActiveTrack()]; if (prevKey) { int idx = sync_find_key(track, getRowPos()); if (idx < 0) idx = -idx - 1; setRowPos(track->keys[emaxi(idx - 1, 0)].row); if (selection == DO_SELECTION) viewInfo->selectStopRow = getRowPos(); else viewInfo->selectStartRow = viewInfo->selectStopRow = getRowPos(); } else { int row = 0; int idx = key_idx_floor(track, getRowPos()); if (idx < 0) row = track->keys[0].row; else if (idx > (int)track->num_keys - 2) row = track->keys[track->num_keys - 1].row; else row = track->keys[idx + 1].row; setRowPos(row); if (selection == DO_SELECTION) viewInfo->selectStopRow = row; else viewInfo->selectStartRow = viewInfo->selectStopRow = row; } }
static void onEnterCurrentValue() { int idx; struct track_key key; struct sync_track* track; struct sync_track** tracks = getTracks(); const int rowPos = getRowPos(); const int activeTrack = getActiveTrack(); if (!tracks) return; track = tracks[activeTrack]; if (!track->keys) { key.row = rowPos; key.value = 0.0f; key.type = 0; Commands_addOrUpdateKey(activeTrack, &key); updateNeedsSaving(); return; } idx = sync_find_key(track, rowPos); if (idx < 0) idx = -idx - 1; key.row = rowPos; if (track->num_keys > 0) { key.value = (float)sync_get_val(track, rowPos); key.type = track->keys[emaxi(idx - 1, 0)].type; } else { key.value = 0.0f; key.type = 0; } Commands_addOrUpdateKey(activeTrack, &key); updateNeedsSaving(); }
int sync_set_key(struct sync_track *t, const struct track_key *k) { int idx = sync_find_key(t, k->row); if (idx < 0) { /* no exact hit, we need to allocate a new key */ void *tmp; idx = -idx - 1; tmp = realloc(t->keys, sizeof(struct track_key) * (t->num_keys + 1)); if (!tmp) return -1; t->num_keys++; t->keys = tmp; memmove(t->keys + idx + 1, t->keys + idx, sizeof(struct track_key) * (t->num_keys - idx - 1)); } t->keys[idx] = *k; return 0; }
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; }