diff --git a/builder/doc.html b/builder/doc.html index bfcdf9b..23a0216 100644 --- a/builder/doc.html +++ b/builder/doc.html @@ -1428,9 +1428,12 @@ -
+
+ + savelink
+ diff --git a/dev/builder_colorcode.png b/dev/builder_colorcode.png new file mode 100755 index 0000000..a9501b8 Binary files /dev/null and b/dev/builder_colorcode.png differ diff --git a/dev/compute_graph.svg b/dev/compute_graph.svg new file mode 100755 index 0000000..5f3413f --- /dev/null +++ b/dev/compute_graph.svg @@ -0,0 +1,12 @@ + + + + + + + +builder-armor-powder-inputbuilder-boost-inputbuilder-powder-special-inputhelmet-inputhelmet-input-displayhelmet-item-displaychestplate-inputchestplate-input-displaychestplate-item-displayleggings-inputleggings-input-displayleggings-item-displayboots-inputboots-input-displayboots-item-displayring1-inputring1-input-displayring1-item-displayring2-inputring2-input-displayring2-item-displaybracelet-inputbracelet-input-displaybracelet-item-displaynecklace-inputnecklace-input-displaynecklace-item-displayweapon-inputweapon-input-displayweapon-item-displayweaponTome1-inputweaponTome1-input-displayweaponTome2-inputweaponTome2-input-displayarmorTome1-inputarmorTome1-input-displayarmorTome2-inputarmorTome2-input-displayarmorTome3-inputarmorTome3-input-displayarmorTome4-inputarmorTome4-input-displayguildTome1-inputguildTome1-input-displayweapon-typelevel-inputbuilder-make-buildbuilder-encodebuilder-url-updatehelmet-powderchestplate-powderleggings-powderboots-powderweapon-powderbuilder-stats-displaybuilder-aggregate-statsbuilder-aggregate-inputsbuilder-sdPct-inputbuilder-sdRaw-inputbuilder-mdPct-inputbuilder-mdRaw-inputbuilder-poison-inputbuilder-fDamPct-inputbuilder-wDamPct-inputbuilder-aDamPct-inputbuilder-tDamPct-inputbuilder-eDamPct-inputbuilder-fDefPct-inputbuilder-wDefPct-inputbuilder-aDefPct-inputbuilder-tDefPct-inputbuilder-eDefPct-inputbuilder-hprRaw-inputbuilder-hprPct-inputbuilder-hpBonus-inputbuilder-atkTier-inputbuilder-spPct1-inputbuilder-spRaw1-inputbuilder-spPct2-inputbuilder-spRaw2-inputbuilder-spPct3-inputbuilder-spRaw3-inputbuilder-spPct4-inputbuilder-spRaw4-inputbuilder-id-setterbuilder-str-inputbuilder-dex-inputbuilder-int-inputbuilder-def-inputbuilder-agi-inputbuilder-powder-special-applybuilder-powder-special-displaybuilder-spell0-selectbuilder-spell0-calcbuilder-spell0-displaybuilder-spell1-selectbuilder-spell1-calcbuilder-spell1-displaybuilder-spell2-selectbuilder-spell2-calcbuilder-spell2-displaybuilder-spell3-selectbuilder-spell3-calcbuilder-spell3-displaybuilder-skillpoint-setterbuilder-show-warnings \ No newline at end of file diff --git a/dev/index.html b/dev/index.html index 438a215..42117a6 100644 --- a/dev/index.html +++ b/dev/index.html @@ -892,12 +892,73 @@ Last updated: 30 May 2022

+
+

+ This section is about how Wynnbuilder's main builder page processes user input and calculates results. + Might be useful if you want to script wynnbuilder or extend it! Or for wynnbuilder developers (internal docs). +

+
+

+ Modeling wynnbuilder's internal computations as a directed graph has a few advantages: +

+ +
+
+ TODO +
+

+ An overview of wynnbuilder's internal structure can be seen here. Arrows indicate flow of information. + Colors correspond roughly as follows: +

+ +

+ The overall logic flow is as follows: +

+

+

+ Outputs are computed as follows: +

+

+
+

+ The build sets default skillpoints and edited IDs automatically, whenever a build item/level is updated. + This is done using "soft links" by two nodes shown in red (builder-skillpoint-setter and builder-id-setter). +

+

+ A soft link is where something goes and manually marks nodes dirty and calls their update methods. + This is useful for these cases because the skillpoints and editable ID fields usually take their value from + user input, but in some cases we want to programatically set them. +

+

+ For example another soft link (not shown) is used to implement the reset button. +

+
+
- - \ No newline at end of file + diff --git a/js/d3_export.js b/js/d3_export.js new file mode 100644 index 0000000..4e92c07 --- /dev/null +++ b/js/d3_export.js @@ -0,0 +1,30 @@ +// http://bl.ocks.org/rokotyan/0556f8facbaf344507cdc45dc3622177 + +// Set-up the export button +function set_export_button(svg, button_id, output_id) { + d3.select('#'+button_id).on('click', function(){ + //get svg source. + var serializer = new XMLSerializer(); + var source = serializer.serializeToString(svg.node()); + console.log(source); + + source = source.replace(/^$/, ''); + //add name spaces. + if(!source.match(/^]+xmlns="http\:\/\/www\.w3\.org\/2000\/svg"/)){ + source = source.replace(/^]+"http\:\/\/www\.w3\.org\/1999\/xlink"/)){ + source = source.replace(/^ colors[color]) + + node_enter.append('text') + .attr("dx", -20) + .attr("dy", -22) + .style('fill', 'white') + .text(({id, color, data}) => data.name); + + // Let's list the force we wanna apply on the network + var simulation = d3.forceSimulation(data.nodes) // Force algorithm is applied to data.nodes + .force("link", d3.forceLink().strength(0.1) // This force provides links between nodes + .id(function(d) { return d.id; }) // This provide the id of a node + .links(data.links) // and this the list of links + ) + .force("charge", d3.forceManyBody().strength(-400)) // This adds repulsion between nodes. Play with the -400 for the repulsion strength + //.force("center", d3.forceCenter(_bbox.width / 2, _bbox.height / 2).strength(0.1)) // This force attracts nodes to the center of the svg area + .on("tick", ticked); + // This function is run at each iteration of the force algorithm, updating the nodes position. + let scale_transform = {k: 1, x: 0, y: 0} + function ticked() { + link + .attr("x1", function(d) { return d.source.x; }) + .attr("y1", function(d) { return d.source.y; }) + .attr("x2", function(d) { return d.target.x; }) + .attr("y2", function(d) { return d.target.y; }); + + node_enter.attr("transform", function (d) { return 'translate('+scale_transform.x+','+scale_transform.y+') scale('+scale_transform.k+') translate('+d.x+','+d.y+')' }) + } + + const drag = d3.drag() + .on("start", dragstart) + .on("drag", dragged); + + node_enter.call(drag).on('click', click); + function click(event, d) { + if (event.ctrlKey) { + // Color cycle. + d.color = (d.color + 1) % n_colors; + d3.select(this).selectAll('circle').style("fill", ({id, color, data}) => colors[color]) + } + else { + delete d.fx; + delete d.fy; + d3.select(this).classed("fixed", false); + simulation.alpha(0.5).restart(); + } + } + + function dragstart() { + d3.select(this).classed("fixed", true); + } + function dragged(event, d) { + d.fx = event.x; + d.fy = event.y; + simulation.alpha(0.5).restart(); + } + + const zoom = d3.zoom() + .scaleExtent([0.01, 10]) + .translateExtent([[-10000, -10000], [10000, 10000]]) + .filter(filter) + .on("zoom", zoomed); + view.call(zoom); + + function zoomed({ transform }) { + link.attr('transform', transform); + scale_transform = transform; + node_enter.attr("transform", function (d) { return 'translate('+scale_transform.x+','+scale_transform.y+') scale('+scale_transform.k+') translate('+d.x+','+d.y+')' }) + redraw_func(); + } + // prevent scrolling then apply the default filter + function filter(event) { + event.preventDefault(); + return (!event.ctrlKey || event.type === 'wheel') && !event.button; + } +} + +set_export_button(svg, 'saveButton', 'saveLink'); + +(async function() { + +// JANKY +while (edit_id_output === undefined) { + await sleep(500); +} + +function redraw() { + _bbox = bbox(); + graph.attr("viewBox", [0, 0, _bbox.width, _bbox.height]); + view.attr("width", _bbox.width - 1) + .attr("height", _bbox.height - 1); +} + +d3.select(window) + .on("resize", function() { + redraw(); + }); +redraw(); + +const data = convert_data(all_nodes); +create_svg(data, redraw); + +console.log("render"); + +})();