00001 #ifndef Impala_Visualization_RotorBrowser_RotorBrowser_h
00002 #define Impala_Visualization_RotorBrowser_RotorBrowser_h
00004 //345678901234567890123456789012345678901234567890123456789012345678901234567890
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 #include <list>
00189
00190
00191 #include "RotorBrowserListener.h"
00192 #include "RotorView.h"
00193 #include "RotorBrowserContext.h"
00194 #include "ThreadClusterSelector.h"
00195
00196 #include "Visualization/KeyBindingsMap.h"
00197 #include "Visualization/GUI/HelpViewer.h"
00198 #include "Visualization/StatusOverlayWindow.h"
00199 #include "Visualization/FontHandler.h"
00200 #include "Visualization/VideoMinimap.h"
00201
00202 #include "Core/VideoSet/SegmentationDocument.h"
00203 #include "Core/Trec/VisualQueryEngine.h"
00204 #include "Core/Trec/ThreadSet.h"
00205 #include "Core/Table/TableTem.h"
00206 #include "Core/Table/Sort.h"
00207
00208 #include "Sandbox/ork/ProgramNameReader.h"
00209 #include "Basis/CmdOptions.h"
00210
00211 namespace Impala {
00212 namespace Visualization {
00213 namespace RotorBrowser {
00214
00215 typedef Core::Table::TableTem
00216 <Core::Column::ColumnTem<Int32>,
00217 Core::Column::ColumnTem<Core::Trec::Thread*> > TableThreadWidthId;
00218
00219 class RotorBrowser : public OglGui::Window, public RotorViewListener
00220 {
00221 public:
00222 typedef std::list<RotorBrowserContext*> RotorBrowserContextList;
00223 typedef std::list<RotorView*> RotorViewList;
00224 typedef Core::Array::Element::Vec3Int32 Vec3Int32;
00225 typedef Core::Trec::VisualQueryEngine VisualQueryEngine;
00226 typedef Core::Trec::ThreadSet ThreadSet;
00227 typedef Core::Trec::Thread Thread;
00228 typedef Core::Trec::ThreadBookmarked ThreadBookmarked;
00229 typedef Core::Trec::ThreadHistory ThreadHistory;
00230 typedef Core::Trec::ThreadVirtual ThreadVirtual;
00231 typedef Core::Trec::ThreadVisualSimilarity ThreadVisualSimilarity;
00232 typedef Core::Trec::KeyframeResult KeyframeResult;
00233 typedef Core::VideoSet::SegmentationDocument SegmentationDocument;
00234 typedef Core::VideoSet::Stills Stills;
00235 typedef Core::ImageSet::ImageSet ImageSet;
00236
00237 RotorBrowser(OglGui::Window *parent, int w, int h, ThreadSet *threadset,
00238 SegmentationDocument *document, String preFix = "") :
00239 OglGui::Window(parent, w, h, false)
00240 {
00241 Init(threadset, document, preFix);
00242 }
00243
00244 RotorBrowser(OglGui::Window *parent, int x, int y, int w, int h,
00245 ThreadSet *threadset, SegmentationDocument *document,
00246 String preFix = "") :
00247 OglGui::Window(parent, x, y, w, h, false)
00248 {
00249 Init(threadset, document, preFix);
00250 }
00251
00252 ~RotorBrowser()
00253 {
00254 ILOG_DEBUG("~RotorBrowser()");
00255 delete mActiveContext;
00256 }
00257
00258 void SetRotorBrowserListener(RotorBrowserListener *listener)
00259 {
00260 mRotorBrowserListener = listener;
00261 }
00262
00263 bool CheckKBN(String keyStr, int c, int state, int n=6)
00264 {
00265 keyStr = mPreFix + keyStr;
00266 return CheckKeyBindingExt(mKeyBindings, keyStr, c, state, n);
00267 }
00268
00269 RotorBrowserContext* GetActiveContext() { return mActiveContext; }
00270 RotorBrowserContextList GetOtherContexts() { return mContexts; }
00271
00272 int GetBrowseMode() { return mBrowseMode; }
00273 bool GetKeepCenterCentered() { return mKeepCenterCentered; }
00274 void SetShowDirection(bool sd) { mShowDirection = sd; }
00275 bool GetShowDirection() { return mShowDirection; }
00276 void SetActiveHorizontal(bool ah) { mActiveHorizontal = ah; }
00277 bool GetActiveHorizontal() { return mActiveHorizontal; }
00278 void SetManageContexts(bool mc) { mManageContexts = mc; }
00279 bool GetManageContexts() { return mManageContexts; }
00280 void SetTopNRelevant(int topn) { mTopN = topn; }
00281 int GetTopNRelevant() { return mTopN; }
00282 void SetMinimapEnabled(bool val) { mMinimapEnabled = val; }
00283 bool GetMinimapEnabled() { return mMinimapEnabled; }
00284 int GetNrActiveContexts() { return mContexts.size() + 1; }
00285 bool GetEnableShotSwallow() { return mEnableShotSwallow; }
00286
00287 void SetProgramNames(Samples::ProgramNameReader *programs)
00288 {
00289 mPrograms = programs;
00290 }
00291
00292 void SetBrowseMode(int mode)
00293 {
00294 ILOG_SYSTEM("RotorBrowser SetBrowseMode to " << mode);
00295 mBrowseMode = mode;
00296 CheckFocus(true);
00297
00298 if (mBrowseMode == MODE_CROSSBROWSER)
00299 {
00300 InitCrossBrowser();
00301 ShowStatusStr("Current Browser", "CrossBrowser", oglDARKGREY);
00302 }
00303 if (mBrowseMode == MODE_ROTORBROWSER)
00304 {
00305 InitRotorBrowser();
00306 ShowStatusStr("Current Browser", "RotorBrowser", 0xffcccc22);
00307 }
00308 if (mBrowseMode == MODE_FORKBROWSER)
00309 {
00310 InitForkBrowser();
00311 ShowStatusStr("Current Browser", "ForkBrowser", 0xff2222cc);
00312 }
00313 UpdateViewsToContext();
00314 }
00315
00316
00317 RotorView* GetCenterRotorView()
00318 {
00319 if (!mActiveContext)
00320 return 0;
00321 return mCache->FindViewFor(mActiveContext->GetName(),
00322 mActiveContext->GetCenter());
00323 }
00324
00325 void EnableCenterVideoStills(bool mode)
00326 {
00327 if (mAutoStills==STILLS_NONE)
00328 mode = false;
00329 RotorView* rotorView = GetCenterRotorView();
00330 if (!rotorView)
00331 return;
00332 if (mode)
00333 {
00334 const int curFileId = mDocument->CurFileId();
00335 if (curFileId != mDisabledCenterVideo)
00336 {
00337 mDisabledCenterVideo =
00338 rotorView->EnableVideoStills(mDocument) ? -1 : curFileId;
00339 if (mDisabledCenterVideo == -1)
00340 return;
00341 }
00342 }
00343 rotorView->DisableVideoStills();
00344 }
00345
00346 virtual void InitFunc()
00347 {
00348 OglGui::Window::InitFunc();
00349 view3DSys.SetCamera(GetOGLWND(),0.0f,0.0f,+4.0f,0.0f,0.0f,0.0f);
00350 }
00351
00352 virtual void DisplayFunc()
00353 {
00354
00355 #ifndef AS_TODS_BROWSER
00356 CheckFocus();
00357 #endif
00358 view3DSys.View3DCameraTransform(GetOGLWND());
00359
00360
00361 if (mBrowseMode==MODE_CROSSBROWSER || mBrowseMode==MODE_FORKBROWSER)
00362 {
00363 RotorBrowserContext *time = GetContext("time");
00364 float w = 1.0 + time->GetDepth() * 2.0;
00365 Printf3D(w/3,-1.05f,-9.1f,0.4f,0.4f,0.1f,time->GetNiceName());
00366 }
00367
00368 if (mBrowseMode == MODE_ROTORBROWSER)
00369 {
00370 RotorBrowserContextList::iterator ctx;
00371 for (ctx = mContexts.begin(); ctx != mContexts.end(); ctx++)
00372 {
00373 glPushMatrix();
00374 float w = 1.0 + (*ctx)->GetDepth() * 3.0;
00375 glRotatef((*ctx)->GetDirection()/M_PI*180.0f,0.f,0.f,1.f);
00376 Printf3D(w/3,-1.05f,-9.1f,0.4f,0.4f,0.1f,(*ctx)->GetNiceName());
00377 glPopMatrix();
00378 }
00379 }
00380
00381 if (mBrowseMode == MODE_ROTORBROWSER && mShowDirection)
00382 {
00383 glPushMatrix();
00384 float w = 1.0 + mActiveContext->GetDepth() * 3.0;
00385 OGC oldOGC;
00386 INT oldBlendInfo[3];
00387 OGCSave(&oldOGC);
00388 oglSys.StartBlend(&oldBlendInfo[0]);
00389 glRotatef(mActiveContext->GetDirection()/M_PI*180.f, 0.f, 0.f, 1.f);
00390 ULONG colL = 0x22ff0000, colR = 0x2200ff00;
00391 SetFillColors(colL,colR,colR,colL,0xee000000);
00392 FillRoundRectExt3D(-w/2, -1.f, -10.1f, w, 2.f, 5.f, 5.f, 5.f, 5.f);
00393 glColor3f(0.5f, 0.f, 0.f);
00394 Printf3D(w/4, -1.f, -8.1f, 0.5f, 0.5f, 0.1f,
00395 mActiveContext->GetNiceName());
00396 oglSys.EndBlend(&oldBlendInfo[0]);
00397 OGCRestore(&oldOGC);
00398 glPopMatrix();
00399 }
00400
00401 if (mBrowseMode == MODE_FORKBROWSER)
00402 {
00403
00404 }
00405
00406
00407 RotorViewList views = mCache->GetViews();
00408
00409
00410 bool updateNeeded = false;
00411 RotorViewList::const_iterator i;
00412 for (i = views.begin(); i != views.end(); i++)
00413 updateNeeded |= (*i)->DrawView();
00414
00415 if (updateNeeded)
00416 UpdateScene();
00417 }
00418
00419
00420 virtual void KeyboardFunc(int c, int state)
00421 {
00422 bool keySwallowed = false;
00423 StopStills();
00424
00425
00426
00427 if (!keySwallowed && mClusterSelector->IsActive())
00428 keySwallowed = KeyboardClusterSelectionFunc(c, state);
00429
00430 if (!keySwallowed)
00431 keySwallowed = StdKeyboardFunc(c,state);
00432
00433 if (!keySwallowed)
00434 {
00435 if (mBrowseMode == MODE_ROTORBROWSER)
00436 keySwallowed = KeyboardRotorFunc(c, state);
00437 if (mBrowseMode == MODE_CROSSBROWSER)
00438 keySwallowed = KeyboardCrossFunc(c, state);
00439 if (mBrowseMode == MODE_FORKBROWSER)
00440 keySwallowed = KeyboardForkFunc(c, state);
00441 }
00442
00443 if (!keySwallowed)
00444 {
00445 ILOG_DEBUG("key "<<c<<" state "<<state<<" still unswallowed." );
00446 Window::KeyboardFunc(c, state);
00447 }
00448 StartStills();
00449 UpdateScene(true);
00450 }
00451
00452 bool StdKeyboardFunc(int c, int state)
00453 {
00454 bool keyHandled = true;
00455 bool book;
00456
00457 if (CheckKBN("StdToggleShowBookmarks", c, state))
00458 {
00459 ILOG_USER("KB: show/hide bookmarks thread");
00460 DoShowBookmarksThread();
00461 }
00462 else if (CheckKBN("StdStopAutoStills", c, state))
00463 {
00464 ILOG_USER("KB: Stop autostill feature");
00465 StopAutoStills();
00466 ShowStatusStr("Shot still player", false);
00467 }
00468 else if (CheckKBN("StdToggleAutoStills", c, state))
00469 {
00470 ILOG_USER("KB: Toggle autostill feature");
00471 ToggleAutoStills();
00472 }
00473 else if (CheckKBN("StdToggleVideoStream", c, state))
00474 {
00475 ILOG_USER( "KB: toggling video stream for center shot" );
00476 ToggleEnableVideoStream();
00477 }
00478 else if (CheckKBN("StdTogglePlayUntilEnd", c, state))
00479 {
00480 ILOG_USER("KB: toggling video continuous to end for center shot");
00481 TogglePlayUntilEnd();
00482 }
00483 else if (CheckKBN("StdIncrAutoStillSpeed", c, state))
00484 {
00485 int va = RotorView::GetStillFrameWait();
00486 va -= 2;
00487 if (va < 1) va = 1;
00488 mStatusOverlay->ShowStatus("Stills animation delay", va, 1, 40);
00489 ILOG_USER( "KB: autostills faster, now " << va );
00490 RotorView::SetStillFrameWait(va);
00491 }
00492 else if (CheckKBN("StdDecrAutoStillSpeed", c, state))
00493 {
00494 int va = RotorView::GetStillFrameWait();
00495 va += 2;
00496 if (va > 40) va = 40;
00497 mStatusOverlay->ShowStatus("Stills animation delay", va, 1, 40);
00498 ILOG_USER( "KB: autostills slower, now " << va );
00499 RotorView::SetStillFrameWait(va);
00500 }
00501 else if (CheckKBN("StdIncrAnimationSpeed", c, state))
00502 {
00503 ILOG_USER( "KB: DEBUG: increase sFactor" );
00504 RotorView::SetSpeedFactor( RotorView::GetSpeedFactor() + 0.8 );
00505 mStatusOverlay->ShowStatus("Animation delay",
00506 RotorView::GetSpeedFactor(), 1, 20);
00507 }
00508 else if (CheckKBN("StdDecrAnimationSpeed", c, state))
00509 {
00510 ILOG_USER( "KB: DEBUG: decrease sFactor" );
00511 RotorView::SetSpeedFactor( RotorView::GetSpeedFactor() - 0.8 );
00512 mStatusOverlay->ShowStatus("Animation delay",
00513 RotorView::GetSpeedFactor(), 1, 20);
00514 }
00515 else if (CheckKBN("StdToggleShowHelp", c, state))
00516 {
00517 ILOG_USER( "KB: Toggle display inline help viewer" );
00518 mHelpViewer->SetVisible(!mHelpViewer->GetVisible());
00519 }
00520 else if (CheckKBN("StdCrossBrowserMode", c, state))
00521 {
00522 ILOG_USER( "KB: switch browser to CrossBrowser" );
00523 SetBrowseMode(RotorBrowser::MODE_CROSSBROWSER);
00524 }
00525 #ifndef AS_TODS_BROWSER
00526 else if (CheckKBN("StdRotorBrowserMode", c, state))
00527 {
00528 ILOG_USER( "KB: switch browser to RotorBrowser" );
00529 SetBrowseMode(RotorBrowser::MODE_ROTORBROWSER);
00530 }
00531 else if (CheckKBN("StdForkBrowserMode", c, state))
00532 {
00533 ILOG_USER("KB: switch browser to ForkBrowser");
00534 SetBrowseMode(RotorBrowser::MODE_FORKBROWSER);
00535 }
00536 #endif
00537 else if (CheckKBN("StdToggleShotSwallow", c, state))
00538 {
00539 SetEnableShotSwallow(!GetEnableShotSwallow());
00540 ILOG_USER("KB: toggle enable shot swallow. Now " <<
00541 GetEnableShotSwallow());
00542 UpdateViewsToContext();
00543 }
00544 else if (CheckKBN("StdToggleShotSwallowThread", c, state))
00545 {
00546 ToggleShotSwallowThread();
00547 ILOG_USER("KB: toggle shot swallow thread.");
00548 UpdateViewsToContext();
00549 }
00550 else if (CheckKBN("StdToggleKeepCenterCentered", c, state))
00551 {
00552 SetKeepCenterCentered(!GetKeepCenterCentered());
00553 ILOG_USER("KB: toggle keep center shot centered. Now " <<
00554 GetKeepCenterCentered() );
00555 UpdateViewsToContext();
00556 }
00557 else if ((book=CheckKBN("StdBookmarkCenterPositive", c, state)) ||
00558 CheckKBN("StdBookmarkCenterNegative", c, state))
00559 {
00560 ILOG_USER("KB: " << (book ? "bookmark" : "remove") << " center " <<
00561 mActiveContext->GetCenter() << " from " <<
00562 mActiveContext->GetName());
00563 BookmarkActiveCenterEx(c==' ');
00564 UpdateViewsToContext();
00565 }
00566 #ifndef AS_TODS_BROWSER
00567 else if (CheckKBN("StdClusterSelect", c, state))
00568 {
00569 ILOG_USER("KB: cluster select in active thread direction");
00570 ClusterSelect();
00571 UpdateViewsToContext();
00572 }
00573 #endif
00574 else if (CheckKBN("StdClearViewedCache", c, state))
00575 {
00576 ILOG_USER("KB: (debug code) reset viewed shots");
00577 ClearViewedCache();
00578 UpdateViewsToContext();
00579 }
00580 else if (CheckKBN("StdJudgeBrowseMode", c, state))
00581 {
00582 ILOG_USER("KB: (debug code) activating judge-browse mode.");
00583 RotorBrowserContext::SetAutoNegatives(false);
00584 RotorView::SetShowNegativeBookmarks(true);
00585 RotorView::SetShowProbabilityFeedback(false);
00586 ClearViewedCache();
00587 UpdateViewsToContext();
00588 }
00589 else if (CheckKBN("StdToggleAutoSelectNegatives", c, state))
00590 {
00591 bool nstate = !RotorBrowserContext::GetAutoNegatives();
00592 ILOG_USER("KB: (debug code) toggle auto-select negatives. " <<
00593 "Now " << nstate);
00594 RotorBrowserContext::SetAutoNegatives(nstate);
00595 RotorView::SetShowNegativeBookmarks(nstate);
00596 RotorView::SetShowProbabilityFeedback(nstate);
00597 if (!nstate)
00598 ClearViewedCache();
00599 UpdateViewsToContext();
00600 }
00601 else
00602 keyHandled = false;
00603 return keyHandled;
00604 }
00605
00606
00607
00608 bool KeyboardClusterSelectionFunc(int c, int state)
00609 {
00610 if (mClusterSelector->ClusterKeyboardFunc(c,state))
00611 return true;
00612
00613 bool force = false;
00614 bool positive = false;
00615
00616 if ((positive = CheckKBN("CsBookPositive", c, state)) ||
00617 (force = positive = CheckKBN("CsBookPositiveForce", c, state)) ||
00618 (CheckKBN("CsBookNegative", c, state)) ||
00619 (force = CheckKBN("CsBookNegativeForce", c, state)))
00620 {
00621 ILOG_USER("KB: " << (force ? "force" : "") <<
00622 "bookmark cluster viewer selection " <<
00623 (positive ? "" : "as negative"));
00624 DoBookmarkCluster(positive, force);
00625 return true;
00626 }
00627 return false;
00628 }
00629
00630 bool CrossBrowserNavigateKey(int c, int state, bool keepCenter)
00631 {
00632 int up=0, down=0, left=0, right=0;
00633
00634 if ((up = CheckKBN("CbGoUp", c, state)) ||
00635 (down = CheckKBN("CbGoDown", c, state)) ||
00636 (left = CheckKBN("CbGoLeft", c, state)) ||
00637 (right = CheckKBN("CbGoRight", c, state)))
00638 {
00639 state = 0;
00640 }
00641 else if ((up = CheckKBN("CbBookmarkUpNegative", c, state)) ||
00642 (down = CheckKBN("CbBookmarkDownNegative", c, state)) ||
00643 (left = CheckKBN("CbBookmarkPrevNegative", c, state)) ||
00644 (right= CheckKBN("CbBookmarkNextNegative", c, state)))
00645 {
00646 state = oglControl;
00647 }
00648 else if ((up = CheckKBN("CbBookmarkUpPositive", c, state)) ||
00649 (down = CheckKBN("CbBookmarkDownPositive", c, state)) ||
00650 (left = CheckKBN("CbBookmarkPrevPositive", c, state)) ||
00651 (right= CheckKBN("CbBookmarkNextPositive", c, state)))
00652 {
00653 state = oglShift;
00654 }
00655 if (up) c = oglUP;
00656 if (down) c = oglDOWN;
00657 if (left) c = oglLEFT;
00658 if (right) c = oglRIGHT;
00659
00660 if (!(left || right || up || down))
00661 return false;
00662
00663 char* dirStr[] = {"UP (forward)", "DOWN (backward)", "LEFT", "RIGHT"};
00664 String action = (state==oglControl) ? " removing " : " bookmarking ";
00665
00666 if (!keepCenter && (state==oglShift || state==oglControl))
00667 {
00668 BookmarkActiveCenterEx(state==oglShift);
00669 ILOG_USER("KB: " << action << " center " <<
00670 mActiveContext->GetCenter() << " from " <<
00671 mActiveContext->GetName() << " and....");
00672 }
00673
00674 SwitchToContext((left||right) ? "time" : "shots_initialquery");
00675
00676 if (keepCenter && (state == oglControl || state == oglShift))
00677 {
00678 int dir = (left || up) ? -1 : 1;
00679 int target = mActiveContext->GetRelative(dir);
00680
00681 BookmarkSpecificEx(target, state==oglShift);
00682 ILOG_USER("KB: " << action << dirStr[c-oglUP] << target);
00683 UpdateViewsToContext();
00684 }
00685
00686 if (!keepCenter)
00687 {
00688 ILOG_USER("KB: crossbrowser " << dirStr[c-oglUP]);
00689 if (left || down)
00690 mActiveContext->GoLeft();
00691 if (right || up)
00692 mActiveContext->GoRight();
00693 UpdateViewsToContext();
00694 PublishContextMoved((left || down) ? -1 : 1);
00695 }
00696 return true;
00697 }
00698
00699 bool VisualQueryKey(int c, int state)
00700 {
00701 String visStr = "";
00702 if (CheckKBN("VisualQuery_vissemgabor", c, state))
00703 visStr = "vissemgabor";
00704 if (CheckKBN("VisualQuery_vissem", c, state))
00705 visStr = "vissem";
00706 if (CheckKBN("VisualQuery_fusionvissemgabor", c, state))
00707 visStr = "fusionvissemgabor";
00708 if (CheckKBN("VisualQuery_labhistogram", c, state))
00709 visStr = "labhistogram";
00710
00711 if (!visStr.empty())
00712 {
00713 int center = mActiveContext->GetCenter();
00714 if (mBrowseMode==MODE_CROSSBROWSER)
00715 ILOG_USER("KB: CrossBrowser switching initialquery to " <<
00716 visStr << " for active " << center);
00717 if (mBrowseMode==MODE_ROTORBROWSER)
00718 ILOG_USER("KB: RotorBrowser generate visual " << visStr <<
00719 " thread for active " << center);
00720 DoVisualQuery(visStr);
00721 return true;
00722 }
00723 return false;
00724 }
00725
00726 bool KeyboardCrossFunc(int c, int state)
00727 {
00728 if (CrossBrowserNavigateKey(c,state,mKeepCenterCentered))
00729 return true;
00730
00731 if (VisualQueryKey(c,state))
00732 return true;
00733
00734
00735 bool keyHandled = true;
00736
00737 if (CheckKBN("CbGoFirst", c, state))
00738 {
00739 ILOG_USER( "KB: CrossBrowser moving to FIRST" );
00740 ResetRanking();
00741 }
00742 if (CheckKBN("CbGoLast", c, state))
00743 {
00744 ILOG_USER( "KB: CrossBrowser moving to LAST" );
00745 SwitchToContext("shots_initialquery");
00746 mActiveContext->GoLast();
00747 UpdateViewsToContext();
00748 PublishContextMoved(1);
00749 }
00750 if (CheckKBN("CbGoInitialQuery", c, state))
00751 {
00752 ILOG_USER("KB: Return to original search query");
00753 DoReturnToFirstQuery();
00754 }
00755 else
00756 keyHandled = false;
00757
00758 return keyHandled;
00759 }
00760
00761 bool RotorBrowserNavigateKey(int k, int state, bool keepCenter)
00762 {
00763 int c = 0;
00764 if ( CheckKBN("RbGoForward", k, state))
00765 c = 'd';
00766 else if (CheckKBN("RbGoBackward", k, state))
00767 c = 'a';
00768 else if (CheckKBN("RbGoFirst", k, state))
00769 c = 'q';
00770 else if (CheckKBN("RbGoLast", k, state))
00771 c = 'e';
00772 else if (CheckKBN("RbBookmarkNext", k, state))
00773 c = 'D';
00774 else if (CheckKBN("RbBookmarkPrev", k, state))
00775 c = 'A';
00776
00777 if (!c)
00778 return false;
00779
00780 if (c=='a') mActiveContext->GoLeft();
00781 if (c=='d') mActiveContext->GoRight();
00782 if (c=='q') mActiveContext->GoFirst();
00783 if (c=='e') mActiveContext->GoLast();
00784
00785 if (c=='q' || c=='e')
00786 ILOG_USER("KB: RotorBrowser moving active " <<
00787 mActiveContext->GetName() << " to " <<
00788 (c=='q' ? "FIRST" : "LAST"));
00789
00790
00791 if (c=='A' || c=='D')
00792 {
00793 if (!mKeepCenterCentered) {
00794 ILOG_USER("KB: bookmark center " <<
00795 mActiveContext->GetCenter() << " from " <<
00796 mActiveContext->GetName() << " and go " <<
00797 (c=='A' ? "LEFT" : "RIGHT") << " in "<<
00798 mActiveContext->GetName());
00799 int nextshot = mActiveContext->GetRelative(c=='A'? -1 : 1);
00800 BookmarkActiveCenter();
00801 mActiveContext->GoTo(nextshot);
00802 }
00803 else
00804 {
00805 int target = mActiveContext->GetRelative(c=='A' ? -1 : 1);
00806 ILOG_USER("KB: RotorBrowser bookmark " << target <<
00807 (c=='A'? "left" : "right") << " of center from " <<
00808 mActiveContext->GetName() );
00809 BookmarkSpecific(target);
00810 }
00811 }
00812 UpdateViewsToContext();
00813 if ( !(keepCenter && (c=='A' || c=='D')))
00814 PublishContextMoved((c=='A' || c=='a' || c=='q') ? -1 : 1);
00815
00816 return true;
00817 }
00818
00819 bool KeyboardRotorFunc(int c, int state)
00820 {
00821 if (VisualQueryKey(c,state))
00822 return true;
00823
00824 if (RotorBrowserNavigateKey(c,state,mKeepCenterCentered))
00825 return true;
00826
00827 bool keySwallowed = true;
00828 if (CheckKBN("RbSwitchToContextNext", c, state))
00829 {
00830 ILOG_USER( "KB: RotorBrowser switch to NEXT context" );
00831 SwitchToNextContext();
00832 UpdateViewsToContext();
00833 }
00834 else if (CheckKBN("RbSwitchToContextPrev", c, state))
00835 {
00836 ILOG_USER( "KB: RotorBrowser switch to PREVIOUS context" );
00837 SwitchToPreviousContext();
00838 UpdateViewsToContext();
00839 }
00840 else if (CheckKBN("RbSwitchToContextTime", c, state))
00841 {
00842 ILOG_USER( "KB: RotorBrowser switch to context 'time'" );
00843 SwitchToContext("time");
00844 UpdateViewsToContext();
00845 }
00846 else if (CheckKBN("RbSwitchToContextBookmark", c, state))
00847 {
00848 ILOG_USER( "KB: RotorBrowser switch to context 'bookmarked'" );
00849 if (!HasContext("bookmarked"))
00850 {
00851 Thread* t = GetThreadByName("bookmarked");
00852 mContexts.push_back(new RotorBrowserContext(mCache,t,0,0.0f,4));
00853 }
00854 SwitchToContext("bookmarked");
00855 UpdateViewsToContext();
00856 }
00857 else if (CheckKBN("RbReturnLastInitialQuery", c, state))
00858 {
00859 ILOG_USER("KB: return to last known initialquery position " <<
00860 mInitialQueryPosition );
00861 SwitchToContext("shots_initialquery");
00862 if (mActiveContext->GetName() == "shots_initialquery")
00863 {
00864 ILOG_DEBUG("current context = initialquery" );
00865 mActiveContext->GoTo(mInitialQueryPosition);
00866 ILOG_DEBUG("current context = " << mActiveContext->GetCenter());
00867 UpdateViewsToContext();
00868 }
00869 else
00870 ILOG_DEBUG("return to context failed, current context=" <<
00871 mActiveContext->GetName() );
00872 }
00873 else if (CheckKBN("RbToggleShowRankThreads", c, state))
00874 {
00875 ILOG_USER( "KB: toggling show rank threads" );
00876 mShowRankThreads = !mShowRankThreads;
00877 ShowStatusStr("Show extra threads", mShowRankThreads);
00878 UpdateViewsToContext();
00879 }
00880 else
00881 keySwallowed = false;
00882
00883 return keySwallowed;
00884 }
00885
00886 void KbBookmarkActiveCenter(bool positive)
00887 {
00888 ILOG_USER("KB: bookmarking center " << mActiveContext->GetCenter() <<
00889 " from " << mActiveContext->GetName() << " and....");
00890 if (positive)
00891 BookmarkActiveCenter();
00892 else
00893 BookmarkActiveCenterNegative();
00894 }
00895
00896 void KbNavigateFork(char* str, int dir, char* logStr )
00897 {
00898 ILOG_USER("KB: ForkBrowser " << logStr);
00899 SwitchToContext(str);
00900 if (dir == -1)
00901 mActiveContext->GoLeft();
00902 if (dir == 1)
00903 mActiveContext->GoRight();
00904 AddCenterToHistory();
00905 if (!strcmp(str,"shots_initialquery"))
00906 mForkLastQueryShot = mActiveContext->GetCenter();
00907 UpdateViewsToContext();
00908 PublishContextMoved(dir);
00909 }
00910
00911 bool KeyboardForkFunc(int c, int state)
00912 {
00913 int l = 0, r = 0, v = 0, g = 0, q = 0, h = 0;
00914
00915 if (
00916 (l = CheckKBN("FbBookmarkPositiveTimeBackward", c, state)) ||
00917 (r = CheckKBN("FbBookmarkPositiveTimeForward", c, state)) ||
00918 (v = CheckKBN("FbBookmarkPositiveVissemForward", c, state)) ||
00919 (g = CheckKBN("FbBookmarkPositiveGaborForward", c, state)) ||
00920 (q = CheckKBN("FbBookmarkPositiveQueryForward", c, state)) ||
00921 (h = CheckKBN("FbBookmarkPositiveHistoryGoLast", c, state)))
00922 {
00923 KbBookmarkActiveCenter(true);
00924 }
00925 else if (
00926 (l = CheckKBN("FbBookmarkNegativeTimeBackward", c, state)) ||
00927 (r = CheckKBN("FbBookmarkNegativeTimeForward", c, state)) ||
00928 (v = CheckKBN("FbBookmarkNegativeVissemForward", c, state)) ||
00929 (g = CheckKBN("FbBookmarkNegativeGaborForward", c, state)) ||
00930 (q = CheckKBN("FbBookmarkNegativeQueryForward", c, state)) ||
00931 (h = CheckKBN("FbBookmarkNegativeHistoryGoLast", c, state)))
00932 {
00933 KbBookmarkActiveCenter(false);
00934 }
00935 else if (
00936 (l = CheckKBN("FbTimeBackward", c, state)) ||
00937 (r = CheckKBN("FbTimeForward", c, state)) ||
00938 (v = CheckKBN("FbVissemForward", c, state)) ||
00939 (g = CheckKBN("FbGaborForward", c, state)) ||
00940 (q = CheckKBN("FbQueryForward", c, state)) ||
00941 (h = CheckKBN("FbLastHistory", c, state)))
00942 {}
00943
00944 bool keySwallowed = true;
00945 if (l)
00946 KbNavigateFork("time",-1,"LEFT in TIME");
00947 else if (r)
00948 KbNavigateFork("time",1,"RIGHT in TIME");
00949 else if (g)
00950 KbNavigateFork("visual_vissemgabor",1,"NEXT in visually similar");
00951 else if (v)
00952 KbNavigateFork("visual_vissem",1,"NEXT in conceptually similar");
00953 else if (q)
00954 KbNavigateFork("shots_initialquery",1,"NEXT in QUERY");
00955 else if (h)
00956 {
00957 ILOG_USER( "KB: ForkBrowser LAST in HISTORY" );
00958 SwitchToContext("history");
00959 mActiveContext->GoLeft();
00960 UpdateViewsToContext();
00961 PublishContextMoved(-1);
00962 }
00963 else if (CheckKBN("FbLastQueryShot", c, state))
00964 {
00965 ILOG_USER("KB: ForkBrowser return to last shot selected from QUERY "
00966 << mForkLastQueryShot);
00967
00968 if (mForkLastQueryShot > -1)
00969 {
00970 SwitchToContext("shots_initialquery");
00971 mActiveContext->GoTo(mForkLastQueryShot);
00972 AddCenterToHistory();
00973 UpdateViewsToContext();
00974 }
00975 }
00976 else
00977 keySwallowed = false;
00978 return keySwallowed;
00979 }
00980
00981 void PublishContextMoved(int dir)
00982 {
00983 if (!mRotorBrowserListener || !mActiveContext)
00984 return;
00985 int center = mActiveContext->GetCenter();
00986 mRotorBrowserListener->ContextMoveEvent(this, dir, center);
00987 }
00988
00989 void AddCenterToHistory()
00990 {
00991 if (mActiveContext != 0)
00992 AddToHistory(mActiveContext->GetCenter());
00993 }
00994
00995 void AddToHistory(int shot)
00996 {
00997 ThreadHistory *history = (ThreadHistory*)GetThreadByName("history");
00998 if (history != 0)
00999 {
01000 history->Remove(shot);
01001 history->Push(shot);
01002 if (mTrailHistory)
01003 mTrailHistory->Push(shot);
01004 }
01005 }
01006
01007 virtual void MouseFunc(int msg, int but, int state, int x, int y)
01008 {
01009 if (msg == oglMouseWheelUp)
01010 {
01011 KeyboardFunc('s', state);
01012 return;
01013 }
01014
01015 if (msg == oglMouseWheelDown)
01016 {
01017 KeyboardFunc('w', state);
01018 return;
01019 }
01020
01021 if ((state & oglAlt) || (msg != oglMouseDown))
01022 {
01023 #ifndef AS_TODS_BROWSER
01024 Window::MouseFunc(msg, but, state, x, y);
01025 #endif
01026 return;
01027 }
01028 OGLVIEW3D *v = view3DSys.FindView(mOglWnd, x, y);
01029 if (v == NULL) return;
01030 RotorView *view = RotorViewCache::OGLVIEW3DToRotorView(v);
01031 if (view == NULL) return;
01032
01033 if (but == oglLeftButton)
01034 {
01035 if (state & oglShift)
01036 {
01037
01038 int vNr = view->GetNR();
01039 RotorBrowserContext *c = FindContextForPosition(vNr);
01040 if (!c) return;
01041
01042 ILOG_USER("MOUSE: move to shot " << vNr <<
01043 " from context " << c->GetName() );
01044 if (SwitchToContext(c->GetName()))
01045 {
01046 mActiveContext->GoTo(vNr);
01047 UpdateViewsToContext();
01048 PublishContextMoved(0);
01049 }
01050 }
01051 else
01052 {
01053 ILOG_USER("MOUSE: click on shot " << view->GetNR() <<
01054 " at " << view->GetName());
01055 BookmarkSpecific(view->GetNR());
01056 view->UpdateBookmarkState();
01057 if (mBrowseMode == MODE_FORKBROWSER)
01058 {
01059 AddToHistory(view->GetNR());
01060 UpdateViewsToContext();
01061 }
01062 }
01063 }
01064 if (but == oglRightButton)
01065 {
01066 ILOG_USER("MOUSE: rightclick on shot " << view->GetNR() <<
01067 " at " << view->GetName() );
01068 BookmarkSpecificNegative(view->GetNR());
01069 view->UpdateBookmarkState();
01070 }
01071 }
01072
01073 void AddContext(Thread *thread, int initialpos, float direction=0.0f,
01074 int depth=3)
01075 {
01076 if (HasContext(thread->GetName()))
01077 {
01078 ILOG_DEBUG("RotorBrowser::AddContext(" << thread->GetName() <<
01079 "): already exists. not added." );
01080 return;
01081 }
01082 ILOG_DEBUG("RotorBrowser::AddContext(" << thread->GetName() <<
01083 ", " << initialpos <<")" );
01084
01085 if (thread->GetName() == "shots_initialquery")
01086 mInitialQueryPosition = -1;
01087
01088 RotorBrowserContext *add =
01089 new RotorBrowserContext(mCache,thread,initialpos,direction,depth);
01090 add->SetSwallowThread(GetThreadByName("virtual_hidden"));
01091 add->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
01092 mContexts.push_back(add);
01093
01094 RepositionContexts();
01095 UpdateViewsToContext();
01096 }
01097
01098 void ReloadCrossBrowser(int position = -1)
01099 {
01100 ILOG_DEBUG( "ReloadCrossBrowser()" );
01101 SwitchToContext("shots_initialquery");
01102 if (mActiveContext->GetName() != "shots_initialquery")
01103 {
01104 ILOG_WARN("active context is not initialquery. " <<
01105 "Aborting ReloadCrossBrowser." );
01106 return;
01107 }
01108 delete mActiveContext;
01109 mActiveContext = NULL;
01110 InitCrossBrowser(position);
01111 UpdateViewsToContext();
01112 }
01113
01114
01115 void ReloadForkBrowser()
01116 {
01117 ILOG_DEBUG("ReloadForkBrowser()");
01118 SwitchToContext("shots_initialquery");
01119 if (mActiveContext->GetName() != "shots_initialquery")
01120 {
01121 ILOG_WARN("active context is not initialquery. " <<
01122 "Aborting ReloadForkBrowser." );
01123 return;
01124 }
01125 delete mActiveContext;
01126 mActiveContext = NULL;
01127 InitForkBrowser();
01128 UpdateViewsToContext();
01129
01130
01131 }
01132
01133 void ReloadInitial()
01134 {
01135 if (mClusterSelector->IsActive())
01136 {
01137 ILOG_DEBUG("hiding cluster selector");
01138 mClusterSelector->Hide();
01139 }
01140
01141 ClearTrails();
01142
01143 if (mBrowseMode==MODE_CROSSBROWSER || mBrowseMode==MODE_FORKBROWSER)
01144 {
01145 UpdateViewsToContext();
01146 return;
01147 }
01148
01149 ILOG_SYSTEM( "reloading initial query" );
01150 if (!mActiveContext || mActiveContext->GetName()!="shots_initalquery")
01151 {
01152 ILOG_DEBUG( "initialquery was not active, activating..." );
01153 SwitchToContext("shots_initialquery");
01154 }
01155 if (mActiveContext && mActiveContext->GetName()=="shots_initialquery")
01156 {
01157 delete mActiveContext;
01158 mActiveContext = NULL;
01159 SwitchToContext("time");
01160 UpdateViewsToContext();
01161 SwitchToContext("shots_initialquery");
01162 }
01163 }
01164
01165 void ResetRanking()
01166 {
01167 SwitchToContext("shots_initialquery");
01168 mActiveContext->GoFirst();
01169 UpdateViewsToContext();
01170 PublishContextMoved(-1);
01171 }
01172
01173 void RemoveContext(String name)
01174 {
01175 if (mActiveContext->GetName() == name)
01176 {
01177 if (mContexts.size() < 1)
01178 {
01179 ILOG_DEBUG("RotorBrowser::RemoveContext(" << name <<
01180 "): is active and alone. Not removed.");
01181 return;
01182 }
01183 SwitchToNextContext();
01184 }
01185 RotorBrowserContextList::iterator context;
01186 for (context=mContexts.begin(); context!=mContexts.end(); context++)
01187 if ((*context)->GetName() == name)
01188 break;
01189
01190 if (context != mContexts.end())
01191 {
01192 delete *context;
01193 mContexts.erase(context);
01194 ILOG_DEBUG("RotorBrowser::RemoveContext(" << name <<
01195 "): erased. " << mContexts.size() <<
01196 " contexts remaining.");
01197 }
01198 else
01199 ILOG_DEBUG("RotorBrowser::RemoveContext(" << name <<
01200 "): was not in active contexts. " );
01201
01202 RepositionContexts();
01203 UpdateViewsToContext();
01204 }
01205
01206 void SetEnableShotSwallow(bool swallow)
01207 {
01208 if (mKeepCenterCentered)
01209 {
01210 ShowStatusStr("Bookmarked shots", "hidden, keep center enabled",
01211 0xffdddd22);
01212 return;
01213 }
01214 mEnableShotSwallow = swallow;
01215 RotorBrowserContext::SetGlobalShotSwallow(swallow);
01216 if (swallow)
01217 ShowStatusStr("Bookmarked shots", "hidden", oglDARKRED);
01218 else
01219 ShowStatusStr("Bookmarked shots", "shown", oglDARKGREEN);
01220 }
01221
01222 void ToggleShotSwallowThread()
01223 {
01224 ThreadVirtual *v = (ThreadVirtual*)GetThreadByName("virtual_hidden");
01225 Thread *positive = GetThreadByName("bookmarked");
01226 Thread *negative = GetThreadByName("bookmarked_negative");
01227
01228 SetEnableShotSwallow(true);
01229
01230 if (!v)
01231 return;
01232 if (v->HasThread(positive) && v->HasThread(negative))
01233 {
01234 v->RemoveThread(positive);
01235 ShowStatusStr("Hide shots", "only negative", oglDARKRED);
01236 return;
01237 }
01238 if (v->HasThread(negative))
01239 {
01240 v->RemoveThread(negative);
01241 v->AddThread(positive);
01242 ShowStatusStr("Hide shots", "only positive", oglDARKGREEN);
01243 return;
01244 }
01245 if (v->HasThread(positive)) {
01246 v->AddThread(negative);
01247 ShowStatusStr("Hide shots","both positive and negative",0xffdddd22);
01248 return;
01249 }
01250 }
01251
01252 void SetKeepCenterCentered(bool centercentered)
01253 {
01254 if (mBrowseMode==MODE_FORKBROWSER)
01255 {
01256 ShowStatusStr("Center shot stays in center",
01257 "N/A in ForkBrowser mode", 0xffdddd22);
01258 return;
01259 }
01260 mKeepCenterCentered = centercentered;
01261 ShowStatusStr("Center Shot stays in center", mKeepCenterCentered);
01262
01263
01264 if (mKeepCenterCentered)
01265 {
01266 RotorBrowserContext::SetGlobalShotSwallow(true);
01267 if (mActiveContext)
01268 mActiveContext->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
01269 }
01270 else
01271 RotorBrowserContext::SetGlobalShotSwallow(mEnableShotSwallow);
01272 }
01273
01274
01275
01276
01277
01278
01279 void UpdateViewsToContext()
01280 {
01281 if (mBusyManaging)
01282 return;
01283
01284 if (mClusterSelector->IsActive())
01285 {
01286
01287
01288 return;
01289 }
01290 if (mManageContexts)
01291 ManageContexts();
01292
01293 RotorBrowserContext* time;
01294 if (mPrograms && (time = GetContext("time")))
01295 {
01296 String shotTitle = mPrograms->GetTitleForShot(time->GetCenter());
01297 time->SetNiceName("time: " + shotTitle);
01298 }
01299
01300 int cPos = mActiveContext->GetCenter();
01301 if (mActiveContext->GetName() == "shots_initialquery")
01302 mInitialQueryPosition = cPos;
01303 mCache->DoHide(mCache->GetViews());
01304 mActiveContext->UpdateViewsToContext();
01305 if (cPos >= 0)
01306 {
01307
01308 mDocument->GotoKeyfr(mThreadSet->GetKeyframes()->GetShotRKF(cPos));
01309 UpdateTrails();
01310 if (mTrailVisited)
01311 mTrailVisited->Push(cPos);
01312 }
01313
01314 RotorBrowserContextList::const_iterator context;
01315
01316 RotorBrowserContext *matchcontext;
01317
01318
01319 if (mBrowseMode == MODE_ROTORBROWSER)
01320 {
01321 matchcontext = mActiveContext;
01322 for (context=mContexts.begin(); context!=mContexts.end(); context++)
01323 (*context)->UpdateViewsToContext(matchcontext);
01324 }
01325 else if (mBrowseMode == MODE_CROSSBROWSER)
01326 {
01327 matchcontext = GetContext("shots_initialquery");
01328 for (context=mContexts.begin(); context!=mContexts.end(); context++)
01329 (*context)->UpdateViewsToContext(matchcontext);
01330 }
01331 else if (mBrowseMode == MODE_FORKBROWSER)
01332 UpdateForkContexts();
01333
01334 mCache->DoCleanup(mCache->GetViews());
01335
01336 UpdateViewedShotBookmarks();
01337 }
01338
01339 void UpdateForkContexts()
01340 {
01341
01342
01343 Thread* visual = GetThreadByName("visual_vissemgabor");
01344 ((ThreadVisualSimilarity*)visual)->SetMaxReturned(100);
01345
01346 Thread* conceptual = GetThreadByName("visual_vissem");
01347 ((ThreadVisualSimilarity*)conceptual)->SetMaxReturned(100);
01348
01349 if (mTrailVisibleVisualA && mTrailVisibleVisualB)
01350 {
01351 mTrailVisibleVisualA->AddThread(visual, 9);
01352 mTrailVisibleVisualB->AddThread(conceptual, 9);
01353 }
01354
01355
01356 RotorBrowserContextList::const_iterator context;
01357 for (context = mContexts.begin(); context != mContexts.end(); context++)
01358 {
01359 if ((*context)->GetName() == "shots_initialquery")
01360 (*context)->UpdateViewsToContext(*context);
01361 else if ((*context)->GetName() == "history")
01362 {
01363
01364 (*context)->GoLast();
01365 (*context)->UpdateViewsToContext(*context);
01366 }
01367 else
01368 (*context)->UpdateViewsToContext(mActiveContext);
01369 }
01370 }
01371
01372 void Redraw()
01373 {
01374 UpdateViewsToContext();
01375 }
01376
01377
01378
01379
01380 void RegisterShotTrails(VideoMinimap *map)
01381 {
01382 mTrailBookmarks =
01383 new ShotTrail("bookmarks", 1000, Vec3Int32(0,128,0), 0.0);
01384 mTrailVisibleTime =
01385 new ShotTrail("visible_time", 20, Vec3Int32(0,255,0), 0.05);
01386 mTrailVisibleQuery =
01387 new ShotTrail("visible_query", 100, Vec3Int32(255,0,255), 0.01);
01388 mTrailVisibleVisualA =
01389 new ShotTrail("visible_visualA", 10, Vec3Int32(255,255,0), 0.1);
01390 mTrailVisibleVisualB =
01391 new ShotTrail("visible_visualB", 10, Vec3Int32(255,255,0), 0.1);
01392 mTrailVisited =
01393 new ShotTrail("visited", 80000, Vec3Int32(64,64,64), 0.001);
01394 mTrailHistory =
01395 new ShotTrail("history", 100, Vec3Int32(255, 0, 0), 0.01);
01396 map->RegisterTrail(mTrailVisited);
01397 map->RegisterTrail(mTrailVisibleTime);
01398 map->RegisterTrail(mTrailVisibleVisualA);
01399 map->RegisterTrail(mTrailVisibleVisualB);
01400 map->RegisterTrail(mTrailVisibleQuery);
01401 map->RegisterTrail(mTrailHistory);
01402 map->RegisterTrail(mTrailBookmarks);
01403 mMinimapEnabled = true;
01404 }
01405
01406 void ClearTrails()
01407 {
01408 ClearVisibleTrails();
01409 if (mTrailBookmarks)
01410 mTrailBookmarks->Clear();
01411 if (mTrailHistory)
01412 mTrailHistory->Clear();
01413 if (mTrailVisited)
01414 mTrailVisited->Clear();
01415 }
01416
01417 void ClearVisibleTrails()
01418 {
01419 if (mTrailVisibleVisualA)
01420 mTrailVisibleVisualA->Clear();
01421 if (mTrailVisibleVisualB)
01422 mTrailVisibleVisualB->Clear();
01423 if (mTrailVisibleTime)
01424 mTrailVisibleTime->Clear();
01425 if (mTrailVisibleQuery)
01426 mTrailVisibleQuery->Clear();
01427 }
01428
01429 void UpdateTrails()
01430 {
01431 if (!mMinimapEnabled)
01432 return;
01433
01434
01435 ClearVisibleTrails();
01436
01437 String cName = mActiveContext->GetName();
01438
01439 if (mTrailVisibleQuery && cName == "shots_initialquery")
01440 mTrailVisibleQuery->AddBrowserContext(mActiveContext, 100);
01441
01442 if (mTrailVisibleTime && cName == "time")
01443 mTrailVisibleTime->AddBrowserContext(mActiveContext, 20, true);
01444
01445
01446 RotorBrowserContextList::iterator context;
01447 for (context = mContexts.begin(); context != mContexts.end(); context++)
01448 {
01449 if ((*context)->GetName() == "shots_initialquery")
01450 {
01451 if (mTrailVisibleQuery)
01452 mTrailVisibleQuery->AddBrowserContext(*context, 100);
01453 }
01454 else if ((*context)->GetName() == "time")
01455 {
01456 if (mTrailVisibleTime)
01457 mTrailVisibleTime->AddBrowserContext(*context, 20, true);
01458 }
01459 }
01460 }
01461
01462 void ClearViewedCache()
01463 {
01464 mCache->ClearShotViewed();
01465 }
01466
01467 bool ShotHasBeenDumpedByTrecvidAtTheLastMinute(int shotid)
01468 {
01469 switch (mThreadSet->GetSegmentation()->GetVideoId(shotid))
01470 {
01471 case 22:
01472 case 158:
01473 case 187:
01474 case 198:
01475 case 407:
01476 case 514:
01477 case 543:
01478 return true;
01479 default:
01480 return false;
01481 }
01482 }
01483
01484 void BookmarkActiveCenter()
01485 {
01486 if (ShotHasBeenDumpedByTrecvidAtTheLastMinute(mActiveContext->GetCenter()))
01487 {
01488 ILOG_WARN("Shot " << mActiveContext->GetCenter() << " has been dumped by trecvid, not bookmarked.");
01489 return;
01490 }
01491 if (mDocument->AddCursorToBookmarked())
01492 {
01493 int shot = mActiveContext->GetCenter();
01494 if (mRotorBrowserListener)
01495 mRotorBrowserListener->BookmarkEvent(this,shot,true);
01496 RemoveSpecificNegative(shot);
01497 ILOG_DEBUG( "Bookmarked active center " << shot << " POSITIVE." );
01498 RotorView* bookmarked =
01499 mCache->GetViewFor(mActiveContext->GetName(),shot);
01500 bookmarked->Rename("bookmarked");
01501 bookmarked->MoveTo(1.0f, -1.0f, -2.0f, 1.0f, 1.0f);
01502 bookmarked->UpdateBookmarkState();
01503
01504 if (mTrailBookmarks)
01505 mTrailBookmarks->Push(shot);
01506 }
01507 }
01508
01509 void BookmarkActiveCenterNegative()
01510 {
01511 BookmarkSpecificNegative(mActiveContext->GetCenter());
01512 }
01513
01514 void BookmarkActiveCenterEx(bool positive)
01515 {
01516 if (positive)
01517 BookmarkActiveCenter();
01518 else
01519 BookmarkActiveCenterNegative();
01520 }
01521
01522 void BookmarkSpecific(int shotID)
01523 {
01524 if (ShotHasBeenDumpedByTrecvidAtTheLastMinute(shotID))
01525 {
01526 ILOG_WARN("Shot " << shotID << " has been dumped by trecvid, not bookmarked.");
01527 return;
01528 }
01529
01530 if (shotID < 0)
01531 return;
01532 int active = mDocument->CurKeyfr();
01533 mDocument->GotoKeyfr(mThreadSet->GetKeyframes()->GetShotRKF(shotID));
01534 if (mDocument->AddCursorToBookmarked())
01535 {
01536 if (mRotorBrowserListener)
01537 mRotorBrowserListener->BookmarkEvent(this, shotID, true);
01538 RemoveSpecificNegative(shotID);
01539 ILOG_DEBUG("Bookmarked specific shot " << shotID << " POSITIVE.");
01540
01541 if (mTrailBookmarks)
01542 mTrailBookmarks->Push(shotID);
01543 }
01544 mDocument->GotoKeyfr(active);
01545 }
01546
01547 void BookmarkSpecificNegative(int shotID)
01548 {
01549 if (shotID < 0)
01550 return;
01551 ThreadBookmarked *b;
01552 if (b = (ThreadBookmarked*)GetThreadByName("bookmarked_negative"))
01553 {
01554 int keyframe = mThreadSet->GetKeyframes()->GetShotRKF(shotID);
01555 b->AddShot(shotID, keyframe);
01556 ILOG_DEBUG( "Bookmarked specific shot " << shotID << " NEGATIVE." );
01557 }
01558 RemoveSpecific(shotID);
01559 }
01560
01561 void BookmarkSpecificEx(int shotID, bool positive=true)
01562 {
01563 if (positive)
01564 BookmarkSpecific(shotID);
01565 else
01566 BookmarkSpecificNegative(shotID);
01567 }
01568
01569 void RemoveSpecificNegative(int shotid)
01570 {
01571 ThreadBookmarked *b;
01572 if (b = (ThreadBookmarked*)GetThreadByName("bookmarked_negative"))
01573 b->RemoveShot(shotid);
01574 }
01575
01576 void RemoveSpecific(int shotid)
01577 {
01578 ThreadBookmarked *b = (ThreadBookmarked*)GetThreadByName("bookmarked");
01579 if (b)
01580 b->RemoveShot(shotid);
01581 if (mRotorBrowserListener)
01582 mRotorBrowserListener->BookmarkEvent(this, shotid, false);
01583 }
01584
01585
01586
01587
01588 void DoBookmarkCluster(bool markPositive, bool force)
01589 {
01590 if (!mClusterSelector->IsActive()) return;
01591
01592 ThreadBookmarked *positive =
01593 (ThreadBookmarked*)GetThreadByName("bookmarked");
01594 ThreadBookmarked *negative =
01595 (ThreadBookmarked*)GetThreadByName("bookmarked_negative");
01596
01597 std::vector<int> shots = mClusterSelector->GetSelectedShots();
01598 ILOG_SYSTEM("cluster bookmarking " << shots.size() <<
01599 " shots as " << (markPositive ? "POSITIVE" : "NEGATIVE"));
01600 for (int i=0; i<shots.size(); i++)
01601 {
01602 if (markPositive && (force || !negative->Contains(shots[i])))
01603 BookmarkSpecific(shots[i]);
01604 if (!markPositive && (force || !positive->Contains(shots[i])))
01605 BookmarkSpecificNegative(shots[i]);
01606 }
01607 mClusterSelector->Show(mActiveContext);
01608 }
01609
01610 void UpdateViewedShotBookmarks()
01611 {
01612 Impala::Core::Table::AnnotationTable *t = mCache->GetViewedShots();
01613 ThreadBookmarked *positive =
01614 (ThreadBookmarked*)GetThreadByName("bookmarked");
01615 ThreadBookmarked *negative =
01616 (ThreadBookmarked*)GetThreadByName("bookmarked_negative");
01617 if (!positive || !negative) return;
01618
01619 int ctr = 0, booked = 0;
01620 for (int i=0; i < t->Size(); i++)
01621 {
01622 if (!t->IsPositive(i))
01623 continue;
01624 ctr++;
01625 int shot = mThreadSet->GetSegmentation()->GetShotId(t->Get1(i));
01626
01627 if (!positive->Contains(shot) && !negative->Contains(shot))
01628 {
01629 int keyframe = mThreadSet->GetKeyframes()->GetShotRKF(shot);
01630 negative->AddShot(shot, keyframe);
01631 booked ++;
01632 }
01633 }
01634 if (booked)
01635 ILOG_DEBUG("GetViewedShots(): " << ctr << " shots viewed, " <<
01636 booked << " new bookmarks.");
01637 }
01638
01639 void ShowHideStill(RotorView* v, bool show)
01640 {
01641 if (show)
01642 v->SetShowStills(mStills,mDocument->GetImSetStills());
01643 else
01644 v->SetHideStills();
01645 }
01646
01647 void StartStopStills(bool start)
01648 {
01649 if (mAutoStills == STILLS_NONE)
01650 return;
01651
01652 RotorView* v;
01653 String cName = mActiveContext->GetName();
01654 if (mClusterSelector->IsActive())
01655 {
01656 std::vector<int> shots = mClusterSelector->GetVisibleShots();
01657 for (int i=0; i<shots.size(); i++)
01658 if (v = mCache->FindViewFor(cName,shots[i]))
01659 ShowHideStill(v,start);
01660 return;
01661 }
01662
01663 if (mAutoStills == STILLS_CENTER)
01664 {
01665 if (v = mCache->FindViewFor(cName,mActiveContext->GetCenter()))
01666 ShowHideStill(v,start);
01667 }
01668 if (mAutoStills == STILLS_NEARCENTER)
01669 {
01670 for (int i=-2; i<=+2; i++)
01671 if(v=mCache->FindViewFor(cName,mActiveContext->GetRelative(i)))
01672 ShowHideStill(v,start);
01673 }
01674 if (mAutoStills == STILLS_ACTIVE)
01675 {
01676 int depth = mActiveContext->GetDepth();
01677 for (int i = -depth; i<= depth; i++)
01678 if(v=mCache->FindViewFor(cName,mActiveContext->GetRelative(i)))
01679 ShowHideStill(v,start);
01680 }
01681 if (mAutoStills == STILLS_ALL)
01682 {
01683 RotorViewList views = mCache->GetViews();
01684 RotorViewList::const_iterator i;
01685 for (i=views.begin(); i != views.end(); i++)
01686 if ((*i)->IsCurrentlyShown())
01687 ShowHideStill(*i,start);
01688 }
01689 }
01690
01691 void StartStills()
01692 {
01693 StartStopStills(true);
01694 }
01695 void StopStills()
01696 {
01697 StartStopStills(false);
01698 }
01699
01700 int AutoStills()
01701 {
01702 return mAutoStills;
01703 }
01704
01705 void AutoStills(int mode)
01706 {
01707 StopStills();
01708 mAutoStills = mode;
01709 if (mAutoStills > STILLS_ALL)
01710 mAutoStills = STILLS_NONE;
01711 StartStills();
01712 String title = "Shot still player";
01713 switch (mAutoStills)
01714 {
01715 case STILLS_NONE:
01716 ShowStatusStr(title,false); break;
01717 case STILLS_CENTER:
01718 ShowStatusStr(title,"center shot only",oglDARKGREEN); break;
01719 case STILLS_NEARCENTER:
01720 ShowStatusStr(title,"local area",oglDARKGREEN); break;
01721 case STILLS_ACTIVE:
01722 ShowStatusStr(title,"active thread",oglDARKGREEN); break;
01723 case STILLS_ALL:
01724 ShowStatusStr(title,"all shots",oglDARKGREEN); break;
01725 }
01726 }
01727
01728
01729 void ToggleAutoStills()
01730 {
01731 AutoStills(++mAutoStills);
01732 }
01733
01734 void ToggleEnableVideoStream()
01735 {
01736 RotorView* v;
01737 String cName = mActiveContext->GetName();
01738 if (mClusterSelector->IsActive())
01739 {
01740 std::vector<int> shots = mClusterSelector->GetVisibleShots();
01741 for (int i=0; i<shots.size(); i++)
01742 {
01743 if (!(v = mCache->FindViewFor(cName,shots[i])))
01744 continue;
01745 if (v->GetVideoStillsEnabled())
01746 v->DisableVideoStills();
01747 else
01748 v->EnableVideoStills(mDocument);
01749 }
01750 return;
01751 }
01752
01753 if (v = mCache->FindViewFor(cName,mActiveContext->GetCenter()))
01754 {
01755 bool enabled = v->GetVideoStillsEnabled();
01756 if (enabled)
01757 v->DisableVideoStills();
01758 else
01759 v->EnableVideoStills(mDocument);
01760 ShowStatusStr("Center shot video player",!enabled);
01761 }
01762 }
01763
01764 void TogglePlayUntilEnd()
01765 {
01766 if (mClusterSelector->IsActive())
01767 return;
01768
01769 RotorView* center = mCache->FindViewFor(mActiveContext->GetName(),
01770 mActiveContext->GetCenter());
01771 if (center)
01772 center->SetPlayUntilEnd(!center->GetPlayUntilEnd());
01773 ShowStatusStr("Center shot plays until end of video",
01774 center->GetPlayUntilEnd());
01775 }
01776
01777 void StopAutoStills()
01778 {
01779 StopStills();
01780 mAutoStills = STILLS_NONE;
01781 StartStills();
01782 }
01783
01784 void TakeFocus()
01785 {
01786 oglFocusWnd = GetOGLWND();
01787 CheckFocus();
01788 }
01789
01790 void ClusterSelect()
01791 {
01792
01793 if (!mClusterSelector->IsActive())
01794 {
01795 ILOG_DEBUG("ClusterSelect(): showing...");
01796 mClusterSelector->Show(mActiveContext);
01797 if (mActiveContext->GetThread()->GetType() == Thread::VISUAL)
01798 mClusterSelector->SetPagemode(false);
01799 else
01800 mClusterSelector->SetPagemode(true);
01801 }
01802 else
01803 {
01804 ILOG_DEBUG("ClusterSelect(): hiding...");
01805 mClusterSelector->Hide();
01806 }
01807 }
01808
01809 Thread* GetThreadByName(CString name)
01810 {
01811 return mThreadSet->GetThreadByName(name);
01812 }
01813
01814 virtual void
01815 OnRectangleSelect(int shotID, float x, float y, float w, float h)
01816 {
01817 ILOG_DEBUG("OnRectangleSelect: shot ID="<<shotID<<" x=" << x <<
01818 " y=" << y << " w=" << w << " h=" << h);
01819 int keyframe = mThreadSet->GetKeyframes()->GetShotRKF(shotID);
01820 DoQueryByRegion(keyframe, x, y, w, h);
01821 }
01822
01823 virtual void OnRectangleSelectByKeyframe(int keyframeID, float x, float y,
01824 float w, float h)
01825 {
01826 ILOG_DEBUG("OnRectangleSelect: keyframe ID="<<keyframeID<<" x=" <<
01827 x << " y=" << y << " w=" << w << " h=" << h);
01828 DoQueryByRegion(keyframeID, x, y, w, h);
01829 }
01830
01831 bool ValidateContext(CString name)
01832 {
01833 RotorBrowserContext* ctx = GetContextByName(name);
01834 if (!ctx || !ctx->ThreadValid())
01835 return false;
01836 return true;
01837 }
01838
01839 private:
01840 void InitHelp()
01841 {
01842 int w = WndWidth(), h = WndHeight();
01843 if (w < 600 || h < 200)
01844 mHelpViewer = new GUI::HelpViewer(this,0,0,w,h);
01845 else
01846 mHelpViewer = new GUI::HelpViewer(this,(w-600)/2,60,600,h-120);
01847 mHelpViewer->ConnectTo(this);
01848 mHelpViewer->SetVisible(false);
01849 }
01850
01851 void ShowStatusStr(String s1, String s2, ULONG col=0)
01852 {
01853 if (!mStatusOverlay) return;
01854
01855 mStatusOverlay->ShowStatus(s1,s2,col);
01856 }
01857
01858 void ShowStatusStr(String s1, bool mode)
01859 {
01860 if (!mStatusOverlay) return;
01861
01862 mStatusOverlay->ShowStatus(s1,mode);
01863 }
01864
01865 void Printf3D(float x, float y, float z,
01866 float scaleX, float scaleY, float scaleZ, String str)
01867 {
01868 glPushMatrix();
01869 int fBase = mFontHandler->GetFontBase(this);
01870 oglSys.Printf3D(fBase,x,y,z,scaleX,scaleY,scaleZ,str.c_str());
01871 glPopMatrix();
01872 }
01873
01874 void DoReturnToFirstQuery()
01875 {
01876 if (!mHasReturnQuery) return;
01877
01878 mThreadSet->RemoveThread("shots_initialquery");
01879 Thread* t = GetThreadByName("shots_returnquery");
01880 mThreadSet->CopyToShotsThread(t,"initialquery");
01881 ILOG_DEBUG("Returning to previous query, position = "<<mReturnPosition);
01882 mHasReturnQuery = false;
01883 UpdateViewsToContext();
01884 ReloadCrossBrowser(mReturnPosition);
01885 }
01886
01887 void DoShowBookmarksThread()
01888 {
01889
01890 if (mHasReturnQuery)
01891 {
01892 DoReturnToFirstQuery();
01893 return;
01894 }
01895
01896 Thread* t = GetThreadByName("bookmarked");
01897 if (t->GetLength()<1) return;
01898
01899 ClearReturnQuery();
01900 if (!mHasReturnQuery)
01901 {
01902 t = GetThreadByName("shots_initialquery");
01903 mThreadSet->CopyToShotsThread(t,"returnquery");
01904 mHasReturnQuery = true;
01905 mReturnPosition = GetContext("shots_initialquery")->GetCenter();
01906 ILOG_DEBUG("Stored return query with position " << mReturnPosition);
01907 }
01908 mThreadSet->RemoveThread("shots_initialquery");
01909 mThreadSet->CopyToShotsThread(GetThreadByName("bookmarked"),
01910 "initialquery");
01911 ILOG_DEBUG("Showing bookmark thread");
01912 UpdateViewsToContext();
01913 mActiveContext->GoFirst();
01914 UpdateViewsToContext();
01915 }
01916
01917 void ClearReturnQuery()
01918 {
01919 mThreadSet->RemoveThread("shots_returnquery");
01920 mHasReturnQuery = false;
01921 mReturnPosition = 0;
01922 }
01923
01924 void DoVisualQuery(String type)
01925 {
01926 if (mBrowseMode == MODE_FORKBROWSER)
01927 {
01928 ILOG_WARN("DoVisualQuery redundant in ForkBrowser, not executing.");
01929 return;
01930 }
01931
01932 int active = mActiveContext->GetCenter();
01933
01934 String tname = "vis_" + type + "_" + MakeString(active);
01935 if (mBrowseMode==MODE_ROTORBROWSER && GetThreadByName("shots_"+tname))
01936 {
01937 ILOG_WARN("DoVisualQuery: thread " << tname << " already exists." );
01938 return;
01939 }
01940
01941 active = mThreadSet->GetKeyframes()->GetShotRKF(active);
01942 std::list<KeyframeResult> visual =
01943 mVisualQueryEngine->QueryVisual(type, active);
01944 if (visual.empty())
01945 {
01946 ILOG_WARN("DoVisualQuery: " << type << " no results");
01947 return;
01948 }
01949
01950 if (mBrowseMode == MODE_CROSSBROWSER)
01951 {
01952 ClearReturnQuery();
01953 if (!mHasReturnQuery)
01954 {
01955 Thread* t = GetThreadByName("shots_initialquery");
01956 mThreadSet->CopyToShotsThread(t,"returnquery");
01957 mHasReturnQuery = true;
01958 mReturnPosition = GetContext("shots_initialquery")->GetCenter();
01959 ILOG_DEBUG("Stored return query with position " <<
01960 mReturnPosition);
01961 }
01962 mThreadSet->RemoveThread("shots_initialquery");
01963 mThreadSet->AddThreadShots("initialquery", visual);
01964 ReloadCrossBrowser();
01965 UpdateViewsToContext();
01966 return;
01967 }
01968
01969
01970 mThreadSet->AddThreadShots(tname, visual);
01971 UpdateViewsToContext();
01972 SwitchToContext("shots_" + tname);
01973 UpdateViewsToContext();
01974 }
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027 void
02028 DoQueryByRegion(int keyframeID, float x, float y, float w, float h)
02029 {
02030 ILOG_DEBUG("DoQueryByRegion: keyframe ID="<<keyframeID<<" x=" << x
02031 << " y=" << y << " w=" << w << " h=" << h);
02032
02033 if (mBrowseMode == MODE_FORKBROWSER) {
02034 ILOG_ERROR("Handling of Query By Region queries in ForkBrowser " <<
02035 "not yet implemented.");
02036 return;
02037 }
02038
02039 if (mBrowseMode == MODE_CROSSBROWSER)
02040 {
02041 std::list<KeyframeResult> qbyr =
02042 mVisualQueryEngine->QueryByRegion(keyframeID,x,y,x+w,y+h);
02043 if (qbyr.size() > 1)
02044 {
02045 ILOG_DEBUG("Got "<<qbyr.size()<<" results from webservice.");
02046 std::ostringstream bla;
02047 bla << "Found " << qbyr.size() << " query by region results.";
02048 ShowStatusStr("Query by Region",bla.str(),oglGREEN);
02049 mThreadSet->RemoveThread("shots_initialquery");
02050 mThreadSet->AddThreadShots("initialquery", qbyr);
02051 UpdateViewsToContext();
02052 ReloadCrossBrowser();
02053 }
02054 else
02055 {
02056 ILOG_DEBUG("Got no results from webservice.");
02057 char *t = "No query by region result found for this selection.";
02058 ShowStatusStr("Error",t,oglRED);
02059 }
02060 return;
02061 }
02062 String tname = "qbyr_" + MakeString(keyframeID);
02063 if (GetThreadByName("shots_" + tname) != NULL)
02064 ILOG_WARN( "thread " << tname << " already exists." );
02065
02066 std::list<KeyframeResult> qbyr =
02067 mVisualQueryEngine->QueryByRegion(keyframeID,x,y,x+w,y+h);
02068
02069 mThreadSet->AddThreadShots(tname, qbyr);
02070 UpdateViewsToContext();
02071 SwitchToContext("shots_" + tname);
02072 UpdateViewsToContext();
02073 }
02074
02075 void AddRelevantContexts()
02076 {
02077 int active = mActiveContext->GetCenter();
02078 ILOG_DEBUG("Searching for relevant contexts for " <<
02079 mActiveContext->GetName());
02080 TableThreadWidthId *queue =
02081 new TableThreadWidthId(mThreadSet->GetNrThreads());
02082 for (int i=0; i < mThreadSet->GetNrThreads(); i++)
02083 {
02084 Thread *t = mThreadSet->GetThread(i);
02085 if (t->GetName() == "shots_videos")
02086 continue;
02087 if (t->GetType() == Thread::RANK && !mShowRankThreads)
02088 continue;
02089 int relevancy = IsRelevant(t, active);
02090 if (relevancy > 0)
02091 queue->Add(relevancy, t);
02092 }
02093
02094 Impala::Core::Table::Sort(queue, 1, true);
02095
02096 for (int i=0; i < queue->Size(); i++)
02097 {
02098 if (i > 4 && queue->Get1(i) > 3)
02099 break;
02100 if (i > 6)
02101 break;
02102 AddContext(queue->Get2(i), active);
02103 }
02104
02105 delete queue;
02106 ILOG_DEBUG( " end of relevant context search." );
02107 }
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117 int IsRelevant(Thread *t, int position)
02118 {
02119 switch (t->GetType())
02120 {
02121 case Thread::VISUAL:
02122 case Thread::BOOKMARK:
02123 case Thread::HISTORY:
02124 return 0;
02125 case Thread::TIME:
02126 return 1;
02127 case Thread::SHOTS:
02128 if (t->GetName() == "shots_initialquery") return 1;
02129 if (t->GetName() == "shots_supplement") return 0;
02130 if (t->GetName().find("vis_") != String::npos)
02131 {
02132 if (t->GetShotPosition(position) < mTopN &&
02133 t->GetShotPosition(position) >= 0)
02134 return 2;
02135 return 0;
02136 }
02137 return 3;
02138 default:
02139 int pos = t->GetShotPosition(position);
02140 if (pos >=0 && pos < mTopN)
02141 return pos+4;
02142
02143 if (pos > 0 && pos < 79484 &&
02144 t->GetName().find("rank_thread_all") != String::npos)
02145 return 3;
02146 }
02147 return 0;
02148 }
02149
02150 void ManageContexts()
02151 {
02152 if (mBrowseMode == MODE_ROTORBROWSER)
02153 return ManageRotorContexts();
02154 }
02155
02156 void ManageRotorContexts()
02157 {
02158 mBusyManaging = true;
02159
02160
02161 RotorBrowserContextList newposition;
02162
02163
02164 RotorBrowserContextList::iterator context;
02165 for (context=mContexts.begin(); context!=mContexts.end(); context++)
02166 {
02167 if ((*context)->GetName() == "time" ||
02168 IsRelevant((*context)->GetThread(),mActiveContext->GetCenter()))
02169 {
02170
02171 newposition.push_back(*context);
02172 if (mManageDepth)
02173 (*context)->SetDepth(4);
02174 continue;
02175 }
02176 delete (*context);
02177 }
02178 mContexts.clear();
02179 mContexts = newposition;
02180 AddRelevantContexts();
02181
02182 if (mManageDepth)
02183 mActiveContext->SetDepth(6);
02184 mBusyManaging = false;
02185 RepositionContexts();
02186 }
02187
02188 Thread* GetInitBrowserThread(char* str)
02189 {
02190 ILOG_SYSTEM("Init " << str);
02191 Thread *query = GetThreadByName("shots_initialquery");
02192 if (query == NULL || query->GetLength() == 0)
02193 {
02194 ILOG_WARN("tried to inialize " << str << " but no initial " <<
02195 "query present. Aborting." );
02196 SetBrowseMode(MODE_ROTORBROWSER);
02197 }
02198 return query;
02199 }
02200
02201 int CheckInitBrowserFirstShot(Thread* query, char* str)
02202 {
02203 int pos;
02204 if ((pos = query->GetFirstShot()) < 0)
02205 {
02206 ILOG_WARN("tried to inialize " << str << " but initial " <<
02207 "query has no first shot. Switching to RotorBrowser." );
02208 SetBrowseMode(MODE_ROTORBROWSER);
02209 }
02210 return pos;
02211 }
02212
02213 void InitCrossBrowser(int startposition = -1)
02214 {
02215 Thread* query = GetInitBrowserThread("CrossBrowser");
02216 if (!query) return;
02217
02218 int pos = mActiveContext ? mActiveContext->GetCenter() : 0;
02219 if (pos == 0)
02220 {
02221 if ((pos = CheckInitBrowserFirstShot(query,"CrossBrowser")) < 0)
02222 return;
02223 if (startposition >= 0)
02224 pos = startposition;
02225 ILOG_DEBUG("setting up CrossBrowser start position at " << pos);
02226 }
02227
02228 if (mActiveContext != NULL)
02229 delete mActiveContext;
02230
02231 RotorBrowserContextList::iterator context;
02232 for (context=mContexts.begin(); context!=mContexts.end(); context++)
02233 delete (*context);
02234 mContexts.clear();
02235
02236 mActiveContext = new RotorBrowserContext(mCache,query,pos,M_PI/2,6);
02237 mActiveContext->SetSwallowThread(GetThreadByName("virtual_hidden"));
02238 mActiveContext->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
02239
02240 RotorBrowserContext *time =
02241 new RotorBrowserContext(mCache,GetThreadByName("time"),pos,0.0,6);
02242 time->SetSwallowThread(GetThreadByName("virtual_hidden"));
02243 time->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
02244 mContexts.push_back(time);
02245 }
02246
02247 void InitForkBrowser()
02248 {
02249 Thread* query = GetInitBrowserThread("ForkBrowser");
02250 if (!query) return;
02251
02252 RotorBrowserContext::SetGlobalShotSwallow(true);
02253
02254 mForkLastQueryShot = -1;
02255
02256 int position = mActiveContext ? mActiveContext->GetCenter() : 0;
02257 if (position == 0)
02258 {
02259 if ((position = CheckInitBrowserFirstShot(query,"ForkBrowser")) < 0)
02260 return;
02261 ILOG_DEBUG("setting up ForkBrowser start position at " << position);
02262 }
02263
02264
02265 if (mActiveContext != NULL)
02266 delete mActiveContext;
02267
02268 RotorBrowserContextList::iterator context;
02269 for (context = mContexts.begin(); context != mContexts.end(); context++)
02270 delete (*context);
02271 mContexts.clear();
02272
02273 Thread* threadHidden = GetThreadByName("virtual_hidden");
02274
02275
02276 mActiveContext =
02277 new RotorBrowserContext(mCache, query, position, M_PI/2, 6);
02278 mActiveContext->SetDrawDirection(RotorBrowserContext::DIRECTION_UP);
02279 mActiveContext->SetSwallowThread(threadHidden);
02280 mActiveContext->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
02281
02282
02283 Thread* threadHistory = GetThreadByName("history");
02284 RotorBrowserContext *history =
02285 new RotorBrowserContext(mCache,threadHistory,position,M_PI/2,6);
02286 history->SetDrawDirection(RotorBrowserContext::DIRECTION_DOWN);
02287 history->SetSwallowThread(threadHidden);
02288 history->SetSwallowMode(RotorBrowserContext::SWALLOW_NONE);
02289 mContexts.push_back(history);
02290
02291
02292 RotorBrowserContext *time =
02293 new RotorBrowserContext(mCache,GetThreadByName("time"),position,0,6);
02294 time->SetSwallowThread(threadHidden);
02295 time->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
02296 mContexts.push_back(time);
02297
02298 Thread* visSemGabor = GetThreadByName("visual_vissemgabor");
02299 RotorBrowserContext *visual =
02300 new RotorBrowserContext(mCache,visSemGabor,position,M_PI/4,6);
02301 visual->SetDrawDirection(RotorBrowserContext::DIRECTION_UP);
02302 visual->SetSwallowThread(threadHidden);
02303 visual->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
02304 mContexts.push_back(visual);
02305
02306 Thread* visSem = GetThreadByName("visual_vissem");
02307 RotorBrowserContext *contextual =
02308 new RotorBrowserContext(mCache,visSem,position,M_PI/4+M_PI/2,6);
02309 contextual->SetDrawDirection(RotorBrowserContext::DIRECTION_UP);
02310 contextual->SetSwallowThread(threadHidden);
02311 contextual->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
02312 mContexts.push_back(contextual);
02313 }
02314
02315 void InitRotorBrowser()
02316 {
02317 RotorBrowserContext *query = GetContext("shots_initialquery");
02318 ILOG_SYSTEM( "Init RotorBrowser" );
02319 mInitialQueryPosition = -1;
02320 if (query)
02321 query->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
02322 if (mActiveContext)
02323 mActiveContext->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
02324 }
02325
02326 RotorBrowserContext* GetContextByName(String name)
02327 {
02328 if (mActiveContext->GetName() == name)
02329 return mActiveContext;
02330
02331 RotorBrowserContextList::iterator context;
02332 for (context=mContexts.begin(); context!=mContexts.end(); context++)
02333 {
02334 if ((*context)->GetName() == name)
02335 return *context;
02336 }
02337 return NULL;
02338 }
02339
02340 RotorBrowserContext* FindContextForPosition(int ID)
02341 {
02342 if (mActiveContext->ShowsPosition(ID))
02343 return mActiveContext;
02344
02345 RotorBrowserContextList::iterator context;
02346 for (context=mContexts.begin(); context!=mContexts.end(); context++)
02347 {
02348 if ((*context)->ShowsPosition(ID))
02349 return *context;
02350 }
02351 return NULL;
02352 }
02353
02354 bool HasContext(String name)
02355 {
02356 return GetContextByName(name) != NULL;
02357 }
02358
02359 bool SwitchToPreviousContext()
02360 {
02361 return SwitchToNextContext(-1);
02362 }
02363
02364 bool SwitchToNextContext(int direction = +1)
02365 {
02366 if (mBrowseMode != MODE_ROTORBROWSER)
02367 return false;
02368 if (mContexts.size() == 0)
02369 {
02370 ILOG_DEBUG( "RotorBrowser::SwitchToNextContext: no other contexts");
02371 return false;
02372 }
02373 RotorBrowserContext *next;
02374 if (direction < 0)
02375 {
02376 next = mContexts.back();
02377 mContexts.pop_back();
02378 mContexts.push_front(mActiveContext);
02379 }
02380 else
02381 {
02382 next = mContexts.front();
02383 mContexts.pop_front();
02384 mContexts.push_back(mActiveContext);
02385 }
02386 if (mManageDepth)
02387 {
02388 next->SetDepth(5);
02389 mActiveContext->SetDepth(3);
02390 }
02391 mActiveContext = next;
02392 ILOG_DEBUG("RotorBrowser::SwitchToNextContext: active context now: " <<
02393 mActiveContext->GetName() );
02394 if (mRotorBrowserListener)
02395 mRotorBrowserListener->ContextChangeEvent(this, mActiveContext);
02396 RepositionContexts();
02397 return true;
02398 }
02399
02400 bool SwitchToContext(String name)
02401 {
02402 if (mActiveContext && mActiveContext->GetName() == name)
02403 return true;
02404 if (mContexts.size() == 0) {
02405 ILOG_DEBUG( "SwitchToContext: no other contexts found." );
02406 return false;
02407 }
02408 if (mActiveContext == NULL)
02409 {
02410 mActiveContext = mContexts.front();
02411 mContexts.pop_front();
02412 ILOG_WARN("no active context found. Active context set to "
02413 << mActiveContext->GetName() );
02414 }
02415
02416 String scontext = mActiveContext->GetName();
02417 int maxr = 0;
02418 while (mActiveContext->GetName() != name)
02419 {
02420 RotorBrowserContext *next = mContexts.front();
02421 mContexts.pop_front();
02422 if (mBrowseMode == MODE_ROTORBROWSER && mManageDepth)
02423 {
02424 next->SetDepth(5);
02425 mActiveContext->SetDepth(3);
02426 }
02427 mContexts.push_back(mActiveContext);
02428 mActiveContext = next;
02429 if (mActiveContext->GetName() == scontext && ++maxr==2)
02430 return false;
02431 }
02432 ILOG_DEBUG("RotorBrowser::SwitchToContext: active context now: "
02433 << mActiveContext->GetName() );
02434 if (mRotorBrowserListener)
02435 mRotorBrowserListener->ContextChangeEvent(this, mActiveContext);
02436 RepositionContexts();
02437 return true;
02438 }
02439
02440 RotorBrowserContext* GetContext(String name)
02441 {
02442 if (mActiveContext->GetName() == name)
02443 return mActiveContext;
02444
02445 RotorBrowserContextList::iterator context;
02446 for (context=mContexts.begin(); context != mContexts.end(); context++)
02447 {
02448 if ((*context)->GetName() == name)
02449 return *context;
02450 }
02451 return NULL;
02452 }
02453
02454 void RepositionContexts()
02455 {
02456 if (mBusyManaging || mBrowseMode != MODE_ROTORBROWSER)
02457 return;
02458
02459 if (mActiveHorizontal)
02460 mActiveContext->SetDirection(0.0);
02461
02462 double cDi = M_PI / ((double)mContexts.size()+1);
02463 double cD = mActiveContext->GetDirection() + cDi;
02464 RotorBrowserContextList::const_iterator context;
02465 for (context=mContexts.begin(); context!=mContexts.end(); context++)
02466 {
02467 (*context)->SetDirection(cD);
02468 cD += cDi;
02469 }
02470 }
02471
02472 void CheckFocus(bool force=false)
02473 {
02474 bool hasFocus = (GetOGLWND() == oglFocusWnd);
02475 if ((hasFocus && !mHadFocus) || (force && mHadFocus))
02476 {
02477 mHadFocus = true;
02478 if (!force)
02479 mBackNormal = GetBorderBackground();
02480 if (mBrowseMode == MODE_ROTORBROWSER)
02481 SetBorderBackground(0x80802020);
02482 else if (mBrowseMode == MODE_FORKBROWSER)
02483 SetBorderBackground(0x802020A0);
02484 else
02485 SetBorderBackground(0x80206020);
02486 }
02487 if (!hasFocus && mHadFocus)
02488 {
02489 mHadFocus = false;
02490 SetBorderBackground(mBackNormal);
02491 }
02492 }
02493
02494 void InitKB(String keyStr, String dfltStr0,
02495 String dfltStr1="", String dfltStr2="",
02496 String dfltStr3="", String dfltStr4="",
02497 String dfltStr5="", String dfltStr6="")
02498 {
02499 KeyBindingsMap& kb = mKeyBindings;
02500 keyStr = mPreFix + keyStr;
02501 InitKeyBinding(kb, keyStr, dfltStr0, dfltStr1, dfltStr2, dfltStr3,
02502 dfltStr4, dfltStr5, dfltStr6);
02503 }
02504
02505 void InitKeyBindings()
02506 {
02507 KeyBindingsMap& kb = mKeyBindings;
02508
02509 InitKB("CsBookPositive", "space");
02510 InitKB("CsBookPositiveForce", "shift#space");
02511 InitKB("CsBookNegative", "x");
02512 InitKB("CsBookNegativeForce", "X");
02513
02514 InitKB("StdToggleShowBookmarks", "b");
02515 InitKB("StdStopAutoStills", "esc");
02516 InitKB("StdToggleAutoStills", "\t");
02517 InitKB("StdToggleVideoStream", "1");
02518 InitKB("StdTogglePlayUntilEnd", "2");
02519 InitKB("StdIncrAutoStillSpeed", "=");
02520 InitKB("StdDecrAutoStillSpeed", "-");
02521 InitKB("StdIncrAnimationSpeed", "]");
02522 InitKB("StdDecrAnimationSpeed", "[");
02523 InitKB("StdToggleShowHelp", "h", "H");
02524 InitKB("StdCrossBrowserMode", "fn5");
02525 InitKB("StdRotorBrowserMode", "fn6");
02526 InitKB("StdForkBrowserMode", "fn7");
02527 InitKB("StdToggleShotSwallow", "`");
02528 InitKB("StdToggleShotSwallowThread", "~");
02529 InitKB("StdToggleKeepCenterCentered", ".", "l");
02530 InitKB("StdBookmarkCenterPositive", "space");
02531 InitKB("StdBookmarkCenterNegative", "x", "X");
02532 InitKB("StdClusterSelect", "f", "F");
02533 InitKB("StdClearViewedCache", "O");
02534 InitKB("StdJudgeBrowseMode", "ctrl-shift#l");
02535 InitKB("StdToggleAutoSelectNegatives", "L");
02536
02537 InitKB("VisualQuery_vissemgabor", "V");
02538 InitKB("VisualQuery_vissem", "B");
02539 InitKB("VisualQuery_fusionvissemgabor", "N");
02540 InitKB("VisualQuery_labhistogram", "M");
02541
02542 InitKB("RbGoForward", "d");
02543 InitKB("RbGoBackward", "a");
02544 InitKB("RbGoFirst", "q");
02545 InitKB("RbGoLast", "e");
02546 InitKB("RbBookmarkNext", "D");
02547 InitKB("RbBookmarkPrev", "A");
02548 InitKB("RbSwitchToContextNext", "w");
02549 InitKB("RbSwitchToContextPrev", "W");
02550 InitKB("RbSwitchToContextTime", "t");
02551 InitKB("RbSwitchToContextBookmark", "T");
02552 InitKB("RbReturnLastInitialQuery", "r", "R");
02553 InitKB("RbToggleShowRankThreads", "o");
02554
02555 InitKB("CbGoFirst", "q");
02556 InitKB("CbGoLast", "e");
02557 InitKB("CbGoInitialQuery", "r", "R");
02558 InitKB("CbGoUp", "w", "up");
02559 InitKB("CbGoDown", "s", "down");
02560 InitKB("CbGoLeft", "a", "left");
02561 InitKB("CbGoRight", "d", "right");
02562 InitKB("CbBookmarkPrevNegative", "ctrl#a", "ctrl#left");
02563 InitKB("CbBookmarkNextNegative", "ctrl#d", "ctrl#right");
02564 InitKB("CbBookmarkPrevPositive", "A","shift#left");
02565 InitKB("CbBookmarkNextPositive", "D", "shift#right");
02566 InitKB("CbBookmarkUpNegative", "ctrl#w", "ctrl#up");
02567 InitKB("CbBookmarkDownNegative", "ctrl#s", "ctrl#down");
02568 InitKB("CbBookmarkUpPositive", "W", "shift#up");
02569 InitKB("CbBookmarkDownPositive", "s", "shift#down");
02570
02571 InitKB("FbTimeBackward", "a", "left");
02572 InitKB("FbTimeForward", "d", "right");
02573 InitKB("FbBookmarkPositiveTimeBackward", "A", "shift#left");
02574 InitKB("FbBookmarkPositiveTimeForward", "D", "shift#right");
02575 InitKB("FbBookmarkNegativeTimeBackward", "ctrl#a", "ctrl#left");
02576 InitKB("FbBookmarkNegativeTimeForward", "ctrl#d", "ctrl#right");
02577 InitKB("FbLastHistory", "s", "down");
02578 InitKB("FbBookmarkPositiveHistoryGoLast", "S", "shift#down");
02579 InitKB("FbBookmarkNegativeHistoryGoLast", "ctrl#s","ctrl#down");
02580 InitKB("FbLastQueryShot", "r");
02581 InitKB("FbQueryForward", "w", "up");
02582 InitKB("FbBookmarkPositiveQueryForward", "W", "shift#up");
02583 InitKB("FbBookmarkNegativeQueryForward", "ctrl#w","ctrl#up");
02584 InitKB("FbGaborForward", "e");
02585 InitKB("FbBookmarkPositiveGaborForward", "E");
02586 InitKB("FbBookmarkNegativeGaborForward", "ctrl#e");
02587 InitKB("FbVissemForward", "q");
02588 InitKB("FbBookmarkPositiveVissemForward", "Q");
02589 InitKB("FbBookmarkNegativeVissemForward", "ctrl#q");
02590 }
02591
02592 void
02593 Init(ThreadSet *threadset, SegmentationDocument *document, String preFix)
02594 {
02595 ILOG_DEBUG("RotorBrowser::init()");
02596 oglSys.SetAllowCameraMove(GetOGLWND(), CamMove_Keys | CamMove_Mouse);
02597
02598 CmdOptions &options = CmdOptions::GetInstance();
02599
02600 mRotorBrowserListener = NULL;
02601 mThreadSet = threadset;
02602 mDocument = document;
02603 mPreFix = options.GetString("RbKeybindingPrefix", preFix);
02604 mPrograms = 0;
02605
02606 mBrowseMode = MODE_ROTORBROWSER;
02607 mAutoStills = STILLS_NONE;
02608 mBackNormal = GetBackground();
02609 mTopN = 30;
02610 mInitialQueryPosition = -1;
02611 mReturnPosition = 0;
02612 mDisabledCenterVideo = -1;
02613
02614
02615 mTrailBookmarks = 0;
02616 mTrailVisited = 0;
02617 mTrailHistory = 0;
02618 mTrailVisibleTime = 0;
02619 mTrailVisibleQuery = 0;
02620 mTrailVisibleVisualA = 0;
02621 mTrailVisibleVisualB = 0;
02622
02623 mHadFocus = false;
02624 mShowRankThreads = false;
02625 mEnableShotSwallow = false;
02626 mKeepCenterCentered = false;
02627 mBusyManaging = false;
02628 mHasReturnQuery = false;
02629 mActiveHorizontal = true;
02630 mShowDirection = true;
02631 mManageContexts = true;
02632 mManageDepth = true;
02633
02634 Thread* timeThr = GetThreadByName("time");
02635 Thread* hiddenThr = GetThreadByName("virtual_hidden");
02636
02637 mFontHandler = new FontHandler();
02638 mStatusOverlay = new StatusOverlayWindow(this);
02639 mCache = new RotorViewCache(this, threadset, this);
02640 mClusterSelector = new ThreadClusterSelector(mCache);
02641 mVisualQueryEngine = new VisualQueryEngine(mThreadSet,mTopN*2);
02642 mStills = new Stills(mDocument->GetVideoSet(),"stills");
02643 mActiveContext = new RotorBrowserContext(mCache,timeThr,0,0.0,5);
02644
02645 mActiveContext->SetSwallowThread(hiddenThr);
02646 mActiveContext->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
02647
02648 SetEnableShotSwallow(false);
02649 RotorView::SetStillFrameWait(15);
02650
02651 InitHelp();
02652 InitKeyBindings();
02653
02654
02655
02656
02657 SetDisableOGLViewKeys(false);
02658 SetBorderBackground(0x80202020);
02659
02660 }
02661
02662 KeyBindingsMap mKeyBindings;
02663 String mPreFix;
02664
02665 ThreadSet* mThreadSet;
02666 SegmentationDocument* mDocument;
02667 VisualQueryEngine* mVisualQueryEngine;
02668 ThreadClusterSelector* mClusterSelector;
02669 Samples::ProgramNameReader* mPrograms;
02670 Stills* mStills;
02671
02672 RotorBrowserContextList mContexts;
02673 RotorBrowserContext* mActiveContext;
02674 RotorBrowserListener* mRotorBrowserListener;
02675 RotorViewCache* mCache;
02676
02677
02678 ShotTrail* mTrailVisited;
02679 ShotTrail* mTrailBookmarks;
02680 ShotTrail* mTrailHistory;
02681 ShotTrail* mTrailVisibleTime;
02682 ShotTrail* mTrailVisibleQuery;
02683 ShotTrail* mTrailVisibleVisualA;
02684 ShotTrail* mTrailVisibleVisualB;
02685
02686 Visualization::GUI::HelpViewer* mHelpViewer;
02687 FontHandler* mFontHandler;
02688 StatusOverlayWindow* mStatusOverlay;
02689
02690 int mTopN;
02691 int mBrowseMode;
02692 int mForkLastQueryShot;
02693 int mInitialQueryPosition;
02694 int mReturnPosition;
02695 int mAutoStills;
02696
02697
02698
02699 int mDisabledCenterVideo;
02700
02701 bool mHadFocus;
02702 bool mShowDirection;
02703 bool mActiveHorizontal;
02704 bool mManageContexts;
02705 bool mBusyManaging;
02706 bool mManageDepth;
02707 bool mEnableShotSwallow;
02708 bool mKeepCenterCentered;
02709 bool mShowRankThreads;
02710 bool mMinimapEnabled;
02711 bool mHasReturnQuery;
02712
02713 ULONG mBackNormal;
02714
02715 public:
02716 static const int MODE_CROSSBROWSER = 1;
02717 static const int MODE_ROTORBROWSER = 2;
02718 static const int MODE_FORKBROWSER = 3;
02719
02720 static const int STILLS_NONE = 1;
02721 static const int STILLS_CENTER = 2;
02722 static const int STILLS_NEARCENTER = 3;
02723 static const int STILLS_ACTIVE = 4;
02724 static const int STILLS_ALL = 5;
02725
02726 ILOG_VAR_DEC;
02727
02728 };
02729
02730 ILOG_VAR_INIT(RotorBrowser, Visualization.RotorBrowser);
02731
02732 }
02733 }
02734 }
02735 #endif
02736