Skip to content

Commit

Permalink
Support shader int uniform
Browse files Browse the repository at this point in the history
Towards: #1830
  • Loading branch information
yiqunw700 committed Jan 24, 2025
1 parent 03bc675 commit 746337a
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 2 deletions.
10 changes: 9 additions & 1 deletion crates/figma_import/src/shader_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
use crate::figma_schema::FigmaColor;
use dc_bundle::definition::view::shader_uniform_value::FloatVec;
use dc_bundle::definition::view::shader_uniform_value::ValueType::{
FloatColorValue, FloatValue, FloatVecValue,
FloatColorValue, FloatValue, FloatVecValue, IntValue,
};
use dc_bundle::definition::view::{ShaderUniform, ShaderUniformValue};
use log::error;
Expand Down Expand Up @@ -74,6 +74,14 @@ impl Into<(String, ShaderUniform)> for ShaderUniformJson {
value_type: Some(FloatColorValue(parsed_color)),
})
}
"int" => {
if let Some(int_val) = self.uniform_value.as_i64() {
Some(ShaderUniformValue { value_type: Some(IntValue(int_val as i32)) })
} else {
error!("Error parsing integer for shader int uniform {}", self.uniform_name);
None
}
}
_ => None,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,11 @@ fun ShaderUniform.applyToShader(
else -> Log.e(TAG, "Invalid shader uniform $name $definedType")
}
}
ValueTypeCase.INT_VALUE -> {
if (definedType == "int") {
shader.setIntUniform(name, value.intValue)
}
}

else -> {
Log.w(TAG, "Invalid shader uniform $name")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import android.os.Build
import androidx.compose.animation.core.withInfiniteAnimationFrameMillis
import androidx.compose.runtime.Composable
import androidx.compose.runtime.FloatState
import androidx.compose.runtime.IntState
import androidx.compose.runtime.State
import androidx.compose.runtime.asFloatState
import androidx.compose.runtime.derivedStateOf
Expand Down Expand Up @@ -91,4 +92,18 @@ object ShaderHelper {
): State<ShaderUniform> {
return remember { derivedStateOf { value.toShaderUniform(name) } }
}

/** Creates a shader uniform from an int value. */
fun createShaderIntUniform(name: String, value: Int): ShaderUniform {
return shaderUniform {
this.name = name
this.value = shaderUniformValue { intValue = value }
}
}

/** Creates a state of shader uniform from an int state. */
@Composable
fun IntState.toShaderUniformState(name: String): State<ShaderUniform> {
return remember { derivedStateOf { createShaderIntUniform(name, intValue) } }
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package com.android.designcompose.testapp.validation.examples

import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.asIntState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.Color
Expand All @@ -42,6 +43,7 @@ interface BrushFromShaderPluginTest {
@Design(node = "#color-custom") customColors: ShaderUniformList,
@Design(node = "#text-color-custom") customTextColors: ShaderUniformList,
@Design(node = "#color-state-custom") customColorStates: ShaderUniformStateList,
@Design(node = "#int-state-custom") customIntStates: ShaderUniformStateList,
)
}

Expand Down Expand Up @@ -70,11 +72,16 @@ fun BrushFromShaderPluginTest() {
)
val colorState = remember { derivedStateOf { colors[iTimeState.floatValue.toInt() % 2] } }
customColorStates.add(colorState.toShaderUniformState("iColor"))

val customIntStates = ArrayList<State<ShaderUniform>>()
val intState = remember { derivedStateOf { iTimeState.floatValue.toInt() % 5 }.asIntState() }
customIntStates.add(intState.toShaderUniformState("iCase"))
BrushFromShaderPluginTestDoc.MainFrame(
rootShaderUniformStates = rootShaderUniformStates,
rootShaderUniforms = rootShaderUniforms,
customColors = customColors,
customTextColors = customColors,
customColorStates = customColorStates,
customIntStates = customIntStates,
)
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions proto/definition/view/view.proto
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ message ShaderUniformValue {
// uniform "type" is "color3" or "color4" in the plugin data. Alpha would be
// ignored for "color3" when set uniform value to the runtime shader.
definition.element.FloatColor float_color_value = 3;

int32 int_value = 4;
}
}

Expand Down
66 changes: 65 additions & 1 deletion support-figma/extended-layout-plugin/src/shader.html
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@
<label><input type="radio" name="uniformType" value="floatArray">Float Array</label>
<br>
<label><input type="radio" name="uniformType" value="color">Color</label>
<br>
<label><input type="radio" name="uniformType" value="int">Int</label>
</p>
<div style="display: flex; gap: 4px;">
<button id="continueButton" class="button--primary" style="flex-grow: 1;"
Expand Down Expand Up @@ -177,6 +179,20 @@
</div>
</dialog>

<dialog id="createIntUniformDialog">
<div><b>Create int uniform</b></div>
<p>
<div style="display: flex; gap: 8px;">
<label for="intUniformName" style="flex-grow: 1;">Name:</label>
<input type="text" id="intUniformName" placeholder="iCase" autofocus></input>
</div>
</p>
<div style="display: flex; gap: 4px;">
<button id="createIntUniformButton" class="button--primary" style="flex-grow: 1;">Create</button>
<button id="closeIntUniformButton" class="button--primary" style="flex-grow: 1;">Close</button>
</div>
</dialog>

</div>
<!-- END OF SHADER PLUGIN UI -->

Expand Down Expand Up @@ -217,6 +233,7 @@
const createFloatUniformDialog = document.getElementById("createFloatUniformDialog");
const createFloatArrayUniformDialog = document.getElementById("createFloatArrayUniformDialog");
const createColorUniformDialog = document.getElementById("createColorUniformDialog");
const createIntUniformDialog = document.getElementById("createIntUniformDialog");

function createUniform() {
createUniformDialog.showModal();
Expand All @@ -235,6 +252,9 @@
case "color":
createColorUniformDialog.showModal();
break;
case "int":
createIntUniformDialog.showModal();
break;
}
createUniformDialog.close();
} else {
Expand Down Expand Up @@ -390,6 +410,42 @@
createColorUniformDialog.close();
};

const createIntUniformButton = document.getElementById("createIntUniformButton");
const closeIntUniformButton = document.getElementById("closeIntUniformButton");
const intUniformNameInput = document.getElementById("intUniformName");

// "Create" button closes the dialog and creates the uniform
createIntUniformButton.onclick = async () => {
const uniformName = intUniformNameInput.value;
createShaderIntUniform(intUniformNameInput.value, null);
await runShader();
};

function createShaderIntUniform(uniformName, intValue) {
let newUniformEntry = createShaderUniform(uniformName, "int");
if (!newUniformEntry) {
return;
}

// Uniform is created successfully. Close the creation dialog.
createIntUniformDialog.close();

// Create inputs fields
const inputsLine = document.createElement("div");
let input = document.createElement("input");
input.id = `input_${uniformName}`;
input.type = "number";
input.value = intValue ? intValue : 0;
inputsLine.appendChild(input);
newUniformEntry.appendChild(inputsLine);

uniforms.appendChild(newUniformEntry);
}

closeIntUniformButton.onclick = () => {
createIntUniformDialog.close();
};

function createShaderUniform(uniformName, uniformType) {
if (presetUniforms.includes(uniformName) || customUniforms.includes(uniformName)) {
alert("This uniform already exists, please use a different name.");
Expand Down Expand Up @@ -494,6 +550,9 @@
floatArray.push(parseFloat(alpha.value));
}
return floatArray;
case "int":
const input = document.getElementById(`input_${uniform}`);
return parseInt(input.value);
}
}

Expand All @@ -504,6 +563,7 @@
case "float2":
case "float3":
case "float4":
case "int":
return previewUniformValue(uniform);
case "color3":
case "color4":
Expand Down Expand Up @@ -666,6 +726,7 @@
};
shaderUniforms.push(shaderUniform);
});

const color = useShaderFallbackColor.checked ? "#FF46A2" : undefined;
parent.postMessage({
pluginMessage: {
Expand Down Expand Up @@ -731,6 +792,7 @@
nodeActions.style.display = "block";
document.getElementById("nodeId").innerHTML = `Node selected: ${msg.nodeId}`;
if (msg.shader) {
loadShaderButton.style.display = "block";
loadShaderButton.onclick = async () => {
clearUniforms();
shaderCodeInput.value = msg.shader;
Expand All @@ -754,12 +816,14 @@
case "color4":
createShaderColorUniform(shaderUniform.uniformName, shaderUniform.uniformType, shaderUniform.uniformValue);
break;
case "int":
createShaderIntUniform(shaderUniform.uniformName, shaderUniform.uniformValue);
break;
}
console.log(`${shaderUniform.uniformName} ${shaderUniform.uniformType} = ${shaderUniform.uniformValue}`);
}
await runShader();
};
loadShaderButton.style.display = "block";
} else {
loadShaderButton.style.display = "none";
}
Expand Down

0 comments on commit 746337a

Please sign in to comment.