/* * pawssetupwindow.cpp - Author: Ian Donderwinkel * * Copyright (C) 2004 Atomic Blue (info@planeshift.it, http://www.atomicblue.org) * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation (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. * */ ////////////////////////////////////////////////////////////////////// #include #include "globals.h" #include #include #include #include #include #include #include #include #include #include #include #include #include // PAWS INCLUDES #include "pawssetupwindow.h" #include "paws/pawsmanager.h" #include "paws/pawsradio.h" #include "paws/pawscheckbox.h" #include "paws/pawstextbox.h" #include "paws/pawscrollbar.h" #include "paws/pawsprogressbar.h" #include "paws/pawslistbox.h" #define PS_QUERY_PLUGIN(myref,intf, str) \ myref = CS_QUERY_REGISTRY (object_reg, intf); \ if (!myref) { \ printf ("No " str " plugin!");\ return false;\ } // Customized progress bar SCF_IMPLEMENT_IBASE (pawsRelightProgress) SCF_IMPLEMENTS_INTERFACE (iProgressMeter) SCF_IMPLEMENT_IBASE_END pawsRelightProgress::pawsRelightProgress (pawsTextBox* file,const char* map, pawsProgressBar* bar,int n) : granularity(10), tick_scale(2), total(n), current(0), anchor(0) { this->bar = bar; bar->SetTotalValue(100.0f); real_current = 0; this->map = map; this->file = file; SCF_CONSTRUCT_IBASE (0); } pawsRelightProgress::~pawsRelightProgress() { SCF_DESTRUCT_IBASE (); } void RefreshDraw() { PawsManager::GetSingleton().GetGraphics3D()->BeginDraw (CSDRAW_2DGRAPHICS); PawsManager::GetSingleton().Draw (); PawsManager::GetSingleton().GetGraphics3D()->FinishDraw (); PawsManager::GetSingleton().GetGraphics2D()->Print (0); } void pawsRelightProgress::Step(unsigned int n) { real_current += n; csString format; format.Format("%s (%d)",map.GetData(),real_current); file->SetText(format); if(current < total) { current += n; int const units = (current == total ? 100 : (((100 * current) / total) / granularity) * granularity); bar->SetCurrentValue(units); RefreshDraw(); } } void pawsRelightProgress::Restart() { Reset(); bar->SetCurrentValue(0.0f); RefreshDraw(); } void pawsRelightProgress::Abort () { current = total; bar->SetCurrentValue(100.0f); RefreshDraw(); } void pawsRelightProgress::Finalize () { current = total; bar->SetCurrentValue(100.0f); RefreshDraw(); } void pawsRelightProgress::SetGranularity(int n) { if (n >= 1 && n <= 100) granularity = n; } void pawsRelightProgress::SetTickScale(int n) { if (n >= 1 && n <= 100) tick_scale = n; } pawsSetupWindow::pawsSetupWindow() { AdvancedMode(false); customWidth = 1280; customHeight = 960; } bool pawsSetupWindow::PostSetup() { csRef vfs = CS_QUERY_REGISTRY (PawsManager::GetSingleton().GetObjectRegistry(), iVFS); configClient = new csConfigFile("/planeshift/psclient.cfg", vfs); configGlobal = new csConfigFile("/planeshift/planeshift.cfg", vfs); rbgResolution= (pawsRadioButtonGroup*)FindWidget("resbox"); rbgDepth = (pawsRadioButtonGroup*)FindWidget("depthbox"); rbgVBO = (pawsRadioButtonGroup*)FindWidget("vbobox"); cbSound = (pawsCheckBox*)FindWidget("sound"); cbFullScreen = (pawsCheckBox*)FindWidget("fullscreen"); cbAllMaps = (pawsCheckBox*)FindWidget("allmaps"); cbMultiQuality = (pawsCheckBox*)FindWidget("ms_quality"); cbKeepMaps = (pawsCheckBox*)FindWidget("keepmaps"); btnOK = (pawsButton*)FindWidget("OKButton"); btnCancel = (pawsButton*)FindWidget("CancelButton"); btnLaunch = (pawsButton*)FindWidget("LaunchButton"); btnRelightMaps = (pawsButton*)FindWidget("relightMaps"); btnRelightMap = (pawsButton*)FindWidget("relightMap"); btnShowRelight = (pawsButton*)FindWidget("showRelight"); edtCustomWidth = (pawsEditTextBox*)FindWidget("screenwidth"); edtCustomHeight = (pawsEditTextBox*)FindWidget("screenheight"); edtStencil = (pawsEditTextBox*)FindWidget("stencil"); lblStreamBuffer = (pawsTextBox*)FindWidget("streambufferlbl"); lblAnisotropy = (pawsTextBox*)FindWidget("at"); lblMultiSampling= (pawsTextBox*)FindWidget("ms"); lblTextureSample= (pawsTextBox*)FindWidget("texdownc"); lblRelightTarget= (pawsTextBox*)FindWidget("relightTarget"); lblFontScale = (pawsTextBox*)FindWidget("fontscalepct"); scbAnisotropy = (pawsScrollBar*)FindWidget("ani"); scbMultiSampling= (pawsScrollBar*)FindWidget("multi"); scbTextureSample= (pawsScrollBar*)FindWidget("texdown"); scbFontScale = (pawsScrollBar*)FindWidget("fontscale"); relightProgress = (pawsProgressBar*)FindWidget("relightProgress"); lsbMapFiles = (pawsListBox*)FindWidget("maps"); // Enum all maps iObjectRegistry* object_reg = setupApp->GetObjReg(); PS_QUERY_PLUGIN (engine, iEngine, "iEngine"); PS_QUERY_PLUGIN (vfs, iVFS, "iVFS"); csRef maps = vfs->FindFiles("/planeshift/art/world/"); csArray files; // Bug in VFS making stuff appear twice for(size_t i = 0; i < maps->Length();i++) { csString map = maps->Get(i); // Zip? if(map.Slice(map.Length()-3,3) != "zip") continue; size_t start = map.FindLast('/')+1; map = map.Slice(start,map.Length() - start); map = map.Slice(0,map.Length()-4); // Inserted this? bool found = false; for(size_t z = 0; z < files.Length();z++) if(files[z] == map) found = true; if(found) break; // Second walk, break // Insert it pawsListBoxRow* row = lsbMapFiles->NewRow(); pawsTextBox* box = (pawsTextBox*)row->GetColumn(0); box->SetText(map); files.Push(map); } LoadSettings(); return true; } bool pawsSetupWindow::OnButtonPressed( int mouseButton, int keyModifier, pawsWidget* widget ) { if (widget==btnOK) { SaveSettings(); setupApp->Quit(); } else if (widget==btnCancel) { setupApp->Quit(); } else if (widget==btnLaunch) { SaveSettings(); #ifdef CS_PLATFORM_WIN32 // Lanuch PlaneShift in the win way STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); ZeroMemory( &pi, sizeof(pi) ); // Start the second updater process. CreateProcess( NULL, // No module name (use command line). "psclient.exe", // Command line. NULL, // Process handle not inheritable. NULL, // Thread handle not inheritable. FALSE, // Set handle inheritance to FALSE. CREATE_NEW_CONSOLE, // Give the process it's own console NULL, // Use parent's environment block. NULL, // Use parent's starting directory. &si, // Pointer to STARTUPINFO structure. &pi ); // Pointer to PROCESS_INFORMATION structure. #elif defined(CS_PLATFORM_UNIX) // *NIX have a quite easier way to do that :) system("./psclient &"); #elif defined(CS_PLATFORM_MACOSX) //is this the right define? //system("open ./psclient.app &"); #else #error "Bad platform for launch" #endif setupApp->Quit(); } else if(widget == cbAllMaps && cbAllMaps->GetState()) { PawsManager::GetSingleton().CreateWarningBox("Warning! While this will eliminate all loading while ingame, this will demand much more RAM and the first loading will take longer to load"); } else if(widget == cbKeepMaps && cbKeepMaps->GetState()) { PawsManager::GetSingleton().CreateWarningBox("This experimental mode will only load zones as you enter them, but will keep them loaded. It does not unload zones yet."); } else if(!strcmp(widget->GetName(),"Skins")) { pawsWidget* skin = PawsManager::GetSingleton().FindWidget("skin"); if(skin) { skin->SetFade(false); skin->SetMaxAlpha(1); skin->Show(); } } else if(widget == btnRelightMap) { csString file; if ( lsbMapFiles->GetSelected() ) { pawsTextBox* txt = (pawsTextBox*)lsbMapFiles->GetSelected()->GetColumn(0); file.Format("/planeshift/art/world/%s.zip",txt->GetText()); RelightMap(file); } } else if(widget == btnRelightMaps) { RelightMaps(); } else if(widget == btnShowRelight) { btnShowRelight->Hide(); relightProgress->Show(); lsbMapFiles->Show(); btnRelightMap->Show(); if(advanced) btnRelightMaps->Show(); lblRelightTarget->Show(); } return false; } void pawsSetupWindow::LoadSettings() { char buf[256]; // video settings int width = configGlobal->GetInt("Video.ScreenWidth"); int height = configGlobal->GetInt("Video.ScreenHeight"); sprintf(buf,"%ix%i",width,height); csString res(buf); if (!rbgResolution->SetActive(buf)) { rbgResolution->SetActive("rescustom"); customWidth = width; customHeight = height; } sprintf(buf,"%i",customWidth); edtCustomWidth->SetText(buf); sprintf(buf,"%i",customHeight); edtCustomHeight->SetText(buf); cbFullScreen->SetState(configGlobal->GetBool("Video.Fullscreen")); rbgDepth->SetActive(configGlobal->GetStr("Video.ScreenDepth")); // Stencil int stencil = configClient->GetInt("Video.OpenGL.StencilThreshold",50); csString stenstr; stenstr.Format("%d",stencil); edtStencil->SetText(stenstr); // VBO if(!configClient->KeyExists("Video.OpenGL.UseExtension.GL_ARB_vertex_buffer_object")) { rbgVBO->SetActive("def"); } else { bool value = configClient->GetBool("Video.OpenGL.UseExtension.GL_ARB_vertex_buffer_object",true); if(value) rbgVBO->SetActive("on"); else rbgVBO->SetActive("off"); } // sound cbSound->SetState(configClient->KeyExists("System.PlugIns.iSndSysRenderer")); // all maps cbAllMaps->SetState(configClient->GetBool("Planeshift.Client.Loading.AllMaps",false)); // keep maps cbKeepMaps->SetState(configClient->GetBool("Planeshift.Client.Loading.KeepMaps",false)); // Multisampling quality cbMultiQuality->SetState(configClient->GetBool("Video.OpenGL.MultisampleFavorQuality",true)); // Anisotropy float aniso = configClient->GetFloat("Video.OpenGL.TextureFilterAnisotropy",1.0f); scbAnisotropy->SetMinValue(1.0f); scbAnisotropy->SetMaxValue(16.0f); scbAnisotropy->SetTickValue(0.5f); scbAnisotropy->SetCurrentValue(aniso,true); // Multisampling int multi = configClient->GetInt("Video.OpenGL.MultiSamples",0); scbMultiSampling->SetMaxValue(8.0f); scbMultiSampling->SetTickValue(0.0f); // handled extra in onscroll scbMultiSampling->SetCurrentValue((float)multi,true); // Texture downsampling int samp = configClient->GetInt("Video.OpenGL.TextureDownsample",0); scbTextureSample->SetMaxValue(4.0f); scbTextureSample->SetTickValue(1.0f); // handled extra in onscroll scbTextureSample->SetCurrentValue((float)samp,true); // Font scaling int fontFactor = configClient->GetInt("Font.ScalePercent",100); scbFontScale->SetMinValue(50.0f); scbFontScale->SetMaxValue(150.0f); scbFontScale->SetTickValue(5.0f); // handled extra in onscroll scbFontScale->SetCurrentValue((float)fontFactor,true); } bool pawsSetupWindow::OnScroll(int dir,pawsScrollBar* widget) { if(widget == scbAnisotropy) { // Easy, just update the label csString lbl; lbl.Format("%.1f",widget->GetCurrentValue()); lblAnisotropy->SetText(lbl); } else if(widget == scbMultiSampling) { // Harder, needs to be 1,2,4,8,16,32 int value = (int)widget->GetCurrentValue(); int pow = 0; while(value > 0) { value = value >> 1; pow++; } pow--; if(pow >= 0) value = 1 << pow; else value = 0; // Note: direction seems to be reversed while horz if(value == 0 && dir == SCROLL_DOWN) value = 1; else if(dir != SCROLL_SET) { if(dir == SCROLL_UP) value = value >> 1; else value = value << 1; } if(value > (int)widget->GetMaxValue()) { value = (int)widget->GetMaxValue(); } widget->SetCurrentValue(value,false); // Update label csString lbl; lbl.Format("%d",value); lblMultiSampling->SetText(lbl); } else if(widget == scbTextureSample) { int pow = (int)widget->GetCurrentValue(); int value = 1 << pow; csString lbl; lbl.Format("1/%d",value); lblTextureSample->SetText(lbl); } else if(widget == scbFontScale) { int value = (int)widget->GetCurrentValue(); csString lbl; lbl.Format("%d%%",value); lblFontScale->SetText(lbl); } else return false; // Unkown widget return true; } bool pawsSetupWindow::RelightMaps() { iObjectRegistry* object_reg = setupApp->GetObjReg(); PS_QUERY_PLUGIN (vfs, iVFS, "iVFS"); // Get all maps csRef files = vfs->FindFiles("/planeshift/art/world/"); csArray ok; csArray failed; for(size_t i = 0; i < files->Length();i++) { csString file,ext; file = files->Get(i); size_t start = file.FindLast('.'); if( start != -1) ext = file.Slice(start,file.Length() - start); if(ext != ".zip") continue; // Not a map // load and relight RelightMap(file); } return true; } bool pawsSetupWindow::RelightMap(const char* zip) { iObjectRegistry* object_reg = setupApp->GetObjReg(); PS_QUERY_PLUGIN (vfs, iVFS, "iVFS"); static csArray litt; // Litt this already? for(size_t i = 0; i < litt.Length();i++) if(litt[i] == zip) return true; // Already done, so return true printf("Relightning map %s\n",zip); // Load the loader plugin if(!loader.IsValid()) { csRef pluginMgr; PS_QUERY_PLUGIN(pluginMgr,iPluginManager,"iPluginManager"); if(!loader) { loader = CS_LOAD_PLUGIN(pluginMgr,"crystalspace.level.loader",iLoader); if(!loader) { printf("Couldn't load the loader plugin! Can't relight maps!\n"); return false; } } } // Load the map if it exists if(!vfs->Exists(zip)) return false; vfs->PushDir(); lblRelightTarget->SetText("Loading map.."); RefreshDraw(); // Reset lighnining engine->SetCacheManager(NULL); engine->SetLightingCacheMode(CS_ENGINE_CACHE_WRITE); // This will force a relightning and write the result to the zip engine->ResetWorldSpecificSettings(); csRef real = vfs->GetRealPath(zip); vfs->Mount("/lev/relightlvl",real->GetData()); SetMapDir("relightlvl"); // Recreate the cache manager engine->GetCacheManager(); // Create the region and clear it if it existed before iRegion* region = engine->CreateRegion("relight_level"); region->DeleteAll(); // load the map if(!loader->LoadMapFile("world",false,region,false,true)) return false; // Update the target label, it will be redrawn when the progress bar advances csString smallZip = zip; size_t start = smallZip.FindLast('/')+1; smallZip = smallZip.Slice(start,smallZip.Length() - start); smallZip = smallZip.Slice(0,smallZip.Length()-4); // Remove .zip // Create a progress meter pawsRelightProgress* meter = new pawsRelightProgress(lblRelightTarget,smallZip,relightProgress); region->PrepareTextures(); engine->Prepare(meter); // relight engine->GetCacheManager()->Flush(); vfs->Sync(); delete meter; // Remove and unmount region->DeleteAll(); vfs->Unmount("/lev/relightlvl",real->GetData()); vfs->PopDir(); // If this is the last, nothing will overwrite this message lblRelightTarget->SetText("Relightning done"); litt.Push(zip); return true; } bool pawsSetupWindow::SetMapDir (const char* map_dir) { csStringArray paths; paths.Push ("/lev/"); if (!vfs->ChDirAuto (map_dir, &paths, 0, "world")) { printf("Error setting directory '%s'!", map_dir); return false; } return true; } void pawsSetupWindow::SaveSettings() { configGlobal->SetBool("Video.Fullscreen",cbFullScreen->GetState()); configGlobal->SetStr("Video.ScreenDepth",rbgDepth->GetActive()); configClient->SetInt("Video.OpenGL.StencilThreshold",atoi(edtStencil->GetText())); // VBO int value; csString vbo = rbgVBO->GetActive(); if(vbo == "def") value = 2; else if(vbo == "on") value = 1; else value = 0; if(value==2) configClient->DeleteKey("Video.OpenGL.UseExtension.GL_ARB_vertex_buffer_object"); else configClient->SetBool("Video.OpenGL.UseExtension.GL_ARB_vertex_buffer_object",(value ? true : false)); // resolution int width, height; csString res = rbgResolution->GetActive(); if (res=="800x600") { width=800; height=600; } else if (res=="1024x768") { width=1024; height=768; } else { width=atoi(edtCustomWidth->GetText()); height=atoi(edtCustomHeight->GetText()); } configGlobal->SetInt("Video.ScreenWidth",width); configGlobal->SetInt("Video.ScreenHeight",height); // sound enabled/disabled if (cbSound->GetState()) { configClient->SetStr("System.PlugIns.iSndSysRenderer","crystalspace.sndsys.renderer.software"); } else { configClient->DeleteKey("System.PlugIns.iSndSysRenderer"); } // all maps configClient->SetBool("Planeshift.Client.Loading.AllMaps",cbAllMaps->GetState()); // keep maps configClient->SetBool("Planeshift.Client.Loading.KeepMaps",cbKeepMaps->GetState()); configClient->SetBool ("Video.OpenGL.MultisampleFavorQuality" ,cbMultiQuality->GetState()); configClient->SetInt ("Video.OpenGL.MultiSamples" ,(int)scbMultiSampling->GetCurrentValue()); configClient->SetFloat("Video.OpenGL.TextureFilterAnisotropy" ,scbAnisotropy->GetCurrentValue()); configClient->SetInt ("Video.OpenGL.TextureDownsample" ,(int)scbTextureSample->GetCurrentValue()); configClient->SetInt("Font.ScalePercent", (int)scbFontScale->GetCurrentValue() ); configGlobal->Save(); configClient->Save(); }