diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index fb716f715..458ab82be 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -479,7 +479,7 @@ void EditorComponent::Load() }); loader->onFinished([=] { main->ActivatePath(this, 0.2f, wiColor::Black()); - weatherWnd->UpdateFromRenderer(); + weatherWnd->Update(); }); main->ActivatePath(loader, 0.2f, wiColor::Black()); ResetHistory(); @@ -714,6 +714,7 @@ void EditorComponent::Update(float dt) CameraComponent& camera = wiRenderer::GetCamera(); animWnd->Update(); + weatherWnd->Update(); selectionOutlineTimer += dt; diff --git a/Editor/EmitterWindow.cpp b/Editor/EmitterWindow.cpp index a4dc34492..df70892ad 100644 --- a/Editor/EmitterWindow.cpp +++ b/Editor/EmitterWindow.cpp @@ -446,6 +446,34 @@ void EmitterWindow::SetEntity(Entity entity) if (emitter != nullptr) { + emitterNameField->SetEnabled(true); + restartButton->SetEnabled(true); + shaderTypeComboBox->SetEnabled(true); + meshComboBox->SetEnabled(true); + debugCheckBox->SetEnabled(true); + sortCheckBox->SetEnabled(true); + depthCollisionsCheckBox->SetEnabled(true); + sphCheckBox->SetEnabled(true); + pauseCheckBox->SetEnabled(true); + maxParticlesSlider->SetEnabled(true); + emitCountSlider->SetEnabled(true); + emitSizeSlider->SetEnabled(true); + emitRotationSlider->SetEnabled(true); + emitNormalSlider->SetEnabled(true); + emitScalingSlider->SetEnabled(true); + emitLifeSlider->SetEnabled(true); + emitRandomnessSlider->SetEnabled(true); + emitLifeRandomnessSlider->SetEnabled(true); + emitMotionBlurSlider->SetEnabled(true); + emitMassSlider->SetEnabled(true); + timestepSlider->SetEnabled(true); + sph_h_Slider->SetEnabled(true); + sph_K_Slider->SetEnabled(true); + sph_p0_Slider->SetEnabled(true); + sph_e_Slider->SetEnabled(true); + + shaderTypeComboBox->SetSelected((int)emitter->shaderType); + sortCheckBox->SetCheck(emitter->IsSorted()); depthCollisionsCheckBox->SetCheck(emitter->IsDepthCollisionEnabled()); sphCheckBox->SetCheck(emitter->IsSPHEnabled()); @@ -472,6 +500,32 @@ void EmitterWindow::SetEntity(Entity entity) else { infoLabel->SetText("No emitter object selected."); + + emitterNameField->SetEnabled(false); + restartButton->SetEnabled(false); + shaderTypeComboBox->SetEnabled(false); + meshComboBox->SetEnabled(false); + debugCheckBox->SetEnabled(false); + sortCheckBox->SetEnabled(false); + depthCollisionsCheckBox->SetEnabled(false); + sphCheckBox->SetEnabled(false); + pauseCheckBox->SetEnabled(false); + maxParticlesSlider->SetEnabled(false); + emitCountSlider->SetEnabled(false); + emitSizeSlider->SetEnabled(false); + emitRotationSlider->SetEnabled(false); + emitNormalSlider->SetEnabled(false); + emitScalingSlider->SetEnabled(false); + emitLifeSlider->SetEnabled(false); + emitRandomnessSlider->SetEnabled(false); + emitLifeRandomnessSlider->SetEnabled(false); + emitMotionBlurSlider->SetEnabled(false); + emitMassSlider->SetEnabled(false); + timestepSlider->SetEnabled(false); + sph_h_Slider->SetEnabled(false); + sph_K_Slider->SetEnabled(false); + sph_p0_Slider->SetEnabled(false); + sph_e_Slider->SetEnabled(false); } } diff --git a/Editor/LightWindow.cpp b/Editor/LightWindow.cpp index c1f7e5d47..2b064b9f8 100644 --- a/Editor/LightWindow.cpp +++ b/Editor/LightWindow.cpp @@ -328,6 +328,7 @@ void LightWindow::SetEntity(Entity entity) staticCheckBox->SetEnabled(true); staticCheckBox->SetCheck(light->IsStatic()); colorPicker->SetEnabled(true); + colorPicker->SetPickColor(wiColor::fromFloat3(light->color)); typeSelectorComboBox->SetSelected((int)light->GetType()); SetLightType(light->GetType()); diff --git a/Editor/MaterialWindow.cpp b/Editor/MaterialWindow.cpp index 53f93b3a9..ebfffef11 100644 --- a/Editor/MaterialWindow.cpp +++ b/Editor/MaterialWindow.cpp @@ -810,7 +810,9 @@ void MaterialWindow::SetEntity(Entity entity) alphaRefSlider->SetValue(material->alphaRef); materialWindow->SetEnabled(true); baseColorPicker->SetEnabled(true); + baseColorPicker->SetPickColor(wiColor::fromFloat4(material->baseColor)); emissiveColorPicker->SetEnabled(true); + emissiveColorPicker->SetPickColor(wiColor::fromFloat4(material->emissiveColor)); blendModeComboBox->SetSelected((int)material->userBlendMode); shaderTypeComboBox->SetSelected(max(0, material->GetCustomShaderID() + 1)); diff --git a/Editor/ObjectWindow.cpp b/Editor/ObjectWindow.cpp index 3bd92bc62..c37e86696 100644 --- a/Editor/ObjectWindow.cpp +++ b/Editor/ObjectWindow.cpp @@ -619,6 +619,7 @@ void ObjectWindow::SetEntity(Entity entity) renderableCheckBox->SetCheck(object->IsRenderable()); cascadeMaskSlider->SetValue((float)object->cascadeMask); ditherSlider->SetValue(object->GetTransparency()); + colorPicker->SetPickColor(wiColor::fromFloat4(object->color)); const RigidBodyPhysicsComponent* physicsComponent = scene.rigidbodies.GetComponent(entity); diff --git a/Editor/WeatherWindow.cpp b/Editor/WeatherWindow.cpp index e065d176e..23403ca81 100644 --- a/Editor/WeatherWindow.cpp +++ b/Editor/WeatherWindow.cpp @@ -211,8 +211,8 @@ WeatherWindow::WeatherWindow(wiGUI* gui) : GUI(gui) auto& weather = GetWeather(); weather.ambient = XMFLOAT3(0.01f, 0.01f, 0.02f); - weather.horizon = XMFLOAT3(0.02f, 0.05f, 0.1f); - weather.zenith = XMFLOAT3(0.01f, 0.02f, 0.04f); + weather.horizon = XMFLOAT3(0.04f, 0.1f, 0.2f); + weather.zenith = XMFLOAT3(0.02f, 0.04f, 0.08f); weather.cloudiness = 0.28f; weather.fogStart = 10; weather.fogEnd = 400; @@ -278,7 +278,6 @@ WeatherWindow::WeatherWindow(wiGUI* gui) : GUI(gui) }); weatherWindow->AddWidget(zenithColorPicker); - weatherWindow->Translate(XMFLOAT3(130, 30, 0)); weatherWindow->SetVisible(false); } @@ -291,17 +290,25 @@ WeatherWindow::~WeatherWindow() SAFE_DELETE(weatherWindow); } -void WeatherWindow::UpdateFromRenderer() +void WeatherWindow::Update() { - auto& weather = GetWeather(); + Scene& scene = wiSceneSystem::GetScene(); + if (scene.weathers.GetCount() > 0) + { + auto& weather = scene.weathers[0]; - fogStartSlider->SetValue(weather.fogStart); - fogEndSlider->SetValue(weather.fogEnd); - fogHeightSlider->SetValue(weather.fogHeight); - cloudinessSlider->SetValue(weather.cloudiness); - cloudScaleSlider->SetValue(weather.cloudScale); - cloudSpeedSlider->SetValue(weather.cloudSpeed); - windSpeedSlider->SetValue(wiMath::Length(weather.windDirection)); + fogStartSlider->SetValue(weather.fogStart); + fogEndSlider->SetValue(weather.fogEnd); + fogHeightSlider->SetValue(weather.fogHeight); + cloudinessSlider->SetValue(weather.cloudiness); + cloudScaleSlider->SetValue(weather.cloudScale); + cloudSpeedSlider->SetValue(weather.cloudSpeed); + windSpeedSlider->SetValue(wiMath::Length(weather.windDirection)); + + ambientColorPicker->SetPickColor(wiColor::fromFloat3(weather.ambient)); + horizonColorPicker->SetPickColor(wiColor::fromFloat3(weather.horizon)); + zenithColorPicker->SetPickColor(wiColor::fromFloat3(weather.zenith)); + } } WeatherComponent& WeatherWindow::GetWeather() const diff --git a/Editor/WeatherWindow.h b/Editor/WeatherWindow.h index 0afd9dcd8..5f5b27115 100644 --- a/Editor/WeatherWindow.h +++ b/Editor/WeatherWindow.h @@ -14,7 +14,7 @@ public: WeatherWindow(wiGUI* gui); ~WeatherWindow(); - void UpdateFromRenderer(); + void Update(); wiSceneSystem::WeatherComponent& GetWeather() const; void InvalidateProbes() const; diff --git a/WickedEngine/LoadingScreen.cpp b/WickedEngine/LoadingScreen.cpp index 019b7d416..1b2d855f0 100644 --- a/WickedEngine/LoadingScreen.cpp +++ b/WickedEngine/LoadingScreen.cpp @@ -16,7 +16,7 @@ void LoadingScreen::addLoadingFunction(function loadingFunction) } } -void LoadingScreen::addLoadingComponent(RenderPath* component, MainComponent* main, float fadeSeconds, const wiColor& fadeColor) +void LoadingScreen::addLoadingComponent(RenderPath* component, MainComponent* main, float fadeSeconds, wiColor fadeColor) { addLoadingFunction([=] { component->Load(); diff --git a/WickedEngine/LoadingScreen.h b/WickedEngine/LoadingScreen.h index 1d5366da5..4ce618e73 100644 --- a/WickedEngine/LoadingScreen.h +++ b/WickedEngine/LoadingScreen.h @@ -21,7 +21,7 @@ public: //use std::bind( YourFunctionPointer ) void addLoadingFunction(std::function loadingFunction); //Helper for loading a whole renderable component - void addLoadingComponent(RenderPath* component, MainComponent* main, float fadeSeconds = 0, const wiColor& fadeColor = wiColor(0, 0, 0, 255)); + void addLoadingComponent(RenderPath* component, MainComponent* main, float fadeSeconds = 0, wiColor fadeColor = wiColor(0, 0, 0, 255)); //Set a function that should be called when the loading finishes //use std::bind( YourFunctionPointer ) void onFinished(std::function finishFunction); diff --git a/WickedEngine/MainComponent.cpp b/WickedEngine/MainComponent.cpp index 9f2edf368..69c112fc9 100644 --- a/WickedEngine/MainComponent.cpp +++ b/WickedEngine/MainComponent.cpp @@ -81,7 +81,7 @@ void MainComponent::Initialize() wiLua::GetGlobal()->RunFile("startup.lua"); } -void MainComponent::ActivatePath(RenderPath* component, float fadeSeconds, const wiColor& fadeColor) +void MainComponent::ActivatePath(RenderPath* component, float fadeSeconds, wiColor fadeColor) { if (component == nullptr) { diff --git a/WickedEngine/MainComponent.h b/WickedEngine/MainComponent.h index 7c7eaac31..ef5a5e183 100644 --- a/WickedEngine/MainComponent.h +++ b/WickedEngine/MainComponent.h @@ -31,7 +31,7 @@ public: // This will activate a RenderPath as the active one, so it will run its Update, FixedUpdate, Render and Compose functions // You can set a fade time and fade screen color so that switching components will happen when the screen is faded out. Then it will fade back to the new component - void ActivatePath(RenderPath* component, float fadeSeconds = 0, const wiColor& fadeColor = wiColor(0,0,0,255)); + void ActivatePath(RenderPath* component, float fadeSeconds = 0, wiColor fadeColor = wiColor(0,0,0,255)); inline RenderPath* GetActivePath(){ return activePath; } // You can use this as a self-contained resource manager if you want to avoid using the wiResourceManager::GetGlobal() diff --git a/WickedEngine/wiColor.h b/WickedEngine/wiColor.h index 7df8d5b1b..118a5e1d5 100644 --- a/WickedEngine/wiColor.h +++ b/WickedEngine/wiColor.h @@ -46,7 +46,7 @@ struct wiColor return wiColor((uint8_t)(value.x * 255), (uint8_t)(value.y * 255), (uint8_t)(value.z * 255)); } - static constexpr wiColor lerp(const wiColor& a, const wiColor& b, float i) + static constexpr wiColor lerp(wiColor a, wiColor b, float i) { return fromFloat4(wiMath::Lerp(a.toFloat4(), b.toFloat4(), i)); } diff --git a/WickedEngine/wiFadeManager.h b/WickedEngine/wiFadeManager.h index 7c8aef720..6a4e1e2dd 100644 --- a/WickedEngine/wiFadeManager.h +++ b/WickedEngine/wiFadeManager.h @@ -28,7 +28,7 @@ public: Clear(); } void Clear(); - void Start(float seconds, const wiColor& color, std::function onFadeFunction) + void Start(float seconds, wiColor color, std::function onFadeFunction) { targetFadeTimeInSeconds = seconds; this->color = color; diff --git a/WickedEngine/wiFont.h b/WickedEngine/wiFont.h index 2b76e061b..7775b513c 100644 --- a/WickedEngine/wiFont.h +++ b/WickedEngine/wiFont.h @@ -27,7 +27,7 @@ struct wiFontParams wiColor shadowColor; wiFontParams(int posX = 0, int posY = 0, int size = 16, wiFontAlign h_align = WIFALIGN_LEFT, wiFontAlign v_align = WIFALIGN_TOP - , int spacingX = 0, int spacingY = 0, const wiColor& color = wiColor(255, 255, 255, 255), const wiColor& shadowColor = wiColor(0,0,0,0)) + , int spacingX = 0, int spacingY = 0, wiColor color = wiColor(255, 255, 255, 255), wiColor shadowColor = wiColor(0,0,0,0)) :posX(posX), posY(posY), size(size), h_align(h_align), v_align(v_align), spacingX(spacingX), spacingY(spacingY), color(color), shadowColor(shadowColor) {} }; diff --git a/WickedEngine/wiMath.cpp b/WickedEngine/wiMath.cpp index 059563bee..1ffd0e3ce 100644 --- a/WickedEngine/wiMath.cpp +++ b/WickedEngine/wiMath.cpp @@ -88,13 +88,6 @@ namespace wiMath return Distance(point, projection); } - XMFLOAT3 HueToRGB(float H) - { - float R = fabsf(H * 6 - 3) - 1; - float G = 2 - fabsf(H * 6 - 2); - float B = 2 - fabsf(H * 6 - 4); - return XMFLOAT3(saturate(R), saturate(G), saturate(B)); - } float GetAngle(const XMFLOAT2& a, const XMFLOAT2& b) { float dot = a.x*b.x + a.y*b.y; // dot product diff --git a/WickedEngine/wiMath.h b/WickedEngine/wiMath.h index 7f44b3331..7c801cd1f 100644 --- a/WickedEngine/wiMath.h +++ b/WickedEngine/wiMath.h @@ -156,7 +156,6 @@ namespace wiMath XMVECTOR GetClosestPointToLine(const XMVECTOR& A, const XMVECTOR& B, const XMVECTOR& P, bool segmentClamp = false); float GetPointSegmentDistance(const XMVECTOR& point, const XMVECTOR& segmentA, const XMVECTOR& segmentB); - XMFLOAT3 HueToRGB(float H); float GetAngle(const XMFLOAT2& a, const XMFLOAT2& b); void ConstructTriangleEquilateral(float radius, XMFLOAT4& A, XMFLOAT4& B, XMFLOAT4& C); void GetBarycentric(const XMVECTOR& p, const XMVECTOR& a, const XMVECTOR& b, const XMVECTOR& c, float &u, float &v, float &w, bool clamp = false); diff --git a/WickedEngine/wiTextureHelper.cpp b/WickedEngine/wiTextureHelper.cpp index aa3dd6161..a6648dbf0 100644 --- a/WickedEngine/wiTextureHelper.cpp +++ b/WickedEngine/wiTextureHelper.cpp @@ -157,7 +157,7 @@ namespace wiTextureHelper return getColor(wiColor(0, 0, 0, 0)); } - const Texture2D* getColor(const wiColor& color) + const Texture2D* getColor(wiColor color) { colorlock.lock(); auto it = colorTextures.find(color.rgba); diff --git a/WickedEngine/wiTextureHelper.h b/WickedEngine/wiTextureHelper.h index 3a95ab5e3..b329aac6f 100644 --- a/WickedEngine/wiTextureHelper.h +++ b/WickedEngine/wiTextureHelper.h @@ -15,7 +15,7 @@ namespace wiTextureHelper const wiGraphics::Texture2D* getWhite(); const wiGraphics::Texture2D* getBlack(); const wiGraphics::Texture2D* getTransparent(); - const wiGraphics::Texture2D* getColor(const wiColor& color); + const wiGraphics::Texture2D* getColor(wiColor color); HRESULT CreateTexture(wiGraphics::Texture2D& texture, const uint8_t* data, UINT width, UINT height, wiGraphics::FORMAT format = wiGraphics::FORMAT_R8G8B8A8_UNORM); }; diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index d4227dde2..1d2850484 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates const int minor = 30; // minor bug fixes, alterations, refactors, updates - const int revision = 11; + const int revision = 12; long GetVersion() diff --git a/WickedEngine/wiWidget.cpp b/WickedEngine/wiWidget.cpp index 8e17a2fb4..f00dcacc8 100644 --- a/WickedEngine/wiWidget.cpp +++ b/WickedEngine/wiWidget.cpp @@ -20,35 +20,14 @@ using namespace wiSceneSystem; static wiGraphics::PipelineState PSO_colorpicker; - -wiWidget::wiWidget() : TransformComponent() -{ - state = IDLE; - enabled = true; - visible = true; - colors[IDLE] = wiColor::Booger(); - colors[FOCUS] = wiColor::Gray(); - colors[ACTIVE] = wiColor::White(); - colors[DEACTIVATING] = wiColor::Gray(); - scissorRect.bottom = 0; - scissorRect.left = 0; - scissorRect.right = 0; - scissorRect.top = 0; - parent = nullptr; - tooltipTimer = 0; - textColor = wiColor(255, 255, 255, 255); - textShadowColor = wiColor(0, 0, 0, 255); - translation = XMFLOAT3(0, 0, 0); - scale = XMFLOAT3(1, 1, 1); -} -wiWidget::~wiWidget() -{ -} void wiWidget::Update(wiGUI* gui, float dt) { assert(gui != nullptr && "Ivalid GUI!"); - if (GetState() == WIDGETSTATE::FOCUS && !tooltip.empty()) + Hitbox2D pointerHitbox = Hitbox2D(gui->GetPointerPos(), XMFLOAT2(1, 1)); + hitBox = Hitbox2D(XMFLOAT2(translation.x, translation.y), XMFLOAT2(scale.x, scale.y)); + + if (GetState() != WIDGETSTATE::ACTIVE && !tooltip.empty() && pointerHitbox.intersects(hitBox)) { tooltipTimer++; } @@ -88,7 +67,7 @@ void wiWidget::Detach() } void wiWidget::RenderTooltip(const wiGUI* gui, CommandList cmd) const { - if (!IsEnabled() || !IsVisible()) + if (!IsVisible()) { return; } @@ -219,7 +198,7 @@ void wiWidget::Deactivate() { state = DEACTIVATING; } -void wiWidget::SetColor(const wiColor& color, WIDGETSTATE state) +void wiWidget::SetColor(wiColor color, WIDGETSTATE state) { if (state == WIDGETSTATE_COUNT) { @@ -420,7 +399,7 @@ void wiButton::OnDragEnd(function func) -wiLabel::wiLabel(const std::string& name) :wiWidget() +wiLabel::wiLabel(const std::string& name) { SetName(name); SetText(fastName.GetString()); @@ -471,7 +450,7 @@ void wiLabel::Render(const wiGUI* gui, CommandList cmd) const string wiTextInputField::value_new = ""; -wiTextInputField::wiTextInputField(const std::string& name) :wiWidget() +wiTextInputField::wiTextInputField(const std::string& name) { SetName(name); SetText(fastName.GetString()); @@ -648,8 +627,7 @@ void wiTextInputField::DeleteFromInput() -wiSlider::wiSlider(float start, float end, float defaultValue, float step, const std::string& name) :wiWidget() -, start(start), end(end), value(defaultValue), step(std::max(step, 1.0f)) +wiSlider::wiSlider(float start, float end, float defaultValue, float step, const std::string& name) : start(start), end(end), value(defaultValue), step(std::max(step, 1.0f)) { SetName(name); SetText(fastName.GetString()); @@ -833,8 +811,7 @@ void wiSlider::OnSlide(function func) -wiCheckBox::wiCheckBox(const std::string& name) :wiWidget() -, checked(false) +wiCheckBox::wiCheckBox(const std::string& name) { SetName(name); SetText(fastName.GetString()); @@ -968,15 +945,12 @@ bool wiCheckBox::GetCheck() const -wiComboBox::wiComboBox(const std::string& name) :wiWidget() -, selected(-1), combostate(COMBOSTATE_INACTIVE), hovered(-1) +wiComboBox::wiComboBox(const std::string& name) { SetName(name); SetText(fastName.GetString()); OnSelect([](wiEventArgs args) {}); SetSize(XMFLOAT2(100, 20)); - SetMaxVisibleItemCount(8); - firstItemVisible = 0; } wiComboBox::~wiComboBox() { @@ -1257,8 +1231,7 @@ int wiComboBox::GetSelected() static const float windowcontrolSize = 20.0f; -wiWindow::wiWindow(wiGUI* gui, const std::string& name) :wiWidget() -, gui(gui) +wiWindow::wiWindow(wiGUI* gui, const std::string& name) : gui(gui) { assert(gui != nullptr && "Ivalid GUI!"); @@ -1521,27 +1494,133 @@ bool wiWindow::IsMinimized() const +struct rgb { + float r; // a fraction between 0 and 1 + float g; // a fraction between 0 and 1 + float b; // a fraction between 0 and 1 +}; + +struct hsv { + float h; // angle in degrees + float s; // a fraction between 0 and 1 + float v; // a fraction between 0 and 1 +}; + +hsv rgb2hsv(rgb in) +{ + hsv out; + float min, max, delta; + + min = in.r < in.g ? in.r : in.g; + min = min < in.b ? min : in.b; + + max = in.r > in.g ? in.r : in.g; + max = max > in.b ? max : in.b; + + out.v = max; // v + delta = max - min; + if (delta < 0.00001f) + { + out.s = 0; + out.h = 0; // undefined, maybe nan? + return out; + } + if (max > 0.0f) { // NOTE: if Max is == 0, this divide would cause a crash + out.s = (delta / max); // s + } + else { + // if max is 0, then r = g = b = 0 + // s = 0, h is undefined + out.s = 0.0f; + out.h = NAN; // its now undefined + return out; + } + if (in.r >= max) // > is bogus, just keeps compilor happy + out.h = (in.g - in.b) / delta; // between yellow & magenta + else + if (in.g >= max) + out.h = 2.0f + (in.b - in.r) / delta; // between cyan & yellow + else + out.h = 4.0f + (in.r - in.g) / delta; // between magenta & cyan + + out.h *= 60.0f; // degrees + + if (out.h < 0.0f) + out.h += 360.0f; + + return out; +} + + +rgb hsv2rgb(hsv in) +{ + float hh, p, q, t, ff; + long i; + rgb out; + + if (in.s <= 0.0f) { // < is bogus, just shuts up warnings + out.r = in.v; + out.g = in.v; + out.b = in.v; + return out; + } + hh = in.h; + if (hh >= 360.0f) hh = 0.0f; + hh /= 60.0f; + i = (long)hh; + ff = hh - i; + p = in.v * (1.0f - in.s); + q = in.v * (1.0f - (in.s * ff)); + t = in.v * (1.0f - (in.s * (1.0f - ff))); + + switch (i) { + case 0: + out.r = in.v; + out.g = t; + out.b = p; + break; + case 1: + out.r = q; + out.g = in.v; + out.b = p; + break; + case 2: + out.r = p; + out.g = in.v; + out.b = t; + break; + + case 3: + out.r = p; + out.g = q; + out.b = in.v; + break; + case 4: + out.r = t; + out.g = p; + out.b = in.v; + break; + case 5: + default: + out.r = in.v; + out.g = p; + out.b = q; + break; + } + return out; +} + wiColorPicker::wiColorPicker(wiGUI* gui, const std::string& name) :wiWindow(gui, name) { SetSize(XMFLOAT2(300, 260)); SetColor(wiColor::Ghost()); RemoveWidget(resizeDragger_BottomRight); RemoveWidget(resizeDragger_UpperLeft); - - hue_picker = XMFLOAT2(0, 0); - saturation_picker = XMFLOAT2(0, 0); - saturation_picker_barycentric = XMFLOAT3(0, 1, 0); - hue_color = XMFLOAT4(1, 0, 0, 1); - final_color = XMFLOAT4(1, 1, 1, 1); - angle = 0; } -wiColorPicker::~wiColorPicker() -{ -} -static const float __colorpicker_center = 120; -static const float __colorpicker_radius_triangle = 75; -static const float __colorpicker_radius = 80; -static const float __colorpicker_width = 16; +static const float colorpicker_center = 120; +static const float colorpicker_radius_triangle = 75; +static const float colorpicker_radius = 80; +static const float colorpicker_width = 16; void wiColorPicker::Update(wiGUI* gui, float dt) { wiWindow::Update(gui, dt); @@ -1561,18 +1640,18 @@ void wiColorPicker::Update(wiGUI* gui, float dt) state = IDLE; } - XMFLOAT2 center = XMFLOAT2(translation.x + __colorpicker_center, translation.y + __colorpicker_center); + XMFLOAT2 center = XMFLOAT2(translation.x + colorpicker_center, translation.y + colorpicker_center); XMFLOAT2 pointer = gui->GetPointerPos(); float distance = wiMath::Distance(center, pointer); - bool hover_hue = (distance > __colorpicker_radius) && (distance < __colorpicker_radius + __colorpicker_width); + bool hover_hue = (distance > colorpicker_radius) && (distance < colorpicker_radius + colorpicker_width); float distTri = 0; XMFLOAT4 A, B, C; - wiMath::ConstructTriangleEquilateral(__colorpicker_radius_triangle, A, B, C); + wiMath::ConstructTriangleEquilateral(colorpicker_radius_triangle, A, B, C); XMVECTOR _A = XMLoadFloat4(&A); XMVECTOR _B = XMLoadFloat4(&B); XMVECTOR _C = XMLoadFloat4(&C); - XMMATRIX _triTransform = XMMatrixRotationZ(-angle) * XMMatrixTranslation(center.x, center.y, 0); + XMMATRIX _triTransform = XMMatrixRotationZ(-hue / 360.0f * XM_2PI) * XMMatrixTranslation(center.x, center.y, 0); _A = XMVector4Transform(_A, _triTransform); _B = XMVector4Transform(_B, _triTransform); _C = XMVector4Transform(_C, _triTransform); @@ -1619,15 +1698,38 @@ void wiColorPicker::Update(wiGUI* gui, float dt) if (huefocus && dragged) { //hue pick - angle = wiMath::GetAngle(XMFLOAT2(pointer.x - center.x, pointer.y - center.y), XMFLOAT2(__colorpicker_radius, 0)); - XMFLOAT3 color3 = wiMath::HueToRGB(angle / XM_2PI); - hue_color = XMFLOAT4(color3.x, color3.y, color3.z, 1); + const float angle = wiMath::GetAngle(XMFLOAT2(pointer.x - center.x, pointer.y - center.y), XMFLOAT2(colorpicker_radius, 0)); + hue = angle / XM_2PI * 360.0f; gui->ActivateWidget(this); } else if (!huefocus && dragged) { // saturation pick - wiMath::GetBarycentric(O, _A, _B, _C, saturation_picker_barycentric.x, saturation_picker_barycentric.y, saturation_picker_barycentric.z, true); + float u, v, w; + wiMath::GetBarycentric(O, _A, _B, _C, u, v, w, true); + // u = saturated corner (color) + // v = desaturated corner (white) + // w = no luminosity corner (black) + + hsv source; + source.h = hue; + source.s = 1; + source.v = 1; + rgb result = hsv2rgb(source); + + XMVECTOR color_corner = XMVectorSet(result.r, result.g, result.b, 1); + XMVECTOR white_corner = XMVectorSet(1, 1, 1, 1); + XMVECTOR black_corner = XMVectorSet(0, 0, 0, 1); + XMVECTOR inner_point = u * color_corner + v * white_corner + w * black_corner; + + result.r = XMVectorGetX(inner_point); + result.g = XMVectorGetY(inner_point); + result.b = XMVectorGetZ(inner_point); + source = rgb2hsv(result); + + saturation = source.s; + luminance = source.v; + gui->ActivateWidget(this); } else if (state != IDLE) @@ -1635,16 +1737,10 @@ void wiColorPicker::Update(wiGUI* gui, float dt) gui->DeactivateWidget(this); } - float r = __colorpicker_radius + __colorpicker_width * 0.5f; - hue_picker = XMFLOAT2(center.x + r * cos(angle), center.y + r * -sin(angle)); - XMStoreFloat2(&saturation_picker, _A*saturation_picker_barycentric.x + _B * saturation_picker_barycentric.y + _C * saturation_picker_barycentric.z); - XMStoreFloat4(&final_color, XMLoadFloat4(&hue_color)*saturation_picker_barycentric.x + XMVectorSet(1, 1, 1, 1)*saturation_picker_barycentric.y + XMVectorSet(0, 0, 0, 1)*saturation_picker_barycentric.z); - if (dragged) { wiEventArgs args; args.clickPos = pointer; - args.fValue = angle; args.color = GetPickColor(); onColorChanged(args); } @@ -1682,7 +1778,7 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const vertices_saturation.push_back({ XMFLOAT4(0,0,0,0),XMFLOAT4(1,0,0,1) }); // hue vertices_saturation.push_back({ XMFLOAT4(0,0,0,0),XMFLOAT4(1,1,1,1) }); // white vertices_saturation.push_back({ XMFLOAT4(0,0,0,0),XMFLOAT4(0,0,0,1) }); // black - wiMath::ConstructTriangleEquilateral(__colorpicker_radius_triangle, vertices_saturation[0].pos, vertices_saturation[1].pos, vertices_saturation[2].pos); + wiMath::ConstructTriangleEquilateral(colorpicker_radius_triangle, vertices_saturation[0].pos, vertices_saturation[1].pos, vertices_saturation[2].pos); GPUBufferDesc desc; desc.BindFlags = BIND_VERTEX_BUFFER; @@ -1704,9 +1800,14 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const float t = p * XM_2PI; float x = cos(t); float y = -sin(t); - XMFLOAT3 rgb = wiMath::HueToRGB(p); - vertices.push_back({ XMFLOAT4(__colorpicker_radius * x, __colorpicker_radius * y, 0, 1), XMFLOAT4(rgb.x,rgb.y,rgb.z,1) }); - vertices.push_back({ XMFLOAT4((__colorpicker_radius + __colorpicker_width) * x, (__colorpicker_radius + __colorpicker_width) * y, 0, 1), XMFLOAT4(rgb.x,rgb.y,rgb.z,1) }); + hsv source; + source.h = p * 360.0f; + source.s = 1; + source.v = 1; + rgb result = hsv2rgb(source); + XMFLOAT4 color = XMFLOAT4(result.r, result.g, result.b, 1); + vertices.push_back({ XMFLOAT4(colorpicker_radius * x, colorpicker_radius * y, 0, 1), color }); + vertices.push_back({ XMFLOAT4((colorpicker_radius + colorpicker_width) * x, (colorpicker_radius + colorpicker_width) * y, 0, 1), color }); } GPUBufferDesc desc; @@ -1770,9 +1871,11 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const hr = wiRenderer::GetDevice()->CreateBuffer(&desc, &data, &vb_preview); } - } + const wiColor final_color = GetPickColor(); + const float angle = hue / 360.0f * XM_2PI; + const XMMATRIX Projection = wiRenderer::GetDevice()->GetScreenProjection(); wiRenderer::GetDevice()->BindConstantBuffer(VS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CBSLOT_RENDERER_MISC, cmd); @@ -1784,13 +1887,18 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const { if (vb_saturation.IsValid() && !vertices_saturation.empty()) { - vertices_saturation[0].col = hue_color; + hsv source; + source.h = hue; + source.s = 1; + source.v = 1; + rgb result = hsv2rgb(source); + vertices_saturation[0].col = XMFLOAT4(result.r, result.g, result.b, 1); wiRenderer::GetDevice()->UpdateBuffer(&vb_saturation, vertices_saturation.data(), cmd, vb_saturation.GetDesc().ByteWidth); } XMStoreFloat4x4(&cb.g_xTransform, XMMatrixRotationZ(-angle) * - XMMatrixTranslation(translation.x + __colorpicker_center, translation.y + __colorpicker_center, 0) * + XMMatrixTranslation(translation.x + colorpicker_center, translation.y + colorpicker_center, 0) * Projection ); cb.g_xColor = IsEnabled() ? float4(1, 1, 1, 1) : float4(0.5f, 0.5f, 0.5f, 1); @@ -1808,7 +1916,7 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const // render hue circle { XMStoreFloat4x4(&cb.g_xTransform, - XMMatrixTranslation(translation.x + __colorpicker_center, translation.y + __colorpicker_center, 0) * + XMMatrixTranslation(translation.x + colorpicker_center, translation.y + colorpicker_center, 0) * Projection ); cb.g_xColor = IsEnabled() ? float4(1, 1, 1, 1) : float4(0.5f, 0.5f, 0.5f, 1); @@ -1826,11 +1934,19 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const // render hue picker if(IsEnabled()) { + const float angle = hue / 360.0f * XM_2PI; + const float r = colorpicker_radius + colorpicker_width * 0.5f; XMStoreFloat4x4(&cb.g_xTransform, - XMMatrixTranslation(hue_picker.x, hue_picker.y, 0) * + XMMatrixTranslation(translation.x + colorpicker_center + r * cos(angle), translation.y + colorpicker_center + r * -sin(angle), 0) * Projection ); - cb.g_xColor = float4(1 - hue_color.x, 1 - hue_color.y, 1 - hue_color.z, 1); + + hsv source; + source.h = hue; + source.s = 1; + source.v = 1; + rgb result = hsv2rgb(source); + cb.g_xColor = float4(1 - result.r, 1 - result.g, 1 - result.b, 1); wiRenderer::GetDevice()->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); const GPUBuffer* vbs[] = { &vb_picker, @@ -1845,11 +1961,43 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const // render saturation picker if (IsEnabled()) { + XMFLOAT2 center = XMFLOAT2(translation.x + colorpicker_center, translation.y + colorpicker_center); + XMFLOAT4 A, B, C; + wiMath::ConstructTriangleEquilateral(colorpicker_radius_triangle, A, B, C); + XMVECTOR _A = XMLoadFloat4(&A); + XMVECTOR _B = XMLoadFloat4(&B); + XMVECTOR _C = XMLoadFloat4(&C); + XMMATRIX _triTransform = XMMatrixRotationZ(-hue / 360.0f * XM_2PI) * XMMatrixTranslation(center.x, center.y, 0); + _A = XMVector4Transform(_A, _triTransform); + _B = XMVector4Transform(_B, _triTransform); + _C = XMVector4Transform(_C, _triTransform); + + hsv source; + source.h = hue; + source.s = 1; + source.v = 1; + rgb result = hsv2rgb(source); + + XMVECTOR color_corner = XMVectorSet(result.r, result.g, result.b, 1); + XMVECTOR white_corner = XMVectorSet(1, 1, 1, 1); + XMVECTOR black_corner = XMVectorSet(0, 0, 0, 1); + + source.h = hue; + source.s = saturation; + source.v = luminance; + result = hsv2rgb(source); + XMVECTOR inner_point = XMVectorSet(result.r, result.g, result.b, 1); + + float u, v, w; + wiMath::GetBarycentric(inner_point, color_corner, white_corner, black_corner, u, v, w, true); + + XMVECTOR picker_center = u * _A + v * _B + w * _C; + XMStoreFloat4x4(&cb.g_xTransform, - XMMatrixTranslation(saturation_picker.x, saturation_picker.y, 0) * + XMMatrixTranslationFromVector(picker_center) * Projection ); - cb.g_xColor = float4(1 - final_color.x, 1 - final_color.y, 1 - final_color.z, 1); + cb.g_xColor = float4(1 - final_color.toFloat3().x, 1 - final_color.toFloat3().y, 1 - final_color.toFloat3().z, 1); wiRenderer::GetDevice()->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); const GPUBuffer* vbs[] = { &vb_picker, @@ -1867,7 +2015,7 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const XMMatrixTranslation(translation.x + 260, translation.y + 40, 0) * Projection ); - cb.g_xColor = GetPickColor().toFloat4(); + cb.g_xColor = final_color.toFloat4(); wiRenderer::GetDevice()->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); const GPUBuffer* vbs[] = { &vb_preview, @@ -1880,21 +2028,43 @@ void wiColorPicker::Render(const wiGUI* gui, CommandList cmd) const } // RGB values: - stringstream _rgb(""); - _rgb << "R: " << (int)(final_color.x * 255) << endl; - _rgb << "G: " << (int)(final_color.y * 255) << endl; - _rgb << "B: " << (int)(final_color.z * 255) << endl; - wiFont(_rgb.str(), wiFontParams((int)(translation.x + 200), (int)(translation.y + 200), WIFONTSIZE_DEFAULT, WIFALIGN_LEFT, WIFALIGN_TOP, 0, 0, + stringstream ss(""); + ss << "R: " << int(final_color.getR()) << endl; + ss << "G: " << int(final_color.getG()) << endl; + ss << "B: " << int(final_color.getB()) << endl; + ss << endl; + ss << "H: " << int(hue) << endl; + ss << "S: " << int(saturation * 100) << endl; + ss << "V: " << int(luminance * 100) << endl; + wiFont(ss.str(), wiFontParams((int)(translation.x + 240), (int)(translation.y + 80), WIFONTSIZE_DEFAULT, WIFALIGN_LEFT, WIFALIGN_TOP, 0, 0, textColor, textShadowColor)).Draw(cmd); } -const wiColor& wiColorPicker::GetPickColor() const +wiColor wiColorPicker::GetPickColor() const { - return wiColor::fromFloat4(final_color); + hsv source; + source.h = hue; + source.s = saturation; + source.v = luminance; + rgb result = hsv2rgb(source); + return wiColor::fromFloat3(XMFLOAT3(result.r, result.g, result.b)); } -void wiColorPicker::SetPickColor(const wiColor& value) +void wiColorPicker::SetPickColor(wiColor value) { - // TODO + rgb source; + source.r = value.toFloat3().x; + source.g = value.toFloat3().y; + source.b = value.toFloat3().z; + hsv result = rgb2hsv(source); + if ( + (value.getR() < 255 || value.getG() < 255 || value.getB() < 255) && + (value.getR() > 0 || value.getG() > 0 || value.getB() > 0) + ) + { + hue = result.h; // only change the hue when not pure black or white because those don't retain the saturation value + } + saturation = result.s; + luminance = result.v; } void wiColorPicker::OnColorChanged(function func) { diff --git a/WickedEngine/wiWidget.h b/WickedEngine/wiWidget.h index aa86f96c3..9474119ac 100644 --- a/WickedEngine/wiWidget.h +++ b/WickedEngine/wiWidget.h @@ -31,39 +31,38 @@ class wiWidget : public wiSceneSystem::TransformComponent public: enum WIDGETSTATE { - // widget is doing nothing - IDLE, - // widget got pointer dragged on or selected - FOCUS, - // widget is interacted with right now - ACTIVE, - // widget has last been active but no more interactions are occuring - DEACTIVATING, + IDLE, // widget is doing nothing + FOCUS, // widget got pointer dragged on or selected + ACTIVE, // widget is interacted with right now + DEACTIVATING, // widget has last been active but no more interactions are occuring WIDGETSTATE_COUNT, }; private: - float fontScaling; - int tooltipTimer; + int tooltipTimer = 0; protected: wiHashString fastName; std::string text; std::string tooltip; std::string scriptTip; - bool enabled; - bool visible; + bool enabled = true; + bool visible = true; - WIDGETSTATE state; + WIDGETSTATE state = IDLE; void Activate(); void Deactivate(); - wiColor colors[WIDGETSTATE_COUNT]; wiGraphics::Rect scissorRect; - wiColor textColor; - wiColor textShadowColor; -public: - wiWidget(); - virtual ~wiWidget(); + wiColor colors[WIDGETSTATE_COUNT] = { + wiColor::Booger(), + wiColor::Gray(), + wiColor::White(), + wiColor::Gray(), + }; + static_assert(ARRAYSIZE(colors) == WIDGETSTATE_COUNT, "Every WIDGETSTATE needs a default color!"); + wiColor textColor = wiColor(255, 255, 255, 255); + wiColor textShadowColor = wiColor(0, 0, 0, 255); +public: const wiHashString& GetName() const; void SetName(const std::string& value); const std::string& GetText() const; @@ -78,23 +77,23 @@ public: virtual void SetVisible(bool val); bool IsVisible() const; // last param default: set color for all states - void SetColor(const wiColor& color, WIDGETSTATE state = WIDGETSTATE_COUNT); + void SetColor(wiColor color, WIDGETSTATE state = WIDGETSTATE_COUNT); wiColor GetColor() const; void SetScissorRect(const wiGraphics::Rect& rect); - void SetTextColor(const wiColor& value) { textColor = value; } - void SetTextShadowColor(const wiColor& value) { textShadowColor = value; } + void SetTextColor(wiColor value) { textColor = value; } + void SetTextShadowColor(wiColor value) { textShadowColor = value; } virtual void Update(wiGUI* gui, float dt); virtual void Render(const wiGUI* gui, wiGraphics::CommandList cmd) const = 0; void RenderTooltip(const wiGUI* gui, wiGraphics::CommandList cmd) const; - XMFLOAT3 translation; - XMFLOAT3 scale; + XMFLOAT3 translation = XMFLOAT3(0, 0, 0); + XMFLOAT3 scale = XMFLOAT3(1, 1, 1); Hitbox2D hitBox; - wiSceneSystem::TransformComponent* parent; - XMFLOAT4X4 world_parent_bind; + wiSceneSystem::TransformComponent* parent = nullptr; + XMFLOAT4X4 world_parent_bind = IDENTITYMATRIX; void AttachTo(wiSceneSystem::TransformComponent* parent); void Detach(); @@ -109,8 +108,8 @@ protected: std::function onDragStart; std::function onDrag; std::function onDragEnd; - XMFLOAT2 dragStart; - XMFLOAT2 prevPos; + XMFLOAT2 dragStart = XMFLOAT2(0, 0); + XMFLOAT2 prevPos = XMFLOAT2(0, 0); public: wiButton(const std::string& name = ""); virtual ~wiButton(); @@ -168,9 +167,9 @@ class wiSlider : public wiWidget { protected: std::function onSlide; - float start, end; - float step; - float value; + float start = 0, end = 1; + float step = 1000; + float value = 0; wiTextInputField* valueInputField; public: @@ -196,7 +195,7 @@ class wiCheckBox :public wiWidget { protected: std::function onClick; - bool checked; + bool checked = false; public: wiCheckBox(const std::string& name = ""); virtual ~wiCheckBox(); @@ -215,22 +214,19 @@ class wiComboBox :public wiWidget { protected: std::function onSelect; - int selected; - int maxVisibleItemCount; - int firstItemVisible; + int selected = -1; + int maxVisibleItemCount = 8; + int firstItemVisible = 0; // While the widget is active (rolled down) these are the inner states that control behaviour enum COMBOSTATE { - // When the list is just being dropped down, or the widget is not active - COMBOSTATE_INACTIVE, - // The widget is in drop-down state with the last item hovered highlited - COMBOSTATE_HOVER, - // The hovered item is clicked - COMBOSTATE_SELECTING, + COMBOSTATE_INACTIVE, // When the list is just being dropped down, or the widget is not active + COMBOSTATE_HOVER, // The widget is in drop-down state with the last item hovered highlited + COMBOSTATE_SELECTING, // The hovered item is clicked COMBOSTATE_COUNT, - } combostate; - int hovered; + } combostate = COMBOSTATE_INACTIVE; + int hovered = -1; std::vector items; @@ -265,7 +261,7 @@ protected: wiButton* resizeDragger_BottomRight = nullptr; wiButton* moveDragger = nullptr; std::list childrenWidgets; - bool minimized; + bool minimized = false; public: wiWindow(wiGUI* gui, const std::string& name = ""); virtual ~wiWindow(); @@ -288,22 +284,18 @@ class wiColorPicker : public wiWindow { protected: std::function onColorChanged; - XMFLOAT2 hue_picker; - XMFLOAT2 saturation_picker; - XMFLOAT3 saturation_picker_barycentric; - XMFLOAT4 hue_color; - XMFLOAT4 final_color; - float angle; - bool huefocus; // whether the hue is in focus or the saturation + bool huefocus = false; // whether the hue picker is in focus or the saturation + float hue = 0.0f; // [0, 360] degrees + float saturation = 0.0f; // [0, 1] + float luminance = 1.0f; // [0, 1] public: wiColorPicker(wiGUI* gui, const std::string& name = ""); - virtual ~wiColorPicker(); virtual void Update(wiGUI* gui, float dt ) override; virtual void Render(const wiGUI* gui, wiGraphics::CommandList cmd) const override; - const wiColor& GetPickColor() const; - void SetPickColor(const wiColor& value); + wiColor GetPickColor() const; + void SetPickColor(wiColor value); void OnColorChanged(std::function func); };