Noiser Texture Creator - Source Preview


double NoiserFrame::parseDouble(wxString setting)
{
    int index = setting.Find('=');
    if (index == wxNOT_FOUND) index = -1;
    setting = setting.SubString(index + 1, setting.Length());
    double ret;
    if (!setting.ToDouble(&ret)) {
        StatusBar->SetStatusText(_("Error: Bad module parameter. Failed to parse double value from \"") + setting + _("\". Module removed."));
        isRendering = false;
        return NULL;
    } else return ret;
}
 
int NoiserFrame::parseInt(wxString setting, int minimum, int maximum)
{
    int index = setting.Find('=');
    if (index == wxNOT_FOUND) index = -1;
    setting = setting.SubString(index + 1, setting.Length());
    int ret = wxAtoi(setting);
    if (ret >= minimum && ret <= maximum) return ret;
    StatusBar->SetStatusText(_("Error: Bad module parameter. Value parsed from \"") + setting + _("\" is out of bounds. Module removed."));
    isRendering = false;
    return true;
}
 
int NoiserFrame::parseQuality(wxString setting)
{
    int index = setting.Find('=');
    if (index == wxNOT_FOUND) index = -1;
    setting = setting.SubString(index + 1, setting.Length());
    if (setting == _("QUALITY_FAST")) {
        return 0;
    } else if (setting == _("QUALITY_STD")) {
        return 1;
    } else if (setting == _("QUALITY_BEST")) {
        return 2;
    } else {
        StatusBar->SetStatusText(_("Error: Bad module parameter. Failed to parse quality from \"") + setting + _("\". Module removed."));
        isRendering = false;
        return NULL;
    }
}
 
std::vector<int> NoiserFrame::parseRGBA(wxString setting)
{
    int index = setting.Find('(');
    std::vector<int> ret(4, -1);
    if (index == wxNOT_FOUND) index = -1;
 
    wxString colorArrayString = setting.SubString(index + 1, setting.Length());
    int indexRed = colorArrayString.Find(',');
    wxString colorRed = colorArrayString.SubString(0, indexRed - 1);
    int red = wxAtoi(colorRed);
 
    colorArrayString = colorArrayString.SubString(indexRed + 1, colorArrayString.Length());
    int indexGreen = colorArrayString.Find(',');
    wxString colorGreen = colorArrayString.SubString(0, indexGreen - 1);
    int green = wxAtoi(colorGreen);
 
    colorArrayString = colorArrayString.SubString(indexGreen + 1, colorArrayString.Length());
    int indexBlue = colorArrayString.Find(',');
    wxString colorBlue = colorArrayString.SubString(0, indexBlue - 1);
    int blue = wxAtoi(colorBlue);
 
    colorArrayString = colorArrayString.SubString(indexBlue + 1, colorArrayString.Length());
    int indexAlpha = colorArrayString.Find(')');
    wxString colorAlpha = colorArrayString.SubString(0, indexAlpha - 1);
    int alpha = wxAtoi(colorAlpha);
 
    if ((red >= 0 && red <= 255) &&
        (green >= 0 && green <= 255) &&
        (blue >= 0 && blue <= 255) &&
        (alpha >= 0 && alpha <= 255)) {
        ret[0] = red;
        ret[1] = green;
        ret[2] = blue;
        ret[3] = alpha;
        return ret;
    } else {
        StatusBar->SetStatusText(_("Error: Bad module parameter. Failed to parse color values from \"") + setting + _("\". Module removed."));
        isRendering = false;
        return ret;
    }
}
 
bool NoiserFrame::parseBool(wxString setting)
{
    int index = setting.Find('=');
    if (index == wxNOT_FOUND) index = -1;
    setting = setting.SubString(index + 1, setting.Length());
    if (setting == _("true") || setting == _("True")) {
        return true;
    } else if (setting == _("false") || setting == _("False")) {
        return false;
    } else {
        StatusBar->SetStatusText(_("Error: Bad module parameter. Failed to parse boolean value from \"") + setting + _("\". Module removed."));
        isRendering = false;
        return NULL;
    }
}
 
bool NoiserFrame::parseProjectSet(wxString tag)
{
    int indexPosSpace = tag.Find(' ');
    int indexPosSpace2 = tag.Find(' ', true);
    int indexPosSpace2Times = tag.Find('x', true);
    if (indexPosSpace == wxNOT_FOUND || indexPosSpace2  == wxNOT_FOUND
        || indexPosSpace2Times  == wxNOT_FOUND) {
      return false;
    } else {
        wxString stringProject = tag.SubString(0, indexPosSpace - 1);
        if (stringProject == _("Project")) {
            wxString stringProjectName = tag.SubString(indexPosSpace + 1, indexPosSpace2 - 1);
            this->projectName = stringProjectName;
            int width = parseInt(tag.SubString(indexPosSpace2 + 1, indexPosSpace2Times - 1), 0, INT_MAX);
            int height = parseInt(tag.SubString(indexPosSpace2Times + 1, tag.Length()), 0, INT_MAX);
            if (width >= 0 && height >=0) {
                this->projectHeight = height;
                this->projectWidth = width;
                this->SetTitle(_("Noiser - ") + stringProjectName);
                return true;
            } else return false;
        } else return false;
    }
}
 
int NoiserFrame::parseSourceModule(wxString setting) {
    int index = setting.Find('=');
    if (index == wxNOT_FOUND) index = -1;
    setting = setting.SubString(index + 1, setting.Length());
    if (setting.Length() > 0) {
        int indexSpace = setting.Find(' ');
        wxString moduleIndexString = setting.SubString(0, indexSpace);
        wxString moduleTitleString = setting.SubString(indexSpace + 1, setting.Length());
        int ret = wxAtoi(moduleIndexString);
        if (ret >= 0 && ret < logTreeStrings.GetCount()) {
            if (logTreeStrings.Item(ret) == moduleTitleString) return ret;
            else {
                StatusBar->SetStatusText(_("Error: Bad source module setting. Could not locate correct source module for \"") + setting + _("\". Module removed."));
                isRendering = false;
                // Cleanup on next update.
                requestUpdate = true;
                return 0;
            }
        } else {
            StatusBar->SetStatusText(_("Error: Bad module parameter. Failed to parse source module from \"") + setting + _("\". Module removed."));
            isRendering = false;
            return 0;
        }
    } else {
        StatusBar->SetStatusText(_("Error: Bad module parameter. Failed to parse source module from \"") + setting + _("\". Module removed."));
        isRendering = false;
        return 0;
    }
}
 
std::vector<double> NoiserFrame::parseControlPoints(wxString setting, int minimum)
{
    int index = setting.Find('=');
    std::vector<double> ret;
    if (index == wxNOT_FOUND) index = -1;
    setting = setting.SubString(index + 1, setting.Length());
    int indexSep;
    while (!(indexSep == wxNOT_FOUND)) {
        indexSep = setting.Find(',');
        wxString doubleValue = setting.SubString(0, indexSep - 1);
        setting = setting.SubString(indexSep + 1, setting.Length());
        double pushMe = parseDouble(doubleValue);
        if (isRendering) {
            ret.push_back(pushMe);
        }
    }
    if (ret.size() >= minimum) return ret;
    else {
        StatusBar->SetStatusText(_("Error: Bad module parameter. The control point array requires ") + wxString::Format(wxT("%i"),minimum) + _(" values. Module removed."));
        isRendering = false;
        return ret;
    }
}
 
void NoiserFrame::RenderTexture(wxString requestType)
{
    if (isRendering) return;
    isRendering = true;
    ButtonRender->Enable(false);
    wxString appendDone = _("");
    logTreeStrings.Clear();
    // RootNode
    wxTreeItemId rootNode = NoiseTree->GetRootItem();
    if (!parseProjectSet(NoiseTree->GetItemText(rootNode))) {
        // Failed to parse project settings; Revert to default.
        NoiseTree->SetItemText(rootNode, _("Project Default 512x512"));
    }
    if ((this->projectWidth > 512 || this->projectHeight > 512) && sizeReminder) {
        MenuItemAutoRender->Check(false);
        sizeReminder = false;
        StatusBar->SetStatusText(_("Warning: An image of this size will take some time to render. Auto-update disabled."));
        requestUpdate = false;
        ButtonRender->Enable(true);
        isRendering = false;
        return;
    }
    // ModuleNode
    wxTreeItemIdValue cookie;
    wxTreeItemId moduleNode = NoiseTree->GetFirstChild(rootNode, cookie);
    if (NoiseTree->GetChildrenCount(moduleNode) == 0) {
        isRendering = false;
        ButtonRender->Enable(true);
        return;
    }
    // The most important; The array of module-pointers
    std::vector<noise::module::Module*> moduleHolder;
    // First ModuleNode Child
    wxTreeItemIdValue cookieSub;
    wxTreeItemId child = NoiseTree->GetFirstChild(moduleNode, cookieSub);
    wxString moduleTitleCheck = NoiseTree->GetItemText(child);
    if (moduleTitleCheck != _("Billow") &&
        moduleTitleCheck != _("Const") &&
        moduleTitleCheck != _("Cylinders") &&
        moduleTitleCheck != _("Perlin") &&
        moduleTitleCheck != _("RidgedMulti") &&
        moduleTitleCheck != _("Spheres") &&
        moduleTitleCheck != _("Voronoi") ) {
        StatusBar->SetStatusText(_("Error: Please add a generator module first."));
        NoiseTree->Delete(child);
        ButtonRender->Enable(true);
        isRendering = false;
        requestUpdate = true;
        return;
    }
 
    // Build the Module-Tree
    while(child.IsOk()) {
        wxString moduleTitle = NoiseTree->GetItemText(child);
        logTreeStrings.Add(moduleTitle);
 
        wxTreeItemIdValue cookieSubModuleSetting;
        wxTreeItemId childModuleSetting = NoiseTree->GetFirstChild(child, cookieSubModuleSetting);
 
        // Generators
        if (moduleTitle == _("Billow")) {
            module::Billow* module = new module::Billow();
            module->SetFrequency(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetLacunarity(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetOctaveCount(parseInt(NoiseTree->GetItemText(childModuleSetting), 1, 30));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetPersistence(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetNoiseQuality(parseQuality(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetSeed(parseInt(NoiseTree->GetItemText(childModuleSetting), 0, INT_MAX));
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("Checkerboard")) {
            module::Checkerboard* module = new module::Checkerboard();
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("Const")) {
            module::Const* module = new module::Const();
            module->SetConstValue(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("Cylinders")) {
            module::Cylinders* module = new module::Cylinders();
            module->SetFrequency(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("Perlin")) {
            module::Perlin* module = new module::Perlin();
            module->SetFrequency(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetLacunarity(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetOctaveCount(parseInt(NoiseTree->GetItemText(childModuleSetting), 1, 30));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetPersistence(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetNoiseQuality(parseQuality(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetSeed(parseInt(NoiseTree->GetItemText(childModuleSetting), 0, INT_MAX));
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("RidgedMulti")) {
            module::RidgedMulti* module = new module::RidgedMulti();
            module->SetFrequency(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetLacunarity(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetOctaveCount(parseInt(NoiseTree->GetItemText(childModuleSetting), 1, 30));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetNoiseQuality(parseQuality(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetSeed(parseInt(NoiseTree->GetItemText(childModuleSetting), 0, INT_MAX));
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("Spheres")) {
            module::Spheres* module = new module::Spheres();
            module->SetFrequency(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("Voronoi")) {
            module::Voronoi* module = new module::Voronoi();
            module->EnableDistance(parseBool(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetDisplacement(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetFrequency(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetSeed(parseInt(NoiseTree->GetItemText(childModuleSetting), 0, INT_MAX));
            moduleHolder.push_back(module);
        // Transformers
        } else if (moduleTitle == _("Displace")) {
            module::Displace* module = new module::Displace();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetSourceModule(1, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetSourceModule(2, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetSourceModule(3, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("RotatePoint")) {
            module::RotatePoint* module = new module::RotatePoint();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetXAngle(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetYAngle(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetZAngle(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("ScalePoint")) {
            module::ScalePoint* module = new module::ScalePoint();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetXScale(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetYScale(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetZScale(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("TranslatePoint")) {
            module::TranslatePoint* module = new module::TranslatePoint();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetXTranslation(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetYTranslation(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetZTranslation(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("Turbulence")) {
            module::Turbulence* module = new module::Turbulence();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetFrequency(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetPower(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetRoughness(parseInt(NoiseTree->GetItemText(childModuleSetting), 0, 30));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetSeed(parseInt(NoiseTree->GetItemText(childModuleSetting), 0, INT_MAX));
            moduleHolder.push_back(module);
        // Modifiers
        } else if (moduleTitle == _("Abs")) {
            module::Abs* module = new module::Abs();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("Clamp")) {
            module::Clamp* module = new module::Clamp();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            double lowerBound = parseDouble(NoiseTree->GetItemText(childModuleSetting));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetBounds(lowerBound, parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("Curve")) {
            module::Curve* module = new module::Curve();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            std::vector<double> pointPairs = parseControlPoints(NoiseTree->GetItemText(childModuleSetting), 4);
            if (pointPairs.size() >= 4) {
                for (int i = 0; i < pointPairs.size(); i+=2) {
                    module->AddControlPoint(pointPairs[i], pointPairs[i + 1]);
                }
            } else {
                StatusBar->SetStatusText(_("Error: Bad module parameter. The control point array requires 4 values. Module removed."));
                isRendering = false;
            }
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("Exponent")) {
            module::Exponent* module = new module::Exponent();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetExponent(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("Invert")) {
            module::Invert* module = new module::Invert();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("ScaleBias")) {
            module::ScaleBias* module = new module::ScaleBias();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetBias(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetScale(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("Terrace")) {
            module::Terrace* module = new module::Terrace();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            std::vector<double> pointPairs = parseControlPoints(NoiseTree->GetItemText(childModuleSetting), 2);
            if (pointPairs.size() >= 2) {
                for (int i = 0; i < pointPairs.size(); i++) {
                    module->AddControlPoint(pointPairs[i]);
                }
            } else {
                StatusBar->SetStatusText(_("Error: Bad module parameter. The control point array requires 2 values. Module removed."));
                isRendering = false;
            }
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->InvertTerraces(parseBool(NoiseTree->GetItemText(childModuleSetting)));
            moduleHolder.push_back(module);
        // Combiners
        } else if (moduleTitle == _("Add")) {
            module::Add* module = new module::Add();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetSourceModule(1, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("Max")) {
            module::Max* module = new module::Max();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetSourceModule(1, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("Min")) {
            module::Min* module = new module::Min();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetSourceModule(1, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("Multiply")) {
            module::Multiply* module = new module::Multiply();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetSourceModule(1, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("Power")) {
            module::Power* module = new module::Power();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetSourceModule(1, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            moduleHolder.push_back(module);
        // Selectors
        } else if (moduleTitle == _("Blend")) {
            module::Blend* module = new module::Blend();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetSourceModule(1, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetSourceModule(2, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            moduleHolder.push_back(module);
        } else if (moduleTitle == _("Select")) {
            module::Select* module = new module::Select();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetSourceModule(1, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetControlModule(*moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetEdgeFalloff(parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            double lowerBound = parseDouble(NoiseTree->GetItemText(childModuleSetting));
            childModuleSetting = NoiseTree->GetNextSibling(childModuleSetting);
            module->SetBounds(lowerBound, parseDouble(NoiseTree->GetItemText(childModuleSetting)));
            moduleHolder.push_back(module);
        // Miscellaneous
        } else if (moduleTitle == _("Cache")) {
            module::Cache* module = new module::Cache();
            module->SetSourceModule(0, *moduleHolder[parseSourceModule(NoiseTree->GetItemText(childModuleSetting))]);
            moduleHolder.push_back(module);
        }
        if (!isRendering) {
            NoiseTree->Delete(child);
            ButtonRender->Enable(true);
            requestUpdate = false;
            return;
        }
        if (child == NoiseTree->GetLastChild(child)) break;
        else if (NoiseTree->IsSelected(child)) break;
        else child = NoiseTree->GetNextSibling(child);
    }
    // Renderer settings
    wxTreeItemId rendererNode = NoiseTree->GetNextChild(rootNode, cookie);
    wxTreeItemIdValue cookieRenderSub;
    wxTreeItemId rendererSetting = NoiseTree->GetFirstChild(rendererNode, cookieRenderSub);
    utils::RendererImage renderer;
    renderer.ClearGradient();
    renderer.EnableLight(true);
    utils::NoiseMap noiseMap;
    utils::Image texture;
    renderer.SetDestImage(texture);
    renderer.SetLightAzimuth(parseDouble(NoiseTree->GetItemText(rendererSetting)));
    rendererSetting = NoiseTree->GetNextChild(rendererNode, cookieRenderSub);
    renderer.SetLightBrightness(parseDouble(NoiseTree->GetItemText(rendererSetting)));
    rendererSetting = NoiseTree->GetNextChild(rendererNode, cookieRenderSub);
    std::vector<int> returnColor = parseRGBA(NoiseTree->GetItemText(rendererSetting));
    renderer.SetLightColor(utils::Color(returnColor[0], returnColor[1], returnColor[2], returnColor[3]));
    rendererSetting = NoiseTree->GetNextChild(rendererNode, cookieRenderSub);
    renderer.SetLightContrast(parseDouble(NoiseTree->GetItemText(rendererSetting)));
    rendererSetting = NoiseTree->GetNextChild(rendererNode, cookieRenderSub);
    renderer.SetLightElev(parseDouble(NoiseTree->GetItemText(rendererSetting)));
    rendererSetting = NoiseTree->GetNextChild(rendererNode, cookieRenderSub);
    renderer.SetLightIntensity(parseDouble(NoiseTree->GetItemText(rendererSetting)));
    if (ListBoxColors->GetCount() < 2) {
        ListBoxColors->Clear();
        ListBoxColors->Append(_("-1.0=rgba(255,255,255,255)"));
        ListBoxColors->Append(_("1.0=rgba(0,0,0,255)"));
        appendDone = _(" Please set at least 2 render colors. Render colors reset to default.");
    }
    double rememberDouble = -2.0;
    for (unsigned int i = 0; i < ListBoxColors->GetCount(); i++) {
        wxString currentSet = ListBoxColors->GetString(i);
        int indexPosition = currentSet.Find('=');
        wxString currentSetDouble = currentSet.SubString(0, indexPosition - 1);
        double currentDouble = parseDouble(currentSetDouble);
        // Skip duplicate positions.
        if (rememberDouble == currentDouble) continue;
        else rememberDouble = currentDouble;
        wxString settingRGBA = currentSet.SubString(indexPosition + 1, currentSet.Length());
        std::vector<int> color = parseRGBA(settingRGBA);
        renderer.AddGradientPoint(currentDouble, utils::Color(color[0], color[1], color[2], color[3]));
    }
    // Surface
    if (RadioBoxSurface->GetSelection() == 0) {
        // Planar
        utils::NoiseMapBuilderPlane plane;
        rendererSetting = NoiseTree->GetNextChild(rendererNode, cookieRenderSub);
        wxTreeItemIdValue cookieBuilder;
        wxTreeItemId builderNode = NoiseTree->GetFirstChild(rendererSetting, cookieBuilder);
        if (CheckBoxSeamless->IsChecked()) {
            plane.EnableSeamless(true);
            NoiseTree->SetItemText(builderNode, _("EnableSeamless=true"));
        } else {
            plane.EnableSeamless(false);
            NoiseTree->SetItemText(builderNode, _("EnableSeamless=false"));
        }
        builderNode = NoiseTree->GetNextSibling(builderNode);
        double lowerXBound = parseDouble(NoiseTree->GetItemText(builderNode));
        builderNode = NoiseTree->GetNextSibling(builderNode);
        double upperXBound = parseDouble(NoiseTree->GetItemText(builderNode));
        builderNode = NoiseTree->GetNextSibling(builderNode);
        double lowerZBound = parseDouble(NoiseTree->GetItemText(builderNode));
        builderNode = NoiseTree->GetNextSibling(builderNode);
        double upperZBound = parseDouble(NoiseTree->GetItemText(builderNode));
        if (lowerXBound >= upperXBound || lowerZBound >= upperZBound) {
            plane.SetBounds(-1.0, 1.0, -1.0, 1.0);
            appendDone = _(" Incoherent planar bounds. Defaults used.");
        } else plane.SetBounds(lowerXBound, upperXBound, lowerZBound, upperZBound);
        plane.SetDestSize(this->projectWidth, this->projectHeight);
        plane.SetSourceModule(*moduleHolder[moduleHolder.size() - 1]);
        plane.SetDestNoiseMap(noiseMap);
        this->StatusBar->SetStatusText(wxT("Building Planar Map ..."));
        plane.Build(this->RenderGauge);
    } else if (RadioBoxSurface->GetSelection() == 1) {
        // Cylindrical
        rendererSetting = NoiseTree->GetNextChild(rendererNode, cookieRenderSub);
        rendererSetting = NoiseTree->GetNextChild(rendererNode, cookieRenderSub);
        rendererSetting = NoiseTree->GetNextChild(rendererNode, cookieRenderSub);
        wxTreeItemIdValue cookieBuilder;
        wxTreeItemId builderNode = NoiseTree->GetFirstChild(rendererSetting, cookieBuilder);
        utils::NoiseMapBuilderCylinder cylinder;
        double lowerAngleBound = parseDouble(NoiseTree->GetItemText(builderNode));
        builderNode = NoiseTree->GetNextSibling(builderNode);
        double upperAngleBound = parseDouble(NoiseTree->GetItemText(builderNode));
        builderNode = NoiseTree->GetNextSibling(builderNode);
        double lowerHeightBound = parseDouble(NoiseTree->GetItemText(builderNode));
        builderNode = NoiseTree->GetNextSibling(builderNode);
        double upperHeightBound = parseDouble(NoiseTree->GetItemText(builderNode));
        if (lowerAngleBound >= upperAngleBound || lowerHeightBound >= upperHeightBound) {
            cylinder.SetBounds(-180.0, 180.0, -10.0, 10.0);
            appendDone = _(" Incoherent cylindrical bounds. Defaults used.");
        } else cylinder.SetBounds(lowerAngleBound, upperAngleBound, lowerHeightBound, upperHeightBound);
        cylinder.SetDestSize(this->projectWidth, this->projectHeight);
        cylinder.SetSourceModule(*moduleHolder[moduleHolder.size() - 1]);
        cylinder.SetDestNoiseMap(noiseMap);
        this->StatusBar->SetStatusText(wxT("Building Cylindrical Map ..."));
        cylinder.Build(this->RenderGauge);
    } else {
        // Spherical
        rendererSetting = NoiseTree->GetNextChild(rendererNode, cookieRenderSub);
        rendererSetting = NoiseTree->GetNextChild(rendererNode, cookieRenderSub);
        wxTreeItemIdValue cookieBuilder;
        this->projectWidth *= 2;
        wxTreeItemId builderNode = NoiseTree->GetFirstChild(rendererSetting, cookieBuilder);
        utils::NoiseMapBuilderSphere sphere;
        double southLatBound = parseDouble(NoiseTree->GetItemText(builderNode));
        builderNode = NoiseTree->GetNextSibling(builderNode);
        double northLatBound = parseDouble(NoiseTree->GetItemText(builderNode));
        builderNode = NoiseTree->GetNextSibling(builderNode);
        double westLonBound = parseDouble(NoiseTree->GetItemText(builderNode));
        builderNode = NoiseTree->GetNextSibling(builderNode);
        double eastLonBound = parseDouble(NoiseTree->GetItemText(builderNode));
        if (southLatBound >= northLatBound || westLonBound >= eastLonBound) {
            sphere.SetBounds(-90.0, 90.0, -180.0, 180.0);
            appendDone = _(" Incoherent spherical bounds. Defaults used.");
        } else sphere.SetBounds(southLatBound, northLatBound, westLonBound, eastLonBound);
        sphere.SetDestSize(this->projectWidth, this->projectHeight);
        sphere.SetSourceModule(*moduleHolder[moduleHolder.size() - 1]);
        sphere.SetDestNoiseMap(noiseMap);
        this->StatusBar->SetStatusText(wxT("Building Spherical Map ..."));
        sphere.Build(this->RenderGauge);
    }
    if (requestType == _("Normals")) {
        utils::RendererNormalMap normalMapRenderer;
        texture.SetSize(this->projectWidth, this->projectHeight);
        normalMapRenderer.SetSourceNoiseMap(noiseMap);
        normalMapRenderer.EnableWrap(CheckBoxSeamless->IsChecked());
        normalMapRenderer.SetDestImage(texture);
        normalMapRenderer.SetBumpHeight(4.0);
        this->StatusBar->SetStatusText(wxT("Rendering Normal Map..."));
        this->NoiseImage->Destroy();
        this->NoiseImage = new wxImage(this->projectWidth, this->projectHeight);
        if (!this->NoiseImage->HasAlpha()) this->NoiseImage->InitAlpha();
        normalMapRenderer.Render(this->RenderGauge, this->NoiseImage);
    } else if (requestType == _("Terr")) {
        utils::WriterTER terrainWriter;
        terrainWriter.SetSourceNoiseMap (noiseMap);
        terrainWriter.SetDestFilename (this->TerExportPath.data());
        terrainWriter.SetMetersPerPoint (240.0);
        this->StatusBar->SetStatusText(wxT("Exporting to Terrain File..."));
        terrainWriter.WriteDestFile();
    } else if (requestType == _("Raw")) {
        this->StatusBar->SetStatusText(wxT("Exporting to Raw Heightfield File..."));
        int x, y;
        uint8* pLineBuffer = new uint8[this->projectWidth * 2];
        std::ofstream os;
        os.open (this->RawExportPath.data(), std::ios::out | std::ios::binary);
        for (y = 0; y < this->projectHeight; y++) {
            float* pSource = noiseMap.GetSlabPtr (y);
            uint8* pDest = pLineBuffer;
            for (x = 0; x < this->projectWidth; x++) {
                int16 elev = (int16)(floor (*pSource));
                *pDest++ = (uint8)(((uint16)elev & 0xff00) >> 8);
                *pDest++ = (uint8)(((uint16)elev & 0x00ff)     );
                ++pSource;
            }
            os.write ((char*)pLineBuffer, this->projectWidth * 2);
        }
        os.close ();
        delete[] pLineBuffer;
    } else {
        renderer.SetSourceNoiseMap(noiseMap);
        this->StatusBar->SetStatusText(wxT("Rendering Texture..."));
        renderer.Render(this->RenderGauge);
        this->NoiseImage->Destroy();
        this->NoiseImage = new wxImage(this->projectWidth, this->projectHeight);
        if (!this->NoiseImage->HasAlpha()) this->NoiseImage->InitAlpha();
    }
 
    if (requestType == _("Grayscale")) {
        for (int x = 0; x < texture.GetWidth(); x++) {
            for (int y = 0; y < texture.GetHeight(); y++) {
                const utils::Color* source = texture.GetConstSlabPtr(x, y);
                this->NoiseImage->SetRGB(x, y, (source->red + source->green + source->blue) / 3,
                                         (source->red + source->green + source->blue) / 3,
                                         (source->red + source->green + source->blue) / 3);
                this->NoiseImage->SetAlpha(x, y, source->alpha);
            }
        }
    } else if (requestType == _("Normals")) {
        // NULL
    } else if (requestType == _("Default")) {
        for (int x = 0; x < texture.GetWidth(); x++) {
            for (int y = 0; y < texture.GetHeight(); y++) {
                const utils::Color* source = texture.GetConstSlabPtr(x, y);
                this->NoiseImage->SetRGB(x, y, source->red, source->green, source->blue);
                this->NoiseImage->SetAlpha(x, y, source->alpha);
            }
        }
    }
    wxImage noiseImageCopy = this->NoiseImage->Copy();
    noiseImageCopy = noiseImageCopy.Scale(noiseImageCopy.GetWidth() * scope, noiseImageCopy.GetHeight() * scope);
    this->BitmapView->Hide();
    this->BitmapView->SetMaxSize(wxSize(noiseImageCopy.GetWidth(), noiseImageCopy.GetHeight()));
    this->BitmapView->SetMinSize(wxSize(noiseImageCopy.GetWidth(), noiseImageCopy.GetHeight()));
    this->BitmapView->SetBitmap(noiseImageCopy);
    this->BitmapView->Show();
    this->BoxSizerAll->Fit(this);
    this->BoxSizerMain->Fit(this);
    this->BoxSizerHorizontal->Fit(this);
 
    this->StatusBar->SetStatusText(wxT("Done.") + appendDone);
    ButtonRender->Enable(true);
    isRendering = false;
    requestUpdate = false;
    return;
}
 
void NoiserFrame::AddNoiseDialog(void)
{
    wxArrayString choices;
    choices.Add(wxT("Generator: Billow"));
    // choices.Add(wxT("Generator: Checkerboard"));
    choices.Add(wxT("Generator: Const"));
    choices.Add(wxT("Generator: Cylinders"));
    choices.Add(wxT("Generator: Perlin"));
    choices.Add(wxT("Generator: RidgedMulti"));
    choices.Add(wxT("Generator: Spheres"));
    choices.Add(wxT("Generator: Voronoi"));
    choices.Add(wxT("Transformer: Displace (4 source modules required)"));
    choices.Add(wxT("Transformer: RotatePoint (1 source module required)"));
    choices.Add(wxT("Transformer: ScalePoint (1 source module required)"));
    choices.Add(wxT("Transformer: TranslatePoint (1 source module required)"));
    choices.Add(wxT("Transformer: Turbulence (1 source module required)"));
    choices.Add(wxT("Modifier: Abs (1 source module required)"));
    choices.Add(wxT("Modifier: Clamp (1 source module required)"));
    choices.Add(wxT("Modifier: Curve (1 source module required)"));
    choices.Add(wxT("Modifier: Exponent (1 source module required)"));
    choices.Add(wxT("Modifier: Invert (1 source module required)"));
    choices.Add(wxT("Modifier: ScaleBias (1 source module required)"));
    choices.Add(wxT("Modifier: Terrace (1 source module required)"));
    choices.Add(wxT("Combiner: Add (2 source modules required)"));
    choices.Add(wxT("Combiner: Max (2 source modules required)"));
    choices.Add(wxT("Combiner: Min (2 source modules required)"));
    choices.Add(wxT("Combiner: Multiply (2 source modules required)"));
    choices.Add(wxT("Combiner: Power (2 source modules required)"));
    choices.Add(wxT("Selector: Blend (3 source modules required)"));
    choices.Add(wxT("Selector: Select (3 source modules required)"));
    choices.Add(wxT("Miscellaneous: Cache (1 source module required)"));
    wxSingleChoiceDialog addNoiseDialog(this,
                        _("Add Module"),
                        _("Please choose a Noise Module"),
                        choices);
    if (addNoiseDialog.ShowModal() == wxID_OK) {
        // RootNode\
        wxTreeItemId rootNode = NoiseTree->GetRootItem();
        // ModuleNode
        wxTreeItemIdValue cookie;
        wxTreeItemId moduleNode = NoiseTree->GetFirstChild(rootNode, cookie);
        wxTreeItemId newChild;
        wxString moduleTitle;
        wxArrayString sourceModuleChoices;
        if (NoiseTree->GetChildrenCount(moduleNode, false) == 0) {
            // ModuleNode Empty
            moduleTitle = addNoiseDialog.GetStringSelection();
            moduleTitle = moduleTitle.SubString(moduleTitle.Find(' ') + 1, moduleTitle.Length());
            newChild = NoiseTree->InsertItem(moduleNode, 0, moduleTitle, wxT("NULL"));
        } else {
            // First ModuleNode Child
            wxTreeItemIdValue cookieSub;
            wxTreeItemId child = NoiseTree->GetFirstChild(moduleNode, cookieSub);
            int insertIndex = 0;
            while (child.IsOk()) {
                insertIndex++;
                sourceModuleChoices.Add(NoiseTree->GetItemText(child));
                //this->StatusBar->SetStatusText(NoiseTree->GetItemText(child));
                //wxString moduleTitle = NoiseTree->GetItemText(child);
                if (NoiseTree->IsSelected(child)) break;
                else if (child == NoiseTree->GetLastChild(child)) break;
                else child = NoiseTree->GetNextSibling(child);
            }
            moduleTitle = addNoiseDialog.GetStringSelection();
            moduleTitle = moduleTitle.SubString(moduleTitle.Find(' ') + 1, moduleTitle.Length());
            if (moduleTitle.Contains(_("("))){
                moduleTitle = moduleTitle.SubString(0, moduleTitle.Find('(') - 2);
            }
            newChild = NoiseTree->InsertItem(moduleNode, insertIndex, moduleTitle, wxT("NULL"));
        }
        // Generators
        if (moduleTitle == _("Billow")) {
            AddModuleProperty(wxT("Frequency=1.0"));
            AddModuleProperty(wxT("Lacunarity=2.0"));
            AddModuleProperty(wxT("OctaveCount=6")); // BILLOW_MAX_OCTAVE = 30
            AddModuleProperty(wxT("Persistence=0.5"));
            AddModuleProperty(wxT("Quality=QUALITY_BEST"));
            AddModuleProperty(wxT("Seed=0"));
        } else if (moduleTitle == _("Checkerboard")) {
            // NULL
        } else if (moduleTitle == _("Const")) {
            AddModuleProperty(wxT("ConstValue=0.0"));
        } else if (moduleTitle == _("Cylinders")) {
            AddModuleProperty(wxT("Frequency=1.0"));
        } else if (moduleTitle == _("Perlin")) {
            AddModuleProperty(wxT("Frequency=1.0"));
            AddModuleProperty(wxT("Lacunarity=2.0"));
            AddModuleProperty(wxT("OctaveCount=6")); // PERLIN_MAX_OCTAVE = 30
            AddModuleProperty(wxT("Persistence=0.5"));
            AddModuleProperty(wxT("Quality=QUALITY_BEST"));
            AddModuleProperty(wxT("Seed=0"));
        } else if (moduleTitle == _("RidgedMulti")) {
            AddModuleProperty(wxT("Frequency=1.0"));
            AddModuleProperty(wxT("Lacunarity=2.0"));
            AddModuleProperty(wxT("OctaveCount=6")); // RIDGED_MAX_OCTAVE = 30
            AddModuleProperty(wxT("Quality=QUALITY_BEST"));
            AddModuleProperty(wxT("Seed=0"));
        } else if (moduleTitle == _("Spheres")) {
            AddModuleProperty(wxT("Frequency=1.0"));
        } else if (moduleTitle == _("Voronoi")) {
            AddModuleProperty(wxT("EnableDistance=true"));
            AddModuleProperty(wxT("Displacement=1.0"));
            AddModuleProperty(wxT("Frequency=1.0"));
            AddModuleProperty(wxT("Seed=0"));
        // Transformers
        } else if (moduleTitle == _("Displace")) {
            if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 4) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxMultiChoiceDialog addSourceModulesDialog(this, wxT("Please choose four source modules:"),
                wxT("Select source modules"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                wxArrayInt moduleIndex = addSourceModulesDialog.GetSelections();
                if (moduleIndex.Count() >= 4) {
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[0]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[0]]);
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[1]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[1]]);
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[2]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[2]]);
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[3]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[3]]);
                } else {
                    NoiseTree->Delete(newChild);
                    return;
                }
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        } else if (moduleTitle == _("RotatePoint")) {
            if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 1) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxSingleChoiceDialog addSourceModulesDialog(this, wxT("Please choose one source module:"),
                wxT("Select source module"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                int moduleIndex = addSourceModulesDialog.GetSelection();
                AddModuleProperty(wxT("SourceModule=")
                                + wxString::Format(wxT("%i"), moduleIndex) + wxT(" ")
                                + addSourceModulesDialog.GetStringSelection());
                AddModuleProperty(wxT("RotateX=0.0"));
                AddModuleProperty(wxT("RotateY=0.0"));
                AddModuleProperty(wxT("RotateZ=0.0"));
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        } else if (moduleTitle == _("ScalePoint")) {
            if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 1) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxSingleChoiceDialog addSourceModulesDialog(this, wxT("Please choose one source module:"),
                wxT("Select source module"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                int moduleIndex = addSourceModulesDialog.GetSelection();
                AddModuleProperty(wxT("SourceModule=")
                                + wxString::Format(wxT("%i"), moduleIndex) + wxT(" ")
                                + addSourceModulesDialog.GetStringSelection());
                AddModuleProperty(wxT("ScaleX=1.0"));
                AddModuleProperty(wxT("ScaleY=1.0"));
                AddModuleProperty(wxT("ScaleZ=1.0"));
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        } else if (moduleTitle == _("TranslatePoint")) {
            if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 1) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxSingleChoiceDialog addSourceModulesDialog(this, wxT("Please choose one source module:"),
                wxT("Select source module"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                int moduleIndex = addSourceModulesDialog.GetSelection();
                AddModuleProperty(wxT("SourceModule=")
                                + wxString::Format(wxT("%i"), moduleIndex) + wxT(" ")
                                + addSourceModulesDialog.GetStringSelection());
                AddModuleProperty(wxT("TranslateX=0.0"));
                AddModuleProperty(wxT("TranslateY=0.0"));
                AddModuleProperty(wxT("TranslateZ=0.0"));
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        } else if (moduleTitle == _("Turbulence")) {
            if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 1) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxSingleChoiceDialog addSourceModulesDialog(this, wxT("Please choose one source module:"),
                wxT("Select source module"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                int moduleIndex = addSourceModulesDialog.GetSelection();
                AddModuleProperty(wxT("SourceModule=")
                                + wxString::Format(wxT("%i"), moduleIndex) + wxT(" ")
                                + addSourceModulesDialog.GetStringSelection());
                AddModuleProperty(wxT("Frequency=1.0"));
                AddModuleProperty(wxT("Power=1.0"));
                AddModuleProperty(wxT("Roughness=3")); // RIDGED_MAX_OCTAVE = 30
                AddModuleProperty(wxT("Seed=0"));
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        // Modifiers
        } else if (moduleTitle == _("Abs")) {
            if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 1) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxSingleChoiceDialog addSourceModulesDialog(this, wxT("Please choose one source module:"),
                wxT("Select source module"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                int moduleIndex = addSourceModulesDialog.GetSelection();
                AddModuleProperty(wxT("SourceModule=")
                                + wxString::Format(wxT("%i"), moduleIndex) + wxT(" ")
                                + addSourceModulesDialog.GetStringSelection());
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        } else if (moduleTitle == _("Clamp")) {
           if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 1) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxSingleChoiceDialog addSourceModulesDialog(this, wxT("Please choose one source module:"),
                wxT("Select source module"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                int moduleIndex = addSourceModulesDialog.GetSelection();
                AddModuleProperty(wxT("SourceModule=")
                                + wxString::Format(wxT("%i"), moduleIndex) + wxT(" ")
                                + addSourceModulesDialog.GetStringSelection());
                AddModuleProperty(wxT("LowerBound=-1.0"));
                AddModuleProperty(wxT("UpperBound=1.0"));
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        } else if (moduleTitle == _("Curve")) {
           if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 1) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxSingleChoiceDialog addSourceModulesDialog(this, wxT("Please choose one source module:"),
                wxT("Select source module"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                int moduleIndex = addSourceModulesDialog.GetSelection();
                AddModuleProperty(wxT("SourceModule=")
                                + wxString::Format(wxT("%i"), moduleIndex) + wxT(" ")
                                + addSourceModulesDialog.GetStringSelection());
                AddModuleProperty(wxT("ControlPoints=-1.0,-1.0,-0.5,-0.5,0.5,0.5,1.0,1.0"));
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        } else if (moduleTitle == _("Exponent")) {
 
           if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 1) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxSingleChoiceDialog addSourceModulesDialog(this, wxT("Please choose one source module:"),
                wxT("Select source module"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                int moduleIndex = addSourceModulesDialog.GetSelection();
                AddModuleProperty(wxT("SourceModule=")
                                + wxString::Format(wxT("%i"), moduleIndex) + wxT(" ")
                                + addSourceModulesDialog.GetStringSelection());
                AddModuleProperty(wxT("Exponent=1.0"));
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        } else if (moduleTitle == _("Invert")) {
            if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 1) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxSingleChoiceDialog addSourceModulesDialog(this, wxT("Please choose one source module:"),
                wxT("Select source module"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                int moduleIndex = addSourceModulesDialog.GetSelection();
                AddModuleProperty(wxT("SourceModule=")
                                + wxString::Format(wxT("%i"), moduleIndex) + wxT(" ")
                                + addSourceModulesDialog.GetStringSelection());
                AddModuleProperty(wxT("Exponent=1.0"));
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        } else if (moduleTitle == _("ScaleBias")) {
            if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 1) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxSingleChoiceDialog addSourceModulesDialog(this, wxT("Please choose one source module:"),
                wxT("Select source module"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                int moduleIndex = addSourceModulesDialog.GetSelection();
                AddModuleProperty(wxT("SourceModule=")
                                + wxString::Format(wxT("%i"), moduleIndex) + wxT(" ")
                                + addSourceModulesDialog.GetStringSelection());
                AddModuleProperty(wxT("Bias=0.0"));
                AddModuleProperty(wxT("Scale=1.0"));
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        } else if (moduleTitle == _("Terrace")) {
            if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 1) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxSingleChoiceDialog addSourceModulesDialog(this, wxT("Please choose one source module:"),
                wxT("Select source module"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                int moduleIndex = addSourceModulesDialog.GetSelection();
                AddModuleProperty(wxT("SourceModule=")
                                + wxString::Format(wxT("%i"), moduleIndex) + wxT(" ")
                                + addSourceModulesDialog.GetStringSelection());
                AddModuleProperty(wxT("ControlPoints=-1.0,1.0"));
                AddModuleProperty(wxT("InvertTerraces=true"));
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        // Combiners
        } else if (moduleTitle == _("Add")) {
            if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 2) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxMultiChoiceDialog addSourceModulesDialog(this, wxT("Please choose two source modules:"),
                wxT("Select source modules"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                wxArrayInt moduleIndex = addSourceModulesDialog.GetSelections();
                if (moduleIndex.Count() >= 2) {
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[0]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[0]]);
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[1]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[1]]);
                } else {
                    NoiseTree->Delete(newChild);
                    return;
                }
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        } else if (moduleTitle == _("Max")) {
            if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 2) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxMultiChoiceDialog addSourceModulesDialog(this, wxT("Please choose two source modules:"),
                wxT("Select source modules"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                wxArrayInt moduleIndex = addSourceModulesDialog.GetSelections();
                if (moduleIndex.Count() >= 2) {
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[0]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[0]]);
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[1]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[1]]);
                } else {
                    NoiseTree->Delete(newChild);
                    return;
                }
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        } else if (moduleTitle == _("Min")) {
            if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 2) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxMultiChoiceDialog addSourceModulesDialog(this, wxT("Please choose two source modules:"),
                wxT("Select source modules"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                wxArrayInt moduleIndex = addSourceModulesDialog.GetSelections();
                if (moduleIndex.Count() >= 2) {
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[0]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[0]]);
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[1]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[1]]);
                } else {
                    NoiseTree->Delete(newChild);
                    return;
                }
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        } else if (moduleTitle == _("Multiply")) {
            if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 2) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxMultiChoiceDialog addSourceModulesDialog(this, wxT("Please choose two source modules:"),
                wxT("Select source modules"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                wxArrayInt moduleIndex = addSourceModulesDialog.GetSelections();
                if (moduleIndex.Count() >= 2) {
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[0]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[0]]);
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[1]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[1]]);
                } else {
                    NoiseTree->Delete(newChild);
                    return;
                }
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        } else if (moduleTitle == _("Power")) {
            if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 2) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxMultiChoiceDialog addSourceModulesDialog(this, wxT("Please choose two source modules:"),
                wxT("Select source modules"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                wxArrayInt moduleIndex = addSourceModulesDialog.GetSelections();
                if (moduleIndex.Count() >= 2) {
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[0]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[0]]);
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[1]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[1]]);
                } else {
                    NoiseTree->Delete(newChild);
                    return;
                }
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        // Selectors
        } else if (moduleTitle == _("Blend")) {
            if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 3) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxMultiChoiceDialog addSourceModulesDialog(this, wxT("Please choose three source modules:"),
                wxT("Select source modules"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                wxArrayInt moduleIndex = addSourceModulesDialog.GetSelections();
                if (moduleIndex.Count() >= 3) {
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[0]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[0]]);
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[1]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[1]]);
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[2]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[2]]);
                } else {
                    NoiseTree->Delete(newChild);
                    return;
                }
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        } else if (moduleTitle == _("Select")) {
            if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 3) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxMultiChoiceDialog addSourceModulesDialog(this, wxT("Please choose three source modules:"),
                wxT("Select source modules"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                wxArrayInt moduleIndex = addSourceModulesDialog.GetSelections();
                if (moduleIndex.Count() >= 3) {
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[0]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[0]]);
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[1]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[1]]);
                    AddModuleProperty(wxT("SourceModule=") + wxString::Format(wxT("%i"), moduleIndex[2]) + wxT(" ")
                                + sourceModuleChoices[moduleIndex[2]]);
                    AddModuleProperty(wxT("EdgeFalloff=0.0"));
                    AddModuleProperty(wxT("LowerBound=-1.0"));
                    AddModuleProperty(wxT("UpperBound=1.0"));
                } else {
                    NoiseTree->Delete(newChild);
                    return;
                }
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        // Miscellaneous
        } else if (moduleTitle == _("Cache")) {
            if (NoiseTree->GetChildrenCount(moduleNode, false) - 1 < 1) {
                NoiseTree->Delete(newChild);
                return;
            }
            wxSingleChoiceDialog addSourceModulesDialog(this, wxT("Please choose one source module:"),
                wxT("Select source module"),
                sourceModuleChoices);
            if (addSourceModulesDialog.ShowModal() == wxID_OK) {
                int moduleIndex = addSourceModulesDialog.GetSelection();
                AddModuleProperty(wxT("SourceModule=")
                                + wxString::Format(wxT("%i"), moduleIndex) + wxT(" ")
                                + addSourceModulesDialog.GetStringSelection());
            } else {
                NoiseTree->Delete(newChild);
                return;
            }
        }
        NoiseTree->SetItemBold(newChild, true);
        NoiseTree->Expand(newChild);
        NoiseTree->ScrollTo(newChild);
        NoiseTree->SelectItem(newChild);
    }
    if (MenuItemAutoRender->IsChecked()) this->RenderTexture(_("Default"));
}
 
void NoiserFrame::OnNoiseTreeItemRightClick(wxTreeEvent& event)
{
    NoiseTree->SelectItem(NoiseTree->HitTest(event.GetPoint()));
    PopupMenu(&this->MenuList, event.GetPoint());
    if (NoiseTree->GetSelection().IsOk()) rememberItem = NoiseTree->GetSelection();
}
 
void NoiserFrame::SaveState(wxTreeItemId id, wxXmlNode* node)
{
   if (!node) return;
   if (!id.IsOk()) return;
   node->AddProperty(wxT("Data"), NoiseTree->GetItemText(id));
 
   wxTreeItemIdValue cookie;
   wxTreeItemId child = NoiseTree->GetFirstChild(id, cookie);
   wxXmlNode* child_node;
   while (child.IsOk()) {
      child_node = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("Item"));
      node->AddChild(child_node);
      SaveState(child, child_node);
      if(child == NoiseTree->GetLastChild(id)) break;
      child = NoiseTree->GetNextChild(id, cookie);
      child_node = child_node->GetNext();
   }
}
 
void NoiserFrame::LoadState(wxTreeItemId id, wxXmlNode* node)
{
    if (!node) return;
    wxXmlNode* child_node = node->GetChildren();
    while (child_node) {
        wxTreeItemId sub;
        if (child_node->HasProp(wxT("Color"))) {
            ListBoxColors->Append(child_node->GetPropVal(wxT("Color"), wxT("NULL")));
        } else {
            sub = NoiseTree->AppendItem(id, child_node->GetPropVal(wxT("Data"), wxT("NULL")));
            if (NoiseTree->GetItemText(sub) == _("EnableSeamless=false")) this->CheckBoxSeamless->SetValue(false);
            else if (NoiseTree->GetItemText(sub) == _("EnableSeamless=true")) this->CheckBoxSeamless->SetValue(true);
        }
        if (child_node->GetChildren()) NoiseTree->SetItemBold(sub, true);
        LoadState(sub, child_node);
        child_node = child_node->GetNext();
    }
}
 
void NoiserFrame::SaveSettingsToFile(wxString fileName)
{
    wxXmlDocument document;
    wxTreeItemId root_item = NoiseTree->GetRootItem();
    if (root_item.IsOk()) {
        wxXmlNode* root_node = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("NoiserSettings"));
        document.SetRoot(root_node);
        this->SaveState(root_item, root_node);
        // Colors
        wxArrayString colorPosColors = ListBoxColors->GetStrings();
        for (int i = 0; i < colorPosColors.Count(); i++) {
            wxXmlNode* colorNode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("ColorItem"));
            colorNode->AddProperty(wxT("Color"), colorPosColors.Item(i));
            root_node->AddChild(colorNode);
        }
        document.Save(fileName);
    }
}
 
void NoiserFrame::LoadSettingsFromFile(wxString fileName)
{
    wxXmlDocument document(fileName);
    if (document.IsOk()) {
        wxXmlNode* node = document.GetRoot();
        wxString stringProj = node->GetPropVal(wxT("Data"), wxT("NULL"));
        if (parseProjectSet(stringProj)) {
            NoiseTree->DeleteAllItems();
            wxArrayString emptyStringArray;
            ListBoxColors->Set(emptyStringArray);
            wxTreeItemId root = NoiseTree->AddRoot(stringProj);
            NoiseTree->SetItemBold(root, true);
            NoiseTree->SetItemTextColour(root, *wxBLUE);
            this->LoadState(root, node);
            // Show SubNodes
            NoiseTree->CollapseAll();
            wxTreeItemIdValue cookie;
            wxTreeItemId moduleNode = NoiseTree->GetFirstChild(root, cookie);
            wxTreeItemId renderNode = NoiseTree->GetNextChild(root, cookie);
            NoiseTree->Expand(root);
            NoiseTree->Expand(moduleNode);
            NoiseTree->Expand(renderNode);
            requestUpdate = true;
        } else {
            wxMessageBox(wxT("Failed to read Project XML settings."));
        }
    } else {
        wxMessageBox(wxT("Failed to load XML settings."));
    }
}
 
void NoiserFrame::OnMenuItemSaveAsSelected(wxCommandEvent& event)
{
    wxFileDialog fileDialog(this, wxFileSelectorPromptStr, wxEmptyString, wxEmptyString, _("XML Files (*.xml)|*.xml"), wxSAVE | wxOVERWRITE_PROMPT);
    if (fileDialog.ShowModal() == wxID_OK) {
        rememberSettingsSaveFilename = fileDialog.GetPath();
        this->SaveSettingsToFile(fileDialog.GetPath());
        StatusBar->SetStatusText(_("Settings saved to ") + fileDialog.GetPath());
    }
}
 
void NoiserFrame::OnButtonColorAddClick(wxCommandEvent& event)
{
    wxString entry = TextCtrlColorInput->GetValue();
    int index = entry.Find('=');
    if (index == wxNOT_FOUND) {
      StatusBar->SetStatusText(_("Error: Failed to parse color from \"") + entry + _("\". Color ignored."));
      TextCtrlColorInput->SetValue(_("0.0=rgba(128,128,128,255)"));
    } else {
        wxString settingDouble = entry.SubString(0, index-1);
        wxString settingRGBA = entry.SubString(index + 1, entry.Length());
        double parseSettingDouble;
        if (!settingDouble.ToDouble(&parseSettingDouble)) {
            StatusBar->SetStatusText(_("Error: Failed to parse color position from \"") + entry + _("\". Color ignored."));
            TextCtrlColorInput->SetValue(_("0.0=rgba(128,128,128,255)"));
        } else {
            std::vector<int> color = parseRGBA(settingRGBA);
            if (color[0] == -1 || color[1] == -1 || color[2] == -1 || color[3] == -1|| parseSettingDouble < -1.0 || parseSettingDouble > 1.0) {
                StatusBar->SetStatusText(_("Error: Failed to parse color from \"") + entry + _("\". Color ignored."));
                TextCtrlColorInput->SetValue(_("0.0=rgba(128,128,128,255)"));
            } else {
                bool added = false;
                int numListItems = ListBoxColors->GetCount();
                wxString addEntry = settingDouble + _("=rgba(")
                + wxString::Format(wxT("%i"), color[0]) + _(",") + wxString::Format(wxT("%i"), color[1])
                + _(",") + wxString::Format(wxT("%i"), color[2]) + _(",") + wxString::Format(wxT("%i"), color[3]) + _(")");
                for (unsigned int i = 0; i < numListItems; i++) {
                    wxString currentSet = ListBoxColors->GetString(i);
                    int indexPosition = currentSet.Find('=');
                    currentSet = currentSet.SubString(0, indexPosition - 1);
                    double currentDouble = parseDouble(_("Pos=") + currentSet);
                    if (currentDouble > parseSettingDouble) {
                        ListBoxColors->InsertItems(1, &addEntry, i);
                        requestUpdate = true;
                        added = true;
                        break;
                    }
                }
                if (!added) {
                    ListBoxColors->InsertItems(1, &addEntry, numListItems);
                    requestUpdate = true;
                }
            }
        }
    }
}
 
void NoiserFrame::OnListBoxColorsDoubleClick(wxCommandEvent& event)
{
    int indexSelection = ListBoxColors->GetSelection();
    wxString entry = ListBoxColors->GetString(indexSelection);
    int index = entry.Find('=');
    wxString settingDouble = entry.SubString(0, index-1);
    wxString settingRGBA = entry.SubString(index + 1, entry.Length());
    double parseSettingDouble;
    if (!settingDouble.ToDouble(&parseSettingDouble)) {
        StatusBar->SetStatusText(_("Error: Failed to parse color position from \"") + entry + _("\". Color ignored."));
    } else {
        std::vector<int> color = parseRGBA(settingRGBA);
        if (color[0] == -1 || color[1] == -1 || color[2] == -1 || color[3] == -1|| parseSettingDouble < -1.0 || parseSettingDouble > 1.0) {
            StatusBar->SetStatusText(_("Error: Failed to parse color from \"") + entry + _("\". Color ignored."));
        } else {
            wxColourData colorData;
            colorData.SetChooseFull(true);
            wxColour colorValue(color[0], color[1], color[2]);
            colorData.SetColour(colorValue);
            wxColourDialog colorDialog(this, &colorData);
            if (colorDialog.ShowModal() == wxID_OK) {
                wxColourData returnData = colorDialog.GetColourData();
                wxColour newColor = returnData.GetColour();
                wxString setEntry = settingDouble + _("=rgba(")
                + wxString::Format(wxT("%i"), newColor.Red()) + _(",") + wxString::Format(wxT("%i"), newColor.Green())
                + _(",") + wxString::Format(wxT("%i"), newColor.Blue()) + _(",") + wxString::Format(wxT("%i"), color[3]) + _(")");
                ListBoxColors->SetString(indexSelection, setEntry);
                requestUpdate = true;
            }
        }
    }
}
 
void NoiserFrame::OnMenuItemImageSaveAsSelected(wxCommandEvent& event)
{
    if (NoiseImage->IsOk()) {
        wxFileDialog saveDialog(this, _("Save File As"), wxEmptyString, wxEmptyString,
                            _("*.bmp;*.gif;*.png;*.jpeg;*.tif"),
                            wxSAVE | wxOVERWRITE_PROMPT);
        if (saveDialog.ShowModal() == wxID_OK) {
            wxString filename = saveDialog.GetPath();
            rememberImageSaveFilename = filename;
            if (filename.Find( wxT("jpeg") ) != -1 || filename.Find( wxT("jpg") ) != -1) {
                NoiseImage->SaveFile(saveDialog.GetPath(), wxBITMAP_TYPE_JPEG);
                imageType = wxBITMAP_TYPE_JPEG;
            } else if (filename.Find( wxT("png") ) != -1) {
                NoiseImage->SaveFile(saveDialog.GetPath(), wxBITMAP_TYPE_PNG);
                imageType = wxBITMAP_TYPE_PNG;
            } else if (filename.Find( wxT("bmp") ) != -1) {
                NoiseImage->SaveFile(saveDialog.GetPath(), wxBITMAP_TYPE_BMP);
                imageType = wxBITMAP_TYPE_BMP;
            } else if (filename.Find( wxT("tif") ) != -1) {
                NoiseImage->SaveFile(saveDialog.GetPath(), wxBITMAP_TYPE_TIF);
                imageType = wxBITMAP_TYPE_TIF;
            } else {
                NoiseImage->SaveFile(saveDialog.GetPath(), wxBITMAP_TYPE_GIF);
                imageType = wxBITMAP_TYPE_GIF;
            }
            StatusBar->SetStatusText(_("Image file saved to ") + saveDialog.GetPath());
        }
    }
}
back