diff --git a/src/db/db/dbD25TechnologyComponent.cc b/src/db/db/dbD25TechnologyComponent.cc index 2719bfbb7..88723050b 100644 --- a/src/db/db/dbD25TechnologyComponent.cc +++ b/src/db/db/dbD25TechnologyComponent.cc @@ -119,6 +119,7 @@ D25TechnologyComponent::D25TechnologyComponent () // provide some explanation for the initialization m_src = "# Provide z stack information here\n" + "#\n" "# Each line is one layer. The specification consists of a layer specification, a colon and arguments.\n" "# The arguments are named (like \"x=...\") or in serial. Parameters are separated by comma or blanks.\n" "# Named arguments are:\n" @@ -127,7 +128,7 @@ D25TechnologyComponent::D25TechnologyComponent () "# zstop The upper z position of the extruded layer in µm\n" "# height The height of the extruded layer in µm\n" "#\n" - "# 'height', 'zstart' and 'zstop' can be used in any combination. If no value is given for 'zstart', " + "# 'height', 'zstart' and 'zstop' can be used in any combination. If no value is given for 'zstart',\n" "# the upper level of the previous layer will be used.\n" "#\n" "# If a single unnamed parameter is given, it corresponds to 'height'. Two parameters correspond to\n" @@ -139,6 +140,30 @@ D25TechnologyComponent::D25TechnologyComponent () "# 1: zstop=1.5, zstart=0.5 # same with named parameters\n" "# 1: height=1.0, zstop=1.5 # same with z stop minus height\n" "# 1: 1.0 zstop=1.5 # same with height as unnamed parameter\n" + "#\n" + "# VARIABLES\n" + "#\n" + "# You can declare variables with:\n" + "# var name = value\n" + "#\n" + "# You can use variables inside numeric expressions.\n" + "# Example:\n" + "# var hmetal = 0.48\n" + "# 7/0: 0.5 0.5+hmetal*2 # 2x thick metal\n" + "#\n" + "# You cannot use variables inside layer specifications currently.\n" + "#\n" + "# CONDITIONALS\n" + "#\n" + "# You can enable or disable branches of the table using 'if', 'else', 'elseif' and 'end':\n" + "# Example:\n" + "# var thick_m1 = true\n" + "# if thickm1\n" + "# 1: 0.5 1.5\n" + "# else\n" + "# 1: 0.5 1.2\n" + "# end\n" + "\n" ; } @@ -157,6 +182,9 @@ D25TechnologyComponent::compile_from_source (const std::string &src) try { + tl::Eval eval; + std::vector conditional_stack; + std::vector lines = tl::split (src, "\n"); for (std::vector::const_iterator l = lines.begin (); l != lines.end (); ++l) { @@ -168,6 +196,64 @@ D25TechnologyComponent::compile_from_source (const std::string &src) // ignore comments } else if (ex.at_end ()) { // ignore empty lines + + } else if (ex.test ("if")) { + + tl::Expression x; + eval.parse (x, ex); + conditional_stack.push_back (x.execute ().to_bool ()); + + ex.expect_end (); + + } else if (ex.test ("else")) { + + if (conditional_stack.empty ()) { + throw tl::Exception (tl::to_string (tr ("'else' without 'if'"))); + } + + conditional_stack.back () = ! conditional_stack.back (); + + ex.expect_end (); + + } else if (ex.test ("end")) { + + if (conditional_stack.empty ()) { + throw tl::Exception (tl::to_string (tr ("'end' without 'if'"))); + } + + conditional_stack.pop_back (); + + ex.expect_end (); + + } else if (ex.test ("elsif")) { + + if (conditional_stack.empty ()) { + throw tl::Exception (tl::to_string (tr ("'elsif' without 'if'"))); + } + + tl::Expression x; + eval.parse (x, ex); + conditional_stack.back () = x.execute ().to_bool (); + + ex.expect_end (); + + } else if (! conditional_stack.empty () && ! conditional_stack.back ()) { + + continue; + + } else if (ex.test ("var")) { + + std::string n; + ex.read_name (n); + + ex.expect ("="); + + tl::Expression x; + eval.parse (x, ex); + eval.set_var (n, x.execute ()); + + ex.expect_end (); + } else { db::D25LayerInfo info; @@ -191,16 +277,18 @@ D25TechnologyComponent::compile_from_source (const std::string &src) break; } - double pv = 0.0; + tl::Expression pvx; std::string pn; if (ex.try_read_name (pn)) { ex.expect ("="); - ex.read (pv); + eval.parse (pvx, ex); } else { - ex.read (pv); + eval.parse (pvx, ex); } + double pv = pvx.execute ().to_double (); + ex.test (","); if (pn.empty ()) { @@ -239,28 +327,28 @@ D25TechnologyComponent::compile_from_source (const std::string &src) } else if (args.size () == 1) { if (! h.is_nil ()) { if (! z0.is_nil ()) { - throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstart already given"))); + throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstart already given"))); } if (! z1.is_nil ()) { - throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstop implicitly given"))); + throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstop implicitly given"))); } info.set_zstart (args[0]); info.set_zstop (args[0] + h.to_double ()); } else { if (! z1.is_nil ()) { - throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstop implicitly given"))); + throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstop implicitly given"))); } info.set_zstop ((! z0.is_nil () ? z0.to_double () : info.zstart ()) + args[0]); } } else if (args.size () == 2) { if (! z0.is_nil ()) { - throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstart already given"))); + throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstart already given"))); } if (! z1.is_nil ()) { - throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstop already given"))); + throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstop already given"))); } if (! h.is_nil ()) { - throw tl::Exception (tl::to_string (tr ("Rundundant parameters: height implicitly given"))); + throw tl::Exception (tl::to_string (tr ("Redundant parameters: height implicitly given"))); } info.set_zstart (args[0]); info.set_zstop (args[1]); @@ -268,12 +356,14 @@ D25TechnologyComponent::compile_from_source (const std::string &src) throw tl::Exception (tl::to_string (tr ("Too many parameters (max 2)"))); } - m_layers.push_back (info); - } } + if (! conditional_stack.empty ()) { + throw tl::Exception (tl::to_string (tr ("'if', 'else' or 'elsif' without matching 'end'"))); + } + } catch (tl::Exception &ex) { throw tl::Exception (ex.msg () + tl::sprintf (tl::to_string (tr (" in line %d")), current_line)); } diff --git a/src/laybasic/laybasic/D25TechnologyComponentEditor.ui b/src/laybasic/laybasic/D25TechnologyComponentEditor.ui index b1901ba63..a550fe8ad 100644 --- a/src/laybasic/laybasic/D25TechnologyComponentEditor.ui +++ b/src/laybasic/laybasic/D25TechnologyComponentEditor.ui @@ -44,6 +44,12 @@ Monospace + + QTextEdit::NoWrap + + + false + diff --git a/src/laybasic/laybasic/syntax/d25_text.xml b/src/laybasic/laybasic/syntax/d25_text.xml index 5e0877b74..b90e293f9 100644 --- a/src/laybasic/laybasic/syntax/d25_text.xml +++ b/src/laybasic/laybasic/syntax/d25_text.xml @@ -5,13 +5,33 @@ + + zstart + zstop + height + + + + true + false + nil + + - + + + + + + + + + + - @@ -22,22 +42,52 @@ - - - + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + @@ -46,19 +96,21 @@ - + - + + + @@ -73,4 +125,12 @@ + + + + + + + + diff --git a/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc b/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc index 4aaed12f1..e115b55be 100644 --- a/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc +++ b/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc @@ -246,40 +246,23 @@ D25ViewWidget::wheelEvent (QWheelEvent *event) } else { - // compute vector of line of sight - std::pair ray = camera_normal (cam_perspective () * cam_trans (), px, py); - - // by definition the ray goes through the camera position - QVector3D hp = hit_point_with_scene (ray.second); + double d = event->angleDelta ().y () * (1.0 / (90 * 16)); if (! (event->modifiers () & Qt::ControlModifier)) { - // No Ctrl is closeup + // No Ctrl is "move horizontally along the azimuth axis" - double f = event->angleDelta ().y () * (1.0 / (90 * 8)); - m_displacement += -((f / m_scale_factor) * std::min (cam_dist (), double ((cam_position () - hp).length ()))) * ray.second; + QMatrix4x4 t; + t.rotate (cam_azimuth (), 0.0, 1.0, 0.0); + QVector3D cd = t.inverted ().map (QVector3D (0, 0, cam_dist ())); + + m_displacement += (d / m_scale_factor) * cd; } else { // "Ctrl" is zoom - double f = exp (event->angleDelta ().y () * (1.0 / (90 * 8))); - - QVector3D initial_displacement = m_displacement; - QVector3D displacement = m_displacement; - - m_scale_factor *= f; - displacement += hp * (1.0 - f) / m_scale_factor; - - // normalize the scene translation so the scene does not "flee" - - QMatrix4x4 ct = cam_trans (); - initial_displacement = ct.map (initial_displacement); - displacement = ct.map (displacement); - - lay::normalize_scene_trans (cam_perspective (), displacement, m_scale_factor, initial_displacement.z ()); - - m_displacement = ct.inverted ().map (displacement); + m_scale_factor *= exp (d); emit scale_factor_changed (m_scale_factor);