diff --git a/data/org.kde.kdenlive.appdata.xml b/data/org.kde.kdenlive.appdata.xml index ad1e8eee3..7705fa291 100644 --- a/data/org.kde.kdenlive.appdata.xml +++ b/data/org.kde.kdenlive.appdata.xml @@ -1,325 +1,326 @@ org.kde.kdenlive.desktop CC0-1.0 GPL-2.0+ Kdenlive كدينلايڤ Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive Kdenlive xxKdenlivexx Kdenlive Kdenlive Video Editor محرّر فيديوهات Video uređivač Editor de vídeo Editor de vídeo Editor videa Videoredigering Video-Editor Επεξεργαστής βίντεο Video Editor Editor de video Videoredaktor Bideo editorea Videoeditori Éditeur vidéo Editor de vídeo Editor Video Editor video 동영상 편집기 Videobewerker Videoredigering Edytor wideo Editor de Vídeo Editor de Vídeo Видеоредактор Editor videa Urejevalnik videa Videoeditor Video Düzenleyicisi Відеоредактор xxVideo Editorxx 视频编辑器 影像編輯器

Kdenlive is a non linear video editor. It is based on the MLT framework and accepts many audio and video formats, allows you to add effects, transitions and render into the format of your choice.

«كدينلايڤ» هو محرّر فيديوهات غير خطّي. بُني على إطار عمل MLT ويقبل العديد من نُسق الصّوت والفيديو. كما ويسمح بإضافة التّأثيرات والانتقالات.

El Kdenlive és un editor no lineal de vídeo. Està basat en l'entorn de treball MLT i accepta molts formats d'àudio i vídeo, permetent afegir efectes, transicions i representacions en el format de la vostra elecció.

El Kdenlive és un editor no lineal de vídeo. Està basat en l'entorn de treball MLT i accepta molts formats d'àudio i vídeo, permetent afegir efectes, transicions i representacions en el format de la vostra elecció.

Kdenlive je nelineární video editor. Je založený na frameworku MLT a přehrává mnoho zvukových a video formátů, umožňuje přidat efekty, přechody a renderuje do formátu podle vašeho výběru.

Kdenlive er et ikke-lineært videoredigeringsprogram. Det er baseret på MLT-framework og accepterer mange lyd- og videoformater, som giver dig mulighed for at tilføje effekter, overgange og rendere i det format du ønsker.

Kdenlive ist ein Video-Editor für nichtlinearen Schnitt. Es basiert auf MLT und verarbeitet viele Audio- und Video-Formate. Sie können Effekte und Übergänge benutzen und in Formate Ihrer Wahl umwandeln.

Το Kdenlive είναι ένας μη γραμμικός επεξεργαστής βίντεο. Βασίζεται στο πλαίσιο εργασίας MLT και δέχεται πολλούς τύπους ήχου και βίντεο, επιτρέπει την προσθήκη εφέ, μεταβάσεων και αποτύπωσης στον τύπο αποθήκευσης της επιλογής σας.

Kdenlive is a non linear video editor. It is based on the MLT framework and accepts many audio and video formats, allows you to add effects, transitions and render into the format of your choice.

Kdenlive es un editor no lineal de video. Está basado en la infraestructura MLT y acepta numerosos formatos de audio y video, permitiendo agregar efectos, transiciones y procesar el video final en el formato deseado.

Kdenline on mittelineaarne videoredaktor. See tugineb MLT raamistikule ja võimaldab tarvitada paljusid heli- ja videovorminguid, lisada efekte ja üleminekuid ning renderdada tulemuse vajalikku vormingusse.

Kdenlive bideo editore ez-linear bat da. MLT azpiegituran oinarritua dago eta audio eta bideo formatu asko onartzen ditu, efektuak gehitzeko aukera eskaintzen dizu, trantsizioak eta zuk nahi duzun formatuan errendatzea.

Kdenlive on epälineaarinen videoeditori. Se perustuu MLT-frameworkiin ja toimii monen eri ääni- ja videoformaatin kanssa. Voit lisätä efektejä ja siirtymiä, sekä renderöidä projektin haluamaasi tiedostomuotoon.

Kdenlive est un éditeur vidéo non-linéaire. Il utilise le moteur MLT et accèpte de nombreux formats audio et vidéos, permet d'ajouter des effets et transitions, et exporte le rendu dans le format de votre choix.

Kdenlive é un editor de vídeo non lineal. Está baseado na infraestrutura MLT e permite moitos formatos de son e vídeo, e permite engadir efectos, engadir transicións, e exportar en calquera formato.

Kdenlive adalah sebuah editor video non linier. Ia berdasarkan pada MLT framework dan menerima berbagai format audio dan video, yang memungkinkan kamu untuk menambahkan efek, transisi, dan render ke dalam format yang kamu pilih.

Kdenlive è un editor video non lineare. È basato sull'infrastruttura MLT e accetta numerosi formati audio e video, consente di aggiungere effetti, transizioni e produrre il formato che si desidera.

Kdenlive는 비선형 동영상 편집기입니다. MLT 프레임워크를 사용하며 여러 음악 및 동영상 형식을 지원하고, 효과 및 트랜지션을 추가할 수 있으며, 원하는 형식으로 렌더링할 수 있습니다.

Kdenlive is een niet lineaire videobewerker. Het is gebaseerd op het MLT-framework en accepteert vele audio- en video-formaten, biedt de mogelijkheid effecten en overgangen toe te voegen en om te zetten naar het formaat van uw keuze.

Kdenlive er eit program for ikkje-lineær videoredigering. Det er basert på MLT-rammeverket og støttar mange ulike video- og lydformat. Du kan leggja til spesialeffektar og overgangar, og eksportera til ulike filformat.

Kdenlive jest nieliniowym edytorem wideo. Oparty jest na szkielecie MLT i może pracować na wielu formatach obrazu i dźwięku, umożliwia dodawanie efektów, przejść i renderowanie ich do dowolnego formatu.

O Kdenlive é um editor de vídeo não-linear. Baseia-se na plataforma MLT e aceita diversos formatos de áudio e vídeo, permitindo-lhe adicionar efeitos, transições e gravar no formato da sua escolha.

Kdenlive é um editor de vídeo não-linear. É baseado na plataforma MLT e aceita diversos formatos de áudio e vídeo, permitindo-lhe adicionar efeitos, transições e gravar no formato da sua escolha.

Kdenline je nelineárny video editor. Je založený na frameworku MLT a podporuje veľa audio a video formátov, umožní pridávať efekty, prechody a renderovanie do formátu podľa vášho výberu.

Kdenlive je nelinearni urejevalnik videa, ki temelji na ogrodju MLT. Kdenlive zmore obdelati številne vrste zvočnih in video datotek, omogoča dodajanje učinkov, prehodov in izvoz videa v vrsto po vaši izbiri.

Kdenlive är en icke-linjär videoeditor. Den är baserad på MLT-ramverket och accepterar många ljud- och videoformat, låter dig lägga till effekter, övergångar och återge med valfritt format.

Kdenlive doğrusal olmayan bir video düzenleyicisidir. MLT çalışma çerçevesi tabanlıdır ve birçok ses ile video biçimini destekleyerek; efektler ve geçişler eklemenizi ve istediğiniz biçime dönüştürmenizi sağlar.

Kdenlive — нелінійний відеоредактор. Програму засновано на наборі засобів MLT, вона може працювати з даними у багатьох форматах зберігання відео та звукових даних, дозволяє додавати ефекти, переходи та надає змогу зберегти результати редагування у вибраному вами форматі.

xxKdenlive is a non linear video editor. It is based on the MLT framework and accepts many audio and video formats, allows you to add effects, transitions and render into the format of your choice.xx

Kdenlive 是一个非线性视频编辑器。它基于 MLT 框架并且支持许多音频和视频格式,允许您添加特效,转场并渲染为您想要的格式。

Kdenlive 是一套非線性的影像編輯器。基於 MLT 框架,可接受許多影音格式,讓您可以加入特效,過場並轉編碼成您選擇的格式。

Features:

الميزات:

Svojstva:

Característiques:

Característiques:

Vlastnosti:

Funktioner:

Funktionen:

Χαρακτηριστικά:

Features:

Características:

Omadused:

Eginbideak:

Ominaisuuksia:

Fonctionnalités :

Funcionalidades:

Fitur:

Funzionalità:

기능:

Mogelijkheden:

Funksjonar:

Możliwości:

Funcionalidades:

Funcionalidades:

Возможности:

Funkcie:

Zmožnosti:

Funktioner:

Özellikler:

Можливості:

xxFeatures:xx

功能:

功能:

https://kdenlive.org/ https://bugs.kde.org https://userbase.kde.org/Kdenlive/Manual https://www.kde.org/community/donations/?app=kdenlive&source=appdata Kdenlive 19.08 Kdenlive 19.08 Kdenlive 19.08 Kdenlive 19.08 Kdenlive 19.08 Kdenlive 19.08 Kdenlive 19.08 Kdenlive 19.08 Kdenlive 19.08 Kdenlive 19.08 Kdenlive 19.08 Kdenlive 19.08 + Kdenlive 19.08 Kdenlive 19.08 Kdenlive 19.08 xxKdenlive 19.08xx https://cdn.kde.org/screenshots/kdenlive/19-08.png Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 Kdenlive 18.08 xxKdenlive 18.08xx Kdenlive 18.08 Kdenlive 18.08 https://cdn.kde.org/screenshots/kdenlive/screenshot-monitors.png KDE kdenlive kdenlive_render
diff --git a/src/assets/assetpanel.cpp b/src/assets/assetpanel.cpp index 36ee3b5c5..2f9930841 100644 --- a/src/assets/assetpanel.cpp +++ b/src/assets/assetpanel.cpp @@ -1,354 +1,354 @@ /*************************************************************************** * Copyright (C) 2017 by Nicolas Carion * * This file is part of Kdenlive. See www.kdenlive.org. * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) version 3 or any later version accepted by the * * membership of KDE e.V. (or its successor approved by the membership * * of KDE e.V.), which shall act as a proxy defined in Section 14 of * * version 3 of the license. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ #include "assetpanel.hpp" #include "core.h" #include "definitions.h" #include "effects/effectstack/model/effectitemmodel.hpp" #include "effects/effectstack/model/effectstackmodel.hpp" #include "effects/effectstack/view/effectstackview.hpp" #include "kdenlivesettings.h" #include "model/assetparametermodel.hpp" #include "transitions/transitionsrepository.hpp" #include "transitions/view/transitionstackview.hpp" #include "view/assetparameterview.hpp" #include #include #include #include #include #include #include #include #include #include #include #include AssetPanel::AssetPanel(QWidget *parent) : QWidget(parent) , m_lay(new QVBoxLayout(this)) , m_assetTitle(new KSqueezedTextLabel(this)) , m_container(new QWidget(this)) , m_transitionWidget(new TransitionStackView(this)) , m_effectStackWidget(new EffectStackView(this)) { auto *buttonToolbar = new QToolBar(this); buttonToolbar->addWidget(m_assetTitle); int size = style()->pixelMetric(QStyle::PM_SmallIconSize); QSize iconSize(size, size); buttonToolbar->setIconSize(iconSize); // spacer QWidget *empty = new QWidget(); empty->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum); buttonToolbar->addWidget(empty); m_switchBuiltStack = new QToolButton(this); m_switchBuiltStack->setIcon(QIcon::fromTheme(QStringLiteral("adjustlevels"))); m_switchBuiltStack->setToolTip(i18n("Adjust clip")); m_switchBuiltStack->setCheckable(true); m_switchBuiltStack->setChecked(KdenliveSettings::showbuiltstack()); m_switchBuiltStack->setVisible(false); // connect(m_switchBuiltStack, &QToolButton::toggled, m_effectStackWidget, &EffectStackView::switchBuiltStack); buttonToolbar->addWidget(m_switchBuiltStack); m_splitButton = new KDualAction(i18n("Normal view"), i18n("Compare effect"), this); m_splitButton->setActiveIcon(QIcon::fromTheme(QStringLiteral("view-right-close"))); m_splitButton->setInactiveIcon(QIcon::fromTheme(QStringLiteral("view-split-left-right"))); m_splitButton->setToolTip(i18n("Compare effect")); m_splitButton->setVisible(false); connect(m_splitButton, &KDualAction::activeChangedByUser, this, &AssetPanel::processSplitEffect); buttonToolbar->addAction(m_splitButton); m_enableStackButton = new KDualAction(i18n("Effects disabled"), i18n("Effects enabled"), this); m_enableStackButton->setInactiveIcon(QIcon::fromTheme(QStringLiteral("hint"))); m_enableStackButton->setActiveIcon(QIcon::fromTheme(QStringLiteral("visibility"))); connect(m_enableStackButton, &KDualAction::activeChangedByUser, this, &AssetPanel::enableStack); m_enableStackButton->setVisible(false); buttonToolbar->addAction(m_enableStackButton); m_timelineButton = new KDualAction(i18n("Hide keyframes"), i18n("Display keyframes in timeline"), this); m_timelineButton->setInactiveIcon(QIcon::fromTheme(QStringLiteral("adjustlevels"))); m_timelineButton->setActiveIcon(QIcon::fromTheme(QStringLiteral("adjustlevels"))); m_timelineButton->setToolTip(i18n("Display keyframes in timeline")); m_timelineButton->setVisible(false); connect(m_timelineButton, &KDualAction::activeChangedByUser, this, &AssetPanel::showKeyframes); buttonToolbar->addAction(m_timelineButton); m_lay->addWidget(buttonToolbar); m_lay->setContentsMargins(0, 0, 0, 0); m_lay->setSpacing(0); auto *lay = new QVBoxLayout(m_container); lay->setContentsMargins(0, 0, 0, 0); lay->addWidget(m_transitionWidget); lay->addWidget(m_effectStackWidget); auto *sc = new QScrollArea; sc->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); sc->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); sc->setFrameStyle(QFrame::NoFrame); sc->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding)); m_container->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding)); sc->setWidgetResizable(true); m_lay->addWidget(sc); sc->setWidget(m_container); m_transitionWidget->setVisible(false); m_effectStackWidget->setVisible(false); updatePalette(); connect(m_effectStackWidget, &EffectStackView::seekToPos, this, &AssetPanel::seekToPos); connect(m_effectStackWidget, &EffectStackView::reloadEffect, this, &AssetPanel::reloadEffect); connect(m_transitionWidget, &TransitionStackView::seekToTransPos, this, &AssetPanel::seekToPos); connect(m_effectStackWidget, &EffectStackView::updateEnabledState, [this]() { m_enableStackButton->setActive(m_effectStackWidget->isStackEnabled()); }); } void AssetPanel::showTransition(int tid, const std::shared_ptr &transitionModel) { Q_UNUSED(tid) ObjectId id = transitionModel->getOwnerId(); if (m_transitionWidget->stackOwner() == id) { // already on this effect stack, do nothing return; } clear(); QString transitionId = transitionModel->getAssetId(); QString transitionName = TransitionsRepository::get()->getName(transitionId); - m_assetTitle->setText(i18n("%1 properties", transitionName)); + m_assetTitle->setText(i18n("%1 properties").arg(i18n(transitionName.toUtf8().data()))); m_transitionWidget->setVisible(true); m_timelineButton->setVisible(true); m_enableStackButton->setVisible(false); m_transitionWidget->setModel(transitionModel, QSize(), true); } void AssetPanel::showEffectStack(const QString &itemName, const std::shared_ptr &effectsModel, QSize frameSize, bool showKeyframes) { m_splitButton->setActive(false); if (effectsModel == nullptr) { // Item is not ready m_splitButton->setVisible(false); m_enableStackButton->setVisible(false); clear(); return; } ObjectId id = effectsModel->getOwnerId(); if (m_effectStackWidget->stackOwner() == id) { // already on this effect stack, do nothing return; } clear(); QString title; bool showSplit = false; bool enableKeyframes = false; switch (id.first) { case ObjectType::TimelineClip: title = i18n("%1 effects", itemName); showSplit = true; enableKeyframes = true; break; case ObjectType::TimelineComposition: title = i18n("%1 parameters", itemName); enableKeyframes = true; break; case ObjectType::TimelineTrack: title = i18n("Track %1 effects", itemName); // TODO: track keyframes // enableKeyframes = true; break; case ObjectType::BinClip: title = i18n("Bin %1 effects", itemName); showSplit = true; break; default: title = itemName; break; } m_assetTitle->setText(title); m_splitButton->setVisible(showSplit); m_enableStackButton->setVisible(id.first != ObjectType::TimelineComposition); m_enableStackButton->setActive(effectsModel->isStackEnabled()); if (showSplit) { m_splitButton->setEnabled(effectsModel->rowCount() > 0); QObject::connect(effectsModel.get(), &EffectStackModel::dataChanged, [&]() { if (m_effectStackWidget->isEmpty()) { m_splitButton->setActive(false); } m_splitButton->setEnabled(!m_effectStackWidget->isEmpty()); }); } m_timelineButton->setVisible(enableKeyframes); m_timelineButton->setActive(showKeyframes); // Disable built stack until properly implemented // m_switchBuiltStack->setVisible(true); m_effectStackWidget->setVisible(true); m_effectStackWidget->setModel(effectsModel, frameSize); } void AssetPanel::clearAssetPanel(int itemId) { ObjectId id = m_effectStackWidget->stackOwner(); if (id.first == ObjectType::TimelineClip && id.second == itemId) { clear(); } else { id = m_transitionWidget->stackOwner(); if (id.first == ObjectType::TimelineComposition && id.second == itemId) { clear(); } } } void AssetPanel::clear() { m_transitionWidget->setVisible(false); m_transitionWidget->unsetModel(); m_effectStackWidget->setVisible(false); m_splitButton->setVisible(false); m_timelineButton->setVisible(false); m_switchBuiltStack->setVisible(false); m_effectStackWidget->unsetModel(); m_assetTitle->setText(QString()); } void AssetPanel::updatePalette() { QString styleSheet = getStyleSheet(); setStyleSheet(styleSheet); m_transitionWidget->setStyleSheet(styleSheet); m_effectStackWidget->setStyleSheet(styleSheet); } // static const QString AssetPanel::getStyleSheet() { KColorScheme scheme(QApplication::palette().currentColorGroup(), KColorScheme::View); QColor selected_bg = scheme.decoration(KColorScheme::FocusColor).color(); QColor hgh = KColorUtils::mix(QApplication::palette().window().color(), selected_bg, 0.2); QColor hover_bg = scheme.decoration(KColorScheme::HoverColor).color(); QColor light_bg = scheme.shade(KColorScheme::LightShade); QColor alt_bg = scheme.background(KColorScheme::NormalBackground).color(); QString stylesheet; // effect background stylesheet.append(QStringLiteral("QFrame#decoframe {border-bottom:2px solid " "palette(mid);background: transparent} QFrame#decoframe[active=\"true\"] {background: %1;}") .arg(hgh.name())); // effect in group background stylesheet.append( QStringLiteral("QFrame#decoframesub {border-top:1px solid palette(light);} QFrame#decoframesub[active=\"true\"] {background: %1;}").arg(hgh.name())); // group background stylesheet.append(QStringLiteral("QFrame#decoframegroup {border:2px solid palette(dark);margin:0px;margin-top:2px;} ")); // effect title bar stylesheet.append(QStringLiteral("QFrame#frame {margin-bottom:2px;} QFrame#frame[target=\"true\"] " "{background: palette(highlight);}")); // group effect title bar stylesheet.append(QStringLiteral("QFrame#framegroup {background: palette(dark);} " "QFrame#framegroup[target=\"true\"] {background: palette(highlight);} ")); // draggable effect bar content stylesheet.append(QStringLiteral("QProgressBar::chunk:horizontal {background: palette(button);border-top-left-radius: 4px;border-bottom-left-radius: 4px;} " "QProgressBar::chunk:horizontal#dragOnly {background: %1;border-top-left-radius: 4px;border-bottom-left-radius: 4px;} " "QProgressBar::chunk:horizontal:hover {background: %2;}") .arg(alt_bg.name(), selected_bg.name())); // draggable effect bar stylesheet.append(QStringLiteral("QProgressBar:horizontal {border: 1px solid palette(dark);border-top-left-radius: 4px;border-bottom-left-radius: " "4px;border-right:0px;background:%3;padding: 0px;text-align:left center} QProgressBar:horizontal:disabled {border: 1px " "solid palette(button)} QProgressBar:horizontal#dragOnly {background: %3} QProgressBar:horizontal[inTimeline=\"true\"] { " "border: 1px solid %1;border-right: 0px;background: %2;padding: 0px;text-align:left center } " "QProgressBar::chunk:horizontal[inTimeline=\"true\"] {background: %1;}") .arg(hover_bg.name(), light_bg.name(), alt_bg.name())); // spin box for draggable widget stylesheet.append( QStringLiteral("QAbstractSpinBox#dragBox {border: 1px solid palette(dark);border-top-right-radius: 4px;border-bottom-right-radius: " "4px;padding-right:0px;} QAbstractSpinBox::down-button#dragBox {width:0px;padding:0px;} QAbstractSpinBox:disabled#dragBox {border: 1px " "solid palette(button);} QAbstractSpinBox::up-button#dragBox {width:0px;padding:0px;} QAbstractSpinBox[inTimeline=\"true\"]#dragBox { " "border: 1px solid %1;} QAbstractSpinBox:hover#dragBox {border: 1px solid %2;} ") .arg(hover_bg.name(), selected_bg.name())); // group editable labels stylesheet.append(QStringLiteral("MyEditableLabel { background-color: transparent; color: palette(bright-text); border-radius: 2px;border: 1px solid " "transparent;} MyEditableLabel:hover {border: 1px solid palette(highlight);} ")); // transparent qcombobox stylesheet.append(QStringLiteral("QComboBox { background-color: transparent;} ")); return stylesheet; } void AssetPanel::processSplitEffect(bool enable) { ObjectType id = m_effectStackWidget->stackOwner().first; if (id == ObjectType::TimelineClip) { emit doSplitEffect(enable); } else if (id == ObjectType::BinClip) { emit doSplitBinEffect(enable); } } void AssetPanel::showKeyframes(bool enable) { if (m_transitionWidget->isVisible()) { pCore->showClipKeyframes(m_transitionWidget->stackOwner(), enable); } else { pCore->showClipKeyframes(m_effectStackWidget->stackOwner(), enable); } } ObjectId AssetPanel::effectStackOwner() { if (m_transitionWidget->isVisible()) { return m_transitionWidget->stackOwner(); } if (!m_effectStackWidget->isVisible()) { return ObjectId(ObjectType::NoItem, -1); } return m_effectStackWidget->stackOwner(); } bool AssetPanel::addEffect(const QString &effectId) { if (!m_effectStackWidget->isVisible()) { return false; } return m_effectStackWidget->addEffect(effectId); } void AssetPanel::enableStack(bool enable) { if (!m_effectStackWidget->isVisible()) { return; } m_effectStackWidget->enableStack(enable); } void AssetPanel::deleteCurrentEffect() { if (m_effectStackWidget->isVisible()) { m_effectStackWidget->removeCurrentEffect(); } }