The Parallax Processor is a compact, turnkey automation and control solution designed for customizable deployments. It offers a cost-effective yet robust alternative to traditional systems. With built-in support for GPIO, RS232, and IP control, this versatile system can be readily adapted to a wide range of automation tasks.
The platform comes pre-configured with a Linux-based operating system, complete with Node-RED for logic programming, providing a streamlined setup that allows developers to focus solely on user interface design and logic. Unity software serves as the backbone for frontend development, offering an intuitive yet powerful way to create sophisticated user interfaces. The interconnection between Unity, Node-RED and the .NET console app is pre-established, eliminating the need for additional integration work.
Additionally, the ParallaxUnityLibrary Plugin allows UI programmers to easily drag and drop pre-made scripts onto UI objects, which then automatically integrates them with the control system. This makes it an ideal choice for programmers looking for an all-in-one solution with minimal setup requirements.
Parallax Control Processor: Typical programmer work-flow
Main Components of the Control System:
ParallaxUnityLibrary
: A plugin designed for use with Unity Software. (Note: Unity Software must be obtained separately.)ParallaxControlSystemLibrary
: A plugin intended for integration with a .NET console application.The Parallax Control System utilizes MQTT for communication between the control panel and control processor. Programmers have the option of choosing to handle logic programming in either Node Red or a c# console application depending on preference. The MQTT broker should be setup on the Node-RED server to facilitate communication between system components.
Coming Soon: Integration with .NET MAUI
We are currently expanding our libraries to support ease of deployment for UI with .NET MAUI. .NET MAUI is an evolution of Xamarin.Forms
.NET MAUI was designed to simplify cross-platform app development by offering a unified API and UI framework for building native user interfaces on various platforms. It allows developers to write code once and target multiple platforms, reducing the need to write platform-specific code for each target.
Node Red acts as the MQTT Broker, or message handler. It is the relay of all messages between the control panel and the processor.
The decision to use .net or node red to handle the programming logic depends on the use case and preference of the programmer.
Parallax provides a set of custom nodes for handling logic, and the programmer has the ability to create custom nodes using javascript.
How messages are structured:
MESSAGE COMPONENTS:
INSTANCE ID,
VALUE,
TOPIC
Install Unity Hub:
Add your platform build support. This allows Unity to build UI for those platforms.
Select 2D Core application, Select an Editor Version with LTS that fits your machine.
Follow the steps below to confirm the Api Compatibility Level is set correctly in your Unity Project.
In Unity, navigate to File -> Build Settings. Select Player Settings.
Under Player tab, select Other Settings. Scroll down to Configuration.
Ensure .NET Framework is selected.
If .NET Standard 2.1 is selected by default, you will experience error messages when adding the Parallax plugin for Unity, set it to .NET framework
To add UnityParallaxLibraryMerged.dll to your project simply drag the file into your assets folder.
Press the arrow to expand and view the available scripts for use in your UI program. These scripts can be dragged directly onto objects to enable communication with the control system.
Start a new .NET MAUI project (Note: the Parallax Library is not compatible with Xamarin, you must upgrade to MAUI):
Rider IDE
Add the ParallaxControlSystemLibrary to your project:
The ParallaxControlSystemLibrary offers access to pre-built classes, including the 'MqttBrokerProgram' class, which enables you to easily create an MQTT client by utilizing predefined functions.
Using the "MqttBrokerProgram" class from the "ParallaxControlSystemLibrary" allows the programmer to quickly and easily set up an MQTT client, saving time and effort that would otherwise be spent on writing and debugging MQTT client code from scratch.
Note: Currently this method is being deprecated, the UI will connect to the node red server where the mqtt broker will handle communication. You may use .net for programming by creating a mqtt client and using the pub/sub method.
.NET Connection User Guide
UnityParallaxLibraryMerged.dll, Processor_DotNet.cs
This user guide explains how to use the Processor_DotNet
script included in the Parallax Unity Library plugin.
Using the ParallaxUnityLibrary.dll, Processor_DotNet.cs file
Enter the IP address of the processor.
Port 50001 is by default the first program slot.
Note: as of writing, the system only accepts 1 programming slot. Additional slots which can accommodate unique programs is planned for a future release.
Lastly, press the play button to connect to the control processor.
ParallaxProcessor Script User Guide
This guide outlines the process for setting up the ParallaxProcessor script in your Unity Editor. The script allows for simplified MQTT message handling between the UI and the Control Processor running Node Red.
Steps
Go to the Hierarchy window.
Right-click, then choose Create -> Empty.
Note that the GameObject must be a root in the hierarchy:
With the new empty GameObject selected, drag the ParallaxProcessor script from within the ParallaxUnityLibrary plugin to the object.
After attaching the script, you will see various public fields that need to be filled in.
Provide the MQTT Server Host, Port, User Name, and Password to connect to the processors MQTT broker.
In the Topics To Subscribe field, input the MQTT topics you want to subscribe to. This field accepts an array of strings. Use the + button to add more elements to the array, and fill in the desired topics.
Note that the topics should match the inputs/outputs you’ve defined in your Node Red program.
Be sure the Node Red MQTT Server is deployed and running.
After setting up, make sure to run your Unity scene to test if the MQTT connection is working as expected. Debug logs will provide information on incoming and outgoing messages.
Press the play button, check the Console to see the connection status. Debug shows if the connection has been established:
Access MQTT Server Web Page on the device:
The MQTT Node Red server comes pre-installed on the processor. The web page is accessible by the processors IP Address, at port 1880.
User: admin
Password:
Default Programmatic Access Port: 1883
Default Web Page Port: 1880
Login to the Node Red web page to begin your logic programming.
Note: you may also spin up a node red server on your local machine for pre-programming and testing.
File -> Build Settings
Select the scene (Scene In Build), and select the platform of choice. Unity will then build the necessary files to the folder location of your choosing (create a new UI Build folder for these files).
Building to android is straight forward, it creates a .apk file which can be transferred to your android device via usb or Bluetooth.
Building to apple devices requires an extra step, requires you to have xcode installed on a mac. Please look up instructions online for building Unity apps for mac (non app store).
UTILIZING THE UNITY ASSET STORE:
The Unity asset store is full of asset packages that can be imported and used in your project. Items such as custom buttons and prefabs can be bought to speed up development. Additionally, one of the benefits to using Unity is the ability to create custom prefabs, such as expandable button menus or other dynamic and customizable widgets that can be reused as a standard from project to project.
To connect the touchpanel directly (wirelessly) to the control processors on-board access-point, ensure the touch-panels ip address is set to DHCP as it will acquire an address from the access point. The default SSID is cm4-. The default password is the control processors mac address (all lower-case, no colons).
Note: If connecting to the onboard access point (by wireless laptop, or wireless tablet), the client device will acquire an address in the 192.168.10.0 subnet from the server (processor).
The processor will have a static ip address of 192.168.10.10 on its wireless access point by default.
LOADING USER-INTERFACE PROGRAM TO THE PARALLAX POE TOUCHPANEL:
If using the PoE Android Touchpanel, download the Android File Transfer tool and put the .apk in the touchpanels download folder. A connection can be made by Bluetooth, or usb (recommended). Select apkinstaller -> Install, navigate to the download folder and select the .apk you just built.
SET THE BOOT UI APP:
On the home screen, navigate to settings -> accessibility -> boot app, select your application (must be installed already for it to show on the list).
LOCK/UNLOCK THE UI APP USING THE SERVICE ONLY EXIT SEQUENCE:
To prevent end-users from getting out of the app, press the power button on the back of the touchpanel 3 times within 5 seconds. Test the current state of the app lock/unlock feature by dragging your finger from the bottom of the screen upwards, or from the top downwards. If the app is not locked, you will see the android menus. If the screen is successfully locked no exit or settings menu will appear.
TESTING THE BOOT UI APP AND APP LOCK/UNLOCK FEATURE:
After setting your application to auto-start, and setting the app lock feature, do a full test by simulating a power loss; remove the POE plug from the back of the unit. Plug the POE back into the unit. Once the touchpanel starts it should immediately load your custom .apk user-interface. There should be no way for the user to exit the application.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut orci sapien, cursus tempor aliquet eget, dapibus sed mauris. Duis vehicula non elit id tristique. Integer ut nisi a ligula bibendum luctus. Ut varius pellentesque pellentesque. Mauris tincidunt tellus at sapien sagittis mattis. Proin laoreet lacus eget rutrum aliquam. Nulla porttitor imperdiet posuere. Fusce consectetur hendrerit lacus eget molestie. Integer dolor augue, dictum eu justo sed, efficitur molestie urna. Ut cursus lorem ligula, sed mattis tortor volutpat nec.
Proin semper lobortis felis, vel finibus ipsum mattis quis. Nulla ullamcorper leo eu felis consequat consequat. Donec dignissim accumsan ipsum nec interdum. Donec quis semper nisi. Quisque at sem bibendum, sodales sapien et, ultricies orci. Sed nec sapien eu odio aliquet faucibus vitae nec sem. Sed sed elit porttitor, lobortis nunc quis, efficitur orci. Mauris vehicula ultrices sagittis.
In non imperdiet est. Suspendisse consequat eget libero quis tempus. Suspendisse felis purus, ultrices sed semper sed, malesuada a erat. Sed faucibus a ante at tempor. Etiam lectus est, porta et mauris non, accumsan convallis felis. Suspendisse ut maximus est, quis ornare erat. Maecenas finibus purus ut auctor dignissim. Cras vel nisl dictum, elementum ex non, sollicitudin urna. Nam congue urna consectetur leo vehicula porta eu non justo. Nam ultrices finibus congue. Quisque auctor hendrerit augue, et congue erat fringilla sed. Ut pellentesque diam a suscipit facilisis. Donec eleifend sollicitudin facilisis. Sed ultricies efficitur ante a vehicula.
Nunc ultricies porta libero, sed placerat dui sagittis posuere. Aliquam eget scelerisque orci. Phasellus sollicitudin orci vel turpis semper bibendum. Pellentesque odio justo, elementum nec ex vel, sollicitudin rutrum sem. Phasellus quis enim aliquet, porta arcu et, eleifend orci. Mauris consequat consectetur pretium. Donec vitae tellus maximus, convallis tortor sit amet, viverra quam.
Vestibulum mollis elit felis, maximus bibendum risus egestas id. Maecenas placerat auctor odio, nec dignissim nisi tincidunt vitae. Nulla quis gravida nisl. Proin hendrerit nibh elit, at eleifend ligula placerat eu. Cras ipsum erat, dapibus vel mauris bibendum, rutrum tincidunt arcu. Sed aliquet dapibus ante. Aenean pharetra, mauris aliquet placerat cursus, turpis mauris dictum ligula, suscipit sollicitudin massa metus vitae urna. Vivamus imperdiet, urna vitae gravida convallis, sem ligula egestas mauris, et iaculis ex arcu et lorem. Vestibulum porttitor massa neque, quis tempor sem ornare et. Sed quis pretium dolor. Suspendisse nibh eros, finibus at nisl id, sodales mollis tellus. Nam condimentum turpis nec eros rhoncus, eget imperdiet tellus suscipit. Sed nec commodo augue, sed fringilla nisl. Fusce lacinia arcu at blandit tristique.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut orci sapien, cursus tempor aliquet eget, dapibus sed mauris. Duis vehicula non elit id tristique. Integer ut nisi a ligula bibendum luctus. Ut varius pellentesque pellentesque. Mauris tincidunt tellus at sapien sagittis mattis. Proin laoreet lacus eget rutrum aliquam. Nulla porttitor imperdiet posuere. Fusce consectetur hendrerit lacus eget molestie. Integer dolor augue, dictum eu justo sed, efficitur molestie urna. Ut cursus lorem ligula, sed mattis tortor volutpat nec.
Proin semper lobortis felis, vel finibus ipsum mattis quis. Nulla ullamcorper leo eu felis consequat consequat. Donec dignissim accumsan ipsum nec interdum. Donec quis semper nisi. Quisque at sem bibendum, sodales sapien et, ultricies orci. Sed nec sapien eu odio aliquet faucibus vitae nec sem. Sed sed elit porttitor, lobortis nunc quis, efficitur orci. Mauris vehicula ultrices sagittis.
In non imperdiet est. Suspendisse consequat eget libero quis tempus. Suspendisse felis purus, ultrices sed semper sed, malesuada a erat. Sed faucibus a ante at tempor. Etiam lectus est, porta et mauris non, accumsan convallis felis. Suspendisse ut maximus est, quis ornare erat. Maecenas finibus purus ut auctor dignissim. Cras vel nisl dictum, elementum ex non, sollicitudin urna. Nam congue urna consectetur leo vehicula porta eu non justo. Nam ultrices finibus congue. Quisque auctor hendrerit augue, et congue erat fringilla sed. Ut pellentesque diam a suscipit facilisis. Donec eleifend sollicitudin facilisis. Sed ultricies efficitur ante a vehicula.
Nunc ultricies porta libero, sed placerat dui sagittis posuere. Aliquam eget scelerisque orci. Phasellus sollicitudin orci vel turpis semper bibendum. Pellentesque odio justo, elementum nec ex vel, sollicitudin rutrum sem. Phasellus quis enim aliquet, porta arcu et, eleifend orci. Mauris consequat consectetur pretium. Donec vitae tellus maximus, convallis tortor sit amet, viverra quam.
Vestibulum mollis elit felis, maximus bibendum risus egestas id. Maecenas placerat auctor odio, nec dignissim nisi tincidunt vitae. Nulla quis gravida nisl. Proin hendrerit nibh elit, at eleifend ligula placerat eu. Cras ipsum erat, dapibus vel mauris bibendum, rutrum tincidunt arcu. Sed aliquet dapibus ante. Aenean pharetra, mauris aliquet placerat cursus, turpis mauris dictum ligula, suscipit sollicitudin massa metus vitae urna. Vivamus imperdiet, urna vitae gravida convallis, sem ligula egestas mauris, et iaculis ex arcu et lorem. Vestibulum porttitor massa neque, quis tempor sem ornare et. Sed quis pretium dolor. Suspendisse nibh eros, finibus at nisl id, sodales mollis tellus. Nam condimentum turpis nec eros rhoncus, eget imperdiet tellus suscipit. Sed nec commodo augue, sed fringilla nisl. Fusce lacinia arcu at blandit tristique.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut orci sapien, cursus tempor aliquet eget, dapibus sed mauris. Duis vehicula non elit id tristique. Integer ut nisi a ligula bibendum luctus. Ut varius pellentesque pellentesque. Mauris tincidunt tellus at sapien sagittis mattis. Proin laoreet lacus eget rutrum aliquam. Nulla porttitor imperdiet posuere. Fusce consectetur hendrerit lacus eget molestie. Integer dolor augue, dictum eu justo sed, efficitur molestie urna. Ut cursus lorem ligula, sed mattis tortor volutpat nec.
Proin semper lobortis felis, vel finibus ipsum mattis quis. Nulla ullamcorper leo eu felis consequat consequat. Donec dignissim accumsan ipsum nec interdum. Donec quis semper nisi. Quisque at sem bibendum, sodales sapien et, ultricies orci. Sed nec sapien eu odio aliquet faucibus vitae nec sem. Sed sed elit porttitor, lobortis nunc quis, efficitur orci. Mauris vehicula ultrices sagittis.
In non imperdiet est. Suspendisse consequat eget libero quis tempus. Suspendisse felis purus, ultrices sed semper sed, malesuada a erat. Sed faucibus a ante at tempor. Etiam lectus est, porta et mauris non, accumsan convallis felis. Suspendisse ut maximus est, quis ornare erat. Maecenas finibus purus ut auctor dignissim. Cras vel nisl dictum, elementum ex non, sollicitudin urna. Nam congue urna consectetur leo vehicula porta eu non justo. Nam ultrices finibus congue. Quisque auctor hendrerit augue, et congue erat fringilla sed. Ut pellentesque diam a suscipit facilisis. Donec eleifend sollicitudin facilisis. Sed ultricies efficitur ante a vehicula.
Nunc ultricies porta libero, sed placerat dui sagittis posuere. Aliquam eget scelerisque orci. Phasellus sollicitudin orci vel turpis semper bibendum. Pellentesque odio justo, elementum nec ex vel, sollicitudin rutrum sem. Phasellus quis enim aliquet, porta arcu et, eleifend orci. Mauris consequat consectetur pretium. Donec vitae tellus maximus, convallis tortor sit amet, viverra quam.
Vestibulum mollis elit felis, maximus bibendum risus egestas id. Maecenas placerat auctor odio, nec dignissim nisi tincidunt vitae. Nulla quis gravida nisl. Proin hendrerit nibh elit, at eleifend ligula placerat eu. Cras ipsum erat, dapibus vel mauris bibendum, rutrum tincidunt arcu. Sed aliquet dapibus ante. Aenean pharetra, mauris aliquet placerat cursus, turpis mauris dictum ligula, suscipit sollicitudin massa metus vitae urna. Vivamus imperdiet, urna vitae gravida convallis, sem ligula egestas mauris, et iaculis ex arcu et lorem. Vestibulum porttitor massa neque, quis tempor sem ornare et. Sed quis pretium dolor. Suspendisse nibh eros, finibus at nisl id, sodales mollis tellus. Nam condimentum turpis nec eros rhoncus, eget imperdiet tellus suscipit. Sed nec commodo augue, sed fringilla nisl. Fusce lacinia arcu at blandit tristique.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut orci sapien, cursus tempor aliquet eget, dapibus sed mauris. Duis vehicula non elit id tristique. Integer ut nisi a ligula bibendum luctus. Ut varius pellentesque pellentesque. Mauris tincidunt tellus at sapien sagittis mattis. Proin laoreet lacus eget rutrum aliquam. Nulla porttitor imperdiet posuere. Fusce consectetur hendrerit lacus eget molestie. Integer dolor augue, dictum eu justo sed, efficitur molestie urna. Ut cursus lorem ligula, sed mattis tortor volutpat nec.
Proin semper lobortis felis, vel finibus ipsum mattis quis. Nulla ullamcorper leo eu felis consequat consequat. Donec dignissim accumsan ipsum nec interdum. Donec quis semper nisi. Quisque at sem bibendum, sodales sapien et, ultricies orci. Sed nec sapien eu odio aliquet faucibus vitae nec sem. Sed sed elit porttitor, lobortis nunc quis, efficitur orci. Mauris vehicula ultrices sagittis.
In non imperdiet est. Suspendisse consequat eget libero quis tempus. Suspendisse felis purus, ultrices sed semper sed, malesuada a erat. Sed faucibus a ante at tempor. Etiam lectus est, porta et mauris non, accumsan convallis felis. Suspendisse ut maximus est, quis ornare erat. Maecenas finibus purus ut auctor dignissim. Cras vel nisl dictum, elementum ex non, sollicitudin urna. Nam congue urna consectetur leo vehicula porta eu non justo. Nam ultrices finibus congue. Quisque auctor hendrerit augue, et congue erat fringilla sed. Ut pellentesque diam a suscipit facilisis. Donec eleifend sollicitudin facilisis. Sed ultricies efficitur ante a vehicula.
Nunc ultricies porta libero, sed placerat dui sagittis posuere. Aliquam eget scelerisque orci. Phasellus sollicitudin orci vel turpis semper bibendum. Pellentesque odio justo, elementum nec ex vel, sollicitudin rutrum sem. Phasellus quis enim aliquet, porta arcu et, eleifend orci. Mauris consequat consectetur pretium. Donec vitae tellus maximus, convallis tortor sit amet, viverra quam.
Vestibulum mollis elit felis, maximus bibendum risus egestas id. Maecenas placerat auctor odio, nec dignissim nisi tincidunt vitae. Nulla quis gravida nisl. Proin hendrerit nibh elit, at eleifend ligula placerat eu. Cras ipsum erat, dapibus vel mauris bibendum, rutrum tincidunt arcu. Sed aliquet dapibus ante. Aenean pharetra, mauris aliquet placerat cursus, turpis mauris dictum ligula, suscipit sollicitudin massa metus vitae urna. Vivamus imperdiet, urna vitae gravida convallis, sem ligula egestas mauris, et iaculis ex arcu et lorem. Vestibulum porttitor massa neque, quis tempor sem ornare et. Sed quis pretium dolor. Suspendisse nibh eros, finibus at nisl id, sodales mollis tellus. Nam condimentum turpis nec eros rhoncus, eget imperdiet tellus suscipit. Sed nec commodo augue, sed fringilla nisl. Fusce lacinia arcu at blandit tristique.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut orci sapien, cursus tempor aliquet eget, dapibus sed mauris. Duis vehicula non elit id tristique. Integer ut nisi a ligula bibendum luctus. Ut varius pellentesque pellentesque. Mauris tincidunt tellus at sapien sagittis mattis. Proin laoreet lacus eget rutrum aliquam. Nulla porttitor imperdiet posuere. Fusce consectetur hendrerit lacus eget molestie. Integer dolor augue, dictum eu justo sed, efficitur molestie urna. Ut cursus lorem ligula, sed mattis tortor volutpat nec.
Proin semper lobortis felis, vel finibus ipsum mattis quis. Nulla ullamcorper leo eu felis consequat consequat. Donec dignissim accumsan ipsum nec interdum. Donec quis semper nisi. Quisque at sem bibendum, sodales sapien et, ultricies orci. Sed nec sapien eu odio aliquet faucibus vitae nec sem. Sed sed elit porttitor, lobortis nunc quis, efficitur orci. Mauris vehicula ultrices sagittis.
In non imperdiet est. Suspendisse consequat eget libero quis tempus. Suspendisse felis purus, ultrices sed semper sed, malesuada a erat. Sed faucibus a ante at tempor. Etiam lectus est, porta et mauris non, accumsan convallis felis. Suspendisse ut maximus est, quis ornare erat. Maecenas finibus purus ut auctor dignissim. Cras vel nisl dictum, elementum ex non, sollicitudin urna. Nam congue urna consectetur leo vehicula porta eu non justo. Nam ultrices finibus congue. Quisque auctor hendrerit augue, et congue erat fringilla sed. Ut pellentesque diam a suscipit facilisis. Donec eleifend sollicitudin facilisis. Sed ultricies efficitur ante a vehicula.
Nunc ultricies porta libero, sed placerat dui sagittis posuere. Aliquam eget scelerisque orci. Phasellus sollicitudin orci vel turpis semper bibendum. Pellentesque odio justo, elementum nec ex vel, sollicitudin rutrum sem. Phasellus quis enim aliquet, porta arcu et, eleifend orci. Mauris consequat consectetur pretium. Donec vitae tellus maximus, convallis tortor sit amet, viverra quam.
Vestibulum mollis elit felis, maximus bibendum risus egestas id. Maecenas placerat auctor odio, nec dignissim nisi tincidunt vitae. Nulla quis gravida nisl. Proin hendrerit nibh elit, at eleifend ligula placerat eu. Cras ipsum erat, dapibus vel mauris bibendum, rutrum tincidunt arcu. Sed aliquet dapibus ante. Aenean pharetra, mauris aliquet placerat cursus, turpis mauris dictum ligula, suscipit sollicitudin massa metus vitae urna. Vivamus imperdiet, urna vitae gravida convallis, sem ligula egestas mauris, et iaculis ex arcu et lorem. Vestibulum porttitor massa neque, quis tempor sem ornare et. Sed quis pretium dolor. Suspendisse nibh eros, finibus at nisl id, sodales mollis tellus. Nam condimentum turpis nec eros rhoncus, eget imperdiet tellus suscipit. Sed nec commodo augue, sed fringilla nisl. Fusce lacinia arcu at blandit tristique.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut orci sapien, cursus tempor aliquet eget, dapibus sed mauris. Duis vehicula non elit id tristique. Integer ut nisi a ligula bibendum luctus. Ut varius pellentesque pellentesque. Mauris tincidunt tellus at sapien sagittis mattis. Proin laoreet lacus eget rutrum aliquam. Nulla porttitor imperdiet posuere. Fusce consectetur hendrerit lacus eget molestie. Integer dolor augue, dictum eu justo sed, efficitur molestie urna. Ut cursus lorem ligula, sed mattis tortor volutpat nec.
Proin semper lobortis felis, vel finibus ipsum mattis quis. Nulla ullamcorper leo eu felis consequat consequat. Donec dignissim accumsan ipsum nec interdum. Donec quis semper nisi. Quisque at sem bibendum, sodales sapien et, ultricies orci. Sed nec sapien eu odio aliquet faucibus vitae nec sem. Sed sed elit porttitor, lobortis nunc quis, efficitur orci. Mauris vehicula ultrices sagittis.
In non imperdiet est. Suspendisse consequat eget libero quis tempus. Suspendisse felis purus, ultrices sed semper sed, malesuada a erat. Sed faucibus a ante at tempor. Etiam lectus est, porta et mauris non, accumsan convallis felis. Suspendisse ut maximus est, quis ornare erat. Maecenas finibus purus ut auctor dignissim. Cras vel nisl dictum, elementum ex non, sollicitudin urna. Nam congue urna consectetur leo vehicula porta eu non justo. Nam ultrices finibus congue. Quisque auctor hendrerit augue, et congue erat fringilla sed. Ut pellentesque diam a suscipit facilisis. Donec eleifend sollicitudin facilisis. Sed ultricies efficitur ante a vehicula.
Nunc ultricies porta libero, sed placerat dui sagittis posuere. Aliquam eget scelerisque orci. Phasellus sollicitudin orci vel turpis semper bibendum. Pellentesque odio justo, elementum nec ex vel, sollicitudin rutrum sem. Phasellus quis enim aliquet, porta arcu et, eleifend orci. Mauris consequat consectetur pretium. Donec vitae tellus maximus, convallis tortor sit amet, viverra quam.
Vestibulum mollis elit felis, maximus bibendum risus egestas id. Maecenas placerat auctor odio, nec dignissim nisi tincidunt vitae. Nulla quis gravida nisl. Proin hendrerit nibh elit, at eleifend ligula placerat eu. Cras ipsum erat, dapibus vel mauris bibendum, rutrum tincidunt arcu. Sed aliquet dapibus ante. Aenean pharetra, mauris aliquet placerat cursus, turpis mauris dictum ligula, suscipit sollicitudin massa metus vitae urna. Vivamus imperdiet, urna vitae gravida convallis, sem ligula egestas mauris, et iaculis ex arcu et lorem. Vestibulum porttitor massa neque, quis tempor sem ornare et. Sed quis pretium dolor. Suspendisse nibh eros, finibus at nisl id, sodales mollis tellus. Nam condimentum turpis nec eros rhoncus, eget imperdiet tellus suscipit. Sed nec commodo augue, sed fringilla nisl. Fusce lacinia arcu at blandit tristique.
The default layout
This is the default layout when starting a new project. Rename your scene.
iPhone 12 selected in simulator
Select the Game Tab, then in the drop down, select Simulator, select your device.
Scene tab
In the scene tab you'll see an outline of your workspace. Since we are working in 2D, we can delete the "Main Camera" object.
Add Canvas
Right click to show all the available UI elements to add to your project.
After deleting the Main Camera, add a Canvas to the scene. This will be your main workspace area.
Modify Canvas
After adding the Canvas to the scene, a Canvas Scaler will appear in the Inspector panel. Modify the Render Mode to: Overlay and Screen Match Mode to: Shrink
You are now ready to start laying out the canvas with UI elements.
Add an Image to the scene
Right click Canvas -> UI -> Image
Set the alignment of your newly added Image object
Press Alt and the bottom right option to expand the Image object to fill the space
Expand the image to the extents of the workspace.
You now have a white background.
To learn more about anchoring and aligning objects using the RectTransform, watch this video: https://youtu.be/FeheZqu85WI
View your background on the iPad
Select Simulator -> Select iPad Pro 12.9
Verify your background scales correctly in both portrait and landscape by pressing the Rotate button:
Now that you've added a background to the image, we will overlay a background logo. The final result will look like so:
The image for the logo will be a child component of the background image we created in the previous section.
Right click the background object, add another image. In the Inspector, the Source Image property field accepts a .png. Drag your image to this field.
For organizational purposes, it recommended to create folders for your images. Navigate to the Assets folder, right click Create Folder, name the folder Images.
Drag your image, select It is likely you will want to select Preserve Aspect to maintain the proportions of your image.
Add Header, Footer, Body, Navigation and Pages to the Canvas workspace area.
Current Hierarchy
Under the "bg" component, add a new Empty GameObject, name it "top". Notice the "top" object is now a child of the "bg". This will serve as a placeholder for the top bar area.
With the "top" component selected, go to the Rect Transform, select Alt + Top and Stretch-Top. It should look like this:
Next, add an Image component as a child element of the "top", change the color.
The hierarchy should now look like this:
Next, go back to the Simulator to test. Make sure the objects scales to different devices and rotates properly as well.
Confirm the top flex's properly: Select Simulator, iPad 12.9, Landscape Mode
Now switch back to portrait mode on iPhone. Add in the footer.
To do this, right click on "bg" select Create Empty GameObject. Rename it "footer". Using the Rect Transform, select Alt + Bottom, Stretch.
Now add the background: add an Image as a child of the "footer". Stretch it: In Rect Transform select Alt + Stretch/Stretch. Change the color.
Here is the result:
Next, we will add a body area that will be common to all pages.
Add an Empty GameObject as child of "bg", rename it "body". Align it in Rect Transform: Select Alt + Stretch/Stretch. Note that it will go to the far extents/edges. We only want it to cover the center area of the body, not go past the header or footer:
So to fix this, using the rect tool, drag the blue dots until they encapsulate the area between the header and footer, they will snap in place:
In the next section we will create the Canvas Pages and show how to flip through them using the footer navigation.
Next, add a Canvas as a child component to the "body", set the RectTransform: Select Alt + Stretch/Stretch.
The Canvas should now be covering the body. Rename the Canvas to "Audio_Page". Hide the Canvas by checking the hidden eye icon to the left of the Canvas in the hierarchy:
Select the Audio_Page in the Hierarchy and Ctrl + D to duplicate it, rename it "Video_Page":
Show/Hide your pages in the developer view so they are not in the way of your work.
In this section we will add 3 Buttons as child objects of the "footer_bg". Then use a custom script to toggle between the Canvas on each press.
3 Button's added to footer
In the next section we will explain how to add page flip for the nav bar.
Icons resource: You can use tools like Adobe Photoshop, or Illustrator to create your own graphics and drop them into the Assets/Images folder. Another great paid resource for customizable png images is: https://thenounproject.com
Unhide the Audio_Page and add a GameObject container. Expand it to fill the area and rename it "body".
Next add another GameObject called "MyCustomRowObject", in the RectTransform set it to (ALT + Middle/Stretch) so that it expands to fill the width of the body container. Set it to a height of 50 pixels. Add a background Image. Add a Horizontal Layout Group to the background Image. Next, add an empty GameObject for the slider. Add another empty GameObject for the Text. Both cells should automatically populate next to each other. Add the Slider and Text object as child components to each of the Empty GameObjects.
Next we will save the "MyCustomRowObject" as a prefab. First create a new folder under the Assets folder called Prefabs. Then drag the "MyCustomRowObject" into the folder. When you drag it into the prefab folder it will turn blue indicating it is now a prefab.
Drag the MyCustomRowObject to the newly created Prefab folder, it will turn into a prefab object for reusability.
You can now delete the MyCustomRowObject prefab from your scene, as it is saved as a prefab for later use.
In the next section we will use the prefab in the ScrollingListController script to create a horizontal or vertical scrolling list.
Knowing about raycast targets will save you some headache when developing custom prefabs. A good understanding of these concepts can indeed save a lot of debugging time and make the development process smoother.
A raycast is like a laser beam shooting out from your mouse click or finger, whatever that laser lands on you can interact with. But imagine there is an invisible layer over that button, instead of hitting the button, the laser hits the invisible layer, and so the button is not triggered.
Below is an analogy for Unity Raycast Targets – playing darts.
In a game of darts, you throw darts at a dartboard. The dartboard here represents a 2D game in Unity, and the different scoring sections on the board represent different objects (or UI elements) in the game.
1. **Raycasting:** Throwing a dart at the dartboard is similar to raycasting in Unity. Just like the dart follows a straight line towards the board, raycasting in Unity is about drawing an imaginary line (ray) from a point in a certain direction to check what it hits first.
2. **Raycast Target:** Now, imagine that some sections of the dartboard are covered with a transparent shield. You can see these sections, but when you throw a dart at them, it can't reach the board because of the shield. This shield can be thought of as the "Raycast Target" set to false in Unity. It makes the object (or section of the dartboard) visible but not interactable – the raycast (dart) can't hit it.
3. **Raycast Target true/false:** If there's no shield on the dartboard section (Raycast Target = true), then when you throw a dart (perform a raycast), it will hit and interact with that section. But if there is a shield (Raycast Target = false), the dart will not be able to interact with that section – it's as if the dart "misses" that section and checks for the next thing it can hit.
4. **Hierarchy & Raycasting:** Let's add another layer to this analogy. Say there's a small, secondary dartboard (child object) hanging in front of the larger dartboard (parent object). If you throw a dart aimed at the smaller board (and it doesn't have a shield), you'll hit it – not the larger board behind it. That's because, just like raycasting, the dart will hit the first object it encounters.
To sum up, in Unity 2D, setting the "Raycast Target" option is like deciding whether to put a shield on sections of your dartboard – you're setting whether or not an object can be "hit" by user interactions like clicks or touches.
In Unity's UI system, an Image component with a transparent texture can still block raycasts if its raycastTarget
property is set to true
. The raycast doesn't take the alpha (transparency) value of the image into account. It only cares whether or not the Image component is set as a raycast target and the image's size and position.
So if you have a transparent image in front of a button, and both of them have raycastTarget
set to true
, the raycast will hit the transparent image first and won't reach the button, even if the image is fully transparent and the button is visible to the player.
To make the button interactable, you would need to set the raycastTarget
property of the transparent Image to false
. This way, the raycast will "pass through" the transparent image and can hit the button behind it.
This is an important point to remember when designing UIs in Unity. Even a fully transparent object can block interactions if it's set as a raycast target.
**DigitalInput_NodeRed User Guide**
The DigitalInput_NodeRed script, when dragged onto an image, transforms the image into a clickable button, detecting user input and allowing feedback state adjustments via the control program.
UnityParallaxLibraryMerged.dll, DigitalInput_NodeRed
This user guide explains how to use the DigitalInput_NodeRed script included in the Parallax Unity Library plugin.
This class library provides a Unity component called DigitalInput_NodeRed, which can be attached to a UI Image object in a Unity project. The DigitalInput_NodeRed component receives button press events and changes the image color accordingly, based on the provided feedback value.
To use this class library in your Unity project, ensure that the following requirements are met:
To use the UnityParallaxLibrary, first import it into your Unity project:
To add the DigitalInput_NodeRed component to an Image object in your Unity project, follow these steps:
After adding the DigitalInput_NodeRed component to an Image object, you can configure its properties in the Unity Editor:
To use DigitalInput_NodeRed in your project, follow these steps:
The AnalogInputOutput_NodeRed
script facilitates interaction between a Unity slider and an external system, such as Node-Red, by emitting and receiving analog values.
In your Unity scene, create a Slider UI element. This is the GameObject where you'll attach the AnalogInputOutput_NodeRed
script.
In the Inspector panel, with the script attached:
Instance ID: Set the ID for this particular slider. This ID will help distinguish between multiple instances if you have several sliders in your scene.
Slider Min Val: Set the minimum value for the slider.
Slider Max Val: Set the maximum value for the slider.
This script employs an event-driven approach. It listens for dragging events on the slider, and it emits an event when the slider's value changes.
On Slider Begin Drag: This event is triggered when you start dragging the slider. It will temporarily remove all listeners from the slider to avoid unwanted interactions during dragging.
On Slider End Drag: This event is triggered when you release the slider after dragging. It adds a listener back to the slider to detect value changes, and emits the OnAnalogValueChanged
event to inform external systems of the new value.
The script has a method Processor_NodeRedOnAnalogDataReceived
that listens for incoming analog data events. If the instance ID matches, it updates the _analogVal
which reflects the current analog value received from the external system.
During the Unity frame update, the script checks if the received _analogVal
is different from the current slider value and the last sent value. If there's a mismatch, the slider's value is updated to match _analogVal
.
The script is designed to work seamlessly with systems like Node-Red. The key is the OnAnalogValueChanged
event:
OnAnalogValueChanged: This static action is triggered whenever the slider's value changes. It sends two pieces of data:
External systems can listen to this event and update their processes based on the received value.
The AnalogInputOutput_NodeRed
script provides an interactive bridge between Unity and external analog systems. Through sliders in Unity, users can influence external processes and vice-versa, facilitating a two-way communication channel. Ensure to integrate with an external system (like Node-Red) to fully utilize this script's capabilities.
Scrolling List Setup Using ParallaxUnityLibrary Plugin
The ParallaxUnityLibrary plugin for Unity includes a script named `UIScrollingListController` that helps you create a customizable scrolling list. This could be either horizontal or vertical, depending on your needs. The list will be composed of your custom prefab.
What is a Prefab?
In Unity, a prefab (short for prefabricated object) is essentially a blueprint of a game object. It can be a collection of different components or objects grouped together and saved for future use. This allows you to maintain consistency and efficiency in your design.
Setting Up Your Scrolling List
Here are the steps to create your scrolling list:
1. Open Unity and create a new empty GameObject.
2. Navigate to the ParallaxUnityLibrary plugin and find the `UIScrollingListController` script.
3. Drag and drop the `UIScrollingListController` script into your newly created GameObject.
4. Upon runtime, the `UIScrollingListController` script will automatically configure a scrolling list made up of your custom prefab.
Remember, you can choose whether you want your list to scroll horizontally or vertically. This customization allows you to seamlessly integrate the list into your design.
**Introduction:**
TheDynamicDataArrayHandler
script is developed for Unity to manage and update UI elements. It effectively processes data in the form of bool
, float
, and string
, supporting both array and dictionary data structures. It facilitates dynamic UI updates by subscribing to specific events and modifying UI elements when new data is received. This script is highly suitable for dynamically populating multiple objects' values, or even for use with scrolling lists where duplicated prefab instances need updating.
The script is part of the ParallaxUnityLibrary and should be dragged onto the parent GameObject. Below illustrates the Parent/Child/Child-Sibling/Grandchild relationship used in the hierarchy.
Example of the GameObject Hierarchy. The DynamicDataArray script is placed on the Parent.
Below is an example of using both the DynamicDataArray script with the UIScrollingListController to create and populate data for a scrolling list:
Below the DynamicDataArray as seen in the Unity Inspector
.
**Setup:**
1. Attach the `DynamicDataArrayHandler` script to the parent GameObject of the UI elements that you want to update.
2. This script will traverse through all child and grandchild GameObjects of the parent GameObject.
**Inspector Parameters:**
1. `Tag to Match`: Set this to the tag that you would want your GameObjects to match. Only GameObjects with this tag will be considered for dynamic updates.
2. `Instance ID`: Set the ID that corresponds to the data from the control system for dynamic population.
3.Data Structure Type
: Select the desired data structure from the following options: BoolArray
, FloatArray
, StringArray
for arrays, and BoolDictionary
, FloatDictionary
, StringDictionary
for dictionaries. This determines how the data will be managed and updated.
**Use Cases:**
1. If you have multiple TextMeshProUGUI objects in the same prefab and you want only some of them to be considered for dynamic text updates, you can set the 'Tag to Match' for those you want to be updated. This allows you to selectively choose which UI elements are affected by dynamic updates.
2. If you have two TextMeshProUGUI objects and you want each one to populate from different string arrays, you can set different tags for them. This allows each UI element to independently receive and display data.
3. If you have a scrolling list with duplicate prefabs for each row/column, `DynamicDataArrayHandler` can be used to populate all tagged objects in each prefab with the corresponding array data.
**Important Note:**
The order in which data is populated is determined by the GameObject hierarchy. The search for tagged objects starts from the parent object and works its way down through the children. As each tagged object is found, it is added to the list to receive updates.
**End Notes:**
The DynamicDataArrayHandler script provides a flexible and efficient means to manage array data and dynamically update Unity UI elements based on this data. Its versatility is showcased in its ability to handle different array data types and its compatibility with a range of UI elements and configurations.
## Instructions
1. **Adding the Script to a GameObject**: To start using the `DynamicDataArray` script, you'll first need to add it to a GameObject. To do this, select the GameObject in the Unity Editor's Hierarchy, then in the Inspector, click "Add Component" and search for "DynamicDataArray".
2. **Setting the Tag**: In the Inspector, you'll find an option to set the `Tag To Match`. This tag is used to search for child GameObjects that contain the UI elements you want to update. Only those GameObjects whose tag matches `Tag To Match` will be considered.
Example prefab which has a Text(TMP) object which we have tagged with "textArray". Now the script can identify this text element and add it to the list of Text(TMP) objects to update from programming.
3. **Setting the Instance ID**: The `Instance ID` is used to determine if the data received from the events is meant for this instance of `DynamicDataArray`. When the `Instance ID` matches the ID received from an event, the script will process the data and update the UI.
4. **Setting the Data Type**: You'll need to specify the type of data this `DynamicDataArray` is handling. This can be `BoolArray`, `FloatArray`, `StringArray`, 'BoolDictionary', 'FloatDictionary', 'StringDictionary' and is set in the `Array Data Type` dropdown menu. The choice of data type will determine what kind of UI elements this script will interact with.
5. **Populating the UI**: Populate the child GameObjects (those with the matching tag) with the relevant UI elements:
- If `Array Data Type` is set to `BoolArray`, the script will look for `Button` components and set their `interactable` property based on the received bool array.
- If `Array Data Type` is set to `FloatArray`, the script will look for `Slider` components and set their `value` property based on the received float array.
- If `Array Data Type` is set to `StringArray`, the script will look for `TextMeshProUGUI` components and set their `text` property based on the received string array.
A similar approach applies to BoolDictionary, FloatDictionary and StringDictionary data types. The scripts will match by the key and assign the associated value
6. **Running the Scene**: Run the scene in Unity. Whenever a new Array or Dictionary is received from the subscribed events and its ID matches the `Instance ID` of your `DynamicDataArray`, the relevant UI elements will be updated.
## Troubleshooting
In case you face issues while using `DynamicDataArray`:
- Ensure that the `Tag To Match` is correctly set and matches the tags of the relevant GameObjects in the hierarchy.
- Check that the `Instance ID` matches the ID being passed in the event data.
- Make sure that the `Data Type` matches the type of data being received in the event.
###Summary of data types used for populating the dynamic fields.
Types:
BOOL_ARRAY
FLOAT_ARRAY
STRING_ARRAY
BOOL_DICTIONARY
FLOAT_DICTIONARY
STRING_DICTIONARY
See Raspberry Pi Programming Section/Feedback Nodes for more information on using the DynamicDataArray to set feedback.
# CanvasFlipper Script
The `CanvasFlipper` script is designed to toggle between different canvases in Unity. It enables users to specify UI elements like buttons or images that, when clicked, will activate corresponding canvases. Additionally, the script provides the option to highlight the active UI element using a designated color.
## Features
1. **Toggle Canvases**: Activate one canvas and deactivate all others upon clicking a UI element.
2. **UI Element Pairing**: Link each UI element with a specific canvas to be activated.
3. **Color Highlighting**: Optional setting to highlight the active UI element.
## How to Use
### 1. Importing the Script
- Add the `CanvasFlipper` script to a GameObject in your Unity scene.
### 2. Setting Up UI-Canvas Pairs
- In the Unity Inspector, populate the `UIElementCanvasPairs` list with pairs of UI elements (buttons or images) and the canvases you want them to activate.
### 3. Enable/Disable Highlighting
- If you wish to use the highlighting feature, check the `useHighlight` box.
- If `useHighlight` is enabled, set your desired `activeColor`.
### 4. Original Color Preservation
- The script automatically captures and preserves the original colors of your UI elements.
## Fields Explained
- **UIElementCanvasPair**: A serializable class that holds each UI element (either a button or an image) and the canvas that it activates.
- **uiElementCanvasPairs**: A list of `UIElementCanvasPair` objects that define which UI element activates which canvas.
- **useHighlight**: A boolean that, when set to true, enables the color highlighting feature.
- **activeColor**: The color that will be applied to the active UI element when `useHighlight` is enabled.
- **originalColor**: Stores the original color of each UI element. Hidden from the inspector.
## Example Setup
1. Create two canvases: `Canvas1` and `Canvas2`.
2. Create two buttons: `Button1` and `Button2`.
3. Add `CanvasFlipper` script to an empty GameObject.
4. In `UIElementCanvasPairs`, set `Button1` to activate `Canvas1` and `Button2` to activate `Canvas2`.
5. If you wish, enable `useHighlight` and set an `activeColor`.
## Troubleshooting
- If you see a warning in the console like "Either UI Element or Canvas is null. Skipping this pair," ensure that you've set both the UI element and canvas for every pair.
- If the color of the active UI element does not change as expected, make sure that `useHighlight` is checked and that an `activeColor` is specified.
CanvasAdder
is a utility component provided by UnityParallaxLibrary
to easily set up the necessary components required for using the CanvasFlipper script. The CanvasFlipper script requires the pages be created from a Canvas which also contains a Canvas Group. This script automatically generates the necessary components required when added to an empty GameObject.
To get started with CanvasAdder
:
Once added, CanvasAdder
ensures the existence of the following components:
Canvas
: Serves as the area where UI elements are drawn.CanvasGroup
: Enables interaction with the UI as a whole group.RectTransform
: Defines properties such as position, size, and pivot of the UI elements.CanvasScaler
: Ensures the UI scales properly according to different screen sizes.GraphicRaycaster
: Enables UI interaction, like clicking or dragging.The component automatically checks for the required components mentioned above. If any of these components are missing, CanvasAdder
will add them for you.
By default:
Canvas
will use RenderMode.ScreenSpaceOverlay
, ensuring the UI overlays on top of the game content.
Time
Class in Unity EditorThe Time
class from the UnityParallaxLibrary
namespace enables you to display the current time on a TextMeshProUGUI element within Unity. This class allows you to show various elements of time such as hours, minutes, seconds, and milliseconds. This guide covers how to set up and use this class from the Unity Editor.
If TextMeshPro is not installed:
Window
> Package Manager
.TextMeshPro
and click Install
.UI
and select Canvas
.UI
and select Text - TextMeshPro
.Time
ClassTime
ScriptText - TextMeshPro
GameObject in the Hierarchy.Add Component
.Time
under UnityParallaxLibrary
and attach it.Text - TextMeshPro
GameObject selected, find the Time
component in the Inspector.Display Options
, you'll find checkboxes for displayHours
, displayMinutes
, displaySeconds
, and displayMilliseconds
.Play
button. The Time
script will update the TextMeshProUGUI element to display the current time based on your configurations.Time
script is active in the scene.By following this guide, you will have implemented the Time
class in your Unity project, allowing for real-time display of various time elements. You can further customize this feature according to your project's needs.
Note: The time displayed will come from the physical device where the run-time program is executed
The StringInput_NodeRed
script is a component of the UnityParallaxLibrary
. It acts as an event handler for TextMeshPro Input Fields (TMP_InputField
) in Unity. When text is entered and editing is finalized, the script triggers a static OnTextSubmitted
event, passing an instanceId
and the input string for identification and event handling. This script is particularly useful for projects requiring text input events, especially those that work with Node-Red services.
Project
window.UnityParallaxLibrary
folder.StringInput_NodeRed
script.Hierarchy
window, locate the GameObject that has a TextMeshPro Input Field (TMP_InputField
).Inspector
window, click the Add Component
button.StringInput_NodeRed
and click it to add it to your GameObject as a component.instanceId
FieldStringInput_NodeRed
component within the Inspector
.instanceId
. Assign a unique integer value to this field for identifying different instances of the script.OnTextSubmitted
event for the intended functionality.Play
button in Unity to run your scene.TMP_InputField
linked to your GameObject.OnTextSubmitted
, their respective methods should get invoked.By following this guide, you should have successfully integrated the StringInput_NodeRed
script into your Unity project. This will allow you to effectively handle text input events in Unity, especially if your project interfaces with Node-Red services.
The StringOutput_NodeRed
script is a part of the UnityParallaxLibrary
. It listens to incoming string data events and displays them using a TextMeshPro (TMP_Text
) component in Unity. This script is sends the data to the ParallaxProcessor.
Project
window.UnityParallaxLibrary
folder.StringOutput_NodeRed
script inside this folder.Hierarchy
window, locate or create a GameObject with a TextMeshPro (TMP_Text
) component.Inspector
window, click the Add Component
button.StringOutput_NodeRed
and click on it to add it as a component.instanceId
FieldStringOutput_NodeRed
component within the Inspector
.instanceId
. Assign a unique integer value to this field to identify different instances of the script.Play
button to run your Unity scene.TMP_Text
component linked to your GameObject should update its text based on the received string data.By following this guide, you should be able to successfully integrate the StringOutput_NodeRed
script into your Unity project. This will allow you to display string data dynamically through a TextMeshPro (TMP_Text
) component coming from the ParallaxProcessor.
The StringOutput_NodeRed
script is a part of the UnityParallaxLibrary
. It listens to incoming string data events and displays them using a TextMeshPro (TMP_Text
) component in Unity. This script is sends the data to the ParallaxProcessor.