Skip to content

Commit

Permalink
Displaying corresponding recipe on a node
Browse files Browse the repository at this point in the history
  • Loading branch information
andev0 committed Aug 18, 2024
1 parent 5f153f4 commit 9fced1e
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 4 deletions.
2 changes: 1 addition & 1 deletion dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ <h2 class="title">Select a recipe</h2>

<div class="help">
<p>N - create new node</p>
<p>Alt + Mouse drag - move</p>
<p>Alt (Option) + Mouse drag - move</p>
<p>Mouse drag - move node under cursor</p>
<p>Mouse wheel - zoom</p>
<p>LMB on slot - connect slot</p>
Expand Down
82 changes: 82 additions & 0 deletions dist/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,88 @@ div.help {
fill: #74ce73;
}

/* Recipe display on a node */

.node foreignObject {
pointer-events: none;
}

.node foreignObject .recipe-container {
display: flex;
flex-direction: column;
align-items: stretch;
justify-content: center;

height: 100%;

gap: 2px;

padding: 2px;
}

.node .recipe-container * {
font-size: 10px;
}

.node .recipe-container div.property {
display: flex;
flex-direction: column;

gap: 1px;
}

.node .recipe-container .property>div {
display: flex;
justify-content: center;
align-items: center;

background-color: var(--dimming);

padding: 2px 4px;
}

.node .recipe-container .property>div:first-child {
border-radius: 4px 4px 0 0;
}

.node .recipe-container .property>div:last-child {
border-radius: 0 0 4px 4px;
}

.node .recipe-container .property div.title {
text-align: center;

font-weight: 500;
}

.node .recipe-container .property div.text {
text-align: center;
}

.node .recipe-container .property div.resource {
display: flex;

gap: 4px;
}

.node .recipe-container .property .resource img.icon {
width: 16px;
height: 16px;

min-width: 0;
}

.node .recipe-container .property .resource p.amount {
margin: 0;
}

.node .recipe-container .property .machine img.icon {
width: 20px;
height: 20px;

min-width: 0;
}

/* Node links */

line.link-hint {
Expand Down
7 changes: 7 additions & 0 deletions src/SVG/SvgFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ export abstract class SvgFactory
return result;
}

public static createSvgForeignObject(...classes: string[]): SVGForeignObjectElement
{
let result = this.createSvgElement("foreignObject", ...classes) as SVGForeignObjectElement;

return result;
}

private static createSvgElement(tag: string, ...classes: string[]): SVGElement
{
let result = document.createElementNS("http://www.w3.org/2000/svg", tag);
Expand Down
113 changes: 111 additions & 2 deletions src/Sankey/SankeyNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ import { SankeySlot } from "./Slots/SankeySlot";
import { SlotsGroup } from "./SlotsGroup";
import { SvgFactory } from "../SVG/SvgFactory";
import { GameRecipe } from "../GameData/GameRecipe";
import { GameMachine } from "../GameData/GameMachine";

// Ignore import error as the file only appears on launch of the exporting tool.
// @ts-ignore
import satisfactoryData from '../../dist/GameData/Satisfactory.json';

export class SankeyNode
{
public nodeSvg: SVGElement;
public nodeSvgGroup: SVGGElement;

public static readonly nodeHeight = 240;
public static readonly nodeHeight = 260;
public static readonly nodeWidth = 60;

constructor(
Expand Down Expand Up @@ -73,7 +76,113 @@ export class SankeyNode
nextOutputGroupY += newGroup.maxHeight;
}

let foreignObject = SvgFactory.createSvgForeignObject();

foreignObject.setAttribute("x", "10");
foreignObject.setAttribute("y", "0");
foreignObject.setAttribute("width", `${SankeyNode.nodeWidth}`);
foreignObject.setAttribute("height", `${SankeyNode.nodeHeight}`);


let recipeContainer = document.createElement("div");
recipeContainer.classList.add("recipe-container");


let recipeNameProp = document.createElement("div");
recipeNameProp.classList.add("property");

let recipeNameTitle = document.createElement("div");
recipeNameTitle.classList.add("title");
recipeNameTitle.innerText = "Recipe";

let recipeNameText = document.createElement("div");
recipeNameText.classList.add("text");


let recipeInputsProp = document.createElement("div");
recipeInputsProp.classList.add("property");

let recipeInputsTitle = document.createElement("div");
recipeInputsTitle.classList.add("title");
recipeInputsTitle.innerText = "Input/min";


let recipeOutputsProp = document.createElement("div");
recipeOutputsProp.classList.add("property");

let recipeOutputsTitle = document.createElement("div");
recipeOutputsTitle.classList.add("title");
recipeOutputsTitle.innerText = "Output/min";



recipeNameProp.appendChild(recipeNameTitle);
recipeNameProp.appendChild(recipeNameText);

recipeInputsProp.appendChild(recipeInputsTitle);

recipeOutputsProp.appendChild(recipeOutputsTitle);

recipeContainer.appendChild(recipeNameProp);
recipeContainer.appendChild(recipeInputsProp);
recipeContainer.appendChild(recipeOutputsProp);

foreignObject.appendChild(recipeContainer);



let createResourceDisplay = (parentDiv: HTMLDivElement, craftingTime: number) =>
{
return (recipeResource: RecipeResource) =>
{
let resource = satisfactoryData.resources.find(
(el: typeof satisfactoryData.resources[0]) =>
{
return el.id === recipeResource.id;
}
);

let resourceDiv = document.createElement("div");
resourceDiv.classList.add("resource");

let icon = document.createElement("img");
icon.classList.add("icon");
icon.loading = "lazy";
icon.alt = resource!.displayName;
icon.src = `GameData/SatisfactoryIcons/${resource!.iconPath}`;
icon.title = resource!.displayName;

let amount = document.createElement("p");
amount.classList.add("amount");
amount.innerText = `${+((60 / craftingTime) * recipeResource.amount).toPrecision(3)}`;

resourceDiv.appendChild(icon);
resourceDiv.appendChild(amount);
parentDiv.appendChild(resourceDiv);
};
};



recipeNameText.innerText = recipe.displayName;

// let selectedRecipeMachine = document.querySelector("#selected-recipe-machine>div.machine>img.icon") as HTMLImageElement;
// selectedRecipeMachine.src = `GameData/SatisfactoryIcons/${machine.iconPath}`;
// selectedRecipeMachine.title = machine.displayName;

recipe.ingredients.forEach(createResourceDisplay(recipeInputsProp, recipe.manufacturingDuration));

recipe.products.forEach(createResourceDisplay(recipeOutputsProp, recipe.manufacturingDuration));

// let selectedRecipePower = document.querySelector("#selected-recipe-power>div.text") as HTMLDivElement;
// selectedRecipePower.innerText = `${machine.powerConsumption} MW`;



this.nodeSvgGroup.appendChild(this.nodeSvg);

this.nodeSvgGroup.appendChild(foreignObject);

parentGroup.appendChild(this.nodeSvgGroup);
}

Expand Down
2 changes: 1 addition & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import panzoom from "panzoom";
import { SankeyNode } from "./Sankey/SankeyNode";
import { Point } from "./Point";
import { MouseHandler } from "./MouseHandler";
import { GameRecipe, GameRecipeEvent } from "./GameData/GameRecipe";

// Ignore import error as the file only appears on launch of the exporting tool.
// @ts-ignore
import satisfactoryData from '../dist/GameData/Satisfactory.json';
import { GameRecipe, GameRecipeEvent } from "./GameData/GameRecipe";

async function main()
{
Expand Down

0 comments on commit 9fced1e

Please sign in to comment.