/* * pawseditorapp.cpp * * Copyright (C) 2005 Atomic Blue (info@planeshift.it, http://www.atomicblue.org) * * Credits : * Michael Cummings * * 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 (version 2 * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Creation Date: 1/20/2005 * Description : main class for pawseditor * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "util/pscssetup.h" #include "util/psutil.h" #include "util/psxmlparser.h" #include "util/consoleout.h" #include "paws/pawsmanager.h" #include "paws/pawsmainwidget.h" #include "pewidgettree.h" #include "pawseditorapp.h" #include "pawseditorglobals.h" #include "pemenu.h" #include "peeditablewidget.h" #include "pepawsmanager.h" const char * PawsEditorApp::CONFIG_FILENAME = "/this/pawseditor.cfg"; const char * PawsEditorApp::APP_NAME = "planeshift.pawseditor.application"; const char * PawsEditorApp::WINDOW_CAPTION = "Planeshift Paws Editor"; const char * PawsEditorApp::KEY_DEFS_FILENAME = "/this/data/pawseditor/keys_def.xml"; CS_IMPLEMENT_APPLICATION PawsEditorApp *editApp; PawsEditorApp::PawsEditorApp(iObjectRegistry *obj_reg) :camFlags(CAM_COUNT) { object_reg = obj_reg; paws = 0; drawScreen = true; currentWidget = NULL; widgetTree = NULL; camFlags.Clear(); camYaw = 0.0f; camPitch = 0.0f; fileName = ""; } PawsEditorApp::~PawsEditorApp() { vfs->Unmount( mountedVPath.GetData(), mountedPath.GetData() ); mountedVPath.Empty(); mountedPath.Empty(); if (event_handler && queue) queue->RemoveListener(event_handler); delete paws; } void PawsEditorApp::SevereError(const char* msg) { csReport(object_reg, CS_REPORTER_SEVERITY_ERROR, APP_NAME, msg); } bool PawsEditorApp::Init() { queue = CS_QUERY_REGISTRY(object_reg, iEventQueue); if (!queue) { SevereError("No iEventQueue plugin!"); return false; } vfs = CS_QUERY_REGISTRY(object_reg, iVFS); if (!vfs) { SevereError("No iVFS plugin!"); return false; } engine = CS_QUERY_REGISTRY(object_reg, iEngine); if (!engine) { SevereError("No iEngine plugin!"); return false; } cfgmgr = CS_QUERY_REGISTRY(object_reg, iConfigManager); if (!cfgmgr) { SevereError("No iConfigManager plugin!"); return false; } // Load the log settings LoadLogSettings(); g3d = CS_QUERY_REGISTRY(object_reg, iGraphics3D); if (!g3d) { SevereError("No iGraphics3D plugin!"); return false; } g2d = g3d->GetDriver2D(); if (!g2d) { SevereError("Could not load iGraphics2D!"); return false; } loader = CS_QUERY_REGISTRY(object_reg, iLoader); if (!loader) { SevereError("Could not load iLoader!"); return false; } // set the window caption iNativeWindow *nw = g3d->GetDriver2D()->GetNativeWindow(); if (nw) nw->SetTitle(WINDOW_CAPTION); // paws initialization paws = new pePawsManager(object_reg, "/this/art/pawseditor.zip", "/this/pawseditor.cfg"); if (!paws) { SevereError("Could not initialize PAWS!"); return false; } // Mount base skin to satisfy unskined elements csString skinPath = cfgmgr->GetStr("Planeshift.GUI.Skin.Base","/planeshift/art/skins/base/client_base.zip"); if(!paws->LoadAdditionalSkin(skinPath)) Error2("Couldn't load base skin '%s'!\n",skinPath.GetData()); mainWidget = new pawsMainWidget(); paws->SetMainWidget(mainWidget); mainWidget->LoadFromFile( "data/pawseditor/peBackground.xml" ); RegisterFactories(); // Load and assign a default button click sound for pawsbutton paws->LoadSound("/this/art/music/gui/ccreate/next.wav","sound.standardButtonClick"); if (!LoadWidgets()) { csReport(object_reg, CS_REPORTER_SEVERITY_NOTIFY, APP_NAME, "Warning: Some PAWS widgets failed to load"); } paws->GetMouse()->ChangeImage("peStandardMousePointer"); paws->FindWidget( "peMenu" )->SetAlwaysOnTop( true ); widgetTree = (peWidgetTree *) paws->FindWidget( "peWidgetTree" ); widgetTree->SetAlwaysOnTop( true ); skinSelector = (peSkinSelector *) paws->FindWidget( "peSkinSelector" ); // Register our event handler event_handler = csPtr (new EventHandler (this)); csEventID esub[] = { csevPreProcess (object_reg), csevProcess (object_reg), csevPostProcess (object_reg), csevFinalProcess (object_reg), csevFrame (object_reg), csevMouseEvent (object_reg), csevKeyboardEvent (object_reg), CS_EVENTLIST_END }; queue->RegisterListener(event_handler, esub); // Load Default Skin csString skin = cfgmgr->GetStr("Planeshift.GUI.Skin.Selected"); if( strcmp( skin, "" ) ) LoadSkin( skin ); // Inform debug that everything initialized succesfully csReport (object_reg, CS_REPORTER_SEVERITY_NOTIFY, APP_NAME, "Application initialized successfully."); return true; } void PawsEditorApp::LoadSkin( const char* name ) { csString zip; zip += cfgmgr->GetStr("Planeshift.GUI.Skin.Dir"); zip += name; zip += ".zip"; //const char *zip = "/this/art/skins/cvs.zip"; csString slash(CS_PATH_SEPARATOR); if ( vfs->Exists(zip + slash) ) zip += slash; if ( !vfs->Exists( zip ) ) { Error1("Current skin doesn't exist, skipping..\n"); return; } //// Make sure the skin is selected //if ( skins->GetSelectedRowString() != name ) //{ // skins->Select( name ); // return; // To prevent recursion //} // Get the path csRef real = vfs->GetRealPath(zip); // Unmount the current skin if ( mountedVPath.Length() != 0 ) vfs->Unmount( mountedVPath, mountedPath ); // Temporarily mount zip to read skin.xml // Parse XML vfs->Mount( "/paws/pawseditor/pawsskin", real->GetData() ); csRef xml = ParseFile( object_reg, "/paws/pawseditor/pawsskin/skin.xml" ); if (!xml) { Error1("Failed to parse file /paws/pawseditor/pawsskin/skin.xml" ); return; } vfs->Unmount( "/paws/pawseditor/pawsskin", real->GetData() ); csRef root = xml->GetRoot(); if(!root) { Error1("No XML root in /paws/pawseditor/pawsskin/skin.xml"); return; } root = root->GetNode("xml"); if(!root) { Error1("No tag in /paws/pawseditor/pawsskin/skin.xml"); return; } csRef skinInfo = root->GetNode("skin_information"); if(!skinInfo) { Error1("No tag in /paws/pawseditor/pawsskin/skin.xml"); return; } csRef mountNode = root->GetNode("mount_path"); if( !mountNode ) { printf("skin.xml is missing mount_path!\n"); return; } // Mount the skin mountedVPath = mountNode->GetContentsValue(); mountedPath = real->GetData(); if ( !vfs->Mount( mountedVPath.GetData(), mountedPath.GetData() ) ) { printf( "Failed to mount %s in %s to VFS at %s\n", name, mountedPath.GetData(), mountedVPath.GetData() ); return; } printf( "Mounted %s in %s to VFS at %s\n", name, mountedPath.GetData(), mountedVPath.GetData() ); currentSkin = name; // Load the skin if ( !LoadResources( mountedVPath ) ) { paws->CreateWarningBox("Couldn't load skin! Check the console for detailed output"); return; } } bool PawsEditorApp::LoadResources( const char* mountPath ) { csString imagelist( mountPath ); imagelist += "/imagelist.xml"; // Open the image list csRef xml = ParseFile( object_reg, imagelist ); if(!xml) { Error2("Parse error in %s", imagelist.GetData()); return false; } csRef root = xml->GetRoot(); if(!root) { Error2("No XML root in %s", imagelist.GetData()); return false; } csRef topNode = root->GetNode( "image_list" ); if(!topNode) { Error1("No tag in /paws/pawseditor/pawsskin/skin.xml"); return false; } csRef iter = topNode->GetNodes(); // Find the resource csString filename; csString resource; while ( iter->HasNext() ) { csRef node = iter->Next(); if ( node->GetType() != CS_NODE_ELEMENT ) continue; if ( strcmp( node->GetValue(), "image" ) == 0 ) { // Remove the resource if it exists resource = node->GetAttributeValue( "resource" ); filename = node->GetAttributeValue( "file" ); paws->GetTextureManager()->Remove( resource ); if( !filename.Length() ) { printf( "Couldn't locate resource %s in the current skin!\n", resource.GetData() ); return false; } if( !vfs->Exists( filename ) ) { printf( "Skin is missing the '%s' resource at file '%s'!\n", resource.GetData(), filename.GetData() ); //return false; continue; } // Compile the structure psImageDescription* desc = new psImageDescription( paws->GetTextureManager() ); desc->refCount = 0; desc->resourceName = resource; desc->imageFileLocation = filename; desc->tiled = false; // Add the info paws->GetTextureManager()->AddImageDescription( desc ); } } return true; } void PawsEditorApp::LoadLogSettings() { int count=0; for (int i=0; i< MAX_FLAGS; i++) { if (pslog::GetName(i)) { pslog::SetFlag(pslog::GetName(i),cfgmgr->GetBool(pslog::GetSettingName(i)), 0); if(cfgmgr->GetBool(pslog::GetSettingName(i))) count++; } } if(count==0) { CPrintf(CON_CMDOUTPUT,"All LOGS are off.\n"); } csString debugFile = cfgmgr->GetStr("PlaneShift.DebugFile"); if ( debugFile.Length() > 0 ) { csRef reporter = CS_QUERY_REGISTRY( object_reg, iStandardReporterListener ); reporter->SetMessageDestination (CS_REPORTER_SEVERITY_DEBUG, true, false ,false, false, true, false); reporter->SetMessageDestination (CS_REPORTER_SEVERITY_ERROR, true, false ,false, false, true, false); reporter->SetMessageDestination (CS_REPORTER_SEVERITY_BUG, true, false ,false, false, true, false); time_t curr=time(0); tm* localtm = localtime(&curr); csString timeStr; timeStr.Format("-%d-%02d-%02d-%02d:%02d:%02d", localtm->tm_year+1900, localtm->tm_mon+1, localtm->tm_mday, localtm->tm_hour, localtm->tm_min, localtm->tm_sec); debugFile.Append( timeStr ); reporter->SetDebugFile( debugFile, true ); Debug2(LOG_STARTUP,0, "PlaneShift Server Log Opened............. %s", timeStr.GetData()); } } bool PawsEditorApp::LoadWidget(const char * file) { if (!paws->LoadWidget(file)) { csString err = "Warning: Loading '" + csString(file) + "' failed!"; SevereError(err); return false; } return true; } bool PawsEditorApp::LoadWidgets() { bool succeeded = true; succeeded &= LoadWidget("data/pawseditor/peWidgetTree.xml"); succeeded &= LoadWidget("data/pawseditor/peMenu.xml"); succeeded &= LoadWidget("data/pawseditor/peSkinSelector.xml"); return succeeded; } bool PawsEditorApp::HandleEvent(iEvent &ev) { if (ev.Name == csevMouseMove (object_reg, 0)) { csMouseEventData mouse; csMouseEventHelper::GetEventData(&ev,mouse); mousePointer.x = mouse.x; mousePointer.y = mouse.y; } if (paws->HandleEvent(ev)) return true; if (ev.Name == csevProcess (object_reg)) { Update(); return true; } else if (ev.Name == csevFinalProcess (object_reg)) { g3d->FinishDraw (); g3d->Print (0); return true; } else if (ev.Name == csevPostProcess (object_reg)) { if (drawScreen) { g3d->BeginDraw(engine->GetBeginDrawFlags() | CSDRAW_2DGRAPHICS); paws->Draw(); } else { csSleep(150); } } else if (ev.Name == csevCanvasHidden (object_reg, g3d->GetDriver2D ())) { drawScreen = false; } else if (ev.Name == csevCanvasExposed (object_reg, g3d->GetDriver2D ())) { drawScreen = true; } return false; } csVector2 PawsEditorApp::GetMousePointer() { return mousePointer; } csRef PawsEditorApp::GetConfigManager() { return cfgmgr; } csRef PawsEditorApp::GetVFS() { return vfs; } void PawsEditorApp::Exit() { queue->GetEventOutlet()->Broadcast (csevQuit (object_reg)); } void PawsEditorApp::RegisterFactories() { new peEditableWidgetFactory(); new peWidgetTreeFactory(); new peMenuFactory(); new peSkinSelectorFactory(); } void PawsEditorApp::Update() { } void PawsEditorApp::SetCamFlag(int flag, bool val) { if (val) camFlags.SetBit(flag); else camFlags.ClearBit(flag); } bool PawsEditorApp::GetCamFlag(int flag) { return camFlags.IsBitSet(flag); } void PawsEditorApp::TakeScreenshot(const csString & fileName) { csRef imageio = CS_QUERY_REGISTRY(object_reg, iImageIO); csRef image = g2d->ScreenShot(); csRef buffer = imageio->Save(image, "image/jpg"); vfs->WriteFile(fileName.GetData(), buffer->GetData(), buffer->GetSize()); printf("Screenshot taken.\n"); } csRef PawsEditorApp::ParseWidgetFile( const char* widgetFile ) { csRef doc = ParseFile(paws->GetObjectRegistry(), widgetFile); if (!doc) { Error2("Parse error in %s", widgetFile); return NULL; } csRef root = doc->GetRoot(); if(!root) { Error2("No XML root %s", widgetFile); return NULL; } csRef widgetNode = root->GetNode("widget_description"); if (!widgetNode) Error2("File %s has no tag", widgetFile); return widgetNode; } void PawsEditorApp::ReloadWidget() { if ( fileName.Length() != 0 ) OpenWidget( fileName.GetData() ); } void PawsEditorApp::OpenWidget(const csString & text) { if ( text.Length() == 0 ) return; fileName = text; if ( currentWidget ) { currentWidget->Close(); delete currentWidget; } csRef widgetNode = ParseWidgetFile( text ); csRef iter = widgetNode->GetNodes(); while ( iter->HasNext() ) { csRef node = iter->Next(); if ( node->GetType() != CS_NODE_ELEMENT ) continue; // This is a widget so read it's factory to create it. if ( strcmp( node->GetValue(), "widget" ) == 0 ) { //node->RemoveAttribute( node->GetAttribute( "factory" ) ); node->SetAttribute( "factory" , "peEditableWidget" ); csString name = node->GetAttribute( "name" )->GetValue(); csString factory = node->GetAttribute( "factory" )->GetValue(); widgetTree->LoadWidget( widgetNode ); currentWidget = dynamic_cast ( paws->LoadWidget( node ) ) ; if ( !currentWidget ) { csString err = "Warning: Loading '" + csString( text ) + "' failed!"; editApp->SevereError( err ); return; } paws->GetMainWidget()->FindWidget( "preview" )->AddChild( currentWidget ); currentWidget->SetFilename( text ); currentWidget->SetMinAlpha( 0 ); currentWidget->SetMaxAlpha( 1 ); currentWidget->Show(); return; } } } void PawsEditorApp::OpenImageList(const csString & text) { paws->GetTextureManager()->LoadImageList( text ); } /** Application entry point */ int main (int argc, char *argv[]) { psCSSetup *CSSetup = new psCSSetup(argc, argv, PawsEditorApp::CONFIG_FILENAME, PawsEditorApp::CONFIG_FILENAME); iObjectRegistry *object_reg = CSSetup->InitCS(); editApp = new PawsEditorApp(object_reg); // Initialize application if (!editApp->Init()) { editApp->SevereError("Failed to init app!"); PS_PAUSEEXIT(1); } // start the main event loop csDefaultRunLoop(object_reg); // clean up delete editApp; delete CSSetup; csInitializer::DestroyApplication(object_reg); return 0; }