Jump to content

WidgetMenuBar crashes app on shutdown


photo

Recommended Posts

Hi, I can't reproduce app crush. I'm use this sample:

#include <unigine.h>

WidgetMenuBar bar;

/*
 */
int init() {
	
	Player player = new PlayerSpectator();
	player.setDirection(vec3(0.755f,-1.0f,0.25f));
	engine.game.setPlayer(player);
	
	Gui gui = engine.getGui();
	
	bar = new WidgetMenuBar(gui);
	
	forloop(int i = 0; 5) {
		WidgetMenuBox box = new WidgetMenuBox(gui,0,0);
		forloop(int j = 0; 5) {
			box.addItem(format("item %i",j));
		}
		box.setCallback(GUI_CLICKED,"box_clicked",i);
		bar.addItem(format("box %i",i),box);
	}
	
	gui.addChild(bar);
	
	return 1;
}

void box_clicked(int num) {
	WidgetMenuBox box = bar.getItemMenu(num);
	log.message("%i box, %i item clicked\n",num,box.getCurrentItem());
}

/*
 */
int shutdown() {
	
	return 1;
}

/*
 */
int update() {
	
	return 1;
}

/*
 */
int flush() {
	return 1;
}

Can you send to me your code?

Link to comment

there is script file of framework project:

crash on shutdown if no NULL callback set

#ifndef __MENU_UI_H__
#define __MENU_UI_H__

/******************************************************************************\
 *
 * class MenuUI
 *
\******************************************************************************/

class MenuTable {
	int parent;
	int code;
	string name;
	
	MenuTable(int parent, int code, string name) {
		this.parent = parent;
		this.code = code;
		this.name = name;
	}
};

enum{
	MENU_INSERT = 0, 
		MENU_UBER_PROVIDER, MENU_DOWNLOAD_TILE, MENU_UPLOAD_TEST, MENU_DOWNLOAD_TEST, MENU_PUBLISH_NODE, MENU_PUBLISH_NODE_OFFLINE, 
		MENU_PUBLISH_NODE_OFFLINE_EASY, MENU_NODES_DATABASE_OFFLINE_EDITOR, 
	MENU_LAYERS, 
		MENU_DL_TILES, MENU_DL_ZOOM_TILES, MENU_TEX_LAYER_SAVE_SOLID, MENU_TL_SET_DEF_MAT, 
	MENU_T_HELPER,
		MENU_T_HELPER_SAVE_TILES_TO_CACHE, MENU_T_HELPER_SAVE_TILES_TO_CACHE_NEW, 
		MENU_T_HELPER_RENDER_TILES_FROM_CACHE, MENU_T_HELPER_RENDER_CHESSTILES_FROM_CACHE, MENU_T_HELPER_ADD_CUSTOM_TILE, 
		MENU_T_HELPER_CLEAR_CUSTOM_TILES, MENU_T_HELPER_RENDER_CUSTOM_TILES, MENU_T_HELPER_TILES_SAVE, MENU_T_HELPER_TILE_SAVE, 
		MENU_T_HELPER_GET_BASE, MENU_T_HELPER_ADD_CACHED_TILES_AS_CUSTOM, MENU_T_HELPER_SAVE_VISIBLE_TILES_TO_FILE,
		MENU_T_HELPER_SAVE_CUSTOM_TILES_TO_FILE, 
	MENU_NAVIGATION, 
		MENU_N_SET_GEO_POS, 
	MENU_SETTINGS, 
		MENU_SETTINGS_EDITOR};

class MenuUI : UI {
		
	private:
		WidgetMenuBar menu_bar;
		MenuTable table[0];
		CommanderEntity commander;
		
	public:
		
		MenuUI() {
			
		}
		
		~MenuUI() {
			
		}
		
		void fillTable() {
			table.clear();
			table.append(new MenuTable(-1, MENU_INSERT, "Insert"));
			table.append(new MenuTable(MENU_INSERT, MENU_PUBLISH_NODE, "Publish object"));
			table.append(new MenuTable(MENU_INSERT, MENU_PUBLISH_NODE_OFFLINE, "Publish object offline"));
			table.append(new MenuTable(MENU_INSERT, MENU_PUBLISH_NODE_OFFLINE_EASY, "Easy publish object offline"));
			table.append(new MenuTable(MENU_INSERT, MENU_NODES_DATABASE_OFFLINE_EDITOR, "Offline nodes database editor"));
			table.append(new MenuTable(MENU_INSERT, MENU_UBER_PROVIDER, "Uber provider"));
			table.append(new MenuTable(MENU_INSERT, MENU_DOWNLOAD_TILE, "Download tile"));
			table.append(new MenuTable(MENU_INSERT, MENU_UPLOAD_TEST, "Upload test"));
			table.append(new MenuTable(MENU_INSERT, MENU_DOWNLOAD_TEST, "Download test"));			
			
			table.append(new MenuTable(-1, MENU_LAYERS, "Layers"));
			table.append(new MenuTable(MENU_LAYERS, MENU_DL_TILES, "Download tiles"));
			table.append(new MenuTable(MENU_LAYERS, MENU_DL_ZOOM_TILES, "Download zoom tiles"));
			table.append(new MenuTable(MENU_LAYERS, MENU_TEX_LAYER_SAVE_SOLID, "Save TexLayer image"));
			table.append(new MenuTable(MENU_LAYERS, MENU_TL_SET_DEF_MAT, "Set default material"));
			
			table.append(new MenuTable(-1, MENU_T_HELPER, "Tile helper"));
			table.append(new MenuTable(MENU_T_HELPER, MENU_T_HELPER_SAVE_TILES_TO_CACHE, "Save visible tiles"));
			table.append(new MenuTable(MENU_T_HELPER, MENU_T_HELPER_SAVE_TILES_TO_CACHE_NEW, "Save visible tiles [NEW]"));
			table.append(new MenuTable(MENU_T_HELPER, MENU_T_HELPER_RENDER_TILES_FROM_CACHE, "Render visible tiles"));
			table.append(new MenuTable(MENU_T_HELPER, MENU_T_HELPER_RENDER_CHESSTILES_FROM_CACHE, "Render chess tiles"));
			table.append(new MenuTable(MENU_T_HELPER, MENU_T_HELPER_ADD_CACHED_TILES_AS_CUSTOM, "Add cached tiles as custom"));
			table.append(new MenuTable(MENU_T_HELPER, MENU_T_HELPER_ADD_CUSTOM_TILE, "Add custom tile"));
			table.append(new MenuTable(MENU_T_HELPER, MENU_T_HELPER_CLEAR_CUSTOM_TILES, "Clear custom tiles"));
			table.append(new MenuTable(MENU_T_HELPER, MENU_T_HELPER_RENDER_CUSTOM_TILES, "Render custom tiles"));
			table.append(new MenuTable(MENU_T_HELPER, MENU_T_HELPER_TILES_SAVE, "Save tile cache"));
			table.append(new MenuTable(MENU_T_HELPER, MENU_T_HELPER_TILE_SAVE, "Save tile"));
			table.append(new MenuTable(MENU_T_HELPER, MENU_T_HELPER_GET_BASE, "Get base"));
			table.append(new MenuTable(MENU_T_HELPER, MENU_T_HELPER_SAVE_VISIBLE_TILES_TO_FILE, "Save visible tiles to file"));
			table.append(new MenuTable(MENU_T_HELPER, MENU_T_HELPER_SAVE_CUSTOM_TILES_TO_FILE, "Save custom tiles to file"));
				
			table.append(new MenuTable(-1, MENU_NAVIGATION, "Navigation"));
			table.append(new MenuTable(MENU_NAVIGATION, MENU_N_SET_GEO_POS, "Set GeoPos"));
			
			table.append(new MenuTable(-1, MENU_SETTINGS, "Settings"));
			table.append(new MenuTable(MENU_SETTINGS, MENU_SETTINGS_EDITOR, "Settings editor"));	
		}
		
		void fillMenu(Gui gui) {
			menu_bar = new WidgetMenuBar(gui);
			
			int parents[0];
			//adding top menus
			forloop(int i=0; table.size()) {
				if(table[i].parent == -1) {
					menu_bar.addItem(table[i].name, NULL);
					parents.append(table[i].code);
				}
			}
			
			//adding child menus
			forloop(int i=0; parents.size()) {
				WidgetMenuBox wmb = new WidgetMenuBox(gui);
				wmb.setCallback(GUI_CLICKED, game.getLogicNamespaceName() + "::MenuUI::menuRedirector", this, wmb);
				menu_bar.setItemMenu(i,wmb);
				
				forloop(int j=0; table.size()) {
					if(parents[i] == table[j].parent) {
						wmb.addItem(table[j].name);
					}
				}
			}
			
			gui.addChild(menu_bar, GUI_ALIGN_LEFT);
			menu_bar.arrange();
		}
		
		void menuRedirector(MenuUI menu, WidgetMenuBox wmb) {
			menu.onMenu(wmb);
		}
		
		void onMenu(WidgetMenuBox wmb) {
			forloop(int i=0; menu_bar.getNumItems()) {
				WidgetMenuBox wmbi = menu_bar.getItemMenu(i);
				if(wmb == wmbi) {
					if(commander != NULL) commander.MenuCommand(getChildByPos(getParentByPos(i), wmb.getCurrentItem()));
					break;
				}
			}
		}
		
		int getParentByPos(int pos) {
			int pc = 0;
			forloop(int i=0; table.size()) {
				if(table[i].parent == -1) {
					if(pc == pos) return table[i].code;
					else pc++;
				}
			}
			return -1;
		}
		
		int getChildByPos(int parent, int pos) {
			int pc = 0;
			forloop(int i=0; table.size()) {
				if(table[i].parent == parent) {
					if(pc == pos) return table[i].code;
					else pc++;
				}
			}
			return -1;
		}
		
		void onInit() {
			// place your init code here
			super.onInit();
			
			fillTable();
			fillMenu(gui);
			
			commander = level.getFirstEntity("CommanderEntity");
			if(commander == NULL) {
				log.message("Menu: commander not found\n");
				return;
			}
		}
		
		void onShutdown() {
			// place your shutdown code here
			forloop(int i=0; menu_bar.getNumItems()) {
				WidgetMenuBox wmb = menu_bar.getItemMenu(i);
				wmb.setCallback(GUI_CLICKED, NULL, 0, 0);
			}
		}
		
		void onUpdate() {
			// place your update code here
		}
		
		void onRender() {
			// place your render code here
		}
		
		void onFlush() {
			// place your flush code here
		}
};

#endif /* __MENU_UI_H__ */

Link to comment

Hi, The Game framework works in a Expression, and all logic compiled dynamically. In shutdown framework removes expression and yours logic code. If you create some widgets and set a callback to your function in expression, then in shutdown after expression removed engine try to delete your dynamically created widgets, but widget callback has reference to  not existing function and engine will be crashed. So you need manually remove your dynamically created objects or set callbacks as NULL. This applies to trigger callbacks, body callbacks and all callback in engine. Also you need to control all reference from extern objects to expression. Using "onShutdown()" function to clear all dynamically created objects is best way to resolve this problem.

Link to comment
×
×
  • Create New...