Module:Test: Difference between revisions

From Resonite Wiki
mNo edit summary
mNo edit summary
Line 22: Line 22:
     int = '0, 255, 0',
     int = '0, 255, 0',
     Continuation = '255, 255, 178',
     Continuation = '255, 255, 178',
     Slot = '191, 255, 127'
     Slot = '191, 255, 127',
WebsocketClient = '191, 242, 176'
}
}


Line 32: Line 33:
local outputs = mw.text.jsonDecode(frame.args.Outputs or '[]')
local outputs = mw.text.jsonDecode(frame.args.Outputs or '[]')
local globals = mw.text.jsonDecode(frame.args.Globals or '[]')
local globals = mw.text.jsonDecode(frame.args.Globals or '[]')
local minimal = frame.args.Minimal
-- Create an HTML div element to contain our node UI
-- Create an HTML div element to contain our node UI
Line 67: Line 69:
for i=1,maxRows do
for i=1,maxRows do
CreateConnectorRow(protofluxContainer, processedInputs[i], processedOutputs[i])
CreateConnectorRow(protofluxContainer, processedInputs[i], processedOutputs[i], minimal)
end
end
Line 90: Line 92:
-- @param Input Table containing a Name and Type for the input on this row. Can be nil if no input is to be placed on this row.
-- @param Input Table containing a Name and Type for the input on this row. Can be nil if no input is to be placed on this row.
-- @param Output Table containing a Name and Type for the output on this row. Can be nil if no output is to be placed on this row.
-- @param Output Table containing a Name and Type for the output on this row. Can be nil if no output is to be placed on this row.
function CreateConnectorRow(Container, Input, Output)
function CreateConnectorRow(Container, Input, Output, Minimal)
local connectorRow = Container
local connectorRow = Container
:tag('div') -- HTML div to contain the connector row. We specify a min-height of 70px for consistency.
:tag('div') -- HTML div to contain the connector row. We specify a min-height of 70px for consistency.
Line 97: Line 99:
-- Create the input (left) attachement point
-- Create the input (left) attachement point
CreateConnectorAttachmentPoint(connectorRow, Input, true)
CreateConnectorAttachmentPoint(connectorRow, Input, true)


local c = connectorRow
local c = connectorRow
:tag('div') -- HTML div to contain the input and output labels in the connector row
:tag('div') -- HTML div to contain the input and output labels in the connector row
:cssText( 'flex-grow: 2; overflow: hidden; display: flex; flex-direction: column; justify-content: space-between;')
:cssText( 'flex-grow: 2; overflow: hidden; display: flex; flex-direction: column; justify-content: space-between;')
if Input and Input.Multi and Input.MultiIndex == 1 then
if Minimal then
c
else
:tag('div') -- HTML div to contain the input label
if Input and Input.Multi and Input.MultiIndex == 1 then
:attr('title', Input and (Input.Name .. ' <' .. Input.Type .. '>') or '') -- Add a basic mouseover description
c
:cssText('text-align: left; overflow: hidden; text-overflow: ellipsis; padding-left: 4px;  border-right: 20px solid #11151d; border-bottom: 4px solid #11151d; border-top: 4px solid #11151d; background-color: transparent;')
:tag('div') -- HTML div to contain the input label
:wikitext(Input and Input.Name or '' )
:attr('title', Input and (Input.Name .. ' <' .. Input.Type .. '>') or '') -- Add a basic mouseover description
:done() -- Close input label div
:cssText('text-align: left; overflow: hidden; text-overflow: ellipsis; padding-left: 4px;  border-right: 20px solid #11151d; border-bottom: 4px solid #11151d; border-top: 4px solid #11151d; background-color: transparent;')
elseif Input and Input.Multi and Input.MultiIndex > 1 then
:wikitext(Input and Input.Name or '' )
local c2 = c
:done() -- Close input label div
:tag('div') -- HTML div to contain the input label
elseif Input and Input.Multi and Input.MultiIndex > 1 then
:attr('title', Input and (Input.Name .. ' <' .. Input.Type .. '>') or '') -- Add a basic mouseover description
local c2 = c
:cssText('text-align: left; padding-left: 4px;  border-right: 20px solid #11151d; border-bottom: 4px solid #11151d; border-top: 4px solid #11151d; background-color: transparent;')
:tag('div') -- HTML div to contain the input label
if Input.Multi == Input.MultiIndex then
:attr('title', Input and (Input.Name .. ' <' .. Input.Type .. '>') or '') -- Add a basic mouseover description
c2
:cssText('text-align: left; padding-left: 4px;  border-right: 20px solid #11151d; border-bottom: 4px solid #11151d; border-top: 4px solid #11151d; background-color: transparent;')
:tag('div')
if Input.Multi == Input.MultiIndex then
:cssText('position:relative; top:2rem; display:flex; gap: 4px;')
c2
:tag('div')
:tag('div')
:cssText('font-size: 1.75rem; width: 1em; height: 1em; background-color:grey; border-radius: 2em; display:flex; align-items:center; justify-content:center;')
:cssText('position:relative; top:2rem; display:flex; gap: 4px;')
:wikitext('+')
:tag('div')
:done()
:cssText('font-size: 1.75rem; width: 1em; height: 1em; background-color:grey; border-radius: 2em; display:flex; align-items:center; justify-content:center;')
:wikitext('+')
:done()
:tag('div')
:cssText('font-size: 1.75rem; width: 1em; height: 1em; background-color:grey; border-radius: 2em; display:flex; align-items:center; justify-content:center;')
:wikitext('-')
:done()
end
else
c
:tag('div') -- HTML div to contain the input label
:attr('title', Input and (Input.Name .. ' <' .. Input.Type .. '>') or '') -- Add a basic mouseover description
:cssText('text-align: left; overflow: hidden; text-overflow: ellipsis; padding-left: 4px;  border-right: 20px solid #11151d; border-bottom: 4px solid #11151d; border-top: 4px solid #11151d; background-color:' .. GetTypeColor(Input, 0.6) .. ';')
:wikitext(Input and Input.Name or '' )
:done() -- Close input label div
end
if Output and Output.Multi and Output.MultiIndex == 1 then
c
:tag('div') -- HTML div to contain the output label
:attr('title', Output and (Output.Name .. ' <' .. Output.Type .. '>') or '') -- Add a basic mouseover description
:cssText('text-align: right; overflow: hidden; text-overflow: ellipsis; padding-right: 4px; border-left: 20px solid #11151d; border-bottom: 4px solid #11151d; border-top: 4px solid #11151d; background-color: transparent;')
:wikitext(Output and Output.Name or '')
:done() -- Close output label div
elseif Output and Output.Multi and Output.MultiIndex > 1 then
local c2 = c
:tag('div') -- HTML div to contain the output label
:attr('title', Output and (Output.Name .. ' <' .. Output.Type .. '>') or '') -- Add a basic mouseover description
:cssText('text-align: right; padding-right: 4px; border-left: 20px solid #11151d; border-bottom: 4px solid #11151d; border-top: 4px solid #11151d; background-color: transparent;;')
if Output.Multi == Output.MultiIndex then
c2
:tag('div')
:tag('div')
:cssText('font-size: 1.75rem; width: 1em; height: 1em; background-color:grey; border-radius: 2em; display:flex; align-items:center; justify-content:center;')
:cssText('display:flex; justify-content:flex-end; gap: 4px;')
:wikitext('-')
:tag('div')
:done()
:cssText('font-size: 1.75rem; width: 1em; height: 1em; background-color:grey; border-radius: 2em; display:flex; align-items:center; justify-content:center;')
end
:wikitext('+')
else
:done()
c
:tag('div')
:tag('div') -- HTML div to contain the input label
:cssText('font-size: 1.75rem; width: 1em; height: 1em; background-color:grey; border-radius: 2em; display:flex; align-items:center; justify-content:center;')
:attr('title', Input and (Input.Name .. ' <' .. Input.Type .. '>') or '') -- Add a basic mouseover description
:wikitext('-')
:cssText('text-align: left; overflow: hidden; text-overflow: ellipsis; padding-left: 4px; border-right: 20px solid #11151d; border-bottom: 4px solid #11151d; border-top: 4px solid #11151d; background-color:' .. GetTypeColor(Input, 0.6) .. ';')
:done()
:wikitext(Input and Input.Name or '' )
end
:done() -- Close input label div
else
end
c
if Output and Output.Multi and Output.MultiIndex == 1 then
c
:tag('div') -- HTML div to contain the output label
:tag('div') -- HTML div to contain the output label
:attr('title', Output and (Output.Name .. ' <' .. Output.Type .. '>') or '') -- Add a basic mouseover description
:attr('title', Output and (Output.Name .. ' <' .. Output.Type .. '>') or '') -- Add a basic mouseover description
:cssText('text-align: right; overflow: hidden; text-overflow: ellipsis; padding-right: 4px; border-left: 20px solid #11151d; border-bottom: 4px solid #11151d; border-top: 4px solid #11151d; background-color: transparent;')
:cssText('text-align: right; overflow: hidden; text-overflow: ellipsis; padding-right: 4px; border-left: 20px solid #11151d; border-bottom: 4px solid #11151d; border-top: 4px solid #11151d; background-color: ' .. GetTypeColor(Output, 0.6) .. ';')
:wikitext(Output and Output.Name or '')
:wikitext(Output and Output.Name or '')
:done() -- Close output label div
:done() -- Close output label div
elseif Output and Output.Multi and Output.MultiIndex > 1 then
local c2 = c
:tag('div') -- HTML div to contain the output label
:attr('title', Output and (Output.Name .. ' <' .. Output.Type .. '>') or '') -- Add a basic mouseover description
:cssText('text-align: right; padding-right: 4px; border-left: 20px solid #11151d; border-bottom: 4px solid #11151d; border-top: 4px solid #11151d; background-color: transparent;;')
if Output.Multi == Output.MultiIndex then
c2
:tag('div')
:cssText('display:flex; justify-content:flex-end; gap: 4px;')
:tag('div')
:cssText('font-size: 1.75rem; width: 1em; height: 1em; background-color:grey; border-radius: 2em; display:flex; align-items:center; justify-content:center;')
:wikitext('+')
:done()
:tag('div')
:cssText('font-size: 1.75rem; width: 1em; height: 1em; background-color:grey; border-radius: 2em; display:flex; align-items:center; justify-content:center;')
:wikitext('-')
:done()
end
end
else
end
c
:tag('div') -- HTML div to contain the output label
:attr('title', Output and (Output.Name .. ' <' .. Output.Type .. '>') or '') -- Add a basic mouseover description
:cssText('text-align: right; overflow: hidden; text-overflow: ellipsis; padding-right: 4px; border-left: 20px solid #11151d; border-bottom: 4px solid #11151d; border-top: 4px solid #11151d; background-color: ' .. GetTypeColor(Output, 0.6) .. ';')
:wikitext(Output and Output.Name or '')
:done() -- Close output label div
end
-- Create the output (right) attachment point
-- Create the output (right) attachment point
CreateConnectorAttachmentPoint(connectorRow, Output, false);
CreateConnectorAttachmentPoint(connectorRow, Output, false);

Revision as of 02:16, 25 January 2024

Documentation for this module may be created at Module:Test/doc

-- Package definition to return to Scribunto - this allows us to define methods that can be called
-- when this module is targeted.
local p = {}

-- Type colors - RGB values to be included in the HTML output when a color is needed. This will be replaced with CSS at some point.
local typeColor = 
{
	User = '255, 128, 255',
	Impulse = '179, 255, 255',
	bool = '115, 115, 115',
	AsyncImpulse = '204, 179, 255',
	String = '245, 31, 31',
	Dummy = '255, 0, 255',
	IFormatProvider = '168, 143, 214',
	float = '0, 255, 255',
	ColorProfile = '255, 196, 54',
	colorX = '255, 89, 0',
	Component = '112, 76, 85',
	float3 = '0, 255, 255',
	float2 = '0, 255, 255',
    ulong = '0, 255, 127',
    int = '0, 255, 0',
    Continuation = '255, 255, 178',
    Slot = '191, 255, 127',
	WebsocketClient = '191, 242, 176'
}

--- Method that generates the HTML output
--	@param frame A Scribunto frame instance. frame.args contains the parameters passed into the module call
function p.GenerateUI( frame )
	-- Parse the JSON input, returning an empty array if no argument was passed
	local inputs = mw.text.jsonDecode(frame.args.Inputs or '[]')
	local outputs = mw.text.jsonDecode(frame.args.Outputs or '[]')
	local globals = mw.text.jsonDecode(frame.args.Globals or '[]')
	local minimal = frame.args.Minimal
	
	-- Create an HTML div element to contain our node UI
	local protofluxContainer = mw.html.create( 'div' )
	protofluxContainer
	    :attr('class', frame.args.Inline and '' or 'floatright')
		:cssText('color: rgb(224, 224, 224); background-color: rgb(18, 20, 28); width: 256px; display: flex; flex-direction: column; align-items: stretch;')
		:tag('div') -- HTML div to contain the node title
			:cssText('padding: 10px 0px 10px 0px; text-align:center; font-weight: bold; background-color: rgb(26, 41, 54); font-size: 18pt; flex-grow: 1;')
			:wikitext(frame.args.Name)
			:done() -- Close node title div
	
	local processedInputs = {}
	local processedOutputs = {}
	
	for i=1,#inputs do
		for j=1,(inputs and inputs[i].Multi or 1) do
			inputs[i].MultiIndex = j
			table.insert(processedInputs, { Name=inputs[i].Name, Type=inputs[i].Type, Multi=inputs[i].Multi, MultiIndex=j })
		end
	end
	
	for i=1,#outputs do
		for j=1,(outputs and outputs[i].Multi or 1) do
			table.insert(processedOutputs, { Name=outputs[i].Name, Type=outputs[i].Type, Multi=outputs[i].Multi, MultiIndex=j })
		end
	end
	
	-- Calculate the larger number of rows required (either for inputs or outputs, if the node is asymmetric)
	local maxRows = math.max(#processedInputs, #processedOutputs)
	
	
	-- Iterate over each row, and populate it with the inputs/outputs. If the node is asymmetric,
	-- the value passed for either input or output might be nil.
	
	for i=1,maxRows do
		CreateConnectorRow(protofluxContainer, processedInputs[i], processedOutputs[i], minimal)
	end
	
	-- Iterate over each global value in the node, and create a row. These elements take up the entire width
	-- of the node, and so don't need to be balanced in any way.
	for i=1,#globals do
		CreateGlobalsRow(protofluxContainer, globals[i])
	end
	
	protofluxContainer
		:tag('div') -- HTML div to contain the node category footer
			:cssText('text-align: center; padding: 10px; font-size: 18pt; color: rgb(64,64,64); font-weight: bold;')
			:wikitext(frame.args.Category)
			:done() -- Close category footer div
	
	-- Return the HTML generated above to the wiki page this script is invoked from.
	return tostring(protofluxContainer) .. '[[Category:ProtoFlux:All]]'
end

--- Creates a new ProtoFlux connector row in the output
-- @param Container The Scribunto HTML node we'll be creating this row inside of. Should be a container of some sort.
-- @param Input Table containing a Name and Type for the input on this row. Can be nil if no input is to be placed on this row.
-- @param Output Table containing a Name and Type for the output on this row. Can be nil if no output is to be placed on this row.
function CreateConnectorRow(Container, Input, Output, Minimal)
	local connectorRow = Container
		:tag('div') -- HTML div to contain the connector row. We specify a min-height of 70px for consistency.
			:cssText('display: flex; min-height: 70px;')
	
	-- Create the input (left) attachement point
	CreateConnectorAttachmentPoint(connectorRow, Input, true)
	

	local c = connectorRow
		:tag('div') -- HTML div to contain the input and output labels in the connector row
			:cssText( 'flex-grow: 2; overflow: hidden; display: flex; flex-direction: column; justify-content: space-between;')
	if Minimal then
	else
		if Input and Input.Multi and Input.MultiIndex == 1 then
			c
				:tag('div') -- HTML div to contain the input label
					:attr('title', Input and (Input.Name .. ' <' .. Input.Type .. '>') or '') -- Add a basic mouseover description
					:cssText('text-align: left; overflow: hidden; text-overflow: ellipsis; padding-left: 4px;  border-right: 20px solid #11151d; border-bottom: 4px solid #11151d; border-top: 4px solid #11151d; background-color: transparent;')
					:wikitext(Input and Input.Name or '' )
					:done() -- Close input label div
		elseif Input and Input.Multi and Input.MultiIndex > 1 then
			local c2 = c
				:tag('div') -- HTML div to contain the input label
					:attr('title', Input and (Input.Name .. ' <' .. Input.Type .. '>') or '') -- Add a basic mouseover description
					:cssText('text-align: left; padding-left: 4px;  border-right: 20px solid #11151d; border-bottom: 4px solid #11151d; border-top: 4px solid #11151d; background-color: transparent;')
			if Input.Multi == Input.MultiIndex then
				c2
					:tag('div')
						:cssText('position:relative; top:2rem; display:flex; gap: 4px;')
						:tag('div')
							:cssText('font-size: 1.75rem; width: 1em; height: 1em; background-color:grey; border-radius: 2em; display:flex; align-items:center; justify-content:center;')
							:wikitext('+')
							:done()
						:tag('div')
							:cssText('font-size: 1.75rem; width: 1em; height: 1em; background-color:grey; border-radius: 2em; display:flex; align-items:center; justify-content:center;')
							:wikitext('-')
							:done()
			end
		else
			c
				:tag('div') -- HTML div to contain the input label
					:attr('title', Input and (Input.Name .. ' <' .. Input.Type .. '>') or '') -- Add a basic mouseover description
					:cssText('text-align: left; overflow: hidden; text-overflow: ellipsis; padding-left: 4px;  border-right: 20px solid #11151d; border-bottom: 4px solid #11151d; border-top: 4px solid #11151d; background-color:' .. GetTypeColor(Input, 0.6) .. ';')
					:wikitext(Input and Input.Name or '' )
					:done() -- Close input label div
		end
		if Output and Output.Multi and Output.MultiIndex == 1 then
			c
				:tag('div') -- HTML div to contain the output label
					:attr('title', Output and (Output.Name .. ' <' .. Output.Type .. '>') or '') -- Add a basic mouseover description
					:cssText('text-align: right; overflow: hidden; text-overflow: ellipsis; padding-right: 4px; border-left: 20px solid #11151d; border-bottom: 4px solid #11151d; border-top: 4px solid #11151d; background-color: transparent;')
					:wikitext(Output and Output.Name or '')
					:done() -- Close output label div
		elseif Output and Output.Multi and Output.MultiIndex > 1 then
			local c2 = c
				:tag('div') -- HTML div to contain the output label
					:attr('title', Output and (Output.Name .. ' <' .. Output.Type .. '>') or '') -- Add a basic mouseover description
					:cssText('text-align: right; padding-right: 4px; border-left: 20px solid #11151d; border-bottom: 4px solid #11151d; border-top: 4px solid #11151d; background-color: transparent;;')
			if Output.Multi == Output.MultiIndex then
				c2
					:tag('div')
						:cssText('display:flex; justify-content:flex-end; gap: 4px;')
						:tag('div')
							:cssText('font-size: 1.75rem; width: 1em; height: 1em; background-color:grey; border-radius: 2em; display:flex; align-items:center; justify-content:center;')
							:wikitext('+')
							:done()
						:tag('div')
							:cssText('font-size: 1.75rem; width: 1em; height: 1em; background-color:grey; border-radius: 2em; display:flex; align-items:center; justify-content:center;')
							:wikitext('-')
							:done()
			end
		else
			c
			:tag('div') -- HTML div to contain the output label
				:attr('title', Output and (Output.Name .. ' <' .. Output.Type .. '>') or '') -- Add a basic mouseover description
				:cssText('text-align: right; overflow: hidden; text-overflow: ellipsis; padding-right: 4px; border-left: 20px solid #11151d; border-bottom: 4px solid #11151d; border-top: 4px solid #11151d; background-color: ' .. GetTypeColor(Output, 0.6) .. ';')
				:wikitext(Output and Output.Name or '')
				:done() -- Close output label div
		end
	end
	-- Create the output (right) attachment point
	CreateConnectorAttachmentPoint(connectorRow, Output, false);
end

--- Creates a new ProtoFlux global input field row in the output
--	@param Container The Scribunto HTML node we'll be creating this row inside of. Should be a container of some sort.
--	@param Global Table containing a Name and Type for the global field on this row.
function CreateGlobalsRow(Container, Global)
	Container
		:tag( 'div' )
			:attr('title', Global.Name .. ' <' .. Global.Type .. '>') -- Add a basic mouseover description
			:cssText('display: flex; min-height: 70px; flex-direction: column; border-left: 10px solid ' .. GetTypeColor(Global, 1.0) .. ';')
			:tag( 'div' )
				:cssText('display: flex; flex-direction: row; align-items: center; flex-grow:1; overflow: hidden;')
				:tag( 'span' )
					:cssText('text-align: center; overflow: hidden; text-overflow: ellipsis; font-size: 14pt; font-weight: bold; flex-grow:1;')
					:wikitext(Global.Name)
					:done()
				:done()
			:tag( 'div' )
				:attr('style', 'display:flex; gap: 10px; flex-grow: 1;')
				:tag('div')
					:cssText('border-radius: 16px; background-color: #777; font-style: italic; text-align:center; flex-grow: 3; display: flex; flex-direction: column; justify-content: center;')
					:tag( 'span' )
						:wikitext('null')
						:done()
					:done()
				:tag( 'div')
					:cssText('border-radius: 16px; background-color: #333; text-align:center; flex-grow: 1; display: flex; flex-direction: column; justify-content: center;')
					:tag ( 'span' )
						:wikitext('∅')   
end

--- Creates a new input or output attachement point for a connector row.
--	@param Container The Scribunto HTML node we'll be creating this row inside of. Should be a container of some sort.
--	@param Connector Table containing a Name (Optional) and Type (Required) for the input/output attachment point.
--	@param isInput	True if this is an input side attachment point, false if it is an output side attachment point.
function CreateConnectorAttachmentPoint(Container, Connector, isInput)
	if Connector and (Connector.Type == "Impulse" or Connector.Type == "AsyncImpulse" or Connector.Type == "Continuation")  then
		Container
			:tag( 'div' )
				:attr('title', Connector and (Connector.Name .. ' <' .. Connector.Type .. '>') or '') -- Add a basic mouseover description
				:cssText('width:30px; background-color: black; fill: ' .. GetTypeColor(Connector, 0.3) .. '; stroke: ' .. GetTypeColor(Connector, 1.0))
				:wikitext(mw.getCurrentFrame():expandTemplate({title = 'ProtoFluxConnector', args = {Type="InputArrow"}}))

	elseif Connector then
		Container
			:tag( 'div' )
				:attr('title', Connector and (Connector.Name .. ' <' .. Connector.Type .. '>') or '') -- Add a basic mouseover description
				:cssText('width:30px; fill: ' .. GetTypeColor(Connector, 0.3) .. '; stroke: ' .. GetTypeColor(Connector, 1.0))
				:wikitext(mw.getCurrentFrame():expandTemplate({title = 'ProtoFluxConnector', args = {Type=(isInput and "InputBox" or "OutputBox")}}))
	end
end

--- Returns an RGBA value representing the type color within Resonite
-- @param Connector Table containing a Name (Optional) and Type (Required) for the input/output attachment point.
-- @param Alpha The alpha to use in the RGBA value. 
function GetTypeColor(Connector, Alpha)
	return (Connector and 'rgba(' .. (typeColor[Connector.Type] or '0, 0, 0') .. ',' .. Alpha .. ')' or 'rgba(0, 0, 0, 0)')
end

return p