From 702f197eb663d8fbe532d4cc732617a2fd14caa2 Mon Sep 17 00:00:00 2001
From: Yona-TYT <yonatan.el.amigo@gmail.com>
Date: Thu, 27 Oct 2022 20:26:32 -0400
Subject: [PATCH] Add Script Tools Window

---
 Makefile                                    |   1 +
 cmake/SimutransSourceList.cmake             |   1 +
 src/simutrans/gui/script_tool.cc            | 144 ++++++++++++++++++++
 src/simutrans/gui/script_tool.h             |  57 ++++++++
 src/simutrans/gui/simwin.cc                 |   2 +
 src/simutrans/gui/simwin.h                  |   1 +
 src/simutrans/script/api/api_skeleton.cc    |   9 ++
 src/simutrans/script/script_tool_manager.cc |   1 +
 src/simutrans/tool/simtool-scripted.cc      |  32 ++++-
 src/simutrans/tool/simtool-scripted.h       |  10 ++
 10 files changed, 255 insertions(+), 3 deletions(-)
 create mode 100644 src/simutrans/gui/script_tool.cc
 create mode 100644 src/simutrans/gui/script_tool.h

diff --git a/Makefile b/Makefile
index 12019fc4f..80664db8b 100644
--- a/Makefile
+++ b/Makefile
@@ -459,6 +459,7 @@ SOURCES += src/simutrans/gui/savegame_frame.cc
 SOURCES += src/simutrans/gui/scenario_frame.cc
 SOURCES += src/simutrans/gui/scenario_info.cc
 SOURCES += src/simutrans/gui/schedule_list.cc
+SOURCES += src/simutrans/gui/script_tool.cc
 SOURCES += src/simutrans/gui/script_tool_frame.cc
 SOURCES += src/simutrans/gui/server_frame.cc
 SOURCES += src/simutrans/gui/settings_frame.cc
diff --git a/cmake/SimutransSourceList.cmake b/cmake/SimutransSourceList.cmake
index 7cdd6c7f7..098281d38 100644
--- a/cmake/SimutransSourceList.cmake
+++ b/cmake/SimutransSourceList.cmake
@@ -174,6 +174,7 @@ target_sources(simutrans PRIVATE
 		src/simutrans/gui/scenario_frame.cc
 		src/simutrans/gui/scenario_info.cc
 		src/simutrans/gui/schedule_list.cc
+		src/simutrans/gui/script_tool.cc
 		src/simutrans/gui/script_tool_frame.cc
 		src/simutrans/gui/server_frame.cc
 		src/simutrans/gui/settings_frame.cc
diff --git a/src/simutrans/gui/script_tool.cc b/src/simutrans/gui/script_tool.cc
new file mode 100644
index 000000000..be56eb063
--- /dev/null
+++ b/src/simutrans/gui/script_tool.cc
@@ -0,0 +1,144 @@
+/*
+ * This file is part of the Simutrans project under the Artistic License.
+ * (see LICENSE.txt)
+ */
+
+#include "script_tool.h"
+#include "../world/simworld.h"
+#include "../tool/simtool.h"
+#include "../tool/simtool-scripted.h"
+#include "../display/viewport.h"
+#include "../obj/zeiger.h"
+#include "../dataobj/translator.h"
+#include "../utils/simstring.h"
+
+
+vector_tpl<tool_exec_script_t*> script_tool_t::one_click_script_tools;
+vector_tpl<tool_exec_two_click_script_t*> script_tool_t::two_click_script_tools;
+
+namespace toolscripttext
+{
+	const char* text = "";
+
+	const char* get_tool_text()
+	{
+      return text;
+	}
+	void set_tool_text( const char* tx){
+		text = tx;
+	}
+}
+
+script_tool_t::script_tool_t() :
+	gui_frame_t( translator::translate("Script tool text") )
+{
+	set_table_layout(1,0);
+
+	add_component(&generaltext);
+	generaltext.add_listener(this);
+
+	// fetch texts
+	//update_script_tool_texts(true);
+
+	generaltext.set_text( toolscripttext::get_tool_text() );
+
+	scr_coord pane_pos(D_MARGIN_LEFT, D_MARGIN_TOP);
+
+	set_resizemode(diagonal_resize);
+	reset_min_windowsize();
+	set_windowsize(scr_size(500, D_TITLEBAR_HEIGHT + D_TAB_HEADER_HEIGHT+300));
+}
+
+
+bool script_tool_t::infowin_event(const event_t *ev)
+{
+	if( ev->ev_class == INFOWIN && ev->ev_code == WIN_CLOSE  ) {
+		welt->set_tool( tool_t::general_tool[TOOL_QUERY], welt->get_active_player() );
+	}
+
+	return gui_frame_t::infowin_event(ev);
+}
+
+
+void script_tool_t::draw(scr_coord pos, scr_size size)
+{
+	generaltext.set_text( toolscripttext::get_tool_text() );
+	gui_frame_t::draw(pos, size);
+}
+
+bool script_tool_t::action_triggered(gui_action_creator_t *, value_t v)
+{
+
+	set_dirty();
+	
+	// clean the lists
+	one_click_script_tools.clear();	
+	two_click_script_tools.clear();
+	
+	// parse hyperlink
+	const char *link = (const char*)v.p;
+	if (link  && *link) {
+		if (link[0]=='(') {
+			// jump to coordinate
+			int x=-1, y=-1, z=-1;
+			// try 3d coordinates first
+			int n = sscanf(link, "(%i,%i,%i)", &x, &y, &z);
+			if (n < 3) { // now try 2d
+				n = sscanf(link, "(%i,%i)", &x, &y);
+			}
+			if (n >= 2) { // at least 2d coordinates supplied
+				koord k(x,y);
+				//welt->get_scenario()->koord_sq2w( k );
+				if (welt->is_within_limits(k)) {
+					koord3d p(x,y,z);
+					if (n < 3) {
+						// take z coordinate from ground
+						p = welt->lookup_kartenboden(k)->get_pos();
+					}
+					welt->get_viewport()->change_world_position( p );
+					welt->get_zeiger()->change_pos( p );
+					//const char* err = welt->get_scenario()->jump_to_link_executed(p);
+					//if (err) {
+						//open_error_msg_win(err);
+					//}
+				}
+			}
+		}
+		else if (const char* func = strstart(link, "script:") ) {
+
+			tool_t *tool = welt->get_tool(welt->get_active_player()->get_player_nr());
+
+			if (tool_exec_script_t* ot = dynamic_cast<tool_exec_script_t*>(tool)) {
+				one_click_script_tools.append(ot);
+			}
+			else if (tool_exec_two_click_script_t* tt = dynamic_cast<tool_exec_two_click_script_t*>(tool)) {
+				two_click_script_tools.append(tt);
+			}
+
+			for(uint32 i=0; i<one_click_script_tools.get_count(); i++) {
+				tool_exec_script_t* tool = one_click_script_tools[i];
+				tool->eval_string(func);
+			}
+
+			for(uint32 i=0; i<two_click_script_tools.get_count(); i++) {
+				tool_exec_two_click_script_t* tool = two_click_script_tools[i];
+				tool->eval_string(func);
+			}
+		}
+	}
+
+	return true;
+}
+
+
+void script_tool_t::rdwr( loadsave_t *file )
+{
+	// window size
+	scr_size size = get_windowsize();
+	size.rdwr( file );
+
+	if(  file->is_loading()  ) {
+		reset_min_windowsize();
+		set_windowsize(size);
+	}
+}
diff --git a/src/simutrans/gui/script_tool.h b/src/simutrans/gui/script_tool.h
new file mode 100644
index 000000000..170f56a0d
--- /dev/null
+++ b/src/simutrans/gui/script_tool.h
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the Simutrans project under the Artistic License.
+ * (see LICENSE.txt)
+ */
+
+#ifndef GUI_SCRIPT_TOOL_H
+#define GUI_SCRIPT_TOOL_H
+
+
+#include "gui_frame.h"
+#include "simwin.h"
+#include "components/gui_flowtext.h"
+#include "components/gui_tab_panel.h"
+
+namespace toolscripttext {
+	extern const char* get_tool_text();
+	void set_tool_text( const char* text);
+};
+
+
+class tool_exec_script_t;
+class tool_exec_two_click_script_t;
+
+/**
+ * All messages since the start of the program
+ */
+class script_tool_t : public gui_frame_t, private action_listener_t
+{
+private:
+	/// All one-click script tools
+	static vector_tpl<tool_exec_script_t*> one_click_script_tools;
+	/// All two-click script tools
+	static vector_tpl<tool_exec_two_click_script_t*> two_click_script_tools;
+
+	gui_flowtext_t generaltext;
+
+
+public:
+	script_tool_t();
+
+	/**
+	 * This method is called if an action is triggered
+	 *
+	 * Returns true, if action is done and no more
+	 * components should be triggered.
+	 */
+	bool action_triggered( gui_action_creator_t*, value_t extra) OVERRIDE;
+
+	bool infowin_event( const event_t *ev ) OVERRIDE;
+
+	void draw(scr_coord pos, scr_size size) OVERRIDE;
+
+	uint32 get_rdwr_id() OVERRIDE { return magic_script_tool; }
+	void rdwr( loadsave_t *file ) OVERRIDE;
+};
+
+#endif
diff --git a/src/simutrans/gui/simwin.cc b/src/simutrans/gui/simwin.cc
index b10b1f577..013e1a730 100644
--- a/src/simutrans/gui/simwin.cc
+++ b/src/simutrans/gui/simwin.cc
@@ -73,6 +73,8 @@
 #include "labellist_frame.h"
 #include "display_settings.h"
 #include "optionen.h"
+#include "gui_frame.h"
+#include "script_tool.h"
 
 #include "../simversion.h"
 
diff --git a/src/simutrans/gui/simwin.h b/src/simutrans/gui/simwin.h
index 57dd42494..80981789f 100644
--- a/src/simutrans/gui/simwin.h
+++ b/src/simutrans/gui/simwin.h
@@ -107,6 +107,7 @@ enum magic_numbers {
 	magic_font,
 	magic_soundfont, // only with USE_FLUIDSYNTH_MIDI
 	magic_edit_groundobj,
+	magic_script_tool,
 
 	// magic numbers with big jumps between them
 	magic_convoi_info,
diff --git a/src/simutrans/script/api/api_skeleton.cc b/src/simutrans/script/api/api_skeleton.cc
index e40f35bd9..785fb5182 100644
--- a/src/simutrans/script/api/api_skeleton.cc
+++ b/src/simutrans/script/api/api_skeleton.cc
@@ -374,4 +374,13 @@ register_function("mark_tile");
  */
 register_function("is_valid_pos");
 
+/**
+ * Text shown in the Info window in script tools.
+ *
+ * @param pl player number of active player
+ * @typemask string(integer)
+ * @ingroup tool_skel
+ */
+register_function("tool_text");
+
 #endif
diff --git a/src/simutrans/script/script_tool_manager.cc b/src/simutrans/script/script_tool_manager.cc
index 80bc27ecc..89f692912 100644
--- a/src/simutrans/script/script_tool_manager.cc
+++ b/src/simutrans/script/script_tool_manager.cc
@@ -59,6 +59,7 @@ const scripted_tool_info_t* script_tool_manager_t::get_script_info(const char* p
 		const char* skin_name = contents.get_string("icon", "");
 		info->desc   = skinverwaltung_t::get_extra(skin_name, strlen(skin_name), skinverwaltung_t::cursor);
 		info->is_one_click = !( strcmp(contents.get_string("type", "one_click"), "two_click")==0 );
+		info->window = contents.get_int("window", false);
 	}
 	else {
 		// no description.tab, use default values
diff --git a/src/simutrans/tool/simtool-scripted.cc b/src/simutrans/tool/simtool-scripted.cc
index a1745bb9b..f35eaad76 100644
--- a/src/simutrans/tool/simtool-scripted.cc
+++ b/src/simutrans/tool/simtool-scripted.cc
@@ -17,6 +17,10 @@
 #include "../world/simworld.h"
 #include "../obj/zeiger.h"
 
+#include "../gui/simwin.h"
+#include "../gui/script_tool.h"
+
+
 void export_scripted_tools(HSQUIRRELVM vm);
 
 // -- callback to receive error messages from work/do_work calls
@@ -82,7 +86,6 @@ exec_script_base_t::~exec_script_base_t()
 	delete script;
 }
 
-
 void exec_script_base_t::set_info(const scripted_tool_info_t *i)
 {
 	delete info;
@@ -120,6 +123,11 @@ void exec_script_base_t::load_script(const char* path, player_t* player)
 	if (script == NULL) {
 		return;
 	}
+
+	if (info->window)
+		create_win(new script_tool_t(), w_info, magic_script_tool);
+
+	toolscripttext::set_tool_text(buf);
 	// set my player number
 	script->set_my_player(player->get_player_nr());
 	// export tool-pointer handling
@@ -171,9 +179,16 @@ const char* exec_script_base_t::call_function(script_vm_t::call_type_t ct, const
 
 void exec_script_base_t::step(player_t* player)
 {
+
 	if (script) {
 		script->call_function(script_vm_t::QUEUE, "step");
 
+		if (info->window) {
+			static plainstring msg;
+			script->call_function(script_vm_t::FORCE, "tool_text", msg, player);
+			toolscripttext::set_tool_text(msg.c_str());
+		}
+
 		if (tool_exec_two_click_script_t *tt = dynamic_cast<tool_exec_two_click_script_t*>(this)) {
 			if (tt->needs_call_to_init) {
 				tt->init(player);
@@ -193,6 +208,13 @@ void exec_script_base_t::init_images(tool_t *tool) const
 	}
 }
 
+const char* exec_script_base_t::eval_string(const char* squirrel_string) const
+{
+
+	return script->eval_string(squirrel_string);
+
+}
+
 
 tool_exec_script_t::tool_exec_script_t(const scripted_tool_info_t *info) : tool_t(TOOL_EXEC_SCRIPT | GENERAL_TOOL), exec_script_base_t(info)
 {
@@ -212,18 +234,24 @@ bool tool_exec_script_t::init(player_t* player)
 		cursor_area = koord(old_area.y, old_area.x);
 		cursor_offset = koord(old_area.y-1-old_offset.y, old_offset.x);
 	}
+
 	return init_vm(player)  &&  call_function(script_vm_t::FORCE, "init", player, res)== NULL  &&  res;
 }
 
 
 bool tool_exec_script_t::exit(player_t* player)
 {
+
 	bool res, res2 = false;
 	// exit script
 	res = call_function(script_vm_t::FORCE, "exit", player, res2) == NULL;
 	// shut down vm
 	delete script;
 	script = NULL;
+
+	gui_frame_t *win = win_get_magic( magic_script_tool );
+	destroy_win( win );
+
 	return res  &&  res2;
 }
 
@@ -246,8 +274,6 @@ const char* tool_exec_script_t::work(player_t* player, koord3d pos)
 	return res.c_str();
 }
 
-
-
 tool_exec_two_click_script_t::tool_exec_two_click_script_t(const scripted_tool_info_t *info) : two_click_tool_t(TOOL_EXEC_TWO_CLICK_SCRIPT | GENERAL_TOOL), exec_script_base_t(info)
 {
 	set_marker(IMG_EMPTY);
diff --git a/src/simutrans/tool/simtool-scripted.h b/src/simutrans/tool/simtool-scripted.h
index 7bcd61cb6..3fe4deb56 100644
--- a/src/simutrans/tool/simtool-scripted.h
+++ b/src/simutrans/tool/simtool-scripted.h
@@ -35,6 +35,7 @@ struct scripted_tool_info_t {
 	const skin_desc_t* desc; ///< skin object used for cursor (0), icon (1), and maybe marker (2)
 	bool restart;            ///< true, if script vm has to be restarted after work()
 	bool is_one_click;       ///< true, if tool is one-click (otherwise needs two clicks/coordinates to work)
+	bool window;
 	koord cursor_area;       ///< size of cursor defined in tool_t
 	koord cursor_offset;     ///< cursor offset defined in tool_t
 	/// sets default values
@@ -43,6 +44,7 @@ struct scripted_tool_info_t {
 		desc = NULL;
 		restart = true;
 		is_one_click = true;
+		window = true;
 		cursor_area = koord(1,1);
 		cursor_offset = koord(0,0);
 	}
@@ -79,6 +81,12 @@ public:
 	const char *get_tooltip(const player_t *) const { return info ? info->tooltip.c_str() : ""; }
 	koord get_cursor_area() const { return info->cursor_area; }
 	koord get_cursor_offset() const { return info->cursor_offset; }
+
+	/**
+	 * compiles and executes given string
+	 * @returns error msg (or NULL if succeeded)
+	 */
+	const char* eval_string(const char* squirrel_string) const;
 };
 
 
@@ -131,4 +139,6 @@ public:
 	const char *get_tooltip(const player_t *pl) const OVERRIDE { return exec_script_base_t::get_tooltip(pl); }
 };
 
+
+
 #endif
-- 
2.37.3

