2022-09-24 22:55:05 +02:00
/*
* mainwindow . cpp , part of VCMI engine
*
* Authors : listed in file AUTHORS in main folder
*
* License : GNU General Public License v2 .0 or later
* Full text of license available in license . txt file , in main folder
*
*/
2022-09-18 01:23:17 +02:00
# include "StdInc.h"
# include "mainwindow.h"
# include "ui_mainwindow.h"
# include <QFileDialog>
# include <QFile>
# include <QMessageBox>
# include <QFileInfo>
# include "../lib/VCMIDirs.h"
# include "../lib/VCMI_Lib.h"
# include "../lib/logging/CBasicLogConfigurator.h"
# include "../lib/CConfigHandler.h"
2022-12-20 18:35:40 +02:00
# include "../lib/CModHandler.h"
2022-09-18 01:23:17 +02:00
# include "../lib/filesystem/Filesystem.h"
# include "../lib/GameConstants.h"
# include "../lib/mapping/CMapService.h"
# include "../lib/mapping/CMap.h"
# include "../lib/mapping/CMapEditManager.h"
2023-01-11 15:17:24 +02:00
# include "../lib/RoadHandler.h"
# include "../lib/RiverHandler.h"
2023-01-09 01:17:37 +02:00
# include "../lib/TerrainHandler.h"
2022-09-18 01:23:17 +02:00
# include "../lib/mapObjects/CObjectClassesHandler.h"
# include "../lib/filesystem/CFilesystemLoader.h"
# include "maphandler.h"
# include "graphics.h"
# include "windownewmap.h"
# include "objectbrowser.h"
# include "inspector/inspector.h"
# include "mapsettings.h"
# include "playersettings.h"
# include "validator.h"
static CBasicLogConfigurator * logConfig ;
2022-11-24 22:52:31 +02:00
2022-09-18 01:23:17 +02:00
QJsonValue jsonFromPixmap ( const QPixmap & p )
{
QBuffer buffer ;
buffer . open ( QIODevice : : WriteOnly ) ;
p . save ( & buffer , " PNG " ) ;
auto const encoded = buffer . data ( ) . toBase64 ( ) ;
return { QLatin1String ( encoded ) } ;
}
QPixmap pixmapFromJson ( const QJsonValue & val )
{
auto const encoded = val . toString ( ) . toLatin1 ( ) ;
QPixmap p ;
p . loadFromData ( QByteArray : : fromBase64 ( encoded ) , " PNG " ) ;
return p ;
}
void init ( )
{
loadDLLClasses ( ) ;
logGlobal - > info ( " Initializing VCMI_Lib " ) ;
}
void MainWindow : : loadUserSettings ( )
{
//load window settings
QSettings s ( Ui : : teamName , Ui : : appName ) ;
auto size = s . value ( mainWindowSizeSetting ) . toSize ( ) ;
if ( size . isValid ( ) )
{
resize ( size ) ;
}
auto position = s . value ( mainWindowPositionSetting ) . toPoint ( ) ;
if ( ! position . isNull ( ) )
{
move ( position ) ;
}
}
void MainWindow : : saveUserSettings ( )
{
QSettings s ( Ui : : teamName , Ui : : appName ) ;
s . setValue ( mainWindowSizeSetting , size ( ) ) ;
s . setValue ( mainWindowPositionSetting , pos ( ) ) ;
}
2022-11-27 19:14:14 +02:00
void MainWindow : : parseCommandLine ( ExtractionOptions & extractionOptions )
2022-11-20 18:48:31 +02:00
{
QCommandLineParser parser ;
parser . addHelpOption ( ) ;
parser . addPositionalArgument ( " map " , QCoreApplication : : translate ( " main " , " Filepath of the map to open. " ) ) ;
parser . addOptions ( {
{ " e " , QCoreApplication : : translate ( " main " , " Extract original H3 archives into a separate folder. " ) } ,
{ " s " , QCoreApplication : : translate ( " main " , " From an extracted archive, it Splits TwCrPort, CPRSMALL, FlagPort, ITPA, ITPt, Un32 and Un44 into individual PNG's. " ) } ,
{ " c " , QCoreApplication : : translate ( " main " , " From an extracted archive, Converts single Images (found in Images folder) from .pcx to png. " ) } ,
{ " d " , QCoreApplication : : translate ( " main " , " Delete original files, for the ones splitted / converted. " ) } ,
} ) ;
parser . process ( qApp - > arguments ( ) ) ;
const QStringList positionalArgs = parser . positionalArguments ( ) ;
2022-11-27 19:02:33 +02:00
if ( ! positionalArgs . isEmpty ( ) )
2022-11-20 18:48:31 +02:00
mapFilePath = positionalArgs . at ( 0 ) ;
2022-11-27 19:02:33 +02:00
extractionOptions = {
parser . isSet ( " e " ) , {
parser . isSet ( " s " ) ,
parser . isSet ( " c " ) ,
parser . isSet ( " d " ) } } ;
2022-11-20 18:48:31 +02:00
}
2022-12-26 23:29:42 +02:00
void MainWindow : : loadTranslation ( )
{
# ifdef ENABLE_QT_TRANSLATIONS
2023-01-07 16:51:03 +02:00
std : : string translationFile = settings [ " general " ] [ " language " ] . String ( ) + " .qm " ;
2022-12-26 23:29:42 +02:00
2022-12-29 17:45:32 +02:00
QVector < QString > searchPaths ;
for ( auto const & string : VCMIDirs : : get ( ) . dataPaths ( ) )
searchPaths . push_back ( pathToQString ( string / " mapeditor " / " translation " / translationFile ) ) ;
searchPaths . push_back ( pathToQString ( VCMIDirs : : get ( ) . userDataPath ( ) / " mapeditor " / " translation " / translationFile ) ) ;
for ( auto const & string : boost : : adaptors : : reverse ( searchPaths ) )
{
if ( translator . load ( string ) )
{
if ( ! qApp - > installTranslator ( & translator ) )
logGlobal - > error ( " Failed to install translator " ) ;
return ;
}
}
logGlobal - > error ( " Failed to find translation " ) ;
2022-12-26 23:29:42 +02:00
# endif
}
2022-11-25 00:21:24 +02:00
MainWindow : : MainWindow ( QWidget * parent ) :
2022-09-18 01:23:17 +02:00
QMainWindow ( parent ) ,
ui ( new Ui : : MainWindow ) ,
controller ( this )
{
2022-12-20 17:11:49 +02:00
// Set current working dir to executable folder.
// This is important on Mac for relative paths to work inside DMG.
QDir : : setCurrent ( QApplication : : applicationDirPath ( ) ) ;
2022-11-30 13:22:53 +02:00
for ( auto & string : VCMIDirs : : get ( ) . dataPaths ( ) )
QDir : : addSearchPath ( " icons " , pathToQString ( string / " mapeditor " / " icons " ) ) ;
QDir : : addSearchPath ( " icons " , pathToQString ( VCMIDirs : : get ( ) . userDataPath ( ) / " mapeditor " / " icons " ) ) ;
2022-11-27 19:14:14 +02:00
ExtractionOptions extractionOptions ;
parseCommandLine ( extractionOptions ) ;
2022-11-20 18:48:31 +02:00
2022-09-18 01:23:17 +02:00
//configure logging
2022-10-08 20:55:15 +02:00
const boost : : filesystem : : path logPath = VCMIDirs : : get ( ) . userLogsPath ( ) / " VCMI_Editor_log.txt " ;
2022-09-18 01:23:17 +02:00
console = new CConsoleHandler ( ) ;
logConfig = new CBasicLogConfigurator ( logPath , console ) ;
logConfig - > configureDefault ( ) ;
logGlobal - > info ( " The log file will be saved to %s " , logPath ) ;
2022-11-20 18:48:31 +02:00
2022-09-18 01:23:17 +02:00
//init
2022-11-25 00:21:24 +02:00
preinitDLL ( : : console , false , extractionOptions . extractArchives ) ;
2022-09-18 01:23:17 +02:00
settings . init ( ) ;
2022-11-25 00:21:24 +02:00
2022-09-18 01:23:17 +02:00
// Initialize logging based on settings
logConfig - > configure ( ) ;
logGlobal - > debug ( " settings = %s " , settings . toJsonNode ( ) . toJson ( ) ) ;
2022-11-25 00:21:24 +02:00
2022-09-18 01:23:17 +02:00
// Some basic data validation to produce better error messages in cases of incorrect install
auto testFile = [ ] ( std : : string filename , std : : string message ) - > bool
{
if ( CResourceHandler : : get ( ) - > existsResource ( ResourceID ( filename ) ) )
return true ;
2022-11-25 00:21:24 +02:00
2022-09-18 01:23:17 +02:00
logGlobal - > error ( " Error: %s was not found! " , message ) ;
return false ;
} ;
2022-11-25 00:21:24 +02:00
if ( ! testFile ( " DATA/HELP.TXT " , " Heroes III data " ) | |
! testFile ( " MODS/VCMI/MOD.JSON " , " VCMI data " ) )
2022-09-18 01:23:17 +02:00
{
QApplication : : quit ( ) ;
}
2022-11-25 00:21:24 +02:00
2022-09-18 01:23:17 +02:00
conf . init ( ) ;
logGlobal - > info ( " Loading settings " ) ;
2022-11-25 00:21:24 +02:00
2022-12-26 23:29:42 +02:00
loadTranslation ( ) ;
ui - > setupUi ( this ) ;
loadUserSettings ( ) ; //For example window size
setTitle ( ) ;
2022-09-18 01:23:17 +02:00
init ( ) ;
2022-11-25 00:21:24 +02:00
2022-09-18 01:23:17 +02:00
graphics = new Graphics ( ) ; // should be before curh->init()
graphics - > load ( ) ; //must be after Content loading but should be in main thread
2022-11-20 18:48:31 +02:00
2022-11-25 00:21:24 +02:00
if ( extractionOptions . extractArchives )
ResourceConverter : : convertExtractedResourceFiles ( extractionOptions . conversionOptions ) ;
2022-09-18 01:23:17 +02:00
ui - > mapView - > setScene ( controller . scene ( 0 ) ) ;
ui - > mapView - > setController ( & controller ) ;
ui - > mapView - > setOptimizationFlags ( QGraphicsView : : DontSavePainterState | QGraphicsView : : DontAdjustForAntialiasing ) ;
connect ( ui - > mapView , & MapView : : openObjectProperties , this , & MainWindow : : loadInspector ) ;
ui - > minimapView - > setScene ( controller . miniScene ( 0 ) ) ;
ui - > minimapView - > setController ( & controller ) ;
connect ( ui - > minimapView , & MinimapView : : cameraPositionChanged , ui - > mapView , & MapView : : cameraChanged ) ;
scenePreview = new QGraphicsScene ( this ) ;
ui - > objectPreview - > setScene ( scenePreview ) ;
//loading objects
loadObjectsTree ( ) ;
ui - > tabWidget - > setCurrentIndex ( 0 ) ;
2022-09-24 22:55:05 +02:00
for ( int i = 0 ; i < PlayerColor : : PLAYER_LIMIT . getNum ( ) ; + + i )
2022-09-18 01:23:17 +02:00
{
connect ( getActionPlayer ( PlayerColor ( i ) ) , & QAction : : toggled , this , [ & , i ] ( ) { switchDefaultPlayer ( PlayerColor ( i ) ) ; } ) ;
}
connect ( getActionPlayer ( PlayerColor : : NEUTRAL ) , & QAction : : toggled , this , [ & ] ( ) { switchDefaultPlayer ( PlayerColor : : NEUTRAL ) ; } ) ;
onPlayersChanged ( ) ;
show ( ) ;
//Load map from command line
2022-11-20 18:48:31 +02:00
if ( ! mapFilePath . isEmpty ( ) )
openMap ( mapFilePath ) ;
2022-09-18 01:23:17 +02:00
}
MainWindow : : ~ MainWindow ( )
{
saveUserSettings ( ) ; //save window size etc.
2022-10-08 20:55:15 +02:00
delete ui ;
2022-09-18 01:23:17 +02:00
}
bool MainWindow : : getAnswerAboutUnsavedChanges ( )
{
if ( unsaved )
{
auto sure = QMessageBox : : question ( this , " Confirmation " , " Unsaved changes will be lost, are you sure? " ) ;
if ( sure = = QMessageBox : : No )
{
return false ;
}
}
return true ;
}
void MainWindow : : closeEvent ( QCloseEvent * event )
{
if ( getAnswerAboutUnsavedChanges ( ) )
QMainWindow : : closeEvent ( event ) ;
else
event - > ignore ( ) ;
}
void MainWindow : : setStatusMessage ( const QString & status )
{
statusBar ( ) - > showMessage ( status ) ;
}
void MainWindow : : setTitle ( )
{
QString title = QString ( " %1%2 - %3 (v%4) " ) . arg ( filename , unsaved ? " * " : " " , VCMI_EDITOR_NAME , VCMI_EDITOR_VERSION ) ;
setWindowTitle ( title ) ;
}
void MainWindow : : mapChanged ( )
{
unsaved = true ;
setTitle ( ) ;
}
void MainWindow : : initializeMap ( bool isNew )
{
unsaved = isNew ;
if ( isNew )
filename . clear ( ) ;
setTitle ( ) ;
mapLevel = 0 ;
ui - > mapView - > setScene ( controller . scene ( mapLevel ) ) ;
ui - > minimapView - > setScene ( controller . miniScene ( mapLevel ) ) ;
ui - > minimapView - > dimensions ( ) ;
setStatusMessage ( QString ( " Scene objects: %1 " ) . arg ( ui - > mapView - > scene ( ) - > items ( ) . size ( ) ) ) ;
//enable settings
ui - > actionMapSettings - > setEnabled ( true ) ;
ui - > actionPlayers_settings - > setEnabled ( true ) ;
onPlayersChanged ( ) ;
}
bool MainWindow : : openMap ( const QString & filenameSelect )
{
QFileInfo fi ( filenameSelect ) ;
std : : string fname = fi . fileName ( ) . toStdString ( ) ;
std : : string fdir = fi . dir ( ) . path ( ) . toStdString ( ) ;
ResourceID resId ( " MAPEDITOR/ " + fname , EResType : : MAP ) ;
//addFilesystem takes care about memory deallocation if case of failure, no memory leak here
auto * mapEditorFilesystem = new CFilesystemLoader ( " MAPEDITOR/ " , fdir , 0 ) ;
CResourceHandler : : removeFilesystem ( " local " , " mapEditor " ) ;
CResourceHandler : : addFilesystem ( " local " , " mapEditor " , mapEditorFilesystem ) ;
if ( ! CResourceHandler : : get ( " mapEditor " ) - > existsResource ( resId ) )
{
QMessageBox : : warning ( this , " Failed to open map " , " Cannot open map from this folder " ) ;
return false ;
}
CMapService mapService ;
try
{
controller . setMap ( mapService . loadMap ( resId ) ) ;
}
catch ( const std : : exception & e )
{
QMessageBox : : critical ( this , " Failed to open map " , e . what ( ) ) ;
return false ;
}
filename = filenameSelect ;
initializeMap ( controller . map ( ) - > version ! = EMapFormat : : VCMI ) ;
return true ;
}
void MainWindow : : on_actionOpen_triggered ( )
{
if ( ! getAnswerAboutUnsavedChanges ( ) )
return ;
2022-10-08 20:55:15 +02:00
auto filenameSelect = QFileDialog : : getOpenFileName ( this , tr ( " Open map " ) ,
QString : : fromStdString ( VCMIDirs : : get ( ) . userCachePath ( ) . make_preferred ( ) . string ( ) ) ,
tr ( " All supported maps (*.vmap *.h3m);;VCMI maps(*.vmap);;HoMM3 maps(*.h3m) " ) ) ;
if ( filenameSelect . isEmpty ( ) )
2022-09-18 01:23:17 +02:00
return ;
openMap ( filenameSelect ) ;
}
void MainWindow : : saveMap ( )
{
if ( ! controller . map ( ) )
return ;
if ( ! unsaved )
return ;
//validate map
auto issues = Validator : : validate ( controller . map ( ) ) ;
bool critical = false ;
for ( auto & issue : issues )
critical | = issue . critical ;
if ( ! issues . empty ( ) )
{
if ( critical )
QMessageBox : : warning ( this , " Map validation " , " Map has critical problems and most probably will not be playable. Open Validator from the Map menu to see issues found " ) ;
else
QMessageBox : : information ( this , " Map validation " , " Map has some errors. Open Validator from the Map menu to see issues found " ) ;
}
CMapService mapService ;
try
{
mapService . saveMap ( controller . getMapUniquePtr ( ) , filename . toStdString ( ) ) ;
}
catch ( const std : : exception & e )
{
QMessageBox : : critical ( this , " Failed to save map " , e . what ( ) ) ;
return ;
}
unsaved = false ;
setTitle ( ) ;
}
void MainWindow : : on_actionSave_as_triggered ( )
{
if ( ! controller . map ( ) )
return ;
auto filenameSelect = QFileDialog : : getSaveFileName ( this , tr ( " Save map " ) , " " , tr ( " VCMI maps (*.vmap) " ) ) ;
if ( filenameSelect . isNull ( ) )
return ;
if ( filenameSelect = = filename )
return ;
filename = filenameSelect ;
saveMap ( ) ;
}
void MainWindow : : on_actionNew_triggered ( )
{
if ( getAnswerAboutUnsavedChanges ( ) )
new WindowNewMap ( this ) ;
}
void MainWindow : : on_actionSave_triggered ( )
{
if ( ! controller . map ( ) )
return ;
if ( filename . isNull ( ) )
{
auto filenameSelect = QFileDialog : : getSaveFileName ( this , tr ( " Save map " ) , " " , tr ( " VCMI maps (*.vmap) " ) ) ;
if ( filenameSelect . isNull ( ) )
return ;
filename = filenameSelect ;
}
saveMap ( ) ;
}
2022-10-08 21:54:45 +02:00
void MainWindow : : terrainButtonClicked ( TerrainId terrain )
2022-09-18 01:23:17 +02:00
{
controller . commitTerrainChange ( mapLevel , terrain ) ;
}
2022-10-08 22:11:29 +02:00
void MainWindow : : roadOrRiverButtonClicked ( ui8 type , bool isRoad )
2022-09-18 01:23:17 +02:00
{
controller . commitRoadOrRiverChange ( mapLevel , type , isRoad ) ;
}
void MainWindow : : addGroupIntoCatalog ( const std : : string & groupName , bool staticOnly )
{
auto knownObjects = VLC - > objtypeh - > knownObjects ( ) ;
for ( auto ID : knownObjects )
{
if ( catalog . count ( ID ) )
continue ;
addGroupIntoCatalog ( groupName , true , staticOnly , ID ) ;
}
}
void MainWindow : : addGroupIntoCatalog ( const std : : string & groupName , bool useCustomName , bool staticOnly , int ID )
{
QStandardItem * itemGroup = nullptr ;
auto itms = objectsModel . findItems ( QString : : fromStdString ( groupName ) ) ;
if ( itms . empty ( ) )
{
itemGroup = new QStandardItem ( QString : : fromStdString ( groupName ) ) ;
objectsModel . appendRow ( itemGroup ) ;
}
else
{
itemGroup = itms . front ( ) ;
}
auto knownSubObjects = VLC - > objtypeh - > knownSubObjects ( ID ) ;
for ( auto secondaryID : knownSubObjects )
{
auto factory = VLC - > objtypeh - > getHandlerFor ( ID , secondaryID ) ;
auto templates = factory - > getTemplates ( ) ;
bool singleTemplate = templates . size ( ) = = 1 ;
if ( staticOnly & & ! factory - > isStaticObject ( ) )
continue ;
auto subGroupName = QString : : fromStdString ( factory - > subTypeName ) ;
auto customName = factory - > getCustomName ( ) ;
if ( customName )
subGroupName = tr ( customName - > c_str ( ) ) ;
auto * itemType = new QStandardItem ( subGroupName ) ;
for ( int templateId = 0 ; templateId < templates . size ( ) ; + + templateId )
{
auto templ = templates [ templateId ] ;
//selecting file
const std : : string & afile = templ - > editorAnimationFile . empty ( ) ? templ - > animationFile : templ - > editorAnimationFile ;
//creating picture
QPixmap preview ( 128 , 128 ) ;
preview . fill ( QColor ( 255 , 255 , 255 ) ) ;
QPainter painter ( & preview ) ;
Animation animation ( afile ) ;
animation . preload ( ) ;
auto picture = animation . getImage ( 0 ) ;
if ( picture & & picture - > width ( ) & & picture - > height ( ) )
{
qreal xscale = qreal ( 128 ) / qreal ( picture - > width ( ) ) , yscale = qreal ( 128 ) / qreal ( picture - > height ( ) ) ;
qreal scale = std : : min ( xscale , yscale ) ;
painter . scale ( scale , scale ) ;
painter . drawImage ( QPoint ( 0 , 0 ) , * picture ) ;
}
//add parameters
QJsonObject data { { " id " , QJsonValue ( ID ) } ,
{ " subid " , QJsonValue ( secondaryID ) } ,
{ " template " , QJsonValue ( templateId ) } ,
{ " animationEditor " , QString : : fromStdString ( templ - > editorAnimationFile ) } ,
{ " animation " , QString : : fromStdString ( templ - > animationFile ) } ,
{ " preview " , jsonFromPixmap ( preview ) } } ;
//create object to extract name
std : : unique_ptr < CGObjectInstance > temporaryObj ( factory - > create ( templ ) ) ;
QString translated = useCustomName ? tr ( temporaryObj - > getObjectName ( ) . c_str ( ) ) : subGroupName ;
//do not have extra level
if ( singleTemplate )
{
if ( useCustomName )
itemType - > setText ( translated ) ;
itemType - > setIcon ( QIcon ( preview ) ) ;
itemType - > setData ( data ) ;
}
else
{
if ( useCustomName )
itemType - > setText ( translated ) ;
auto * item = new QStandardItem ( QIcon ( preview ) , QString : : fromStdString ( templ - > stringID ) ) ;
item - > setData ( data ) ;
itemType - > appendRow ( item ) ;
}
}
itemGroup - > appendRow ( itemType ) ;
catalog . insert ( ID ) ;
}
}
void MainWindow : : loadObjectsTree ( )
{
try
{
ui - > terrainFilterCombo - > addItem ( " " ) ;
//adding terrains
2022-12-20 16:14:06 +02:00
for ( auto & terrain : VLC - > terrainTypeHandler - > objects )
2022-09-18 01:23:17 +02:00
{
2023-01-01 22:42:28 +02:00
QPushButton * b = new QPushButton ( QString : : fromStdString ( terrain - > getNameTranslated ( ) ) ) ;
2022-09-18 01:23:17 +02:00
ui - > terrainLayout - > addWidget ( b ) ;
2023-01-01 17:10:47 +02:00
connect ( b , & QPushButton : : clicked , this , [ this , terrain ] { terrainButtonClicked ( terrain - > getId ( ) ) ; } ) ;
2022-09-18 01:23:17 +02:00
//filter
2023-01-01 22:42:28 +02:00
ui - > terrainFilterCombo - > addItem ( QString : : fromStdString ( terrain - > getNameTranslated ( ) ) ) ;
2022-09-18 01:23:17 +02:00
}
//add spacer to keep terrain button on the top
ui - > terrainLayout - > addItem ( new QSpacerItem ( 20 , 20 , QSizePolicy : : Minimum , QSizePolicy : : Expanding ) ) ;
//adding roads
2022-12-20 16:14:06 +02:00
for ( auto & road : VLC - > roadTypeHandler - > objects )
2022-09-18 01:23:17 +02:00
{
2023-01-09 01:19:56 +02:00
QPushButton * b = new QPushButton ( QString : : fromStdString ( road - > getNameTranslated ( ) ) ) ;
2022-09-18 01:23:17 +02:00
ui - > roadLayout - > addWidget ( b ) ;
2023-01-01 17:10:47 +02:00
connect ( b , & QPushButton : : clicked , this , [ this , road ] { roadOrRiverButtonClicked ( road - > getIndex ( ) , true ) ; } ) ;
2022-09-18 01:23:17 +02:00
}
//add spacer to keep terrain button on the top
ui - > roadLayout - > addItem ( new QSpacerItem ( 20 , 20 , QSizePolicy : : Minimum , QSizePolicy : : Expanding ) ) ;
//adding rivers
2022-12-20 16:14:06 +02:00
for ( auto & river : VLC - > riverTypeHandler - > objects )
2022-09-18 01:23:17 +02:00
{
2023-01-09 01:19:56 +02:00
QPushButton * b = new QPushButton ( QString : : fromStdString ( river - > getNameTranslated ( ) ) ) ;
2022-09-18 01:23:17 +02:00
ui - > riverLayout - > addWidget ( b ) ;
2023-01-01 17:10:47 +02:00
connect ( b , & QPushButton : : clicked , this , [ this , river ] { roadOrRiverButtonClicked ( river - > getIndex ( ) , false ) ; } ) ;
2022-09-18 01:23:17 +02:00
}
//add spacer to keep terrain button on the top
ui - > riverLayout - > addItem ( new QSpacerItem ( 20 , 20 , QSizePolicy : : Minimum , QSizePolicy : : Expanding ) ) ;
if ( objectBrowser )
throw std : : runtime_error ( " object browser exists " ) ;
//model
2022-10-08 20:55:15 +02:00
objectsModel . setHorizontalHeaderLabels ( QStringList ( ) < < tr ( " Type " ) ) ;
2022-12-04 04:45:39 +02:00
objectBrowser = new ObjectBrowserProxyModel ( this ) ;
2022-09-18 01:23:17 +02:00
objectBrowser - > setSourceModel ( & objectsModel ) ;
objectBrowser - > setDynamicSortFilter ( false ) ;
objectBrowser - > setRecursiveFilteringEnabled ( true ) ;
ui - > treeView - > setModel ( objectBrowser ) ;
ui - > treeView - > setSelectionBehavior ( QAbstractItemView : : SelectItems ) ;
ui - > treeView - > setSelectionMode ( QAbstractItemView : : SingleSelection ) ;
connect ( ui - > treeView - > selectionModel ( ) , SIGNAL ( currentChanged ( const QModelIndex & , const QModelIndex & ) ) , this , SLOT ( treeViewSelected ( const QModelIndex & , const QModelIndex & ) ) ) ;
//adding objects
addGroupIntoCatalog ( " TOWNS " , false , false , Obj : : TOWN ) ;
addGroupIntoCatalog ( " TOWNS " , false , false , Obj : : RANDOM_TOWN ) ;
addGroupIntoCatalog ( " TOWNS " , true , false , Obj : : SHIPYARD ) ;
addGroupIntoCatalog ( " TOWNS " , true , false , Obj : : GARRISON ) ;
addGroupIntoCatalog ( " TOWNS " , true , false , Obj : : GARRISON2 ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : ALTAR_OF_SACRIFICE ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : ARENA ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : BLACK_MARKET ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : BUOY ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : CARTOGRAPHER ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : SWAN_POND ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : COVER_OF_DARKNESS ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : CORPSE ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : FAERIE_RING ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : FOUNTAIN_OF_FORTUNE ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : FOUNTAIN_OF_YOUTH ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : GARDEN_OF_REVELATION ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : HILL_FORT ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : IDOL_OF_FORTUNE ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : LIBRARY_OF_ENLIGHTENMENT ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : LIGHTHOUSE ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : SCHOOL_OF_MAGIC ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : MAGIC_SPRING ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : MAGIC_WELL ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : MERCENARY_CAMP ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : MERMAID ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : MYSTICAL_GARDEN ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : OASIS ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : LEAN_TO ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : OBELISK ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : REDWOOD_OBSERVATORY ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : PILLAR_OF_FIRE ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : STAR_AXIS ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : RALLY_FLAG ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : WATERING_HOLE ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : SCHOLAR ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : SHRINE_OF_MAGIC_INCANTATION ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : SHRINE_OF_MAGIC_GESTURE ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : SHRINE_OF_MAGIC_THOUGHT ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : SIRENS ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : STABLES ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : TAVERN ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : TEMPLE ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : DEN_OF_THIEVES ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : TRADING_POST ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : TRADING_POST_SNOW ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : LEARNING_STONE ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : TREE_OF_KNOWLEDGE ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : UNIVERSITY ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : WAGON ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : SCHOOL_OF_WAR ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : WAR_MACHINE_FACTORY ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : WARRIORS_TOMB ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : WITCH_HUT ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : FREELANCERS_GUILD ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : SANCTUARY ) ;
addGroupIntoCatalog ( " OBJECTS " , true , false , Obj : : MARLETTO_TOWER ) ;
addGroupIntoCatalog ( " HEROES " , true , false , Obj : : PRISON ) ;
addGroupIntoCatalog ( " HEROES " , false , false , Obj : : HERO ) ;
addGroupIntoCatalog ( " HEROES " , false , false , Obj : : RANDOM_HERO ) ;
addGroupIntoCatalog ( " HEROES " , false , false , Obj : : HERO_PLACEHOLDER ) ;
addGroupIntoCatalog ( " HEROES " , false , false , Obj : : BOAT ) ;
addGroupIntoCatalog ( " ARTIFACTS " , true , false , Obj : : ARTIFACT ) ;
addGroupIntoCatalog ( " ARTIFACTS " , false , false , Obj : : RANDOM_ART ) ;
addGroupIntoCatalog ( " ARTIFACTS " , false , false , Obj : : RANDOM_TREASURE_ART ) ;
addGroupIntoCatalog ( " ARTIFACTS " , false , false , Obj : : RANDOM_MINOR_ART ) ;
addGroupIntoCatalog ( " ARTIFACTS " , false , false , Obj : : RANDOM_MAJOR_ART ) ;
addGroupIntoCatalog ( " ARTIFACTS " , false , false , Obj : : RANDOM_RELIC_ART ) ;
addGroupIntoCatalog ( " ARTIFACTS " , true , false , Obj : : SPELL_SCROLL ) ;
addGroupIntoCatalog ( " ARTIFACTS " , true , false , Obj : : PANDORAS_BOX ) ;
addGroupIntoCatalog ( " RESOURCES " , true , false , Obj : : RANDOM_RESOURCE ) ;
addGroupIntoCatalog ( " RESOURCES " , false , false , Obj : : RESOURCE ) ;
addGroupIntoCatalog ( " RESOURCES " , true , false , Obj : : SEA_CHEST ) ;
addGroupIntoCatalog ( " RESOURCES " , true , false , Obj : : TREASURE_CHEST ) ;
addGroupIntoCatalog ( " RESOURCES " , true , false , Obj : : CAMPFIRE ) ;
addGroupIntoCatalog ( " RESOURCES " , true , false , Obj : : SHIPWRECK_SURVIVOR ) ;
addGroupIntoCatalog ( " RESOURCES " , true , false , Obj : : FLOTSAM ) ;
addGroupIntoCatalog ( " BANKS " , true , false , Obj : : CREATURE_BANK ) ;
addGroupIntoCatalog ( " BANKS " , true , false , Obj : : DRAGON_UTOPIA ) ;
addGroupIntoCatalog ( " BANKS " , true , false , Obj : : CRYPT ) ;
addGroupIntoCatalog ( " BANKS " , true , false , Obj : : DERELICT_SHIP ) ;
addGroupIntoCatalog ( " BANKS " , true , false , Obj : : PYRAMID ) ;
addGroupIntoCatalog ( " BANKS " , true , false , Obj : : SHIPWRECK ) ;
addGroupIntoCatalog ( " DWELLINGS " , true , false , Obj : : CREATURE_GENERATOR1 ) ;
addGroupIntoCatalog ( " DWELLINGS " , true , false , Obj : : CREATURE_GENERATOR2 ) ;
addGroupIntoCatalog ( " DWELLINGS " , true , false , Obj : : CREATURE_GENERATOR3 ) ;
addGroupIntoCatalog ( " DWELLINGS " , true , false , Obj : : CREATURE_GENERATOR4 ) ;
addGroupIntoCatalog ( " DWELLINGS " , true , false , Obj : : REFUGEE_CAMP ) ;
addGroupIntoCatalog ( " DWELLINGS " , false , false , Obj : : RANDOM_DWELLING ) ;
addGroupIntoCatalog ( " DWELLINGS " , false , false , Obj : : RANDOM_DWELLING_LVL ) ;
addGroupIntoCatalog ( " DWELLINGS " , false , false , Obj : : RANDOM_DWELLING_FACTION ) ;
addGroupIntoCatalog ( " GROUNDS " , true , false , Obj : : CURSED_GROUND1 ) ;
addGroupIntoCatalog ( " GROUNDS " , true , false , Obj : : MAGIC_PLAINS1 ) ;
addGroupIntoCatalog ( " GROUNDS " , true , false , Obj : : CLOVER_FIELD ) ;
addGroupIntoCatalog ( " GROUNDS " , true , false , Obj : : CURSED_GROUND2 ) ;
addGroupIntoCatalog ( " GROUNDS " , true , false , Obj : : EVIL_FOG ) ;
addGroupIntoCatalog ( " GROUNDS " , true , false , Obj : : FAVORABLE_WINDS ) ;
addGroupIntoCatalog ( " GROUNDS " , true , false , Obj : : FIERY_FIELDS ) ;
addGroupIntoCatalog ( " GROUNDS " , true , false , Obj : : HOLY_GROUNDS ) ;
addGroupIntoCatalog ( " GROUNDS " , true , false , Obj : : LUCID_POOLS ) ;
addGroupIntoCatalog ( " GROUNDS " , true , false , Obj : : MAGIC_CLOUDS ) ;
addGroupIntoCatalog ( " GROUNDS " , true , false , Obj : : MAGIC_PLAINS2 ) ;
addGroupIntoCatalog ( " GROUNDS " , true , false , Obj : : ROCKLANDS ) ;
addGroupIntoCatalog ( " GROUNDS " , true , false , Obj : : HOLE ) ;
addGroupIntoCatalog ( " TELEPORTS " , true , false , Obj : : MONOLITH_ONE_WAY_ENTRANCE ) ;
addGroupIntoCatalog ( " TELEPORTS " , true , false , Obj : : MONOLITH_ONE_WAY_EXIT ) ;
addGroupIntoCatalog ( " TELEPORTS " , true , false , Obj : : MONOLITH_TWO_WAY ) ;
addGroupIntoCatalog ( " TELEPORTS " , true , false , Obj : : SUBTERRANEAN_GATE ) ;
addGroupIntoCatalog ( " TELEPORTS " , true , false , Obj : : WHIRLPOOL ) ;
addGroupIntoCatalog ( " MINES " , true , false , Obj : : MINE ) ;
addGroupIntoCatalog ( " MINES " , false , false , Obj : : ABANDONED_MINE ) ;
addGroupIntoCatalog ( " MINES " , true , false , Obj : : WINDMILL ) ;
addGroupIntoCatalog ( " MINES " , true , false , Obj : : WATER_WHEEL ) ;
addGroupIntoCatalog ( " TRIGGERS " , true , false , Obj : : EVENT ) ;
addGroupIntoCatalog ( " TRIGGERS " , true , false , Obj : : GRAIL ) ;
addGroupIntoCatalog ( " TRIGGERS " , true , false , Obj : : SIGN ) ;
addGroupIntoCatalog ( " TRIGGERS " , true , false , Obj : : OCEAN_BOTTLE ) ;
addGroupIntoCatalog ( " MONSTERS " , false , false , Obj : : MONSTER ) ;
addGroupIntoCatalog ( " MONSTERS " , true , false , Obj : : RANDOM_MONSTER ) ;
addGroupIntoCatalog ( " MONSTERS " , true , false , Obj : : RANDOM_MONSTER_L1 ) ;
addGroupIntoCatalog ( " MONSTERS " , true , false , Obj : : RANDOM_MONSTER_L2 ) ;
addGroupIntoCatalog ( " MONSTERS " , true , false , Obj : : RANDOM_MONSTER_L3 ) ;
addGroupIntoCatalog ( " MONSTERS " , true , false , Obj : : RANDOM_MONSTER_L4 ) ;
addGroupIntoCatalog ( " MONSTERS " , true , false , Obj : : RANDOM_MONSTER_L5 ) ;
addGroupIntoCatalog ( " MONSTERS " , true , false , Obj : : RANDOM_MONSTER_L6 ) ;
addGroupIntoCatalog ( " MONSTERS " , true , false , Obj : : RANDOM_MONSTER_L7 ) ;
addGroupIntoCatalog ( " QUESTS " , true , false , Obj : : SEER_HUT ) ;
addGroupIntoCatalog ( " QUESTS " , true , false , Obj : : BORDER_GATE ) ;
addGroupIntoCatalog ( " QUESTS " , true , false , Obj : : QUEST_GUARD ) ;
addGroupIntoCatalog ( " QUESTS " , true , false , Obj : : HUT_OF_MAGI ) ;
addGroupIntoCatalog ( " QUESTS " , true , false , Obj : : EYE_OF_MAGI ) ;
addGroupIntoCatalog ( " QUESTS " , true , false , Obj : : BORDERGUARD ) ;
addGroupIntoCatalog ( " QUESTS " , true , false , Obj : : KEYMASTER ) ;
addGroupIntoCatalog ( " wog object " , true , false , Obj : : WOG_OBJECT ) ;
addGroupIntoCatalog ( " OBSTACLES " , true ) ;
addGroupIntoCatalog ( " OTHER " , false ) ;
}
2022-12-08 23:20:42 +02:00
catch ( const std : : exception & )
2022-09-18 01:23:17 +02:00
{
QMessageBox : : critical ( this , " Mods loading problem " , " Critical error during Mods loading. Disable invalid mods and restart. " ) ;
}
}
void MainWindow : : on_actionLevel_triggered ( )
{
if ( controller . map ( ) & & controller . map ( ) - > twoLevel )
{
mapLevel = mapLevel ? 0 : 1 ;
ui - > mapView - > setScene ( controller . scene ( mapLevel ) ) ;
ui - > minimapView - > setScene ( controller . miniScene ( mapLevel ) ) ;
if ( mapLevel = = 0 )
{
ui - > actionLevel - > setToolTip ( tr ( " View underground " ) ) ;
}
else
{
ui - > actionLevel - > setToolTip ( tr ( " View surface " ) ) ;
}
}
}
void MainWindow : : on_actionUndo_triggered ( )
{
QString str ( " Undo clicked " ) ;
statusBar ( ) - > showMessage ( str , 1000 ) ;
if ( controller . map ( ) )
{
controller . undo ( ) ;
}
}
void MainWindow : : on_actionRedo_triggered ( )
{
QString str ( " Redo clicked " ) ;
displayStatus ( str ) ;
if ( controller . map ( ) )
{
controller . redo ( ) ;
}
}
void MainWindow : : on_actionPass_triggered ( bool checked )
{
QString str ( " Passability clicked " ) ;
displayStatus ( str ) ;
if ( controller . map ( ) )
{
controller . scene ( 0 ) - > passabilityView . show ( checked ) ;
controller . scene ( 1 ) - > passabilityView . show ( checked ) ;
}
}
void MainWindow : : on_actionGrid_triggered ( bool checked )
{
QString str ( " Grid clicked " ) ;
displayStatus ( str ) ;
if ( controller . map ( ) )
{
controller . scene ( 0 ) - > gridView . show ( checked ) ;
2022-09-24 22:55:05 +02:00
controller . scene ( 1 ) - > gridView . show ( checked ) ;
2022-09-18 01:23:17 +02:00
}
}
void MainWindow : : changeBrushState ( int idx )
{
}
void MainWindow : : on_toolBrush_clicked ( bool checked )
{
//ui->toolBrush->setChecked(false);
ui - > toolBrush2 - > setChecked ( false ) ;
ui - > toolBrush4 - > setChecked ( false ) ;
ui - > toolArea - > setChecked ( false ) ;
ui - > toolLasso - > setChecked ( false ) ;
if ( checked )
ui - > mapView - > selectionTool = MapView : : SelectionTool : : Brush ;
else
ui - > mapView - > selectionTool = MapView : : SelectionTool : : None ;
ui - > tabWidget - > setCurrentIndex ( 0 ) ;
}
void MainWindow : : on_toolBrush2_clicked ( bool checked )
{
ui - > toolBrush - > setChecked ( false ) ;
//ui->toolBrush2->setChecked(false);
ui - > toolBrush4 - > setChecked ( false ) ;
ui - > toolArea - > setChecked ( false ) ;
ui - > toolLasso - > setChecked ( false ) ;
if ( checked )
ui - > mapView - > selectionTool = MapView : : SelectionTool : : Brush2 ;
else
ui - > mapView - > selectionTool = MapView : : SelectionTool : : None ;
ui - > tabWidget - > setCurrentIndex ( 0 ) ;
}
void MainWindow : : on_toolBrush4_clicked ( bool checked )
{
ui - > toolBrush - > setChecked ( false ) ;
ui - > toolBrush2 - > setChecked ( false ) ;
//ui->toolBrush4->setChecked(false);
ui - > toolArea - > setChecked ( false ) ;
ui - > toolLasso - > setChecked ( false ) ;
if ( checked )
ui - > mapView - > selectionTool = MapView : : SelectionTool : : Brush4 ;
else
ui - > mapView - > selectionTool = MapView : : SelectionTool : : None ;
ui - > tabWidget - > setCurrentIndex ( 0 ) ;
}
void MainWindow : : on_toolArea_clicked ( bool checked )
{
ui - > toolBrush - > setChecked ( false ) ;
ui - > toolBrush2 - > setChecked ( false ) ;
ui - > toolBrush4 - > setChecked ( false ) ;
//ui->toolArea->setChecked(false);
ui - > toolLasso - > setChecked ( false ) ;
if ( checked )
ui - > mapView - > selectionTool = MapView : : SelectionTool : : Area ;
else
ui - > mapView - > selectionTool = MapView : : SelectionTool : : None ;
ui - > tabWidget - > setCurrentIndex ( 0 ) ;
}
2022-12-27 23:14:10 +02:00
void MainWindow : : on_toolLasso_clicked ( bool checked )
{
ui - > toolBrush - > setChecked ( false ) ;
ui - > toolBrush2 - > setChecked ( false ) ;
ui - > toolBrush4 - > setChecked ( false ) ;
ui - > toolArea - > setChecked ( false ) ;
//ui->toolLasso->setChecked(false);
if ( checked )
ui - > mapView - > selectionTool = MapView : : SelectionTool : : Lasso ;
else
ui - > mapView - > selectionTool = MapView : : SelectionTool : : None ;
ui - > tabWidget - > setCurrentIndex ( 0 ) ;
}
2022-09-18 01:23:17 +02:00
void MainWindow : : on_actionErase_triggered ( )
{
on_toolErase_clicked ( ) ;
}
void MainWindow : : on_toolErase_clicked ( )
{
if ( controller . map ( ) )
{
controller . commitObjectErase ( mapLevel ) ;
}
ui - > tabWidget - > setCurrentIndex ( 0 ) ;
}
2022-12-04 12:51:01 +02:00
void MainWindow : : preparePreview ( const QModelIndex & index )
2022-09-18 01:23:17 +02:00
{
scenePreview - > clear ( ) ;
auto data = objectsModel . itemFromIndex ( objectBrowser - > mapToSource ( index ) ) - > data ( ) . toJsonObject ( ) ;
if ( ! data . empty ( ) )
{
auto preview = data [ " preview " ] ;
if ( preview ! = QJsonValue : : Undefined )
{
QPixmap objPreview = pixmapFromJson ( preview ) ;
scenePreview - > addPixmap ( objPreview ) ;
}
}
}
void MainWindow : : treeViewSelected ( const QModelIndex & index , const QModelIndex & deselected )
{
ui - > toolBrush - > setChecked ( false ) ;
ui - > toolBrush2 - > setChecked ( false ) ;
ui - > toolBrush4 - > setChecked ( false ) ;
ui - > toolArea - > setChecked ( false ) ;
ui - > toolLasso - > setChecked ( false ) ;
ui - > mapView - > selectionTool = MapView : : SelectionTool : : None ;
2022-12-04 12:51:01 +02:00
preparePreview ( index ) ;
2022-09-18 01:23:17 +02:00
}
void MainWindow : : on_terrainFilterCombo_currentTextChanged ( const QString & arg1 )
{
if ( ! objectBrowser )
return ;
2022-12-20 18:35:40 +02:00
objectBrowser - > terrain = TerrainId ( ETerrainId : : ANY_TERRAIN ) ;
if ( ! arg1 . isEmpty ( ) )
{
for ( auto const & terrain : VLC - > terrainTypeHandler - > objects )
2023-01-01 22:42:28 +02:00
if ( terrain - > getJsonKey ( ) = = arg1 . toStdString ( ) )
2023-01-01 17:10:47 +02:00
objectBrowser - > terrain = terrain - > getId ( ) ;
2022-12-20 18:35:40 +02:00
}
2022-09-18 01:23:17 +02:00
objectBrowser - > invalidate ( ) ;
objectBrowser - > sort ( 0 ) ;
}
void MainWindow : : on_filter_textChanged ( const QString & arg1 )
{
if ( ! objectBrowser )
return ;
objectBrowser - > filter = arg1 ;
objectBrowser - > invalidate ( ) ;
objectBrowser - > sort ( 0 ) ;
}
void MainWindow : : on_actionFill_triggered ( )
{
QString str ( " Fill clicked " ) ;
displayStatus ( str ) ;
if ( ! controller . map ( ) )
return ;
controller . commitObstacleFill ( mapLevel ) ;
}
void MainWindow : : loadInspector ( CGObjectInstance * obj , bool switchTab )
{
if ( switchTab )
ui - > tabWidget - > setCurrentIndex ( 1 ) ;
Inspector inspector ( controller . map ( ) , obj , ui - > inspectorWidget ) ;
inspector . updateProperties ( ) ;
}
void MainWindow : : on_inspectorWidget_itemChanged ( QTableWidgetItem * item )
{
if ( ! item - > isSelected ( ) )
return ;
int r = item - > row ( ) ;
int c = item - > column ( ) ;
if ( c < 1 )
return ;
auto * tableWidget = item - > tableWidget ( ) ;
//get identifier
auto identifier = tableWidget - > item ( 0 , 1 ) - > text ( ) ;
2022-09-19 01:17:39 +02:00
CGObjectInstance * obj = data_cast < CGObjectInstance > ( identifier . toLongLong ( ) ) ;
2022-09-18 01:23:17 +02:00
//get parameter name
auto param = tableWidget - > item ( r , c - 1 ) - > text ( ) ;
//set parameter
Inspector inspector ( controller . map ( ) , obj , tableWidget ) ;
inspector . setProperty ( param , item - > text ( ) ) ;
controller . commitObjectChange ( mapLevel ) ;
}
void MainWindow : : on_actionMapSettings_triggered ( )
{
auto settingsDialog = new MapSettings ( controller , this ) ;
settingsDialog - > setWindowModality ( Qt : : WindowModal ) ;
settingsDialog - > setModal ( true ) ;
}
void MainWindow : : on_actionPlayers_settings_triggered ( )
{
auto settingsDialog = new PlayerSettings ( controller , this ) ;
settingsDialog - > setWindowModality ( Qt : : WindowModal ) ;
settingsDialog - > setModal ( true ) ;
connect ( settingsDialog , & QDialog : : finished , this , & MainWindow : : onPlayersChanged ) ;
}
QAction * MainWindow : : getActionPlayer ( const PlayerColor & player )
{
if ( player . getNum ( ) = = 0 ) return ui - > actionPlayer_1 ;
if ( player . getNum ( ) = = 1 ) return ui - > actionPlayer_2 ;
if ( player . getNum ( ) = = 2 ) return ui - > actionPlayer_3 ;
if ( player . getNum ( ) = = 3 ) return ui - > actionPlayer_4 ;
if ( player . getNum ( ) = = 4 ) return ui - > actionPlayer_5 ;
if ( player . getNum ( ) = = 5 ) return ui - > actionPlayer_6 ;
if ( player . getNum ( ) = = 6 ) return ui - > actionPlayer_7 ;
if ( player . getNum ( ) = = 7 ) return ui - > actionPlayer_8 ;
return ui - > actionNeutral ;
}
void MainWindow : : switchDefaultPlayer ( const PlayerColor & player )
{
if ( controller . defaultPlayer = = player )
return ;
ui - > actionNeutral - > blockSignals ( true ) ;
ui - > actionNeutral - > setChecked ( PlayerColor : : NEUTRAL = = player ) ;
ui - > actionNeutral - > blockSignals ( false ) ;
2022-10-12 23:40:52 +02:00
for ( int i = 0 ; i < PlayerColor : : PLAYER_LIMIT . getNum ( ) ; + + i )
2022-09-18 01:23:17 +02:00
{
getActionPlayer ( PlayerColor ( i ) ) - > blockSignals ( true ) ;
getActionPlayer ( PlayerColor ( i ) ) - > setChecked ( PlayerColor ( i ) = = player ) ;
getActionPlayer ( PlayerColor ( i ) ) - > blockSignals ( false ) ;
}
controller . defaultPlayer = player ;
}
void MainWindow : : onPlayersChanged ( )
{
if ( controller . map ( ) )
{
getActionPlayer ( PlayerColor : : NEUTRAL ) - > setEnabled ( true ) ;
for ( int i = 0 ; i < controller . map ( ) - > players . size ( ) ; + + i )
getActionPlayer ( PlayerColor ( i ) ) - > setEnabled ( controller . map ( ) - > players . at ( i ) . canAnyonePlay ( ) ) ;
if ( ! getActionPlayer ( controller . defaultPlayer ) - > isEnabled ( ) | | controller . defaultPlayer = = PlayerColor : : NEUTRAL )
switchDefaultPlayer ( PlayerColor : : NEUTRAL ) ;
}
else
{
for ( int i = 0 ; i < PlayerColor : : PLAYER_LIMIT . getNum ( ) ; + + i )
getActionPlayer ( PlayerColor ( i ) ) - > setEnabled ( false ) ;
getActionPlayer ( PlayerColor : : NEUTRAL ) - > setEnabled ( false ) ;
}
}
void MainWindow : : enableUndo ( bool enable )
{
ui - > actionUndo - > setEnabled ( enable ) ;
}
void MainWindow : : enableRedo ( bool enable )
{
ui - > actionRedo - > setEnabled ( enable ) ;
}
void MainWindow : : onSelectionMade ( int level , bool anythingSelected )
{
if ( level = = mapLevel )
{
2022-11-05 22:25:51 +02:00
auto info = QString : : asprintf ( " Selection on layer %d: %s " , level , anythingSelected ? " true " : " false " ) ;
2022-09-18 01:23:17 +02:00
setStatusMessage ( info ) ;
ui - > actionErase - > setEnabled ( anythingSelected ) ;
ui - > toolErase - > setEnabled ( anythingSelected ) ;
}
}
void MainWindow : : displayStatus ( const QString & message , int timeout /* = 2000 */ )
{
statusBar ( ) - > showMessage ( message , timeout ) ;
}
void MainWindow : : on_actionValidate_triggered ( )
{
new Validator ( controller . map ( ) , this ) ;
}
void MainWindow : : on_actionUpdate_appearance_triggered ( )
{
if ( ! controller . map ( ) )
return ;
if ( controller . scene ( mapLevel ) - > selectionObjectsView . getSelection ( ) . empty ( ) )
{
QMessageBox : : information ( this , " Update appearance " , " No objects selected " ) ;
return ;
}
if ( QMessageBox : : Yes ! = QMessageBox : : question ( this , " Update appearance " , " This operation is irreversible. Do you want to continue? " ) )
return ;
controller . scene ( mapLevel ) - > selectionTerrainView . clear ( ) ;
int errors = 0 ;
std : : set < CGObjectInstance * > staticObjects ;
for ( auto * obj : controller . scene ( mapLevel ) - > selectionObjectsView . getSelection ( ) )
{
auto handler = VLC - > objtypeh - > getHandlerFor ( obj - > ID , obj - > subID ) ;
if ( ! controller . map ( ) - > isInTheMap ( obj - > visitablePos ( ) ) )
{
+ + errors ;
continue ;
}
2022-10-08 21:54:45 +02:00
auto * terrain = controller . map ( ) - > getTile ( obj - > visitablePos ( ) ) . terType ;
2022-09-18 01:23:17 +02:00
if ( handler - > isStaticObject ( ) )
{
staticObjects . insert ( obj ) ;
2023-01-01 17:10:47 +02:00
if ( obj - > appearance - > canBePlacedAt ( terrain - > getId ( ) ) )
2022-09-18 01:23:17 +02:00
{
controller . scene ( mapLevel ) - > selectionObjectsView . deselectObject ( obj ) ;
continue ;
}
for ( auto & offset : obj - > appearance - > getBlockedOffsets ( ) )
controller . scene ( mapLevel ) - > selectionTerrainView . select ( obj - > pos + offset ) ;
}
else
{
2023-01-01 17:10:47 +02:00
auto app = handler - > getOverride ( terrain - > getId ( ) , obj ) ;
2022-09-18 01:23:17 +02:00
if ( ! app )
{
2023-01-01 17:10:47 +02:00
if ( obj - > appearance - > canBePlacedAt ( terrain - > getId ( ) ) )
2022-09-18 01:23:17 +02:00
continue ;
2023-01-01 17:10:47 +02:00
auto templates = handler - > getTemplates ( terrain - > getId ( ) ) ;
2022-09-18 01:23:17 +02:00
if ( templates . empty ( ) )
{
+ + errors ;
continue ;
}
app = templates . front ( ) ;
}
auto tiles = controller . mapHandler ( ) - > getTilesUnderObject ( obj ) ;
obj - > appearance = app ;
controller . mapHandler ( ) - > invalidate ( tiles ) ;
controller . mapHandler ( ) - > invalidate ( obj ) ;
controller . scene ( mapLevel ) - > selectionObjectsView . deselectObject ( obj ) ;
}
}
controller . commitObjectChange ( mapLevel ) ;
controller . commitObjectErase ( mapLevel ) ;
controller . commitObstacleFill ( mapLevel ) ;
if ( errors )
QMessageBox : : warning ( this , " Update appearance " , QString ( " Errors occured. %1 objects were not updated " ) . arg ( errors ) ) ;
}
void MainWindow : : on_actionRecreate_obstacles_triggered ( )
{
}
2022-12-04 23:32:50 +02:00
void MainWindow : : on_actionCut_triggered ( )
{
if ( controller . map ( ) )
{
controller . copyToClipboard ( mapLevel ) ;
controller . commitObjectErase ( mapLevel ) ;
}
}
void MainWindow : : on_actionCopy_triggered ( )
{
if ( controller . map ( ) )
{
controller . copyToClipboard ( mapLevel ) ;
}
}
void MainWindow : : on_actionPaste_triggered ( )
{
if ( controller . map ( ) )
{
controller . pasteFromClipboard ( mapLevel ) ;
}
}