Skip to content

Commit

Permalink
Allow reset function for scripted widget
Browse files Browse the repository at this point in the history
updated doc in readme
#2930
  • Loading branch information
supermerill committed Aug 9, 2022
1 parent 8098101 commit 82799c7
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 102 deletions.
82 changes: 80 additions & 2 deletions resources/ui_layout/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ each parameter is separated by ':'
* `floats_or_percents: mandatory`: Array. Tell the sotfware it's a numeric that can acept a % value (boolean return value)
* `strings`: Array. Tell mandatory for a filament or an extruder value. The sotfware it's a numeric an entry field where you can enter a text(string return value)
* `enum$STR$STR[$STR$STR]*`: tell the sotfware it's a combobox (string return value). It has to be followed by $name$label for each option you want to show.
Also, script may depends on normal fields. When a setting it depends is modified, the scripted widget will appear modified. And resetting a widget will reset all depending fields.
* `depends$STR[$STR]*`: add the setting fields this scripted widget depends on. Each one has to be suffixed by a '$'
* Also, script may depends on normal fields. When a setting it depends is modified, the scripted widget will appear modified. And resetting a widget will reset all depending fields.
* `depends$STR[$STR]*`: add the setting fields this scripted widget depends on. Each one has to be suffixed by a '$'

There is also special commands:
* `height:INT`: change the default height of settings. Don't works with every type of setting (mostly multilne text). Set to 0 or -1 to disable.
Expand Down Expand Up @@ -139,9 +139,87 @@ The second one is called when the user change the value in the gui.
At the start of the print.ui file, there is a little dictionnary with he methods available for the script to call.
It also contains the list of methods needed for all types (not only int).

You can also write a `void my_widget_reset()` if the default one (reset the settings from the depends property) isn't what's needed.

## frequent settings

The files freq_fff.ui and freq_sla.ui contains teh frequent settings.
Their layout is similar as other ui files. They still have to define a page and a group.
The group has to be `group:freq_settings_event:no_title:no_search:` to not interfer witht he rest of the gui.
If it use scripted widget, they have to be in the print.as file. The syntax is similar to c++/java.

## Script API: called by the slicer
Here are all the functions you need to define for your custom widget to work (for your type):
### type bool:
* int **OPTNAME_get**()
Will return 1 if checked, 0 if unchecked and -1 if half-checked (not all os, will be unchecked if not available)
* void **OPTNAME_set**(bool set)
### type int:
* int **OPTNAME_get**()
* void **OPTNAME_set**(int set)
### type float & percent:
* float **OPTNAME_get**()
* void **OPTNAME_set**(float set)
### type float_or_percent:
* float **OPTNAME_get**(bool &out is_percent)
* void **OPTNAME_set**(float set, bool is_percent)
### type string:
* void **OPTNAME_get**(string &out get)
* void **OPTNAME_set**(string &in set)
### type enum:
* int **OPTNAME_get**(string &out enum_value)
Only the return value is used unless it's out of bounds, then it tries to use the enum_value
* void **OPTNAME_set**(string &in set_enum_value, int set_idx)
### all type:
* void **OPTNAME_reset**()
Optional, called when clicked on the "reset" button.
If not present, the software will call a reset on all fields from the 'depends' property.
## Script API: called by the script
Here are listed all the functions to the slicer you can call from the script:
### to get the value of a real settings
These functions can be called everywhere.
* bool **get_bool**(string &in key)
* int **get_int**(string &in key)
Can be used by type int and enum (return the index)
* float **get_float**(string &in key)
Can be used by type float, percent and flaot_or_percent
* float **get_computed_float**(string &in key)
Get the float computed value of the field. Useful if it's a floatOrPercent that is computable.
* bool **is_percent**(string &in key)
* void **get_string**(string &in key, string &out get_val)
Can be used by type string and enum (return the enum_value, not the label)

### to set the value of real settings
These functions can only be called in a `set` or `reset` function. If you need to set a variable in a `get`, call ask_for_refresh() and write it in the set method.
* void **set_bool**(string &in key, bool new_val)
* void **set_int**(string &in key, int new_val)
if an enum, it's the index in the c++ enum
* void **set_float**(string &in key, float new_val)
if a float_or_percent, unset the percent flag at the same time
* void **set_percent**(string &in key, float new_val)
if a float_or_percent, set the percent flag at the same time
* void **set_string**(string &in key, string &in new_val))
if an enum, it's one of the enum_value, as saved in a config file
* void **back_initial_value**(string &in key)
revert the setting to the last saved value (same as a click on the reset arrow)
### others
* void **ask_for_refresh**()
ask for a OPTNAME_set() after the current OPTNAME_get(), to be able to set settings.

### to get/set the value of a custom variable
The first argument is the index of the tab setting: 0 for print settings, 1 for filament settings and 2 for printer settings.
Getters return true if the variable exists, false if it doesn't. If the variable doesn't exists, the 'out' variable isn't set.
* bool **get_custom_bool**(int, string &in, bool &out)
* void **set_custom_bool**(int, string &in, bool new_val)
* bool **get_custom_int**(int, string &in, int &out)
* void **set_custom_int**(int, string &in, int new_val)
* bool **get_custom_float**(int, string &in, float &out)
* void **set_custom_float**(int, string &in, float new_val)
* bool **get_custom_string**(int, string &in, string &out)
* void **set_custom_string**(int, string &in, string &in new_val)
* void **back_custom_initial_value**(int, string &in)
To remove a custom variable, use `set_custom_string` with an empty string as `new_val`

### to print on the console, for debugging
* void **print**(string &out)
* void **print_float**(float)
81 changes: 3 additions & 78 deletions resources/ui_layout/default/print.as
Original file line number Diff line number Diff line change
@@ -1,73 +1,3 @@
//////////////////////////////////////////
// Api for SuperSlicer scripted widgets:
//
//// Functions callable ////
//
// -- to print on the console, for debugging --
// void print(string &out)
// void print_float(float)
//
// -- to get the value of real settings --
// bool get_bool(string &in key)
// int get_int(string &in key)
// can be used by type int and enum (return the index)
// float get_float(string &in key)
// can be used by type float, percent and flaot_or_percent
// float get_computed_float(string &in key)
// get the float computed value of the field. Useful if it's a floatOrPercent that is computable.
// bool is_percent(string &in key)
// void get_string(string &in key, string &out get_val)
// can be used by type string and enum (return the enum_value, not the label)
//
// -- to set the value of real settings --
// void set_bool(string &in key, bool new_val)
// void set_int(string &in key, int new_val)
// if an enum, it's the index
// void set_float(string &in key, float new_val)
// if a float_or_percent, unset the percent flag at the same time
// void set_percent(string &in key, float new_val)
// if a float_or_percent, set the percent flag at the same time
// void set_string(string &in key, string &in new_val))
// if an enum, it's one of the enum_value
//
// void back_initial_value(string &in key)
// revert the setting to the last saved value (same as a click on the reset arrow)
//
// ask_for_refresh()
// ask for a OPTNAME_set() if in a OPTNAME_get()
//
//// Functions to define for each script widget ////
//
// note that you can't call set_thing() in an OPTNAME_get(), you can only call these in an OPTNAME_set()
//
// type bool:
// int OPTNAME_get()
// will return 1 if checkd, 0 if unchecked and -1 if half-checked (not all os, will be uncehcked if not available)
// void OPTNAME_set(bool set)
//
// type int:
// int OPTNAME_get()
// void OPTNAME_set(int set)
//
// type float & percent:
// float OPTNAME_get()
// void OPTNAME_set(float set)
//
// type float_or_percent:
// float OPTNAME_get(bool &out is_percent)
// void OPTNAME_set(float set, bool is_percent)
//
// type string:
// void OPTNAME_get(string &out get)
// void OPTNAME_set(string &in set)
//
// type enum:
// int OPTNAME_get(string &out enum_value)
// Only the return value is used unless it's out of bounds, then it tries to use the enum_value
// void OPTNAME_set(string &in set_enum_value, int set_idx)
//
//

//overhangs : quick set/unset like the one in prusalicer

int s_overhangs_get()
Expand All @@ -92,12 +22,6 @@ void s_overhangs_set(bool set)
}
}

void s_overhangs_reset(bool set)
{
back_initial_value("overhangs_width_speed");
back_initial_value("overhangs_width");
}

// "not thick bridge" like in prusaslicer

float compute_overlap()
Expand Down Expand Up @@ -125,11 +49,12 @@ int s_not_thick_bridge_get()
return 0;
}

void s_not_thick_bridge_reset(bool set)
void s_not_thick_bridge_reset()
{
set_custom_bool(0,"not_thick_bridge", false);
set_custom_string(0,"not_thick_bridge", "");
back_initial_value("bridge_type");
back_initial_value("bridge_overlap");
back_initial_value("bridge_overlap_min");
}

void s_not_thick_bridge_set(bool set)
Expand Down
48 changes: 27 additions & 21 deletions src/slic3r/GUI/OptionsGroup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -679,30 +679,36 @@ void ConfigOptionsGroup::back_to_config_value(const DynamicPrintConfig& config,
auto *milling_diameter = dynamic_cast<const ConfigOptionFloats*>(config.option("milling_diameter"));
value = int(milling_diameter->values.size());
} else if (it_opt != m_options.end() && it_opt->second.opt.is_script) {
//when a scripted key is reset, reset its deps
//reset if needed in other tabs
for (const std::string& dep_key : it_opt->second.opt.depends_on) {
for (Tab* tab : wxGetApp().tabs_list) {
if (tab != nullptr && tab->completed()) {
const DynamicPrintConfig& initial_conf = tab->m_presets->get_selected_preset().config;
DynamicPrintConfig& edited_conf = tab->m_presets->get_edited_preset().config;
if (initial_conf.has(dep_key) && edited_conf.has(dep_key)) {
ConfigOption* conf_opt = initial_conf.option(dep_key)->clone();
//set the conf
edited_conf.set_key_value(dep_key, conf_opt);
// when a scripted key is reset, reset its deps
// call the reset function if it exits
if (!it_opt->second.script->call_script_function_reset(it_opt->second.opt)) {
// Fucntion doesn't exists, reset the fields from the 'depends'
// reset in all tabs
// first set_key_value
for (const std::string& dep_key : it_opt->second.opt.depends_on) {
for (Tab* tab : wxGetApp().tabs_list) {
if (tab != nullptr && tab->completed()) {
const DynamicPrintConfig& initial_conf = tab->m_presets->get_selected_preset().config;
DynamicPrintConfig& edited_conf = tab->m_presets->get_edited_preset().config;
if (initial_conf.has(dep_key) && edited_conf.has(dep_key)) {
ConfigOption* conf_opt = initial_conf.option(dep_key)->clone();
//set the conf
edited_conf.set_key_value(dep_key, conf_opt);
}
}
}
}
}
for (const std::string& dep_key : it_opt->second.opt.depends_on) {
for (Tab* tab : wxGetApp().tabs_list) {
if (tab != nullptr && tab->completed()) {
const DynamicPrintConfig& initial_conf = tab->m_presets->get_selected_preset().config;
DynamicPrintConfig& edited_conf = tab->m_presets->get_edited_preset().config;
if (initial_conf.has(dep_key) && edited_conf.has(dep_key)) {
ConfigOption* conf_opt = initial_conf.option(dep_key)->clone();
// update the field
tab->on_value_change(dep_key, conf_opt->getAny());
// now that all keys are set, call the on_value_change to propagate the changes in one go.
for (const std::string& dep_key : it_opt->second.opt.depends_on) {
for (Tab* tab : wxGetApp().tabs_list) {
if (tab != nullptr && tab->completed()) {
const DynamicPrintConfig& initial_conf = tab->m_presets->get_selected_preset().config;
DynamicPrintConfig& edited_conf = tab->m_presets->get_edited_preset().config;
if (initial_conf.has(dep_key) && edited_conf.has(dep_key)) {
ConfigOption* conf_opt = initial_conf.option(dep_key)->clone();
// update the field
tab->on_value_change(dep_key, conf_opt->getAny());
}
}
}
}
Expand Down
60 changes: 59 additions & 1 deletion src/slic3r/GUI/ScriptExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,7 @@ std::string get_type_name(ConfigOptionType type)
default: return "";
}
}

void ScriptContainer::call_script_function_set(const ConfigOptionDef& def, const boost::any& value)
{
if (value.empty() || !is_intialized())
Expand Down Expand Up @@ -828,7 +829,7 @@ void ScriptContainer::call_script_function_set(const ConfigOptionDef& def, const
m_to_update[tab->type()] = {};
m_can_set = true;
// exec
int res = ctx->Execute();
/*int res = */ctx->Execute();
m_can_set = false;
std::map<Preset::Type, DynamicPrintConfig> to_update = m_to_update;
m_to_update.clear();
Expand Down Expand Up @@ -867,6 +868,63 @@ void ScriptContainer::call_script_function_set(const ConfigOptionDef& def, const
}
}
}

bool ScriptContainer::call_script_function_reset(const ConfigOptionDef& def)
{
std::string func_name = ("void " + def.opt_key + "_reset()");
AngelScript::asIScriptFunction* func = m_script_module->GetFunctionByDecl(func_name.c_str());
if (func == nullptr) {
return false;
}
AngelScript::asIScriptContext* ctx = m_script_engine->CreateContext();
if (ctx == nullptr) {
BOOST_LOG_TRIVIAL(error) << "Error, can't create script context for function '" << func_name << "'";
return false;
}
ctx->Prepare(func);
m_can_set = true;
// exec
/*int res = */ctx->Execute();
m_can_set = false;
std::map<Preset::Type, DynamicPrintConfig> to_update = m_to_update;
m_to_update.clear();
auto to_reset = m_to_reset_initial;
m_to_reset_initial.clear();

//update the tabs from the results
for (auto& data : to_update) {
Tab* tab = wxGetApp().get_tab(data.first);
//also reset
if (!to_reset.empty()) {
const DynamicPrintConfig& initial_conf = tab->m_presets->get_selected_preset().config;
for (size_t key_idx = 0; key_idx != to_reset.size(); ++key_idx) {
const std::string& key = to_reset[key_idx];
if (initial_conf.has(key)) {
data.second.set_key_value(key, initial_conf.option(key)->clone());
to_reset.erase(to_reset.begin() + key_idx);
key_idx--;
}
}
}
tab->load_config(data.second);
}
//also call for value_changed, as it's not really a load but a change
for (const auto& data : to_update) {
Tab* tab = wxGetApp().get_tab(data.first);
for (auto opt_key : data.second.keys()) {
tab->on_value_change(opt_key, data.second.option(opt_key)->getAny());
}
}
// refresh the field if needed
if (m_need_refresh && m_tab) {
Field* f = m_tab->get_field(def.opt_key);
if (f != nullptr) {
f->set_value(call_script_function_get_value(def), false);
}
}
return true;
}

//void ScriptContainer::call_script_function_refresh(const std::string& def_id)
//{
// std::string func_name = ("int " + def_id + "_refresh()");
Expand Down
2 changes: 2 additions & 0 deletions src/slic3r/GUI/ScriptExecutor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class ScriptContainer
void init(const std::string& tab_key, Tab* tab);
void call_script_function_set(const ConfigOptionDef& def, const boost::any& value);
void refresh(const ConfigOptionDef& def, boost::any value);
//return false if the function doesn't exists.
bool call_script_function_reset(const ConfigOptionDef& def);
//void call_script_function_refresh(const std::string& def_id);
boost::any call_script_function_get_value(const ConfigOptionDef& def);
};
Expand Down

0 comments on commit 82799c7

Please sign in to comment.