miscellaneous/motionbuilder_shelf/shelveTool.cpp

miscellaneous/motionbuilder_shelf/shelveTool.cpp
//
// Created by Cyrille Fauvel on 11/04/13.
// (C) Copyright 2013 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in object code
// form for any purpose and without fee is hereby granted, provided that the above
// copyright notice appears in all copies and that both that copyright notice and
// the limited warranty and restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. AUTODESK SPECIFICALLY
// DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.
// AUTODESK, INC. DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE UNINTERRUPTED
// OR ERROR FREE.
//
#include "StdAfx.h"
#include "shelveTool.h"
FBToolImplementation (ShelveTool) ;
FBRegisterTool (ShelveTool, ORTOOL__NAME, "The MotionBuilder Shelf", FB_DEFAULT_SDK_ICON) ; // Icon filename (default=Open Reality icon)
bool ShelveTool::FBCreate () {
OnShow.Add (this, (FBCallback)&ShelveTool::EventToolShow) ;
OnInput.Add (this, (FBCallback)&ShelveTool::EventToolInput) ;
OnResize.Add (this, (FBCallback)&ShelveTool::EventToolResize) ;
SetPossibleDockPosition ((FBToolPossibleDockPosition)(
)) ;
FBConfigFile config ("@Application.txt") ;
const char* defaultPosValue = "20,100";
bool bSuccess = config.GetOrSet( ORTOOL__NAME, "Position", defaultPosValue );
if( bSuccess )
{
std::string pos( defaultPosValue ); //"kFBToolPossibleDockPosTop") ;
if (( pos.length() == 1) && (pos[0] == 'k' )) {
// todo - dock it directly
} else {
std::string lPosString(pos);
std::vector<std::string> sts =tokenize (pos, ',') ;
StartPos [0] =atoi (sts [0].c_str ()) ;
StartPos [1] =atoi (sts [1].c_str ()) ;
}
}
std::string size(config.Get (ORTOOL__NAME, "Size", "640,83")) ; // See SHELVES_HEIGHT - ShelveTool.h
std::vector<std::string> sts =tokenize (size, ',') ;
StartSize [0] =628 ;
StartSize [1] =83 ;
if ( atoi (sts [0].c_str ()) < 1600 )
StartSize [0] =atoi (sts [0].c_str ()) + TAB_HEIGHT - 9 ;
if ( atoi (sts [1].c_str ()) < 1200 )
StartSize [1] =atoi (sts [1].c_str ()) + TAB_HEIGHT - 2 ;
AddRegion (
"TabPanel", "TabPanel",
0, kFBAttachLeft, NULL, 1.0,
0, kFBAttachTop, NULL, 1.0,
0, kFBAttachRight, NULL, 1.0,
TAB_HEIGHT, kFBAttachNone, NULL, 1.0
) ;
SetControl ("TabPanel", _Tab) ;
_Tab.OnChange.Add (this, (FBCallback)&ShelveTool::onTabChanged) ;
std::string path (FBSystem ().TheOne ().UserConfigPath.AsString ()) ;
#if defined(KARCH_ENV_WIN32)
path += _T("\\Shelves.xml") ;
#else
path += _T("/Shelves.xml") ;
#endif
std::ifstream infile(path.c_str());
if (!infile)
{
// If there is no Shelves.xml in user config directory, we copy it from the template
// in ORSDK sample ormotionbuilder_shelf.
std::string xml_template (FBSystem ().TheOne ().ApplicationPath.AsString());
#if defined(KARCH_ENV_WIN32)
xml_template += _T("\\..\\..\\OpenRealitySDK\\Samples\\miscellaneous\\motionbuilder_shelf\\Shelves.xml");
#else
xml_template += _T("/../../OpenRealitySDK/Samples/miscellaneous/motionbuilder_shelf/Shelves.xml");
#endif
std::ifstream stream1(xml_template.c_str());
if (!stream1)
{
FBTrace("\nCan't find original xml template %s for Motionbuilder shelf.\n", xml_template.c_str());
return (false) ;
}
std::ofstream stream2(path.c_str());
stream2 << stream1.rdbuf();
stream1.close();
stream2.close();
}
infile.close();
pugi::xml_parse_result result =doc.load_file (path.c_str ()) ;
if ( !result )
{
FBTrace("\nCan't load xml file %s for Motionbuilder shelf.\n", path.c_str());
return (false) ;
}
pugi::xpath_node_set shelves =doc.select_nodes ("/Shelves/Shelf/Item") ;
_Buttons =new FBButton [shelves.size ()] ;
shelves =doc.select_nodes ("/Shelves/Shelf") ;
_Layouts =new FBLayout [shelves.size ()] ;
for ( pugi::xpath_node_set::const_iterator it =shelves.begin () ; it != shelves.end () ; ++it ) {
pugi::xpath_node lnode =*it ;
int iTab =_Tab.Items.GetCount () ;
_Tab.Items.Add (lnode.node ().attribute ("title").value ()) ;
std::string szLayout =format (std::string ("Layout%d"), iTab) ;
_LayoutIds.push_back (szLayout) ;
AddRegion (
szLayout.c_str (), szLayout.c_str (),
0, kFBAttachLeft, "TabPanel", 1.0,
0, kFBAttachBottom, "TabPanel", 1.0,
0, kFBAttachRight, "TabPanel", 1.0,
) ;
SetControl (szLayout.c_str (), _Layouts [iTab]) ;
SetBorder (szLayout.c_str (), kFBStandardBorder, false, true, 1, 0, 90, 0) ;
int n =BUTTON_MARGIN ;
pugi::xpath_node_set items =lnode.node ().select_nodes ("Item") ;
for ( pugi::xpath_node_set::const_iterator it2 =items.begin () ; it2 != items.end () ; ++it2, n +=BUTTON_SIZE ) {
pugi::xpath_node inode =*it2 ;
int iButton =(int)_ButtonIds.size () ;
std::string szButton =format (std::string ("Button%d-%d"), iTab, iButton) ;
_ButtonIds.push_back (szButton) ;
int width =BUTTON_SIZE ;
if ( inode.node ().attribute ("width") )
width =inode.node ().attribute ("width").as_int () ;
_Layouts [iTab].AddRegion (
szButton.c_str (), szButton.c_str (),
n, kFBAttachLeft, szLayout.c_str (), 1.0,
BUTTON_MARGIN, kFBAttachTop, NULL, 1.0,
width, kFBAttachNone, NULL, 1.0,
BUTTON_SIZE, kFBAttachNone, NULL, 1.0
) ;
if ( width != BUTTON_SIZE )
n +=width - BUTTON_SIZE ;
_Layouts [iTab].SetControl (szButton.c_str (), _Buttons [iButton]) ;
if ( inode.node ().attribute ("title") ) {
_Buttons [iButton].Caption.SetPropertyValue (inode.node ().attribute ("title").value ()) ;
}
if ( inode.node ().attribute ("image") ) {
_Buttons [iButton].Style =kFBBitmapButton ;
_Buttons [iButton].SetImageFileNames (inode.node ().attribute ("image").value ()) ;
}
if ( inode.node ().attribute ("hint") ) {
_Buttons [iButton].PropertyList.Find ("Hint")->SetString (inode.node ().attribute ("hint").value ()) ;
}
_Buttons [iButton].OnClick.Add (this, (FBCallback)&ShelveTool::onButtonClicked) ;
if ( inode.node ().attribute ("script") ) {
std::string scriptName =format (std::string ("/Shelves/Scripts/Script[@name='%s']"), inode.node ().attribute ("script").value ()) ;
pugi::xpath_node_set script =doc.select_nodes (scriptName.c_str ()) ;
if ( script.size () == 1 ) {
_scripts [szButton] =(*(script.begin ())).node ().text ().as_string () ;
} else {
_scriptFiles [szButton] =inode.node ().attribute ("script").value () ;
}
} else {
_scripts [szButton] =inode.node ().text ().as_string () ;
}
}
}
const char *tab =config.Get (ORTOOL__NAME, "Tab", "-1") ; // -1 Means default to first, otherwise will contain the name
int index =_Tab.Items.Find (tab) ;
if ( index == -1 )
index =0 ;
_Tab.ItemIndex = index;
SetControl (_LayoutIds [index].c_str (), _Layouts [index]) ;
return (true) ;
}
void ShelveTool::FBDestroy () {
delete [] _Layouts ;
delete [] _Buttons ;
}
void ShelveTool::EventToolInput (HISender pSender, HKEvent pEvent) {
FBEventInput evt (pEvent) ;
}
void ShelveTool::EventToolShow (HISender pSender, HKEvent pEvent) {
FBEventShow evt (pEvent) ;
if ( evt.Shown ) {
// Reset the UI here.
} else {
}
}
void ShelveTool::EventToolResize (HISender pSender, HKEvent pEvent) {
FBEventResize evt (pEvent) ;
FBConfigFile config ("@Application.txt") ;
std::string st =format (std::string ("%d,%d"), evt.Width.AsInt (), evt.Height.AsInt ()) ;
config.Set (ORTOOL__NAME, "Size", st.c_str ()) ;
}
void ShelveTool::onTabChanged (HISender pSender, HKEvent pEvent) {
SetControl (_LayoutIds [_Tab.ItemIndex].c_str (), _Layouts [_Tab.ItemIndex]) ;
FBConfigFile config ("@Application.txt") ;
config.Set (ORTOOL__NAME, "Tab", _Tab.Items[_Tab.ItemIndex]) ;
}
void ShelveTool::onButtonClicked (HISender pSender, HKEvent pEvent) {
FBComponent* lComp = FBGetFBComponent( (HIObject)pSender );
if (lComp == NULL)
return;
int index =0 ;
for ( ; index < _ButtonIds.size () ; index++ ) {
if (_Buttons[index].GetHIObject() == ((FBButton*)lComp)->GetHIObject())
break;
}
if ( index >= _ButtonIds.size () )
return ;
//PyGILState_STATE gstate ;
//gstate =PyGILState_Ensure () ;
std::string szButton =_ButtonIds [index] ;
std::string python =_scripts [szButton] ;
if ( python.empty () ) {
python =_scriptFiles [szButton] ;
bool bRet =FBPython::EvalFile (python.c_str ()) ;
} else {
// Using standard API
bool bRet =FBPython::ParseLine ("from pyfbsdk import *") ;
bRet =FBPython::EvalLine () ;
std::vector<std::string> cmds =tokenize (python, '\n') ;
for ( std::vector<std::string>::iterator it =cmds.begin () ; it != cmds.end () ; it++ ) {
bRet =FBPython::ParseLine ((*it).c_str ()) ;
bRet =FBPython::EvalLine () ;
}
// If using Boost/Python, we can use the following code instead
//int iRet =PyRun_SimpleString ((std::string ("from pyfbsdk import *\n") + python).c_str ()) ;
}
//PyGILState_Release (gstate) ;
}