298 lines
8.5 KiB
C++
298 lines
8.5 KiB
C++
#include "stdafx.h"
|
|
#include "HairParticleWindow.h"
|
|
#include "Editor.h"
|
|
|
|
using namespace std;
|
|
using namespace wiECS;
|
|
using namespace wiScene;
|
|
|
|
HairParticleWindow::HairParticleWindow(EditorComponent* editor) : GUI(&editor->GetGUI())
|
|
{
|
|
assert(GUI && "Invalid GUI!");
|
|
|
|
hairWindow = new wiWindow(GUI, "Hair Particle System Window");
|
|
hairWindow->SetSize(XMFLOAT2(600, 400));
|
|
GUI->AddWidget(hairWindow);
|
|
|
|
float x = 160;
|
|
float y = 0;
|
|
float step = 35;
|
|
|
|
|
|
addButton = new wiButton("Add Hair Particle System");
|
|
addButton->SetPos(XMFLOAT2(x, y += step));
|
|
addButton->SetSize(XMFLOAT2(200, 30));
|
|
addButton->OnClick([=](wiEventArgs args) {
|
|
Scene& scene = wiScene::GetScene();
|
|
Entity entity = scene.Entity_CreateHair("editorHair");
|
|
editor->ClearSelected();
|
|
editor->AddSelected(entity);
|
|
SetEntity(entity);
|
|
});
|
|
addButton->SetTooltip("Add new hair particle system.");
|
|
hairWindow->AddWidget(addButton);
|
|
|
|
meshComboBox = new wiComboBox("Mesh: ");
|
|
meshComboBox->SetSize(XMFLOAT2(300, 25));
|
|
meshComboBox->SetPos(XMFLOAT2(x, y += step));
|
|
meshComboBox->SetEnabled(false);
|
|
meshComboBox->OnSelect([&](wiEventArgs args) {
|
|
auto hair = GetHair();
|
|
if (hair != nullptr)
|
|
{
|
|
if (args.iValue == 0)
|
|
{
|
|
hair->meshID = INVALID_ENTITY;
|
|
}
|
|
else
|
|
{
|
|
Scene& scene = wiScene::GetScene();
|
|
hair->meshID = scene.meshes.GetEntity(args.iValue - 1);
|
|
}
|
|
}
|
|
});
|
|
meshComboBox->SetTooltip("Choose a mesh where hair will grow from...");
|
|
hairWindow->AddWidget(meshComboBox);
|
|
|
|
countSlider = new wiSlider(0, 100000, 1000, 100000, "Strand Count: ");
|
|
countSlider->SetSize(XMFLOAT2(360, 30));
|
|
countSlider->SetPos(XMFLOAT2(x, y += step));
|
|
countSlider->OnSlide([&](wiEventArgs args) {
|
|
auto hair = GetHair();
|
|
if (hair != nullptr)
|
|
{
|
|
hair->strandCount = (uint32_t)args.iValue;
|
|
}
|
|
});
|
|
countSlider->SetEnabled(false);
|
|
countSlider->SetTooltip("Set hair strand count");
|
|
hairWindow->AddWidget(countSlider);
|
|
|
|
lengthSlider = new wiSlider(0, 4, 1, 100000, "Particle Length: ");
|
|
lengthSlider->SetSize(XMFLOAT2(360, 30));
|
|
lengthSlider->SetPos(XMFLOAT2(x, y += step));
|
|
lengthSlider->OnSlide([&](wiEventArgs args) {
|
|
auto hair = GetHair();
|
|
if (hair != nullptr)
|
|
{
|
|
hair->length = args.fValue;
|
|
}
|
|
});
|
|
lengthSlider->SetEnabled(false);
|
|
lengthSlider->SetTooltip("Set hair strand length");
|
|
hairWindow->AddWidget(lengthSlider);
|
|
|
|
stiffnessSlider = new wiSlider(0, 20, 5, 100000, "Particle Stiffness: ");
|
|
stiffnessSlider->SetSize(XMFLOAT2(360, 30));
|
|
stiffnessSlider->SetPos(XMFLOAT2(x, y += step));
|
|
stiffnessSlider->OnSlide([&](wiEventArgs args) {
|
|
auto hair = GetHair();
|
|
if (hair != nullptr)
|
|
{
|
|
hair->stiffness = args.fValue;
|
|
}
|
|
});
|
|
stiffnessSlider->SetEnabled(false);
|
|
stiffnessSlider->SetTooltip("Set hair strand stiffness, how much it tries to get back to rest position.");
|
|
hairWindow->AddWidget(stiffnessSlider);
|
|
|
|
randomnessSlider = new wiSlider(0, 1, 0.2f, 100000, "Particle Randomness: ");
|
|
randomnessSlider->SetSize(XMFLOAT2(360, 30));
|
|
randomnessSlider->SetPos(XMFLOAT2(x, y += step));
|
|
randomnessSlider->OnSlide([&](wiEventArgs args) {
|
|
auto hair = GetHair();
|
|
if (hair != nullptr)
|
|
{
|
|
hair->randomness = args.fValue;
|
|
}
|
|
});
|
|
randomnessSlider->SetEnabled(false);
|
|
randomnessSlider->SetTooltip("Set hair length randomization factor. This will affect randomness of hair lengths.");
|
|
hairWindow->AddWidget(randomnessSlider);
|
|
|
|
segmentcountSlider = new wiSlider(1, 10, 1, 9, "Segment Count: ");
|
|
segmentcountSlider->SetSize(XMFLOAT2(360, 30));
|
|
segmentcountSlider->SetPos(XMFLOAT2(x, y += step));
|
|
segmentcountSlider->OnSlide([&](wiEventArgs args) {
|
|
auto hair = GetHair();
|
|
if (hair != nullptr)
|
|
{
|
|
hair->segmentCount = (uint32_t)args.iValue;
|
|
}
|
|
});
|
|
segmentcountSlider->SetEnabled(false);
|
|
segmentcountSlider->SetTooltip("Set hair strand segment count. This will affect simulation quality and performance.");
|
|
hairWindow->AddWidget(segmentcountSlider);
|
|
|
|
randomSeedSlider = new wiSlider(1, 12345, 1, 12344, "Random seed: ");
|
|
randomSeedSlider->SetSize(XMFLOAT2(360, 30));
|
|
randomSeedSlider->SetPos(XMFLOAT2(x, y += step));
|
|
randomSeedSlider->OnSlide([&](wiEventArgs args) {
|
|
auto hair = GetHair();
|
|
if (hair != nullptr)
|
|
{
|
|
hair->randomSeed = (uint32_t)args.iValue;
|
|
}
|
|
});
|
|
randomSeedSlider->SetEnabled(false);
|
|
randomSeedSlider->SetTooltip("Set hair system-wide random seed value. This will affect hair patch placement randomization.");
|
|
hairWindow->AddWidget(randomSeedSlider);
|
|
|
|
viewDistanceSlider = new wiSlider(0, 1000, 100, 10000, "View distance: ");
|
|
viewDistanceSlider->SetSize(XMFLOAT2(360, 30));
|
|
viewDistanceSlider->SetPos(XMFLOAT2(x, y += step));
|
|
viewDistanceSlider->OnSlide([&](wiEventArgs args) {
|
|
auto hair = GetHair();
|
|
if (hair != nullptr)
|
|
{
|
|
hair->viewDistance = args.fValue;
|
|
}
|
|
});
|
|
viewDistanceSlider->SetEnabled(false);
|
|
viewDistanceSlider->SetTooltip("Set view distance. After this, particles will be faded out.");
|
|
hairWindow->AddWidget(viewDistanceSlider);
|
|
|
|
framesXInput = new wiTextInputField("");
|
|
framesXInput->SetPos(XMFLOAT2(x, y += step));
|
|
framesXInput->SetSize(XMFLOAT2(40, 18));
|
|
framesXInput->SetText("");
|
|
framesXInput->SetTooltip("How many horizontal frames there are in the spritesheet.");
|
|
framesXInput->SetDescription("Frames X: ");
|
|
framesXInput->OnInputAccepted([this](wiEventArgs args) {
|
|
auto hair = GetHair();
|
|
if (hair != nullptr)
|
|
{
|
|
hair->framesX = (uint32_t)args.iValue;
|
|
}
|
|
});
|
|
hairWindow->AddWidget(framesXInput);
|
|
|
|
framesYInput = new wiTextInputField("");
|
|
framesYInput->SetPos(XMFLOAT2(x + 250, y));
|
|
framesYInput->SetSize(XMFLOAT2(40, 18));
|
|
framesYInput->SetText("");
|
|
framesYInput->SetTooltip("How many vertical frames there are in the spritesheet.");
|
|
framesYInput->SetDescription("Frames Y: ");
|
|
framesYInput->OnInputAccepted([this](wiEventArgs args) {
|
|
auto hair = GetHair();
|
|
if (hair != nullptr)
|
|
{
|
|
hair->framesY = (uint32_t)args.iValue;
|
|
}
|
|
});
|
|
hairWindow->AddWidget(framesYInput);
|
|
|
|
step = 20;
|
|
|
|
frameCountInput = new wiTextInputField("");
|
|
frameCountInput->SetPos(XMFLOAT2(x, y += step));
|
|
frameCountInput->SetSize(XMFLOAT2(40, 18));
|
|
frameCountInput->SetText("");
|
|
frameCountInput->SetTooltip("Enter a value to enable the random sprite sheet frame selection's max frame number.");
|
|
frameCountInput->SetDescription("Frame Count: ");
|
|
frameCountInput->OnInputAccepted([this](wiEventArgs args) {
|
|
auto hair = GetHair();
|
|
if (hair != nullptr)
|
|
{
|
|
hair->frameCount = (uint32_t)args.iValue;
|
|
}
|
|
});
|
|
hairWindow->AddWidget(frameCountInput);
|
|
|
|
frameStartInput = new wiTextInputField("");
|
|
frameStartInput->SetPos(XMFLOAT2(x + 250, y));
|
|
frameStartInput->SetSize(XMFLOAT2(40, 18));
|
|
frameStartInput->SetText("");
|
|
frameStartInput->SetTooltip("Specifies the first frame of the sheet that can be used.");
|
|
frameStartInput->SetDescription("First Frame: ");
|
|
frameStartInput->OnInputAccepted([this](wiEventArgs args) {
|
|
auto hair = GetHair();
|
|
if (hair != nullptr)
|
|
{
|
|
hair->frameStart = (uint32_t)args.iValue;
|
|
}
|
|
});
|
|
hairWindow->AddWidget(frameStartInput);
|
|
|
|
|
|
hairWindow->Translate(XMFLOAT3(200, 50, 0));
|
|
hairWindow->SetVisible(false);
|
|
|
|
SetEntity(entity);
|
|
}
|
|
|
|
HairParticleWindow::~HairParticleWindow()
|
|
{
|
|
hairWindow->RemoveWidgets(true);
|
|
GUI->RemoveWidget(hairWindow);
|
|
delete hairWindow;
|
|
}
|
|
|
|
void HairParticleWindow::SetEntity(Entity entity)
|
|
{
|
|
this->entity = entity;
|
|
|
|
auto hair = GetHair();
|
|
|
|
if (hair != nullptr)
|
|
{
|
|
lengthSlider->SetValue(hair->length);
|
|
stiffnessSlider->SetValue(hair->stiffness);
|
|
randomnessSlider->SetValue(hair->randomness);
|
|
countSlider->SetValue((float)hair->strandCount);
|
|
segmentcountSlider->SetValue((float)hair->segmentCount);
|
|
randomSeedSlider->SetValue((float)hair->randomSeed);
|
|
viewDistanceSlider->SetValue(hair->viewDistance);
|
|
framesXInput->SetValue((int)hair->framesX);
|
|
framesYInput->SetValue((int)hair->framesY);
|
|
frameCountInput->SetValue((int)hair->frameCount);
|
|
frameStartInput->SetValue((int)hair->frameStart);
|
|
|
|
hairWindow->SetEnabled(true);
|
|
}
|
|
else
|
|
{
|
|
hairWindow->SetEnabled(false);
|
|
}
|
|
|
|
addButton->SetEnabled(true);
|
|
}
|
|
|
|
wiHairParticle* HairParticleWindow::GetHair()
|
|
{
|
|
if (entity == INVALID_ENTITY)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
Scene& scene = wiScene::GetScene();
|
|
wiHairParticle* hair = scene.hairs.GetComponent(entity);
|
|
|
|
return hair;
|
|
}
|
|
|
|
void HairParticleWindow::UpdateData()
|
|
{
|
|
auto emitter = GetHair();
|
|
if (emitter == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Scene& scene = wiScene::GetScene();
|
|
|
|
meshComboBox->ClearItems();
|
|
meshComboBox->AddItem("NO MESH");
|
|
for (size_t i = 0; i < scene.meshes.GetCount(); ++i)
|
|
{
|
|
Entity entity = scene.meshes.GetEntity(i);
|
|
const NameComponent& name = *scene.names.GetComponent(entity);
|
|
meshComboBox->AddItem(name.name);
|
|
|
|
if (emitter->meshID == entity)
|
|
{
|
|
meshComboBox->SetSelected((int)i + 1);
|
|
}
|
|
}
|
|
}
|