void OBSBasicPreview::DrawSceneEditing() { if (locked) return; OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow()); gs_effect_t *solid = obs_get_base_effect(OBS_EFFECT_SOLID); gs_technique_t *tech = gs_effect_get_technique(solid, "Solid"); vec4 color; vec4_set(&color, 1.0f, 0.0f, 0.0f, 1.0f); gs_effect_set_vec4(gs_effect_get_param_by_name(solid, "color"), &color); gs_technique_begin(tech); gs_technique_begin_pass(tech, 0); OBSScene scene = main->GetCurrentScene(); if (scene) { gs_matrix_push(); gs_matrix_scale3f(main->previewScale, main->previewScale, 1.0f); obs_scene_enum_items(scene, DrawSelectedItem, this); gs_matrix_pop(); } gs_load_vertexbuffer(nullptr); gs_technique_end_pass(tech); gs_technique_end(tech); }
void OBSBasicPreview::GetStretchHandleData(const vec2 &pos) { OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow()); OBSScene scene = main->GetCurrentScene(); if (!scene) return; float scale = main->previewScale / main->devicePixelRatio(); vec2 scaled_pos = pos; vec2_divf(&scaled_pos, &scaled_pos, scale); HandleFindData data(scaled_pos, scale); obs_scene_enum_items(scene, FindHandleAtPos, &data); stretchItem = std::move(data.item); stretchHandle = data.handle; if (stretchHandle != ItemHandle::None) { matrix4 boxTransform; vec3 itemUL; float itemRot; stretchItemSize = GetItemSize(stretchItem); obs_sceneitem_get_box_transform(stretchItem, &boxTransform); itemRot = obs_sceneitem_get_rot(stretchItem); vec3_from_vec4(&itemUL, &boxTransform.t); /* build the item space conversion matrices */ matrix4_identity(&itemToScreen); matrix4_rotate_aa4f(&itemToScreen, &itemToScreen, 0.0f, 0.0f, 1.0f, RAD(itemRot)); matrix4_translate3f(&itemToScreen, &itemToScreen, itemUL.x, itemUL.y, 0.0f); matrix4_identity(&screenToItem); matrix4_translate3f(&screenToItem, &screenToItem, -itemUL.x, -itemUL.y, 0.0f); matrix4_rotate_aa4f(&screenToItem, &screenToItem, 0.0f, 0.0f, 1.0f, RAD(-itemRot)); obs_sceneitem_get_crop(stretchItem, &startCrop); obs_sceneitem_get_pos(stretchItem, &startItemPos); obs_source_t *source = obs_sceneitem_get_source(stretchItem); cropSize.x = float(obs_source_get_width(source) - startCrop.left - startCrop.right); cropSize.y = float(obs_source_get_height(source) - startCrop.top - startCrop.bottom); stretchGroup = obs_sceneitem_get_group(scene, stretchItem); if (stretchGroup) { obs_sceneitem_get_draw_transform(stretchGroup, &invGroupTransform); matrix4_inv(&invGroupTransform, &invGroupTransform); obs_sceneitem_defer_group_resize_begin(stretchGroup); } } }
static void AddExisting(const char *name, bool visible, bool duplicate) { OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow()); OBSScene scene = main->GetCurrentScene(); if (!scene) return; obs_source_t *source = obs_get_source_by_name(name); if (source) { if (duplicate) { obs_source_t *from = source; char *new_name = get_new_source_name(name); source = obs_source_duplicate(from, new_name, false); bfree(new_name); obs_source_release(from); if (!source) return; } AddSourceData data; data.source = source; data.visible = visible; obs_enter_graphics(); obs_scene_atomic_update(scene, AddSource, &data); obs_leave_graphics(); obs_source_release(source); } }
void OBSBasicPreview::DoSelect(const vec2 &pos) { OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow()); OBSScene scene = main->GetCurrentScene(); OBSSceneItem item = GetItemAtPos(pos, true); obs_scene_enum_items(scene, select_one, (obs_sceneitem_t*)item); }
void OBSBasic::AddDropSource(const char *data, DropType image) { OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow()); obs_data_t *settings = obs_data_create(); obs_source_t *source = nullptr; const char *type = nullptr; QString name; switch (image) { case DropType_RawText: obs_data_set_string(settings, "text", data); #ifdef _WIN32 type = "text_gdiplus"; #else type = "text_ft2_source"; #endif break; case DropType_Text: #ifdef _WIN32 obs_data_set_bool(settings, "read_from_file", true); obs_data_set_string(settings, "file", data); name = QUrl::fromLocalFile(QString(data)).fileName(); type = "text_gdiplus"; #else obs_data_set_bool(settings, "from_file", true); obs_data_set_string(settings, "text_file", data); type = "text_ft2_source"; #endif break; case DropType_Image: obs_data_set_string(settings, "file", data); name = QUrl::fromLocalFile(QString(data)).fileName(); type = "image_source"; break; case DropType_Media: obs_data_set_string(settings, "local_file", data); name = QUrl::fromLocalFile(QString(data)).fileName(); type = "ffmpeg_source"; break; } if (name.isEmpty()) name = obs_source_get_display_name(type); source = obs_source_create(type, GenerateSourceName(QT_TO_UTF8(name)).c_str(), settings, nullptr); if (source) { OBSScene scene = main->GetCurrentScene(); obs_scene_add(scene, source); obs_source_release(source); } obs_data_release(settings); }
bool OBSBasicPreview::SelectedAtPos(const vec2 &pos) { OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow()); OBSScene scene = main->GetCurrentScene(); if (!scene) return false; SceneFindData data(pos, false); obs_scene_enum_items(scene, CheckItemSelected, &data); return !!data.item; }
OBSSceneItem OBSBasicPreview::GetItemAtPos(const vec2 &pos, bool selectBelow) { OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow()); OBSScene scene = main->GetCurrentScene(); if (!scene) return OBSSceneItem(); SceneFindData data(pos, selectBelow); obs_scene_enum_items(scene, FindItemAtPos, &data); return data.item; }
void OBSBasicPreview::mouseMoveEvent(QMouseEvent *event) { if (scrollMode && event->buttons() == Qt::LeftButton) { scrollingOffset.x += event->x() - scrollingFrom.x; scrollingOffset.y += event->y() - scrollingFrom.y; scrollingFrom.x = event->x(); scrollingFrom.y = event->y(); emit DisplayResized(); return; } if (locked) return; if (mouseDown) { vec2 pos = GetMouseEventPos(event); if (!mouseMoved && !mouseOverItems && stretchHandle == ItemHandle::None) { ProcessClick(startPos); mouseOverItems = SelectedAtPos(startPos); } pos.x = std::round(pos.x); pos.y = std::round(pos.y); if (stretchHandle != ItemHandle::None) { OBSBasic *main = reinterpret_cast<OBSBasic*>( App()->GetMainWindow()); OBSScene scene = main->GetCurrentScene(); obs_sceneitem_t *group = obs_sceneitem_get_group( scene, stretchItem); if (group) { vec3 group_pos; vec3_set(&group_pos, pos.x, pos.y, 0.0f); vec3_transform(&group_pos, &group_pos, &invGroupTransform); pos.x = group_pos.x; pos.y = group_pos.y; } if (cropping) CropItem(pos); else StretchItem(pos); } else if (mouseOverItems) { MoveItems(pos); } mouseMoved = true; } }
void OBSBasicPreview::SnapItemMovement(vec2 &offset) { OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow()); OBSScene scene = main->GetCurrentScene(); SelectedItemBounds data; obs_scene_enum_items(scene, AddItemBounds, &data); data.tl.x += offset.x; data.tl.y += offset.y; data.br.x += offset.x; data.br.y += offset.y; vec3 snapOffset = GetSnapOffset(data.tl, data.br); const bool snap = config_get_bool(GetGlobalConfig(), "BasicWindow", "SnappingEnabled"); const bool sourcesSnap = config_get_bool(GetGlobalConfig(), "BasicWindow", "SourceSnapping"); if (snap == false) return; if (sourcesSnap == false) { offset.x += snapOffset.x; offset.y += snapOffset.y; return; } const float clampDist = config_get_double(GetGlobalConfig(), "BasicWindow", "SnapDistance") / main->previewScale; OffsetData offsetData; offsetData.clampDist = clampDist; offsetData.tl = data.tl; offsetData.br = data.br; vec3_copy(&offsetData.offset, &snapOffset); obs_scene_enum_items(scene, GetSourceSnapOffset, &offsetData); if (fabsf(offsetData.offset.x) > EPSILON || fabsf(offsetData.offset.y) > EPSILON) { offset.x += offsetData.offset.x; offset.y += offsetData.offset.y; } else { offset.x += snapOffset.x; offset.y += snapOffset.y; } }
void OBSBasicPreview::MoveItems(const vec2 &pos) { Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers(); OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow()); OBSScene scene = main->GetCurrentScene(); vec2 offset, moveOffset; vec2_sub(&offset, &pos, &startPos); vec2_sub(&moveOffset, &offset, &lastMoveOffset); if (!(modifiers & Qt::ControlModifier)) SnapItemMovement(moveOffset); vec2_add(&lastMoveOffset, &lastMoveOffset, &moveOffset); obs_scene_enum_items(scene, move_items, &moveOffset); }
void OBSBasicPreview::SnapItemMovement(vec2 &offset) { OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow()); OBSScene scene = main->GetCurrentScene(); SelectedItemBounds data; obs_scene_enum_items(scene, AddItemBounds, &data); data.tl.x += offset.x; data.tl.y += offset.y; data.br.x += offset.x; data.br.y += offset.y; vec3 snapOffset = GetScreenSnapOffset(data.tl, data.br); offset.x += snapOffset.x; offset.y += snapOffset.y; }
bool OBSBasicSourceSelect::EnumGroups(void *data, obs_source_t *source) { OBSBasicSourceSelect *window = static_cast<OBSBasicSourceSelect*>(data); const char *name = obs_source_get_name(source); const char *id = obs_source_get_id(source); if (strcmp(id, window->id) == 0) { OBSBasic *main = reinterpret_cast<OBSBasic*>( App()->GetMainWindow()); OBSScene scene = main->GetCurrentScene(); obs_sceneitem_t *existing = obs_scene_get_group(scene, name); if (!existing) window->ui->sourceList->addItem(QT_UTF8(name)); } return true; }
void OBSBasicPreview::GetStretchHandleData(const vec2 &pos) { OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow()); OBSScene scene = main->GetCurrentScene(); if (!scene) return; HandleFindData data(pos, main->previewScale); obs_scene_enum_items(scene, FindHandleAtPos, &data); stretchItem = std::move(data.item); stretchHandle = data.handle; if (stretchHandle != ItemHandle::None) { matrix4 boxTransform; vec3 itemUL; float itemRot; stretchItemSize = GetItemSize(stretchItem); obs_sceneitem_get_box_transform(stretchItem, &boxTransform); itemRot = obs_sceneitem_getrot(stretchItem); vec3_from_vec4(&itemUL, &boxTransform.t); /* build the item space conversion matrices */ matrix4_identity(&itemToScreen); matrix4_rotate_aa4f(&itemToScreen, &itemToScreen, 0.0f, 0.0f, 1.0f, RAD(itemRot)); matrix4_translate3f(&itemToScreen, &itemToScreen, itemUL.x, itemUL.y, 0.0f); matrix4_identity(&screenToItem); matrix4_translate3f(&screenToItem, &screenToItem, -itemUL.x, -itemUL.y, 0.0f); matrix4_rotate_aa4f(&screenToItem, &screenToItem, 0.0f, 0.0f, 1.0f, RAD(-itemRot)); } }
void OBSBasic::AddDropSource(const char *data, DropType image) { OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow()); obs_data_t *settings = obs_data_create(); obs_source_t *source = nullptr; const char *type = nullptr; switch (image) { case DropType_RawText: obs_data_set_string(settings, "text", data); type = "text_gdiplus"; break; case DropType_Text: obs_data_set_bool(settings, "read_from_file", true); obs_data_set_string(settings, "file", data); type = "text_gdiplus"; break; case DropType_Image: obs_data_set_string(settings, "file", data); type = "image_source"; break; case DropType_Media: obs_data_set_string(settings, "local_file", data); type = "ffmpeg_source"; break; } const char *name = obs_source_get_display_name(type); source = obs_source_create(type, GenerateSourceName(name).c_str(), settings, nullptr); if (source) { OBSScene scene = main->GetCurrentScene(); obs_scene_add(scene, source); obs_source_release(source); } obs_data_release(settings); }
void OBSBasicPreview::DrawSceneEditing() { OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow()); effect_t solid = obs_get_solid_effect(); technique_t tech = effect_gettechnique(solid, "Solid"); vec4 color; vec4_set(&color, 1.0f, 0.0f, 0.0f, 1.0f); effect_setvec4(solid, effect_getparambyname(solid, "color"), &color); technique_begin(tech); technique_beginpass(tech, 0); OBSScene scene = main->GetCurrentScene(); if (scene) obs_scene_enum_items(scene, DrawSelectedItem, this); gs_load_vertexbuffer(nullptr); technique_endpass(tech); technique_end(tech); }
bool AddNew(QWidget *parent, const char *id, const char *name, const bool visible, OBSSource &newSource) { OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow()); OBSScene scene = main->GetCurrentScene(); bool success = false; if (!scene) return false; obs_source_t *source = obs_get_source_by_name(name); if (source) { OBSMessageBox::information(parent, QTStr("NameExists.Title"), QTStr("NameExists.Text")); } else { source = obs_source_create(id, name, NULL, nullptr); if (source) { AddSourceData data; data.source = source; data.visible = visible; obs_enter_graphics(); obs_scene_atomic_update(scene, AddSource, &data); obs_leave_graphics(); newSource = source; success = true; } } obs_source_release(source); return success; }