Merge branch 'master' of gitorious.org:fg/fgdata
This commit is contained in:
commit
8bbc1217b5
21 changed files with 1154 additions and 168 deletions
|
@ -40,9 +40,11 @@ initialize = func {
|
|||
print("Initializing formation ...");
|
||||
|
||||
# initialise dialogs
|
||||
|
||||
aircraft.data.add("sim/model/formation/variant");
|
||||
formation_dialog = gui.OverlaySelector.new("Select Formation",
|
||||
"Aircraft/Generic/Formations",
|
||||
"sim/model/formation/variant",
|
||||
"sim/model/formation/variant", nil, func(no) {
|
||||
formation_variant_Node.setIntValue(no);
|
||||
tgt_x_offset_Node.setDoubleValue(getprop("/sim/model/formation/position/x-offset"));
|
||||
|
|
|
@ -290,6 +290,7 @@
|
|||
<program>
|
||||
<vertex-shader>Shaders/terrain-haze-ultra.vert</vertex-shader>
|
||||
<fragment-shader>Shaders/terrain-haze-ultra.frag</fragment-shader>
|
||||
<fragment-shader>Shaders/noise.frag</fragment-shader>
|
||||
<fragment-shader>Shaders/cloud-shadowfunc.frag</fragment-shader>
|
||||
</program>
|
||||
<uniform>
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
<quality_level><use>/sim/rendering/shaders/landmass</use></quality_level>
|
||||
<tquality_level><use>/sim/rendering/shaders/transition</use></tquality_level>
|
||||
<wind_effects><use>/sim/rendering/shaders/wind-effects</use></wind_effects>
|
||||
<forest_effects><use>/sim/rendering/shaders/forest</use></forest_effects>
|
||||
<windE><use>/environment/sea/surface/wind-from-east-fps</use></windE>
|
||||
<windN><use>/environment/sea/surface/wind-from-north-fps</use></windN>
|
||||
<cloudpos1_x><use>/local-weather/cloud-shadows/cloudpos-x[0]</use></cloudpos1_x>
|
||||
|
@ -119,6 +120,7 @@
|
|||
<alpha-to-coverage>true</alpha-to-coverage>
|
||||
<program>
|
||||
<vertex-shader>Shaders/tree-haze.vert</vertex-shader>
|
||||
<vertex-shader>Shaders/noise.frag</vertex-shader>
|
||||
<vertex-shader>Shaders/cloud-shadowfunc.frag</vertex-shader>
|
||||
<fragment-shader>Shaders/tree-haze.frag</fragment-shader>
|
||||
</program>
|
||||
|
@ -427,6 +429,11 @@
|
|||
<type>int</type>
|
||||
<value><use>wind_effects</use></value>
|
||||
</uniform>
|
||||
<uniform>
|
||||
<name>forest_effects</name>
|
||||
<type>int</type>
|
||||
<value><use>forest_effects</use></value>
|
||||
</uniform>
|
||||
</pass>
|
||||
</technique>
|
||||
|
||||
|
@ -472,6 +479,7 @@
|
|||
</alpha-test>
|
||||
<program>
|
||||
<vertex-shader>Shaders/tree-haze.vert</vertex-shader>
|
||||
<vertex-shader>Shaders/noise.frag</vertex-shader>
|
||||
<vertex-shader>Shaders/cloud-shadowfunc.frag</vertex-shader>
|
||||
<fragment-shader>Shaders/tree-haze.frag</fragment-shader>
|
||||
</program>
|
||||
|
@ -780,6 +788,11 @@
|
|||
<type>int</type>
|
||||
<value><use>wind_effects</use></value>
|
||||
</uniform>
|
||||
<uniform>
|
||||
<name>forest_effects</name>
|
||||
<type>int</type>
|
||||
<value><use>forest_effects</use></value>
|
||||
</uniform>
|
||||
</pass>
|
||||
</technique>
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
<ground-haze-factor type="double" userarchive="y">1.0</ground-haze-factor>
|
||||
<aux-max-vis-range-m type="double" userarchive="y">11.69524</aux-max-vis-range-m>
|
||||
<max-vis-range-m type="double" userarchive="y">120000.0</max-vis-range-m>
|
||||
<generate-cloud-shadows type="bool" userarchive="y">0</generate-cloud-shadows>
|
||||
</config>
|
||||
<tmp>
|
||||
<tile-management type="string" userarchive="y">realistic weather</tile-management>
|
||||
|
|
|
@ -509,6 +509,10 @@ var Text = {
|
|||
{
|
||||
me.set("text", typeof(text) == 'scalar' ? text : "");
|
||||
},
|
||||
appendText: func(text)
|
||||
{
|
||||
me.set("text", (me.get("text") or "") ~ (typeof(text) == 'scalar' ? text : ""));
|
||||
},
|
||||
# Set alignment
|
||||
#
|
||||
# @param align String, one of:
|
||||
|
@ -544,10 +548,10 @@ var Text = {
|
|||
me.set("font", name);
|
||||
},
|
||||
# Enumeration of values for drawing mode:
|
||||
TEXT: 1, # The text itself
|
||||
BOUNDINGBOX: 2, # A bounding box (only lines)
|
||||
FILLEDBOUNDINGBOX: 4, # A filled bounding box
|
||||
ALIGNMENT: 8, # Draw a marker (cross) at the position of the text
|
||||
TEXT: 0x01, # The text itself
|
||||
BOUNDINGBOX: 0x02, # A bounding box (only lines)
|
||||
FILLEDBOUNDINGBOX: 0x04, # A filled bounding box
|
||||
ALIGNMENT: 0x08, # Draw a marker (cross) at the position of the text
|
||||
# Set draw mode. Binary combination of the values above. Since I haven't found
|
||||
# a bitwise or we have to use a + instead.
|
||||
#
|
||||
|
|
|
@ -99,6 +99,12 @@ DefaultStyle.widgets["scroll-area"] = {
|
|||
me.vert = me._newScroll(me.element, "vert");
|
||||
me.horiz = me._newScroll(me.element, "horiz");
|
||||
},
|
||||
setColorBackground: func
|
||||
{
|
||||
if( size(arg) == 1 )
|
||||
var arg = arg[0];
|
||||
me._bg.setColorFill(arg);
|
||||
},
|
||||
update: func(widget)
|
||||
{
|
||||
me.horiz.reset();
|
||||
|
|
|
@ -7,6 +7,8 @@ gui.widgets.ScrollArea = {
|
|||
m._active = 0;
|
||||
m._pos = [0,0];
|
||||
m._size = cfg.get("size", m._size);
|
||||
m._max_scroll = [0, 0];
|
||||
m._content_size = [0, 0];
|
||||
|
||||
if( style != nil )
|
||||
{
|
||||
|
@ -34,35 +36,79 @@ gui.widgets.ScrollArea = {
|
|||
{
|
||||
return me._scroll.content;
|
||||
},
|
||||
# Set the background color for the content area.
|
||||
#
|
||||
# @param color Vector of 3 or 4 values in [0, 1]
|
||||
setColorBackground: func
|
||||
{
|
||||
if( size(arg) == 1 )
|
||||
var arg = arg[0];
|
||||
me._scroll.setColorBackground(arg);
|
||||
},
|
||||
# Reset the size of the content area, e.g. on window resize.
|
||||
#
|
||||
# @param sz Vector of [x,y] values.
|
||||
setSize: func
|
||||
{
|
||||
if( size(arg) == 1 )
|
||||
var arg = arg[0];
|
||||
var (x,y) = arg;
|
||||
me._size = [x,y];
|
||||
me.update();
|
||||
},
|
||||
# Move the scrollable area to the coordinates x,y (or as far as possible) and
|
||||
# update.
|
||||
#
|
||||
# @param x The x coordinate (positive is right)
|
||||
# @param y The y coordinate (positive is down)
|
||||
moveTo: func(x, y)
|
||||
{
|
||||
var bb = me._updateBB();
|
||||
|
||||
me._pos[0] = math.max(0, math.min(x, me._max_scroll[0]));
|
||||
me._pos[1] = math.max(0, math.min(y, me._max_scroll[1]));
|
||||
|
||||
me.update(bb);
|
||||
},
|
||||
# Move the scrollable area to the top-most position and update.
|
||||
moveToTop: func()
|
||||
{
|
||||
me._pos[1] = 0;
|
||||
|
||||
me.update();
|
||||
},
|
||||
update: func()
|
||||
# Move the scrollable area to the bottom-most position and update.
|
||||
moveToBottom: func()
|
||||
{
|
||||
# TODO only update on content resize
|
||||
var bb = me.getContent().getTightBoundingBox();
|
||||
var bb = me._updateBB();
|
||||
|
||||
if( bb[2] < bb[0] or bb[3] < bb[1] )
|
||||
# Do nothing with invalid bounding box (probably no content yet)
|
||||
return me;
|
||||
me._pos[1] = me._max_scroll[1];
|
||||
|
||||
var w = bb[2] - bb[0];
|
||||
var h = bb[3] - bb[1];
|
||||
me.update(bb);
|
||||
},
|
||||
# Move the scrollable area to the left-most position and update.
|
||||
moveToLeft: func()
|
||||
{
|
||||
me._pos[0] = 0;
|
||||
|
||||
me._max_scroll = [0, 0];
|
||||
if( w > me._size[0] )
|
||||
me._max_scroll[0] = me._size[0] * (1 - me._size[0] / w);
|
||||
if( h > me._size[1] )
|
||||
me._max_scroll[1] = me._size[1] * (1 - me._size[1] / h);
|
||||
me.update();
|
||||
},
|
||||
# Move the scrollable area to the right-most position and update.
|
||||
moveToRight: func()
|
||||
{
|
||||
var bb = me._updateBB();
|
||||
|
||||
me._content_size = [w, h];
|
||||
me._pos[0] = me._max_scroll[0];
|
||||
|
||||
var cur_offset = me.getContent().getTranslation();
|
||||
me._content_offset = [cur_offset[0] - bb[0], cur_offset[1] - bb[1]];
|
||||
me.update(bb);
|
||||
},
|
||||
# Update scroll bar and content area.
|
||||
#
|
||||
# Needs to be called when the size of the content changes.
|
||||
update: func(bb=nil)
|
||||
{
|
||||
if (bb == nil) bb = me._updateBB();
|
||||
if (bb == nil) return me;
|
||||
|
||||
var offset = [ me._content_offset[0],
|
||||
me._content_offset[1] ];
|
||||
|
@ -78,6 +124,8 @@ gui.widgets.ScrollArea = {
|
|||
|
||||
me._scroll.update(me);
|
||||
me.getContent().update();
|
||||
|
||||
return me;
|
||||
},
|
||||
# protected:
|
||||
_setRoot: func(el)
|
||||
|
@ -90,5 +138,27 @@ gui.widgets.ScrollArea = {
|
|||
{
|
||||
me._drag_offsetX = me._pos[0] - e.clientX;
|
||||
me._drag_offsetY = me._pos[1] - e.clientY;
|
||||
}
|
||||
},
|
||||
_updateBB: func() {
|
||||
# TODO only update on content resize
|
||||
var bb = me.getContent().getTightBoundingBox();
|
||||
|
||||
if( bb[2] < bb[0] or bb[3] < bb[1] )
|
||||
return nil;
|
||||
var w = bb[2] - bb[0];
|
||||
var h = bb[3] - bb[1];
|
||||
|
||||
if( w > me._size[0] )
|
||||
me._max_scroll[0] = me._size[0] * (1 - me._size[0] / w);
|
||||
else me._max_scroll[0] = 0;
|
||||
if( h > me._size[1] )
|
||||
me._max_scroll[1] = me._size[1] * (1 - me._size[1] / h);
|
||||
else me._max_scroll[1] = 0;
|
||||
|
||||
me._content_size[0] = w;
|
||||
me._content_size[1] = h;
|
||||
|
||||
var cur_offset = me.getContent().getTranslation();
|
||||
me._content_offset = [cur_offset[0] - bb[0], cur_offset[1] - bb[1]];
|
||||
},
|
||||
};
|
||||
|
|
709
Nasal/console/repl.nas
Normal file
709
Nasal/console/repl.nas
Normal file
|
@ -0,0 +1,709 @@
|
|||
var nocolor = {
|
||||
start: func {
|
||||
me.prev = (string.color("1", "2") != "2");
|
||||
string.setcolors(0);
|
||||
}, end: func() {
|
||||
string.setcolors(me.prev);
|
||||
},
|
||||
};
|
||||
|
||||
var _REPL_dbg_level = "debug";
|
||||
#var _REPL_dbg_level = "alert";
|
||||
|
||||
var REPL = {
|
||||
df_status: 0,
|
||||
whitespace: [" ", "\t", "\n", "\r"],
|
||||
end_statement: [";", ","],
|
||||
statement_types: [
|
||||
"for", "foreach", "forindex",
|
||||
"while", "else", "func", "if", "elsif"
|
||||
],
|
||||
operators_binary_unary: [
|
||||
"~", "+", "-", "*", "/",
|
||||
"!", "?", ":", ".", ",",
|
||||
"<", ">", "="
|
||||
],
|
||||
brackets: {
|
||||
"(":")",
|
||||
"[":"]",
|
||||
"{":"}",
|
||||
},
|
||||
str_chars: ["'", '"', "`"],
|
||||
brackets_rev: {},
|
||||
brackets_start: [], brackets_end: [],
|
||||
new: func(placement, name="<repl>", keep_history=1, namespace=nil) {
|
||||
if (namespace == nil) namespace = {};
|
||||
elsif (typeof(namespace) == 'scalar') namespace = globals[namespace];
|
||||
if (typeof(namespace) != 'hash') die("bad namespace!");
|
||||
var m = {
|
||||
parents: [REPL],
|
||||
placement: placement,
|
||||
name: name,
|
||||
keep_history: keep_history,
|
||||
namespace: namespace,
|
||||
history: [],
|
||||
current: nil,
|
||||
};
|
||||
return m;
|
||||
},
|
||||
execute: func() {
|
||||
var code = string.join("\n", me.current.line);
|
||||
|
||||
me.current = nil;
|
||||
|
||||
printlog(_REPL_dbg_level, "compiling code..."~debug.string(code));
|
||||
|
||||
var fn = call(func compile(code, me.name), nil, var err=[]);
|
||||
if (size(err)) {
|
||||
var msg = err[0];
|
||||
var prefix = "Parse error: ";
|
||||
if (substr(msg, 0, size(prefix)) == prefix)
|
||||
msg = substr(msg, size(prefix));
|
||||
var (msg, line) = split(" at line ", msg);
|
||||
#debug.dump(err);
|
||||
me.placement.handle_parse_error(msg, me.name, line); # message, (file)name, line number
|
||||
return 0;
|
||||
}
|
||||
var res = call(bind(fn, globals), nil, nil, me.namespace, err);
|
||||
if (size(err)) {
|
||||
me.placement.handle_runtime_error(err); # err vec
|
||||
return 0;
|
||||
}
|
||||
me.placement.display_result(res);
|
||||
return 1;
|
||||
},
|
||||
_is_str_char: func(char) {
|
||||
foreach (var c; me.str_chars)
|
||||
if (c == char or c[0] == char) return 1;
|
||||
return 0;
|
||||
},
|
||||
_handle_level: func(level, str, line_number) {
|
||||
if (size(str) != 1)
|
||||
var str = substr(str, 0, 1);
|
||||
if (contains(me.brackets, str)) {
|
||||
append(level, str);
|
||||
printlog(_REPL_dbg_level, "> level add "~str);
|
||||
return 1;
|
||||
} elsif (contains(me.brackets_rev, str)) {
|
||||
var l = pop(level);
|
||||
if (l == nil) {
|
||||
me.placement.handle_parse_error("extra closing bracket "'"'~str~'"', me.name, line_number);
|
||||
return nil;
|
||||
} elsif (me.brackets[l] != str) {
|
||||
me.placement.handle_parse_error("bracket mismatch: "~me.brackets[l]~" vs "~str, me.name, line_number);
|
||||
return nil;
|
||||
} else {
|
||||
printlog(_REPL_dbg_level, "< level pop "~str);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
get_input: func() {
|
||||
var line = me.placement.get_line();
|
||||
if (line == nil or string.trim(line) == "") return me.df_status;
|
||||
var len = size(line);
|
||||
if (me.current == nil)
|
||||
me.current = {
|
||||
line: [],
|
||||
brackets: [],
|
||||
level: [],
|
||||
statement: nil,
|
||||
statement_level: nil,
|
||||
last_operator: nil,
|
||||
};
|
||||
for (var i=0; i<len; i+=1) {
|
||||
if (string.isxspace(line[i])) continue;
|
||||
if (size(me.current.level) and me._is_str_char(me.current.level[-1])) {
|
||||
me.current.last_operator = nil;
|
||||
if (line[i] == `\\`) {
|
||||
i += 1; # skip the next character
|
||||
printlog(_REPL_dbg_level, " skip backslash");
|
||||
} elsif (line[i] == me.current.level[-1][0]) {
|
||||
printlog(_REPL_dbg_level, "< out of string with "~me.current.level[-1]);
|
||||
pop(me.current.level);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (line[i] == `#`) {
|
||||
while(i<len and line[i] != `\n` and line[i] != `\r`) i+=1;
|
||||
continue;
|
||||
}
|
||||
if (me.current.statement != nil) {
|
||||
me.current.last_operator = nil;
|
||||
if (me.current.statement_level == size(me.current.level) and
|
||||
(line[i] == `;` or line[i] == `,`)) {
|
||||
printlog(_REPL_dbg_level, "statement ended by ;/,");
|
||||
me.current.statement = nil;
|
||||
me.current.statement_level = nil;
|
||||
} else {
|
||||
var ret = me._handle_level(me.current.level, chr(line[i]), size(me.current.line)+1);
|
||||
if (ret == nil) {# error
|
||||
me.current = nil;
|
||||
return 0;
|
||||
} elsif (me.current.statement_level > size(me.current.level)) {
|
||||
printlog(_REPL_dbg_level, "statement ended by level below");
|
||||
# cancel out of statement
|
||||
me.current.statement = nil;
|
||||
me.current.statement_level = nil;
|
||||
} elsif (line[i] == `{`) {
|
||||
# cancel out of looking for `;`, because we have a real block here
|
||||
printlog(_REPL_dbg_level, "statement ended by braces");
|
||||
me.current.statement = nil;
|
||||
me.current.statement_level = nil;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
} elsif (string.isalpha(line[i])) {
|
||||
me.current.last_operator = nil;
|
||||
foreach (var stmt; me.statement_types) {
|
||||
if (substr(line, i, size(stmt)) == stmt and
|
||||
(i+size(stmt) >= len
|
||||
or !string.isalnum(line[i+size(stmt)])
|
||||
and line[i+size(stmt)] != `_`)) {
|
||||
printlog(_REPL_dbg_level, "found: "~stmt);
|
||||
me.current.statement = stmt;
|
||||
me.current.statement_level = size(me.current.level);
|
||||
i += size(stmt)-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} elsif (me._is_str_char(line[i])) {
|
||||
me.current.last_operator = nil;
|
||||
append(me.current.level, chr(line[i]));
|
||||
printlog(_REPL_dbg_level, "> into string with "~me.current.level[-1]);
|
||||
} else {
|
||||
var ret = me._handle_level(me.current.level, chr(line[i]), size(me.current.line)+1);
|
||||
me.current.last_operator = nil;
|
||||
if (ret == nil) # error
|
||||
return 0;
|
||||
elsif (ret == 0) {
|
||||
foreach (var o; me.operators_binary_unary)
|
||||
if (line[i] == o[0])
|
||||
{ me.current.last_operator = o; printlog(_REPL_dbg_level, "found operator "~o); break }
|
||||
}
|
||||
}
|
||||
}
|
||||
append(me.current.line, line);
|
||||
if (me.keep_history)
|
||||
append(me.history, {
|
||||
type: "input",
|
||||
line: line,
|
||||
});
|
||||
var execute = (me.current.statement == nil and me.current.last_operator == nil and !size(me.current.level));
|
||||
if (execute) {
|
||||
me.df_status = 0;
|
||||
return me.execute();
|
||||
} else
|
||||
return (me.df_status = -1);
|
||||
},
|
||||
};
|
||||
foreach (var b; keys(REPL.brackets)) {
|
||||
var v = REPL.brackets[b];
|
||||
append(REPL.brackets_start, b);
|
||||
append(REPL.brackets_end, v);
|
||||
REPL.brackets_rev[v] = b;
|
||||
}
|
||||
|
||||
var CanvasPlacement = {
|
||||
instances: [],
|
||||
current_instance: nil,
|
||||
keys: [
|
||||
"ESC", "Exit/close this dialog",
|
||||
"Ctrl-d", "Same as ESC",
|
||||
"Ctrl-v", "Insert text (at the end of the current line)",
|
||||
"Ctrl-c", "Copy the current line of text",
|
||||
"Ctrl-x", "Copy and delete the current line of text",
|
||||
"Up", "Previous line in history",
|
||||
"Down", "Next line in history",
|
||||
"Left", nil,
|
||||
"Right", nil,
|
||||
"Shift+Left", nil,
|
||||
"Shift+Right", nil,
|
||||
],
|
||||
translations: {
|
||||
"bad-result": "[Error: cannot display output]",
|
||||
"key-not-mapped": "[Not Implemented]",
|
||||
"help": "Welcome to the Nasal REPL Interpreter. Press any key to "
|
||||
"exit this message, ESC to exit the dialog (at any time "
|
||||
"afterwards), and type away to test code :).\n\nNote: "
|
||||
"this dialog will capture nearly all key-presses, so don't "
|
||||
"try to fly with the keyboard while this is open!"
|
||||
"\n\nImportant keys:",
|
||||
},
|
||||
styles: {
|
||||
"default": {
|
||||
size: [600, 300],
|
||||
separate_lines: 1,
|
||||
window_style: "default",
|
||||
padding: 5,
|
||||
max_output_chars: 200,
|
||||
colors: {
|
||||
# TODO: integrate colors from debug.nas?
|
||||
text: [1,1,1],
|
||||
text_fill: nil,
|
||||
background: [0.1,0.06,0.4,0.3],
|
||||
error: [1,0.2,0.1],
|
||||
},
|
||||
font_size: 17,
|
||||
font_file: "LiberationFonts/LiberationMono-Bold.ttf",
|
||||
font_aspect_ratio: 1.5,
|
||||
font_max_width: nil,
|
||||
},
|
||||
"transparent-blue": {
|
||||
size: [600, 300],
|
||||
separate_lines: 1,
|
||||
window_style: nil,
|
||||
padding: 5,
|
||||
max_output_chars: 200,
|
||||
colors: {
|
||||
text: [1,1,1],
|
||||
text_fill: nil,
|
||||
background: [0.1,0.06,0.4,0.3],
|
||||
error: [1,0.2,0.1],
|
||||
},
|
||||
font_size: 17,
|
||||
font_file: "LiberationFonts/LiberationMono-Bold.ttf",
|
||||
font_aspect_ratio: 1.5,
|
||||
font_max_width: nil,
|
||||
},
|
||||
"transparent-red": {
|
||||
size: [600, 300],
|
||||
separate_lines: 1,
|
||||
window_style: nil,
|
||||
padding: 5,
|
||||
max_output_chars: 200,
|
||||
colors: {
|
||||
text: [1,1,1],
|
||||
text_fill: nil,
|
||||
background: [0.8,0.06,0.07,0.4],
|
||||
error: [1,0.2,0.1],
|
||||
},
|
||||
font_size: 17,
|
||||
font_file: "LiberationFonts/LiberationMono-Bold.ttf",
|
||||
font_aspect_ratio: 1.5,
|
||||
font_max_width: nil,
|
||||
},
|
||||
"canvas-default": {
|
||||
size: [600, 300],
|
||||
separate_lines: 1,
|
||||
window_style: "default",
|
||||
padding: 5,
|
||||
max_output_chars: 87,
|
||||
colors: {
|
||||
text: [0.8,0.86,0.8],
|
||||
text_fill: nil,
|
||||
background: [0.05,0.03,0.2],
|
||||
error: [1,0.2,0.1],
|
||||
},
|
||||
font_size: 17,
|
||||
font_file: "LiberationFonts/LiberationMono-Bold.ttf",
|
||||
font_aspect_ratio: 1.5,
|
||||
font_max_width: nil,
|
||||
#font_max_width: 588,
|
||||
},
|
||||
},
|
||||
new: func(name="<canvas-repl>", style="canvas-default") {
|
||||
if (typeof(style) == 'scalar') {
|
||||
style = CanvasPlacement.styles[style];
|
||||
}
|
||||
if (typeof(style) != 'hash') die("bad style");
|
||||
var m = {
|
||||
parents: [CanvasPlacement, style],
|
||||
state: "startup",
|
||||
listeners: [],
|
||||
window: canvas.Window.new(style.size, style.window_style, "REPL-interpreter-"~name),
|
||||
lines_of_text: [],
|
||||
history: [],
|
||||
curr: 0,
|
||||
coloring: {parents:[nocolor]},
|
||||
completion_pos: 0,
|
||||
};
|
||||
m.window.set("title", "Nasal REPL Interpreter");
|
||||
#debug.dump(m.window._node);
|
||||
m.window.del = func() {
|
||||
delete(me, "del");
|
||||
me.del(); # inherited canvas.Window.del();
|
||||
m.window = nil;
|
||||
m.del();
|
||||
};
|
||||
if (m.window_style != nil) {
|
||||
m.window.setBool("resize", 1);
|
||||
m.window.onResize = func() {
|
||||
call(canvas.Window.onResize, nil, me);
|
||||
var sz = [nil,nil];
|
||||
for (var i=0; i<2; i+=1)
|
||||
sz[i] = me.get("content-size[" ~ i ~ "]");
|
||||
m.scroll.setSize(sz);
|
||||
};
|
||||
}
|
||||
m.canvas = m.window.createCanvas()
|
||||
.setColorBackground(m.colors.background);
|
||||
m.group = m.canvas.createGroup("content");
|
||||
m.scroll = canvas.gui.widgets
|
||||
. ScrollArea.new(m.group, canvas.style, {"size":m.size})
|
||||
.move(0, 0);
|
||||
m.scroll.setColorBackground(m.colors.background);
|
||||
m.window.addWidget(m.scroll);
|
||||
m.group = m.scroll.getContent();
|
||||
m.create_msg();
|
||||
m.text_group = m.group.createChild("group", "text-display");
|
||||
m.text = nil;
|
||||
m.cursor = m.group.createChild("path")
|
||||
.moveTo(0, -m.padding)
|
||||
.lineTo(0, -11-m.padding)
|
||||
.setStrokeLineWidth(2)
|
||||
.setColor(m.colors.text);
|
||||
m.repl = REPL.new(placement:m, name:name);
|
||||
append(m.listeners, setlistener("/devices/status/keyboard/event", func(event) {
|
||||
if (!event.getNode("pressed").getValue())
|
||||
return;
|
||||
var key = (var keyN = event.getNode("key", 1)).getValue();
|
||||
if (key == nil or key == -1) return;
|
||||
if (m.handle_key(key, event.getNode("modifier").getValues()))
|
||||
keyN.setValue(-1); # drop key event
|
||||
}));
|
||||
m.scroll.update(); # initialize ScrollArea._max_scroll member
|
||||
m.update();
|
||||
append(CanvasPlacement.instances, m);
|
||||
return m;
|
||||
},
|
||||
del: func() {
|
||||
if (me.window != nil)
|
||||
{ me.window.del(); me.window = nil }
|
||||
foreach (var l; me.listeners)
|
||||
removelistener(l);
|
||||
setsize(me.listeners, 0);
|
||||
},
|
||||
add_char: func(char) {
|
||||
me.reset_input_from_history();
|
||||
me.input ~= chr(char);
|
||||
me.text.appendText(chr(char));
|
||||
return nil;
|
||||
},
|
||||
add_text: func(text) {
|
||||
me.reset_input_from_history();
|
||||
me.input ~= text;
|
||||
me.text.appendText(text);
|
||||
return nil;
|
||||
},
|
||||
remove_char: func() {
|
||||
me.reset_input_from_history();
|
||||
me.input = substr(me.input, 0, size(me.input) - 1);
|
||||
var t = me.text.get("text");
|
||||
if (size(t) <= me.text.stop) return nil;
|
||||
me.text.setText(substr(t, 0, size(t)-1));
|
||||
return t[-1];
|
||||
},
|
||||
clear_input: func() {
|
||||
me.reset_input_from_history();
|
||||
var ret = me.input;
|
||||
me.input = "";
|
||||
var t = me.text.get("text");
|
||||
me.text.setText(substr(t, 0, me.text.stop));
|
||||
return ret;
|
||||
},
|
||||
replace_line: func(replacement, replace_input=1) {
|
||||
if (replace_input) me.input = replacement;
|
||||
var t = me.text.get("text");
|
||||
me.text.setText(substr(t, 0, me.text.stop)~replacement);
|
||||
return nil;
|
||||
},
|
||||
add_line: func(text) {
|
||||
me.create_line();
|
||||
me.text.appendText(text);
|
||||
},
|
||||
set_line_color: func(color) {
|
||||
if (me.separate_lines)
|
||||
# Only change colors if this is its own line
|
||||
me.text.setColor(color);
|
||||
},
|
||||
clear: func() {
|
||||
me.text.del();
|
||||
foreach (var t; me.lines_of_text)
|
||||
t.del();
|
||||
setsize(me.history, 0);
|
||||
me.curr = 0;
|
||||
me.input = "";
|
||||
me.text = nil;
|
||||
setsize(me.lines_of_text, 0);
|
||||
},
|
||||
create_msg: func() {
|
||||
# Text drawing mode: text and maybe a bounding box
|
||||
var draw_mode = canvas.Text.TEXT + (me.colors.text_fill != nil ? canvas.Text.FILLEDBOUNDINGBOX : 0);
|
||||
|
||||
me.msg = me.group.createChild("group", "startup-message");
|
||||
me.msg.text = me.msg.createChild("text", "help")
|
||||
.setTranslation(me.padding, me.padding+10)
|
||||
.setAlignment("left-baseline")
|
||||
.setFontSize(me.font_size, me.font_aspect_ratio)
|
||||
.setFont(me.font_file)
|
||||
.setColor(me.colors.text)
|
||||
.setDrawMode(draw_mode)
|
||||
.setMaxWidth(me.window.get("content-size[0]") - me.padding)
|
||||
.setText(me.translations["help"]);
|
||||
if (me.colors.text_fill != nil)
|
||||
me.msg.text.setColorFill(me.colors.text_fill);
|
||||
me.msg.text.update();
|
||||
#debug.dump(me.msg.text.getTransformedBounds());
|
||||
me.msg.left_col = me.msg.createChild("text", "keys")
|
||||
.setTranslation(me.padding, me.msg.text.getTransformedBounds()[3] + 30)
|
||||
.setAlignment("left-baseline")
|
||||
.setFontSize(me.font_size, me.font_aspect_ratio)
|
||||
.setFont(me.font_file)
|
||||
.setColor(me.colors.text)
|
||||
.setDrawMode(draw_mode);
|
||||
if (me.colors.text_fill != nil)
|
||||
me.msg.left_col.setColorFill(me.colors.text_fill);
|
||||
me.msg.left_col.update();
|
||||
for (var i=0; i<size(me.keys); i+=2) {
|
||||
if (i) me.msg.left_col.appendText("\n");
|
||||
me.msg.left_col.appendText("- "~me.keys[i]);
|
||||
}
|
||||
#debug.dump(me.msg.left_col.getTransformedBounds());
|
||||
me.msg.right_col = me.msg.createChild("text", "keys")
|
||||
.setTranslation(me.msg.left_col.getTransformedBounds()[2] + 20,
|
||||
me.msg.text.getTransformedBounds()[3] + 30)
|
||||
.setAlignment("left-baseline")
|
||||
.setFontSize(me.font_size, me.font_aspect_ratio)
|
||||
.setFont(me.font_file)
|
||||
.setColor(me.colors.text)
|
||||
.setDrawMode(draw_mode);
|
||||
if (me.colors.text_fill != nil)
|
||||
me.msg.right_col.setColorFill(me.colors.text_fill);
|
||||
for (var i=0; i<size(me.keys); i+=2) {
|
||||
if (i) me.msg.right_col.appendText("\n");
|
||||
desc = me.keys[i+1];
|
||||
if (desc == nil) desc = me.translations["key-not-mapped"];
|
||||
elsif (desc[-1] != `.`) desc ~= ".";
|
||||
me.msg.right_col.appendText(desc);
|
||||
}
|
||||
},
|
||||
create_line: func() {
|
||||
# c.f. above, in me.create_msg()
|
||||
var draw_mode = canvas.Text.TEXT + (me.colors.text_fill != nil ? canvas.Text.FILLEDBOUNDINGBOX : 0);
|
||||
|
||||
me.input = "";
|
||||
# If we only use one line, and one exists, things are simple:
|
||||
if (!me.separate_lines and me.text != nil) {
|
||||
me.text.appendText("\n");
|
||||
return;
|
||||
}
|
||||
# Else, we have to create a new line
|
||||
if (me.text != nil)
|
||||
append(me.lines_of_text, me.text);
|
||||
me.text = me.text_group
|
||||
.createChild("text", "input"~size(me.lines_of_text))
|
||||
.setAlignment("left-baseline")
|
||||
.setFontSize(me.font_size, me.font_aspect_ratio)
|
||||
.setFont(me.font_file)
|
||||
.setColor(me.colors.text)
|
||||
.setDrawMode(draw_mode)
|
||||
.setText(size(me.lines_of_text) ? ">" : ""); # FIXME: hack, canvas::Text needs a printing character
|
||||
# on the first line in order to recognize the newlines ?
|
||||
if (me.colors.text_fill != nil)
|
||||
me.text.setColorFill(me.colors.text_fill);
|
||||
if (me.font_max_width != nil)
|
||||
if (me.font_max_width < 0)
|
||||
me.text.setMaxWidth(me.window.get("content-size[0]") - me.font_max_width);
|
||||
else
|
||||
me.text.setMaxWidth(me.font_max_width);
|
||||
|
||||
foreach (var t; me.lines_of_text)
|
||||
me.text.appendText("\n");
|
||||
},
|
||||
update: func() {
|
||||
#debug.dump(me.text.getTransformedBounds());
|
||||
if (me.state == "startup") return;
|
||||
me.cursor.setTranslation(
|
||||
me.text.getTransformedBounds()[2] + 6,
|
||||
me.text.getTransformedBounds()[3] + 5
|
||||
);
|
||||
me.scroll.update();
|
||||
},
|
||||
new_line: func() {
|
||||
me.create_line();
|
||||
me.text.appendText(">>> ");
|
||||
me.text.stop = size(me.text.get("text"));
|
||||
me.reset_view();
|
||||
},
|
||||
continue_line: func() {
|
||||
me.create_line();
|
||||
me.text.appendText("... ");
|
||||
me.text.stop = size(me.text.get("text"));
|
||||
me.reset_view();
|
||||
},
|
||||
reset_input_from_history: func() {
|
||||
if (me.curr < size(me.history)) {
|
||||
me.input = me.history[me.curr];
|
||||
me.curr = size(me.history);
|
||||
}
|
||||
me.reset_view();
|
||||
},
|
||||
reset_view: func() {
|
||||
me.group.update();
|
||||
me.scroll.moveToLeft().moveToBottom();
|
||||
},
|
||||
handle_key: func(key, modifiers) {
|
||||
var modifier_str = "";
|
||||
foreach (var m; keys(modifiers)) {
|
||||
if (modifiers[m])
|
||||
modifier_str ~= substr(m,0,1);
|
||||
}
|
||||
if (me.state == "startup") {
|
||||
me.msg.del(); me.msg = nil;
|
||||
me.new_line(); # initialize a new line
|
||||
me.text.stop = size(me.text.get("text"));
|
||||
me.state = "accepting input";
|
||||
|
||||
} elsif (!contains({"s":,"c":,"":}, modifier_str)) {
|
||||
return 0; # had extra modifiers, reject this event
|
||||
|
||||
} elsif (modifiers.ctrl) {
|
||||
if (key == 13) { # ctrl+c
|
||||
printlog(_REPL_dbg_level, "ctrl+c: "~debug.string(me.input));
|
||||
me.reset_input_from_history();
|
||||
if( size(me.input) and !clipboard.setText(me.input) )
|
||||
print("Failed to write to clipboard");
|
||||
} elsif (key == 24) { # ctrl+x
|
||||
printlog(_REPL_dbg_level, "ctrl+x");
|
||||
me.reset_input_from_history();
|
||||
if( size(me.input) and !clipboard.setText(me.clear_input()) )
|
||||
print("Failed to write to clipboard");
|
||||
} elsif (key == 22) { # ctrl+v
|
||||
var input = clipboard.getText();
|
||||
printlog(_REPL_dbg_level, "ctrl+v: "~debug.string(input));
|
||||
me.reset_input_from_history();
|
||||
for (var i=0; i<size(input); i+=1) {
|
||||
if (input[i] == `\t`) {
|
||||
# replace tabs with spaces
|
||||
me.handle_key(` `, {shift:0, ctrl:0});
|
||||
} elsif (string.isascii(input[i])) {
|
||||
me.handle_key(input[i], {shift:0, ctrl:0});
|
||||
}
|
||||
}
|
||||
} elsif (key == 4) { # ctrl-D/EOF
|
||||
printlog(_REPL_dbg_level, "EOF");
|
||||
me.del();
|
||||
return 1;
|
||||
} else return 0;
|
||||
|
||||
} elsif (key == `\n` or key == `\r`) {
|
||||
printlog(_REPL_dbg_level, "return (key: "~key~", shift: "~modifiers.shift~")");
|
||||
me.reset_input_from_history();
|
||||
if (modifiers.shift) {
|
||||
var res = -1;
|
||||
me.input ~= "\n";
|
||||
} else {
|
||||
if (size(string.trim(me.input))) {
|
||||
append(me.history, me.input);
|
||||
me.curr += 1; # simplified version of: me.curr = size(me.history);
|
||||
if (me.curr != size(me.history)) die(me.curr~" vs "~size(me.history));
|
||||
}
|
||||
CanvasPlacement.current_instance = me;
|
||||
var res = me.repl.get_input();
|
||||
CanvasPlacement.current_instance = nil;
|
||||
printlog(_REPL_dbg_level, "return code: "~debug.string(res));
|
||||
}
|
||||
if (res == -1)
|
||||
me.continue_line();
|
||||
else me.new_line();
|
||||
|
||||
} elsif (key == 8) { # backspace
|
||||
printlog(_REPL_dbg_level, "back");
|
||||
me.reset_input_from_history();
|
||||
if (me.remove_char() == nil) return 1; # nothing happened, since the input
|
||||
# field was blank, but capture the event
|
||||
me.completion_pos = -1;
|
||||
|
||||
} elsif (key == 357) { # up
|
||||
printlog(_REPL_dbg_level, "up");
|
||||
if (me.curr == 0) return 1;
|
||||
me.curr -= 1;
|
||||
if (me.curr == size(me.history))
|
||||
me.replace_line(me.input, 0);
|
||||
else
|
||||
me.replace_line(me.history[me.curr], 0);
|
||||
me.completion_pos = -1;
|
||||
|
||||
} elsif (key == 359) { # down
|
||||
printlog(_REPL_dbg_level, "down");
|
||||
if (me.curr == size(me.history)) return 1;
|
||||
me.curr += 1;
|
||||
if (me.curr == size(me.history))
|
||||
me.replace_line(me.input, 0);
|
||||
else
|
||||
me.replace_line(me.history[me.curr], 0);
|
||||
me.completion_pos = -1;
|
||||
|
||||
} elsif (key == 27) { # escape -> cancel
|
||||
printlog(_REPL_dbg_level, "esc");
|
||||
me.del();
|
||||
return 1;
|
||||
|
||||
} elsif (key == `\t`) { # tab
|
||||
printlog(_REPL_dbg_level, "tab");
|
||||
return 0;
|
||||
me.reset_input_from_history();
|
||||
if (size(text) and text[0] == `/`) {
|
||||
me.input = me.complete(me.input, modifiers.shift ? -1 : 1);
|
||||
}
|
||||
|
||||
} elsif (!string.isprint(key)) {
|
||||
printlog(_REPL_dbg_level, "other key: "~key);
|
||||
return 0; # pass other funny events
|
||||
|
||||
} else {
|
||||
printlog(_REPL_dbg_level, "key: "~key~" (`"~chr(key)~"`)");
|
||||
me.reset_input_from_history();
|
||||
me.add_char(key);
|
||||
me.completion_pos = -1;
|
||||
}
|
||||
|
||||
#printlog(_REPL_dbg_level, " -> "~me.input);
|
||||
|
||||
me.update();
|
||||
|
||||
return 1; # discard key event
|
||||
},
|
||||
get_line: func() {
|
||||
return me.input;
|
||||
},
|
||||
display_result: func(res=nil) {
|
||||
if (res == nil) return 1; # don't display NULL results
|
||||
me.coloring.start();
|
||||
var res = call(debug.string, [res], var err=[]);
|
||||
if (size(err)) {
|
||||
me.add_line(me.translations["bad-result"] or die("no translation"));
|
||||
me.set_line_color(me.colors.error);
|
||||
if (me.font_file == "LiberationFonts/LiberationMono-Bold.ttf")
|
||||
me.text.setFont("LiberationFonts/LiberationMono-BoldItalic.ttf");
|
||||
return 1;
|
||||
}
|
||||
me.coloring.end();
|
||||
if (size(res) > me.max_output_chars)
|
||||
res = substr(res, 0, me.max_output_chars-5)~". . .";
|
||||
me.add_line(res);
|
||||
return 1;
|
||||
},
|
||||
handle_runtime_error: func(err) {
|
||||
debug.printerror(err);
|
||||
me.add_line("Runtime error: "~err[0]);
|
||||
me.set_line_color(me.colors.error);
|
||||
for (var i=1; i<size(err); i+=2) {
|
||||
me.add_line(" at "~err[i]~", line "~err[i+1]);
|
||||
}
|
||||
},
|
||||
handle_parse_error: func(msg, file, line) {
|
||||
print("Parse error: "~msg~" on line "~line~" in "~file);
|
||||
me.add_line("Parse error: "~msg~" on line "~line~" in "~file);
|
||||
me.set_line_color(me.colors.error);
|
||||
},
|
||||
};
|
||||
|
||||
var print2 = func(i) {
|
||||
console.CanvasPlacement.current_instance.display_result(i);
|
||||
return nil; # just to suppress output
|
||||
}
|
||||
#CanvasPlacement.new("<styled-canvas-repl>", "canvas-default");
|
||||
|
|
@ -218,7 +218,7 @@ var string = func(o) {
|
|||
return _nil("nil");
|
||||
|
||||
} elsif (t == "scalar") {
|
||||
return num(o) == nil ? _dump_string(o) : _num(o);
|
||||
return num(o) == nil ? _dump_string(o) : _num(o~"");
|
||||
|
||||
} elsif (t == "vector") {
|
||||
var s = "";
|
||||
|
|
|
@ -1867,6 +1867,15 @@ if (edge_bias > 0.0) {height_bias = height_bias + 15.0 *edge_bias + 20.0 * rand
|
|||
y = 200.0;
|
||||
edge = 1.0;
|
||||
create_streak(type,lat,lon, alt+ 0.5* (height*height_bias )-offset_map["Cumulus"], height * height_bias,n,0.0,edge,x,1,0.0,0.0,y,alpha,1.0);
|
||||
|
||||
if (local_weather.cloud_shadow_flag == 1)
|
||||
{
|
||||
var cs = local_weather.cloudShadow.new(lat, lon, 0.9 * (1.5 * x)/5000.0 , 0.7);
|
||||
cs.index = getprop(lw~"tiles/tile-counter");
|
||||
append(cloudShadowCandidateArray,cs);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
else if (size>0.4)
|
||||
|
@ -1881,6 +1890,15 @@ if (edge_bias > 0.0) {height_bias = height_bias + 15.0 *edge_bias + 20.0 * rand
|
|||
var alpha = rand() * 180.0;
|
||||
edge = edge + edge_bias;
|
||||
create_streak(type,lat,lon, alt+ 0.5* (height * height_bias)-offset_map["Cumulus"], height * height_bias,n,0.0,edge,x,1,0.0,0.0,y,alpha,1.0);
|
||||
|
||||
if (local_weather.cloud_shadow_flag == 1)
|
||||
{
|
||||
var cs = local_weather.cloudShadow.new(lat, lon, 0.9 * (1.0 * x)/5000.0 , 0.6);
|
||||
cs.index = getprop(lw~"tiles/tile-counter");
|
||||
append(cloudShadowCandidateArray,cs);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4012,7 +4030,7 @@ weather_tile_management.create_impostors();
|
|||
|
||||
# start the cloud shadow loop
|
||||
|
||||
local_weather.cloud_shadow_flag = getprop("/local-weather/cloud-shadows/cloud-shadow-flag");
|
||||
local_weather.cloud_shadow_flag = getprop("/local-weather/config/generate-cloud-shadows");
|
||||
|
||||
if (local_weather.cloud_shadow_flag == 1)
|
||||
{
|
||||
|
|
|
@ -1279,7 +1279,17 @@ var s = size(active_tile_list);
|
|||
# don't do anything as long as the array is empty
|
||||
|
||||
if (n_max == 0) # nothing to do, loop over
|
||||
{if (getprop(lw~"shadow-loop-flag") ==1) {settimer( func {shadow_management_loop(index)}, 0);} return;}
|
||||
{
|
||||
setprop("/local-weather/cloud-shadows/cloud-shadow-flag",0);
|
||||
if (getprop(lw~"shadow-loop-flag") ==1) {settimer( func {shadow_management_loop(index)}, 0);}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
setprop("/local-weather/cloud-shadows/cloud-shadow-flag",1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
# compute some general-purpose stuff for the loop
|
||||
|
||||
|
@ -1374,7 +1384,7 @@ foreach(s; cloudShadowArray)
|
|||
if (dist > dist_max) {dist_max = dist; index_max = counter;}
|
||||
|
||||
setprop("/local-weather/cloud-shadows/cloudpos-x["~counter~"]",int(diffx) + s.size);
|
||||
setprop("/local-weather/cloud-shadows/cloudpos-y["~counter~"]",int(diffy) + 0.9 );
|
||||
setprop("/local-weather/cloud-shadows/cloudpos-y["~counter~"]",int(diffy) + s.strength );
|
||||
counter = counter+1;
|
||||
}
|
||||
#print("Dist_max:", dist_max, " index_max: ", index_max);
|
||||
|
|
|
@ -122,6 +122,8 @@ var handle_key = func(key, shift) {
|
|||
handle_key(`/`, 0);
|
||||
} else {
|
||||
input = text = substr(text, 0, size(text) - 1);
|
||||
if (text == "")
|
||||
stop(); # nothing in our field? close the dialog
|
||||
}
|
||||
completion_pos = -1;
|
||||
|
||||
|
|
|
@ -128,11 +128,10 @@ dlength = length ( vec2 (x - cloudpos20_x, y - cloudpos20_y));
|
|||
width = fract((cloudpos20_x)) * 5000.0; strength = fract((cloudpos20_y));
|
||||
shadeValue = shadeValue + strength * (1.0-smoothstep(width * 0.5, width, dlength));
|
||||
|
||||
shadeValue = clamp(shadeValue * (0.5 + 2.0 * noise),0.0,1.0);
|
||||
|
||||
shadeValue = shadeValue * (0.8 + 2.0 * shadeValue * smoothstep(0.4,0.6,noise));
|
||||
shadeValue = clamp(shadeValue,0.0,1.0);
|
||||
shadeValue = shadeValue * (1.0 - smoothstep(15000.0, 30000.0,dist));
|
||||
//shadeValue = clamp(shadeValue * (0.5 + 0.5 * noise),0.0,1.0);
|
||||
|
||||
return 1.0 - shadeValue;// exp(- (dlength * dlength)/(width*width));
|
||||
return 1.0 - shadeValue;
|
||||
|
||||
}
|
||||
|
|
192
Shaders/noise.frag
Normal file
192
Shaders/noise.frag
Normal file
|
@ -0,0 +1,192 @@
|
|||
// -*-C++-*-
|
||||
|
||||
// This is a library of noise functions, taking a coordinate vector and a wavelength
|
||||
// as input and returning a number [0:1] as output.
|
||||
|
||||
// * Noise2D(in vec2 coord, in float wavelength) is 2d Perlin noise
|
||||
// * Noise3D(in vec3 coord, in float wavelength) is 3d Perlin noise
|
||||
// * DotNoise2D(in vec2 coord, in float wavelength, in float fractionalMaxDotSize, in float dDensity)
|
||||
// is sparse dot noise and takes a dot density parameter
|
||||
// * VoronoiNoise2D(in vec2 coord, in float wavelength, in float xrand, in float yrand)
|
||||
// is a function mapping the terrain into random domains, based on Voronoi tiling of a regular grid
|
||||
// distorted with xrand and yrand
|
||||
|
||||
// Thorsten Renk 2014
|
||||
|
||||
#version 120
|
||||
|
||||
|
||||
float rand2D(in vec2 co){
|
||||
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
|
||||
}
|
||||
|
||||
float rand3D(in vec3 co){
|
||||
return fract(sin(dot(co.xyz ,vec3(12.9898,78.233,144.7272))) * 43758.5453);
|
||||
}
|
||||
|
||||
float cosine_interpolate(in float a, in float b, in float x)
|
||||
{
|
||||
float ft = x * 3.1415927;
|
||||
float f = (1.0 - cos(ft)) * .5;
|
||||
|
||||
return a*(1.0-f) + b*f;
|
||||
}
|
||||
|
||||
float simple_interpolate(in float a, in float b, in float x)
|
||||
{
|
||||
return a + smoothstep(0.0,1.0,x) * (b-a);
|
||||
}
|
||||
|
||||
float interpolatedNoise2D(in float x, in float y)
|
||||
{
|
||||
float integer_x = x - fract(x);
|
||||
float fractional_x = x - integer_x;
|
||||
|
||||
float integer_y = y - fract(y);
|
||||
float fractional_y = y - integer_y;
|
||||
|
||||
float v1 = rand2D(vec2(integer_x, integer_y));
|
||||
float v2 = rand2D(vec2(integer_x+1.0, integer_y));
|
||||
float v3 = rand2D(vec2(integer_x, integer_y+1.0));
|
||||
float v4 = rand2D(vec2(integer_x+1.0, integer_y +1.0));
|
||||
|
||||
float i1 = simple_interpolate(v1 , v2 , fractional_x);
|
||||
float i2 = simple_interpolate(v3 , v4 , fractional_x);
|
||||
|
||||
return simple_interpolate(i1 , i2 , fractional_y);
|
||||
}
|
||||
|
||||
float interpolatedNoise3D(in float x, in float y, in float z)
|
||||
{
|
||||
float integer_x = x - fract(x);
|
||||
float fractional_x = x - integer_x;
|
||||
|
||||
float integer_y = y - fract(y);
|
||||
float fractional_y = y - integer_y;
|
||||
|
||||
float integer_z = z - fract(z);
|
||||
float fractional_z = z - integer_z;
|
||||
|
||||
float v1 = rand3D(vec3(integer_x, integer_y, integer_z));
|
||||
float v2 = rand3D(vec3(integer_x+1.0, integer_y, integer_z));
|
||||
float v3 = rand3D(vec3(integer_x, integer_y+1.0, integer_z));
|
||||
float v4 = rand3D(vec3(integer_x+1.0, integer_y +1.0, integer_z));
|
||||
|
||||
float v5 = rand3D(vec3(integer_x, integer_y, integer_z+1.0));
|
||||
float v6 = rand3D(vec3(integer_x+1.0, integer_y, integer_z+1.0));
|
||||
float v7 = rand3D(vec3(integer_x, integer_y+1.0, integer_z+1.0));
|
||||
float v8 = rand3D(vec3(integer_x+1.0, integer_y +1.0, integer_z+1.0));
|
||||
|
||||
|
||||
float i1 = simple_interpolate(v1,v5, fractional_z);
|
||||
float i2 = simple_interpolate(v2,v6, fractional_z);
|
||||
float i3 = simple_interpolate(v3,v7, fractional_z);
|
||||
float i4 = simple_interpolate(v4,v8, fractional_z);
|
||||
|
||||
float ii1 = simple_interpolate(i1,i2,fractional_x);
|
||||
float ii2 = simple_interpolate(i3,i4,fractional_x);
|
||||
|
||||
|
||||
return simple_interpolate(ii1 , ii2 , fractional_y);
|
||||
}
|
||||
|
||||
|
||||
float Noise2D(in vec2 coord, in float wavelength)
|
||||
{
|
||||
return interpolatedNoise2D(coord.x/wavelength, coord.y/wavelength);
|
||||
|
||||
}
|
||||
|
||||
float Noise3D(in vec3 coord, in float wavelength)
|
||||
{
|
||||
return interpolatedNoise3D(coord.x/wavelength, coord.y/wavelength, coord.z/wavelength);
|
||||
}
|
||||
|
||||
float dotNoise2D(in float x, in float y, in float fractionalMaxDotSize, in float dDensity)
|
||||
{
|
||||
float integer_x = x - fract(x);
|
||||
float fractional_x = x - integer_x;
|
||||
|
||||
float integer_y = y - fract(y);
|
||||
float fractional_y = y - integer_y;
|
||||
|
||||
if (rand2D(vec2(integer_x+1.0, integer_y +1.0)) > dDensity)
|
||||
{return 0.0;}
|
||||
|
||||
float xoffset = (rand2D(vec2(integer_x, integer_y)) -0.5);
|
||||
float yoffset = (rand2D(vec2(integer_x+1.0, integer_y)) - 0.5);
|
||||
float dotSize = 0.5 * fractionalMaxDotSize * max(0.25,rand2D(vec2(integer_x, integer_y+1.0)));
|
||||
|
||||
|
||||
vec2 truePos = vec2 (0.5 + xoffset * (1.0 - 2.0 * dotSize) , 0.5 + yoffset * (1.0 -2.0 * dotSize));
|
||||
|
||||
float distance = length(truePos - vec2(fractional_x, fractional_y));
|
||||
|
||||
return 1.0 - smoothstep (0.3 * dotSize, 1.0* dotSize, distance);
|
||||
}
|
||||
|
||||
float DotNoise2D(in vec2 coord, in float wavelength, in float fractionalMaxDotSize, in float dDensity)
|
||||
{
|
||||
return dotNoise2D(coord.x/wavelength, coord.y/wavelength, fractionalMaxDotSize, dDensity);
|
||||
}
|
||||
|
||||
|
||||
float voronoiNoise2D(in float x, in float y, in float xrand, in float yrand)
|
||||
{
|
||||
float integer_x = x - fract(x);
|
||||
float fractional_x = x - integer_x;
|
||||
|
||||
float integer_y = y - fract(y);
|
||||
float fractional_y = y - integer_y;
|
||||
|
||||
float val[4];
|
||||
|
||||
val[0] = rand2D(vec2(integer_x, integer_y));
|
||||
val[1] = rand2D(vec2(integer_x+1.0, integer_y));
|
||||
val[2] = rand2D(vec2(integer_x, integer_y+1.0));
|
||||
val[3] = rand2D(vec2(integer_x+1.0, integer_y+1.0));
|
||||
|
||||
float xshift[4];
|
||||
|
||||
xshift[0] = xrand * (rand2D(vec2(integer_x+0.5, integer_y)) - 0.5);
|
||||
xshift[1] = xrand * (rand2D(vec2(integer_x+1.5, integer_y)) -0.5);
|
||||
xshift[2] = xrand * (rand2D(vec2(integer_x+0.5, integer_y+1.0))-0.5);
|
||||
xshift[3] = xrand * (rand2D(vec2(integer_x+1.5, integer_y+1.0))-0.5);
|
||||
|
||||
float yshift[4];
|
||||
|
||||
yshift[0] = yrand * (rand2D(vec2(integer_x, integer_y +0.5)) - 0.5);
|
||||
yshift[1] = yrand * (rand2D(vec2(integer_x+1.0, integer_y+0.5)) -0.5);
|
||||
yshift[2] = yrand * (rand2D(vec2(integer_x, integer_y+1.5))-0.5);
|
||||
yshift[3] = yrand * (rand2D(vec2(integer_x+1.5, integer_y+1.5))-0.5);
|
||||
|
||||
|
||||
float dist[4];
|
||||
|
||||
dist[0] = sqrt((fractional_x + xshift[0]) * (fractional_x + xshift[0]) + (fractional_y + yshift[0]) * (fractional_y + yshift[0]));
|
||||
dist[1] = sqrt((1.0 -fractional_x + xshift[1]) * (1.0-fractional_x+xshift[1]) + (fractional_y +yshift[1]) * (fractional_y+yshift[1]));
|
||||
dist[2] = sqrt((fractional_x + xshift[2]) * (fractional_x + xshift[2]) + (1.0-fractional_y +yshift[2]) * (1.0-fractional_y + yshift[2]));
|
||||
dist[3] = sqrt((1.0-fractional_x + xshift[3]) * (1.0-fractional_x + xshift[3]) + (1.0-fractional_y +yshift[3]) * (1.0-fractional_y + yshift[3]));
|
||||
|
||||
|
||||
|
||||
int i, i_min;
|
||||
float dist_min = 100.0;
|
||||
for (i=0; i<4;i++)
|
||||
{
|
||||
if (dist[i] < dist_min)
|
||||
{
|
||||
dist_min = dist[i];
|
||||
i_min = i;
|
||||
}
|
||||
}
|
||||
|
||||
return val[i_min];
|
||||
//return val[0];
|
||||
|
||||
}
|
||||
|
||||
float VoronoiNoise2D(in vec2 coord, in float wavelength, in float xrand, in float yrand)
|
||||
{
|
||||
return voronoiNoise2D(coord.x/wavelength, coord.y/wavelength, xrand, yrand);
|
||||
}
|
|
@ -69,120 +69,12 @@ float yprime_alt;
|
|||
float mie_angle;
|
||||
|
||||
float shadow_func (in float x, in float y, in float noise, in float dist);
|
||||
|
||||
float rand2D(in vec2 co){
|
||||
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
|
||||
}
|
||||
|
||||
float rand3D(in vec3 co){
|
||||
return fract(sin(dot(co.xyz ,vec3(12.9898,78.233,144.7272))) * 43758.5453);
|
||||
}
|
||||
|
||||
float cosine_interpolate(in float a, in float b, in float x)
|
||||
{
|
||||
float ft = x * 3.1415927;
|
||||
float f = (1.0 - cos(ft)) * .5;
|
||||
|
||||
return a*(1.0-f) + b*f;
|
||||
}
|
||||
|
||||
float simple_interpolate(in float a, in float b, in float x)
|
||||
{
|
||||
return a + smoothstep(0.0,1.0,x) * (b-a);
|
||||
}
|
||||
|
||||
float interpolatedNoise2D(in float x, in float y)
|
||||
{
|
||||
float integer_x = x - fract(x);
|
||||
float fractional_x = x - integer_x;
|
||||
|
||||
float integer_y = y - fract(y);
|
||||
float fractional_y = y - integer_y;
|
||||
|
||||
float v1 = rand2D(vec2(integer_x, integer_y));
|
||||
float v2 = rand2D(vec2(integer_x+1.0, integer_y));
|
||||
float v3 = rand2D(vec2(integer_x, integer_y+1.0));
|
||||
float v4 = rand2D(vec2(integer_x+1.0, integer_y +1.0));
|
||||
|
||||
float i1 = simple_interpolate(v1 , v2 , fractional_x);
|
||||
float i2 = simple_interpolate(v3 , v4 , fractional_x);
|
||||
|
||||
return simple_interpolate(i1 , i2 , fractional_y);
|
||||
}
|
||||
|
||||
float interpolatedNoise3D(in float x, in float y, in float z)
|
||||
{
|
||||
float integer_x = x - fract(x);
|
||||
float fractional_x = x - integer_x;
|
||||
|
||||
float integer_y = y - fract(y);
|
||||
float fractional_y = y - integer_y;
|
||||
|
||||
float integer_z = z - fract(z);
|
||||
float fractional_z = z - integer_z;
|
||||
|
||||
float v1 = rand3D(vec3(integer_x, integer_y, integer_z));
|
||||
float v2 = rand3D(vec3(integer_x+1.0, integer_y, integer_z));
|
||||
float v3 = rand3D(vec3(integer_x, integer_y+1.0, integer_z));
|
||||
float v4 = rand3D(vec3(integer_x+1.0, integer_y +1.0, integer_z));
|
||||
|
||||
float v5 = rand3D(vec3(integer_x, integer_y, integer_z+1.0));
|
||||
float v6 = rand3D(vec3(integer_x+1.0, integer_y, integer_z+1.0));
|
||||
float v7 = rand3D(vec3(integer_x, integer_y+1.0, integer_z+1.0));
|
||||
float v8 = rand3D(vec3(integer_x+1.0, integer_y +1.0, integer_z+1.0));
|
||||
float DotNoise2D(in vec2 coord, in float wavelength, in float fractionalMaxDotSize, in float dot_density);
|
||||
float Noise2D(in vec2 coord, in float wavelength);
|
||||
float Noise3D(in vec3 coord, in float wavelength);
|
||||
float VoronoiNoise2D(in vec2 coord, in float wavelength, in float xrand, in float yrand);
|
||||
|
||||
|
||||
float i1 = simple_interpolate(v1,v5, fractional_z);
|
||||
float i2 = simple_interpolate(v2,v6, fractional_z);
|
||||
float i3 = simple_interpolate(v3,v7, fractional_z);
|
||||
float i4 = simple_interpolate(v4,v8, fractional_z);
|
||||
|
||||
float ii1 = simple_interpolate(i1,i2,fractional_x);
|
||||
float ii2 = simple_interpolate(i3,i4,fractional_x);
|
||||
|
||||
|
||||
return simple_interpolate(ii1 , ii2 , fractional_y);
|
||||
}
|
||||
|
||||
|
||||
float Noise2D(in vec2 coord, in float wavelength)
|
||||
{
|
||||
return interpolatedNoise2D(coord.x/wavelength, coord.y/wavelength);
|
||||
|
||||
}
|
||||
|
||||
float Noise3D(in vec3 coord, in float wavelength)
|
||||
{
|
||||
return interpolatedNoise3D(coord.x/wavelength, coord.y/wavelength, coord.z/wavelength);
|
||||
}
|
||||
|
||||
float dotNoise2D(in float x, in float y, in float fractionalMaxDotSize)
|
||||
{
|
||||
float integer_x = x - fract(x);
|
||||
float fractional_x = x - integer_x;
|
||||
|
||||
float integer_y = y - fract(y);
|
||||
float fractional_y = y - integer_y;
|
||||
|
||||
if (rand2D(vec2(integer_x+1.0, integer_y +1.0)) > dot_density)
|
||||
{return 0.0;}
|
||||
|
||||
float xoffset = (rand2D(vec2(integer_x, integer_y)) -0.5);
|
||||
float yoffset = (rand2D(vec2(integer_x+1.0, integer_y)) - 0.5);
|
||||
float dotSize = 0.5 * fractionalMaxDotSize * max(0.25,rand2D(vec2(integer_x, integer_y+1.0)));
|
||||
|
||||
|
||||
vec2 truePos = vec2 (0.5 + xoffset * (1.0 - 2.0 * dotSize) , 0.5 + yoffset * (1.0 -2.0 * dotSize));
|
||||
|
||||
float distance = length(truePos - vec2(fractional_x, fractional_y));
|
||||
|
||||
return 1.0 - smoothstep (0.3 * dotSize, 1.0* dotSize, distance);
|
||||
}
|
||||
|
||||
float DotNoise2D(in vec2 coord, in float wavelength, in float fractionalMaxDotSize)
|
||||
{
|
||||
return dotNoise2D(coord.x/wavelength, coord.y/wavelength, fractionalMaxDotSize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -339,9 +231,9 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
|
|||
|
||||
// dot noise
|
||||
|
||||
float dotnoise_2m = DotNoise2D(rawPos.xy, 2.0 * dot_size,0.5);
|
||||
float dotnoise_10m = DotNoise2D(rawPos.xy, 10.0 * dot_size, 0.5);
|
||||
float dotnoise_15m = DotNoise2D(rawPos.xy, 15.0 * dot_size, 0.33);
|
||||
float dotnoise_2m = DotNoise2D(rawPos.xy, 2.0 * dot_size,0.5, dot_density);
|
||||
float dotnoise_10m = DotNoise2D(rawPos.xy, 10.0 * dot_size, 0.5, dot_density);
|
||||
float dotnoise_15m = DotNoise2D(rawPos.xy, 15.0 * dot_size, 0.33, dot_density);
|
||||
|
||||
float dotnoisegrad_10m;
|
||||
|
||||
|
@ -540,7 +432,7 @@ if ((dist < 5000.0)&& (quality_level > 3) && (combined_wetness>0.0))
|
|||
noisegrad_2m = (noise_2m - Noise2D(rawPos.xy+ 0.05 * normalize(lightDir.xy),2.0))/0.05;
|
||||
noisegrad_1m = (noise_1m - Noise2D(rawPos.xy+ 0.05 * normalize(lightDir.xy),1.0))/0.05;
|
||||
|
||||
dotnoisegrad_10m = (dotnoise_10m - DotNoise2D(rawPos.xy+ 0.05 * normalize(lightDir.xy),10.0 * dot_size,0.5))/0.05;
|
||||
dotnoisegrad_10m = (dotnoise_10m - DotNoise2D(rawPos.xy+ 0.05 * normalize(lightDir.xy),10.0 * dot_size,0.5, dot_density))/0.05;
|
||||
|
||||
|
||||
NdotL = NdotL + (noisegrad_10m * detail_fade(10.0, view_angle,dist) + 0.5* noisegrad_5m * detail_fade(5.0, view_angle,dist)) * mix_factor/0.8;
|
||||
|
|
|
@ -25,6 +25,7 @@ varying float yprime_alt;
|
|||
|
||||
uniform int colorMode;
|
||||
uniform int wind_effects;
|
||||
uniform int forest_effects;
|
||||
uniform float hazeLayerAltitude;
|
||||
uniform float terminator;
|
||||
uniform float terrain_alt;
|
||||
|
@ -45,6 +46,7 @@ float earthShade;
|
|||
float mie_angle;
|
||||
|
||||
float shadow_func (in float x, in float y, in float noise, in float dist);
|
||||
float VoronoiNoise2D(in vec2 coord, in float wavelength, in float xrand, in float yrand);
|
||||
|
||||
// This is the value used in the skydome scattering shader - use the same here for consistency?
|
||||
const float EarthRadius = 5800000.0;
|
||||
|
@ -105,6 +107,13 @@ void main()
|
|||
position.y = position.y + position.z * (sin(osg_SimulationTime * 1.8 + (gl_Color.x + gl_Color.y + gl_Color.z) * 0.01) + 1.0) * 0.0025 * WindE;
|
||||
}
|
||||
|
||||
// Scale by random domains
|
||||
if (forest_effects > 0)
|
||||
{
|
||||
float voronoi = 0.5 + 1.0 * VoronoiNoise2D(gl_Color.xy, 200.0, 1.5, 1.5);
|
||||
position.xyz = position.xyz * voronoi;
|
||||
}
|
||||
|
||||
// Move to correct location (stored in gl_Color)
|
||||
position = position + gl_Color.xyz;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * vec4(position,1.0);
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
<reload-materials>Reload Materials</reload-materials>
|
||||
<reload-scenery>Reload Scenery</reload-scenery>
|
||||
<nasal-console>Nasal Console</nasal-console>
|
||||
<nasal-repl-interpreter>Nasal REPL Interpreter</nasal-repl-interpreter>
|
||||
<development-keys>Development Keys</development-keys>
|
||||
<configure-dev-extension>Configure Development Extensions</configure-dev-extension>
|
||||
<display-marker>Display Tutorial Marker</display-marker>
|
||||
|
|
|
@ -341,22 +341,46 @@
|
|||
</binding>
|
||||
</checkbox>
|
||||
|
||||
<text>
|
||||
<text>
|
||||
<row>1</row>
|
||||
<col>0</col>
|
||||
<halign>right</halign>
|
||||
<label>Cloud shadows </label>
|
||||
</text>
|
||||
|
||||
<checkbox>
|
||||
<row>1</row>
|
||||
<col>2</col>
|
||||
<halign>left</halign>
|
||||
<property>/local-weather/config/generate-cloud-shadows</property>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
</checkbox>
|
||||
|
||||
<text>
|
||||
<row>1</row>
|
||||
<col>3</col>
|
||||
<halign>right</halign>
|
||||
<label>(needs ALS shaders)</label>
|
||||
</text>
|
||||
|
||||
<text>
|
||||
<row>2</row>
|
||||
<col>0</col>
|
||||
<halign>right</halign>
|
||||
<label>Convective conditions</label>
|
||||
</text>
|
||||
|
||||
<text>
|
||||
<row>1</row>
|
||||
<row>2</row>
|
||||
<col>1</col>
|
||||
<halign>right</halign>
|
||||
<label>rough day</label>
|
||||
</text>
|
||||
|
||||
<slider>
|
||||
<row>1</row>
|
||||
<row>2</row>
|
||||
<col>2</col>
|
||||
<min>0.3</min>
|
||||
<max>1.5</max>
|
||||
|
@ -367,28 +391,28 @@
|
|||
</slider>
|
||||
|
||||
<text>
|
||||
<row>1</row>
|
||||
<row>2</row>
|
||||
<col>3</col>
|
||||
<halign>left</halign>
|
||||
<label>low convection</label>
|
||||
</text>
|
||||
|
||||
<text>
|
||||
<row>2</row>
|
||||
<row>3</row>
|
||||
<col>0</col>
|
||||
<halign>right</halign>
|
||||
<label>Ground haze</label>
|
||||
</text>
|
||||
|
||||
<text>
|
||||
<row>2</row>
|
||||
<row>3</row>
|
||||
<col>1</col>
|
||||
<halign>right</halign>
|
||||
<label>thick</label>
|
||||
</text>
|
||||
|
||||
<slider>
|
||||
<row>2</row>
|
||||
<row>3</row>
|
||||
<col>2</col>
|
||||
<min>0.1</min>
|
||||
<max>1.0</max>
|
||||
|
@ -399,28 +423,28 @@
|
|||
</slider>
|
||||
|
||||
<text>
|
||||
<row>2</row>
|
||||
<row>3</row>
|
||||
<col>3</col>
|
||||
<halign>left</halign>
|
||||
<label>thin</label>
|
||||
</text>
|
||||
|
||||
<text>
|
||||
<row>3</row>
|
||||
<row>4</row>
|
||||
<col>0</col>
|
||||
<halign>right</halign>
|
||||
<label>Air pollution</label>
|
||||
</text>
|
||||
|
||||
<text>
|
||||
<row>3</row>
|
||||
<row>4</row>
|
||||
<col>1</col>
|
||||
<halign>right</halign>
|
||||
<label>clean</label>
|
||||
</text>
|
||||
|
||||
<slider>
|
||||
<row>3</row>
|
||||
<row>4</row>
|
||||
<col>2</col>
|
||||
<min>0.0</min>
|
||||
<max>1.0</max>
|
||||
|
@ -431,28 +455,28 @@
|
|||
</slider>
|
||||
|
||||
<text>
|
||||
<row>3</row>
|
||||
<row>4</row>
|
||||
<col>3</col>
|
||||
<halign>left</halign>
|
||||
<label>smog</label>
|
||||
</text>
|
||||
|
||||
<text>
|
||||
<row>4</row>
|
||||
<row>5</row>
|
||||
<col>0</col>
|
||||
<halign>right</halign>
|
||||
<label>Fog properties</label>
|
||||
</text>
|
||||
|
||||
<text>
|
||||
<row>4</row>
|
||||
<row>5</row>
|
||||
<col>1</col>
|
||||
<halign>right</halign>
|
||||
<label>smooth</label>
|
||||
</text>
|
||||
|
||||
<slider>
|
||||
<row>4</row>
|
||||
<row>5</row>
|
||||
<col>2</col>
|
||||
<min>0.0</min>
|
||||
<max>12.0</max>
|
||||
|
@ -463,14 +487,14 @@
|
|||
</slider>
|
||||
|
||||
<text>
|
||||
<row>4</row>
|
||||
<row>5</row>
|
||||
<col>3</col>
|
||||
<halign>left</halign>
|
||||
<label>structured</label>
|
||||
</text>
|
||||
|
||||
<text>
|
||||
<row>5</row>
|
||||
<row>6</row>
|
||||
<col>0</col>
|
||||
<halign>right</halign>
|
||||
<!--<enable>
|
||||
|
@ -483,14 +507,14 @@
|
|||
</text>
|
||||
|
||||
<text>
|
||||
<row>5</row>
|
||||
<row>6</row>
|
||||
<col>1</col>
|
||||
<halign>right</halign>
|
||||
<label>20 km</label>
|
||||
</text>
|
||||
|
||||
<slider>
|
||||
<row>5</row>
|
||||
<row>6</row>
|
||||
<col>2</col>
|
||||
<!--<enable>
|
||||
<equals>
|
||||
|
@ -507,14 +531,14 @@
|
|||
</slider>
|
||||
|
||||
<text>
|
||||
<row>5</row>
|
||||
<row>6</row>
|
||||
<col>3</col>
|
||||
<halign>left</halign>
|
||||
<label>250 km</label>
|
||||
</text>
|
||||
|
||||
<text>
|
||||
<row>5</row>
|
||||
<row>6</row>
|
||||
<col>4</col>
|
||||
<halign>left</halign>
|
||||
<!--<enable>
|
||||
|
|
|
@ -173,6 +173,30 @@
|
|||
</empty>
|
||||
</group>
|
||||
|
||||
<group>
|
||||
<layout>hbox</layout>
|
||||
<halign>right</halign>
|
||||
<text>
|
||||
<label>Forest</label>
|
||||
</text>
|
||||
<slider>
|
||||
<name>forest</name>
|
||||
<min>0.0</min>
|
||||
<max>1.0</max>
|
||||
<step>1.0</step>
|
||||
<fraction>0.17</fraction>
|
||||
<live>true</live>
|
||||
<property>/sim/rendering/shaders/forest</property>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
<object-name>forest</object-name>
|
||||
</binding>
|
||||
</slider>
|
||||
<empty>
|
||||
<pref-width>55</pref-width>
|
||||
</empty>
|
||||
</group>
|
||||
|
||||
<group>
|
||||
<layout>hbox</layout>
|
||||
<halign>right</halign>
|
||||
|
@ -196,7 +220,7 @@
|
|||
<pref-width>55</pref-width>
|
||||
</empty>
|
||||
</group>
|
||||
|
||||
<!--
|
||||
<group>
|
||||
<layout>hbox</layout>
|
||||
<visible>
|
||||
|
@ -302,7 +326,7 @@
|
|||
<live>true</live>
|
||||
<property>/sim/rendering/dome-density</property>
|
||||
</text>
|
||||
</group>
|
||||
</group>-->
|
||||
|
||||
<group>
|
||||
<layout>hbox</layout>
|
||||
|
|
|
@ -584,6 +584,14 @@
|
|||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<name>nasal-repl-interpreter</name>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>console.CanvasPlacement.new()</script>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<name>development-keys</name>
|
||||
<binding>
|
||||
|
|
|
@ -146,6 +146,7 @@ Started September 2000 by David Megginson, david@megginson.com
|
|||
<urban type="float" userarchive="y">1.0</urban>
|
||||
<water type="float" userarchive="y">1.0</water>
|
||||
<wind-effects type="float" userarchive="y">0.0</wind-effects>
|
||||
<forest type="float" userarchive="y">0.0</forest>
|
||||
<lights type="float" userarchive="y">1.0</lights>
|
||||
<quality-level-internal type="float" userarchive="y">1.0</quality-level-internal>
|
||||
</shaders>
|
||||
|
|
Loading…
Add table
Reference in a new issue