Sculpting Pro APi Documentation
Sculpting Pro Realtime
Full solution of sculpting at runtime. Apply this script to any empty object and properly assign all the required fields.
Public Methods
public void SPR_Setup(Camera mainCamera, Transform targetBrush, bool useMultithreading = true, bool customSculpting = false)
// Complete manual setup of the realtime sculpting - call this method if you are going to use a custom sculpting

// Essential Sculpting Methods

public void SPR_OnProcessSculpting()
// Do sculpting by specified settings on this object
public void SPR_OnStopSculpting()
// Stop sculpting (used mostly on 'MouseUp' event) - releases & refreshes required components when user stops sculpting

public void SPR_OnCustomSculpting(SculptingPro_Model targetModel, Vector3 worldPoint, Vector3 worldNormal, bool raiseBrush, float radius, float intensity, bool recordToHistory = true)
// Do custom sculpting by specified settings in the method parameters (Raise/Lower brush feature only)
public void SPR_OnCustomSculpting(SculptingPro_Model targetModel, Vector3 worldPoint, Vector3 worldNormal, Vector3 worldEuler, SculptingPro_HeightmapBrushSrc hbs, float yRotation, float radius, float intensity, bool recordToHistory = true)
// Do custom sculpting by specified settings in the method parameters (Heightmap feature only)
public void SPR_OnCustomSculpting(SculptingPro_Thread.SculptingInputData sidData, bool recordToHistory = true)
// Do custom sculpting by specified settings in the method parameters (Completely custom 'SculptingInputData')

public void SPR_OnEnableDisableSculpting(bool v)
// Enable or Disable sculpting and overall script (safe way than setting enable/disable)

// Essential Variable-Changing Methods

public void SPR_ChangeRadius(float v)
// Change sculpting radius by custom value
public void SPR_ChangeRadius_Add(float addVal)
// Add sculpting radius by custom value
public void SPR_ChangeRadius_Sub(float subVal)
// Subtract sculpting radius by custom value
public void SPR_ChangeIntensity(float v)
// Change sculpting intensity by custom value
public void SPR_ChangeIntensity_Add(float addVal)
// Add sculpting Intensity by custom value
public void SPR_ChangeIntensity_Sub(float subVal)
// Subtract sculpting Intensity by custom value
public void SPR_ChangeBrushState(int v)
// Change a sculpting brush state by existing option [None = 0, Raise = 1, Lower = 2, Revert = 3, Grab = 4, Noise = 5, Smooth = 6, Stylize = 7, Heightmap = 8]

// Advanced Variable-Changing Methods (sculpting type, noise, smoothing...)

public void SPR_ChangeSculptingType(int v)
// Change sculpting type by existing option [VertexNormal = 0, VertexDirection = 1, SurfaceNormal = 2, CustomDirection = 3, CustomObjectForwardDirection = 4]
public void SPR_ChangeNoiseDirection(int v)
// Change noise direction by existing option [XYZ = 0, XZ = 1, XY = 2, YZ = 3, Z = 4, Y = 5, X = 6, Centrical = 7, VertexNormal = 8]
public void SPR_ChangeSmoothingType(int v)
// Change smoothing type by existing option [LaplacianFilter = 0, HCFilter = 1]
public void SPR_ChangeRadiusType(int v)
// Change radius type by existing option [Expontential = 0, Linear = 1]
public void SPR_EnableDisableDistanceLimit(bool v)
// Enable/ Disable distance limitation
public void SPR_ChangeDistanceLimit(float v)
// Change distance limitation by custom value
public void SPR_ChangeSetHeightYValue(float v)
// Change target set height by custom value
public void SPR_ChangeHeightmapBrush(SculptingPro_HeightmapBrushSrc hbs)
// Change the current heightmap brush
public void SPR_ChangeHeightmapBrushRotationOffset(float v)
// Change current heightmap brush rotation Y offset

// Advanced Functions & Other Features

public void SPR_OnUndo()
// Process undo action (if possible)
public void SPR_OnRestoreTarget()
// Restore target to original/ initial mesh data
public void SPR_SubdivideTarget()
// Process subdivision on locked target model
public void SPR_SmoothTarget()
// Process smooth function on locked target model
public void SPR_FlipTarget()
// Process flip function on locked target model
public void SPR_TryCloseSeamsTarget(float v)
// Try to close broken seams on locked target model (input represents a 'looking-distance' for a possible vertices)
public void SPR_TryAutoCloseSeamsTarget(bool v)
// Try to auto-close broken seams on locked target model
Examples
It's possible to create your own sculpting process at runtime from scratch using the available APi above. You don't have to use the built-in functionality in SculptingPro_Realtime.
Before that, make sure the 'Custom Sculpting' field in the SculptingPro_Realtime is enabled. See the example below - sculpting from a specific external object - the external object represents a 'sculpting raycast origin' from which the actual sculpting will happen. It's a simple sculpting process that controls raise/lower brush features in a certain radius.
using UnityEngine;
using SculptingPro;

/// <summary>
/// Example custom sculpting script. The raycast origin is a sampleGameObject. Assign this script to any object and properly assign all the required empty fields.
/// Do not forget to enable Custom Sculpting field in the SculptingPro_Realtime component.
/// The script uses old legacy Input system.
/// </summary>
public class CustomSculpting : MonoBehaviour
{
// Create a reference indicator to the realtime sculpting object - do not forget to enable 'Custom Sculpting' field
public SculptingPro_Realtime realtimeSculpting;
// Sample object for sculpting origin (raycast origin)
public Transform sampleGameObject;
// Target sculpting model (can be also received from the custom raycast...)
public SculptingPro_Model targetModel;
 [Space]
// Essential sculpting parameters for raising/lowering the mesh
public float customRadius = 0.25f;
public float customIntensity = 0.8f;
public bool lowerBrush = false;
public float sampleGameObjectHeight = 0.1f;

private bool doingSculpting = false;

private void Start()
 {
  if (realtimeSculpting == null)
   Debug.LogError("Realtime sculpting component has not been assigned!");
  if (sampleGameObject == null)
   Debug.LogError("Sample Object has not been assigned!");
  if (targetModel == null)
   Debug.LogError("Target Model has not been assigned!");
 }

// Why would I need a custom sculpting? For example you would like to customize where the ray should cast... See the example below.
private void Update()
 {
  // Simple object movement
  Vector3 p = new Vector3
  {
   x = Mathf.Sin(Time.time * 1.5f) * 0.8f,
   z = Mathf.Cos(Time.time * 1.2f) * 0.8f,
   y = sampleGameObjectHeight
  };
  sampleGameObject.position = p;

  // Create a simple raycast process
  Ray r = new Ray(sampleGameObject.position, -sampleGameObject.up);
  // Simple raycast with custom distance
  if (Physics.Raycast(r, out RaycastHit hit, 1.0f))
  {
   if (hit.collider)
   {
    // Call custom sculpting method with required parameters
    // Target model (can be received from the raycast as well)
    //            World hit point
    //               World hit normal
    //                  Raise or lower feature?
    //                       Brush radius
    //                           Brush intensity
    realtimeSculpting.SPR_OnCustomSculpting(targetModel, hit.point, hit.normal, !lowerBrush, customRadius, customIntensity);
    doingSculpting = true;
   }
   else ReleaseSculpting();
  }
  else ReleaseSculpting();
 }

/// <summary>
/// Called if the raycast is lost
/// </summary>
private void ReleaseSculpting()
 {
  // Return if no sculpting is processed
  if (!doingSculpting) return;

  // Required method to call when the sculpting ends!
  realtimeSculpting.SPR_OnStopSculpting();
  doingSculpting = false;
 }
}
If you would like to make a complete sculpting solution from scratch, you can use the advanced features of the SculptingPro APi. There's a class wrapper that holds
all the essential sculpting data called Sculpting Input Data. Certain fields are required to be assigned in your custom sculpting script. See the example below.
The script contains a complete sculpting process build from scratch using Sculpting Input Data. Please pay attention to the comments.
using UnityEngine;
using SculptingPro;

/// <summary>
/// Example custom sculpting script. The raycast origin is a mouse cursour. Assign this script to any object and properly assign all the required empty fields.
/// Do not forget to enable Custom Sculpting field in the SculptingPro_Realtime component.
/// The script uses old legacy Input system.
/// </summary>
public class CustomSculpting : MonoBehaviour
{
// Cache main camera
public Camera mainCamera;
// Set the global brush state
public SculptingPro_Thread.BrushState brushState = SculptingPro_Thread.BrushState.Raise;
// Essential sculpting input data wrapper - here all the required information are stored - please see the class source for detailed info of each field
public SculptingPro_Thread.SculptingInputData sculptingInputData;
// Create a reference indicator to the realtime sculpting object - do not forget to enable 'Custom Sculpting' field
public SculptingPro_Realtime realtimeSculpting;
// Target sculpting model (can be also received from the custom raycast...)
public SculptingPro_Model targetModel;

private bool doingSculpting = false;
private bool grabSet = false;

private void Start()
 {
  if (mainCamera == null)
   Debug.LogError("Main Camera has not been assigned!");
  if (realtimeSculpting == null)
   Debug.LogError("Realtime sculpting component has not been assigned!");
  if (targetModel == null)
   Debug.LogError("Target Model has not been assigned!");
 }

// Why would I need a custom sculpting? For example you would like to customize where the ray should cast... See the example below.
private void Update()
 {
  // Undo when pressed U
  if (Input.GetKeyDown(KeyCode.U))
   realtimeSculpting.SPR_OnUndo();
  // Restore when pressed R
  if (Input.GetKeyDown(KeyCode.R))
   targetModel.RestoreOriginalMesh();
  // And other additional methods can be implemented... (such as subdivide, combine, change radius, intensity, radius type etc)

  // Return if input is not triggered
  if (!Input.GetMouseButton(0))
  {
   ReleaseSculpting();
   return;
  }

  bool grabFeature = brushState == SculptingPro_Thread.BrushState.Grab;

  // If using the Grab brush state, this is required - set the grab origin to the current mouse position
  if (Input.GetMouseButtonDown(0) && grabFeature)
   sculptingInputData.addParams.grabOrigin = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0);

  // Grab feature requires special handling. See below
  if (grabFeature && grabSet)
  {
   // Setting the actual grab direction towards the grab origin and current mouse position
   sculptingInputData.addParams.grabDirection = mainCamera.transform.TransformDirection(
    new Vector3(Input.mousePosition.x - sculptingInputData.addParams.grabOrigin.x, Input.mousePosition.y - sculptingInputData.addParams.grabOrigin.y, 0));
   realtimeSculpting.SPR_OnCustomSculpting(sculptingInputData);
   return;
  }

  // Create a simple raycast process
  Ray r = mainCamera.ScreenPointToRay(Input.mousePosition);
  // Simple raycast with custom distance
  if (Physics.Raycast(r, out RaycastHit hit, Mathf.Infinity))
  {
   if (hit.collider)
   {
    // These are the essential parameters that need to be pushed to the Sculpting Input Data! Without them the sculpting won't properly work.
    var sid = sculptingInputData;
    sid.worldPoint = hit.point;
    sid.normalVector = hit.normal;
    sid.modelInput = targetModel;
    var t = targetModel.transform;
    // Set the model input transform data
    sid.modelTransformData = new SculptingPro_Thread.SculptingInputData.TransformModelData() { pos = t.position, rot = t.rotation, sca = t.lossyScale };
    // Optional parameters that can be set even through the SculptingInputData in the inspector
    sid.addParams.brushState = brushState;
    grabSet = true;
    // Call a custom sculpting method with required Sculpting Input Data assigned above...
    realtimeSculpting.SPR_OnCustomSculpting(sid);
    doingSculpting = true;
   }
   else ReleaseSculpting();
  }
  else ReleaseSculpting();
 }

/// <summary>
/// Called if the raycast is lost
/// </summary>
private void ReleaseSculpting()
 {
  // Return if no sculpting is processed
  if (!doingSculpting) return;

  // Required method to call when the sculpting ends!
  realtimeSculpting.SPR_OnStopSculpting();
  doingSculpting = false;
  grabSet = false;
 }
}