public static void SceneGUI(BuildrEditMode editMode, BuildrData data, bool shouldSnap, float handleSize)
 {
     if (GUI.changed)
     {
         EditorUtility.SetDirty(editMode);
         EditorUtility.SetDirty(data);
         editMode.UpdateRender();
     }
 }
    public static void InspectorGUI(BuildrEditMode _editMode, BuildrData _data)
    {
        editMode    = _editMode;
        data        = _data;
        constraints = data.generatorConstraints;

        EditModes newmode = (EditModes)EditorGUILayout.EnumPopup(mode);

        if (newmode != mode)
        {
            mode = newmode;
            switch (mode)
            {
            case EditModes.general:
                editMode.stage = BuildrEditMode.stages.building;
                break;

            case EditModes.floorplan:
                editMode.stage = BuildrEditMode.stages.floorplan;
                editMode.SetMode(BuildrEditMode.modes.floorplan);
                break;
            }
        }

        switch (mode)
        {
        case EditModes.general:
            GeneralOptionsInspector();
            break;

        case EditModes.floorplan:
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Constrain Building Generation to Floorplan", GUILayout.Width(280));
            constraints.constrainPlanByPlan = EditorGUILayout.Toggle(constraints.constrainPlanByPlan);
            EditorGUILayout.EndHorizontal();
            EditorGUI.BeginDisabledGroup(!constraints.constrainPlanByPlan);
            BuildrEditModeFloorplan.InspectorGUI(editMode, _data.plan);
            EditorGUI.EndDisabledGroup();

            if (data.plan != null)
            {
                constraints.plan = data.plan.Duplicate();
            }
            break;
        }

        if (GUI.changed)
        {
            EditorUtility.SetDirty(_editMode);
            EditorUtility.SetDirty(_data);
            _editMode.UpdateRender();
        }
    }
Beispiel #3
0
    void OnEnable()
    {
        if (target != null)
        {
            _editMode = (BuildrEditMode)target;
            _data     = _editMode.data;
        }


        bool editing = (_data != null) ? _data.editing : true;

        if (!editing)
        {
            BuildrGenerateModeEditor.OnEnable();
        }
    }
    public static void SceneGUI(BuildrEditMode editMode, BuildrData data, bool shouldSnap, float handleSize)
    {
        if(editMode.fullMesh==null)
            return;

        Rect HUDRect = new Rect(0,0,300,300);
        Handles.BeginGUI();
        GUILayout.BeginArea(HUDRect);

            EditorGUILayout.LabelField("Buildr");
            EditorGUILayout.LabelField("Vertices: "+editMode.fullMesh.vertexCount);
            EditorGUILayout.LabelField("Triangles "+editMode.fullMesh.triangleCount/3);

        GUILayout.EndArea();
        Handles.EndGUI();

        bool isLegal = !(data.plan.illegalPoints.Length > 0);
        if (isLegal)
            isLegal = editMode.transform.localScale == Vector3.one;

        if(isLegal)
            return;

        int numberOfFacades = data.facades.Count;
        int numberOfRoofs = data.roofs.Count;
        int numberOfTextures = data.textures.Count;

        if (numberOfFacades == 0 || numberOfRoofs == 0 || numberOfTextures == 0)
            return;

        Vector3 position = editMode.transform.position;

        BuildrPlan area = data.plan;
        int numberOfVolumes = area.numberOfVolumes;

        int facadeCounter = 0;
        for (int s = 0; s < numberOfVolumes; s++)
        {
            BuildrVolume volume = data.plan.volumes[s];
            int volumeSize = volume.Count;
            Vector3 floorCentre = Vector3.zero;
            Handles.color = Color.red;

            for (int p = 0; p < volumeSize; p++)
            {
                int point = volume.points[p];
                Vector3 pointPos = area.points[point].vector3;
                floorCentre += pointPos;

                List<Vector3> verts = new List<Vector3>();
                int indexB = (p < volumeSize - 1) ? p + 1 : 0;
                Vector3 volumeHeight = Vector3.up * (volume.numberOfFloors * data.floorHeight);
                verts.Add(pointPos + position);
                verts.Add(area.points[volume.points[indexB]].vector3 + position);
                verts.Add(verts[1] + volumeHeight);
                verts.Add(verts[0] + volumeHeight);
                Handles.DrawSolidRectangleWithOutline(verts.ToArray(), new Color(1,0,0,0.2f), Color.red);
                Handles.DrawLine(verts[2], verts[3]);
                facadeCounter++;
            }
        }
    }
Beispiel #5
0
    public static void SceneGUI(BuildrEditMode _editMode, BuildrData _data, bool shouldSnap, float handleSize)
    {
        Vector3 camDirection = Camera.current.transform.forward;
        Vector3 camPosition  = Camera.current.transform.position;
        Vector3 position     = _editMode.transform.position;

        data = _data;
        BuildrPlan   plan               = data.plan;
        BuildrVolume selectedVolume     = plan.volumes[selectedVolumeIndex];
        int          selectedVolumeSize = selectedVolume.Count;

        Handles.color = Color.white;
        int facadeCounter = 0;

        GUIStyle whiteLabelStyle = new GUIStyle();

        whiteLabelStyle.normal.textColor = Color.white;
        whiteLabelStyle.alignment        = TextAnchor.MiddleCenter;
        whiteLabelStyle.fixedWidth       = 75.0f;

        int numberOfVolumes = plan.numberOfVolumes;

        for (int s = 0; s < numberOfVolumes; s++)
        {
            BuildrVolume volume      = data.plan.volumes[s];
            int          volumeSize  = volume.Count;
            Vector3      floorCentre = Vector3.zero;

            for (int p = 0; p < volumeSize; p++)
            {
                int     point    = volume.points[p];
                Vector3 pointPos = plan.points[point].vector3;
                floorCentre += pointPos;
            }
            floorCentre /= volumeSize;

            if (s == selectedVolumeIndex)
            {
                whiteLabelStyle.normal.textColor = BuildrColours.RED;
                whiteLabelStyle.fontStyle        = FontStyle.Bold;
            }
            else
            {
                whiteLabelStyle.normal.textColor = Color.white;
                whiteLabelStyle.fontStyle        = FontStyle.Normal;
            }

            //Volume height/floor number slider
            Vector3 volumeHeightDir = Vector3.up * (volume.numberOfFloors * data.floorHeight);
            Vector3 volumePosition  = floorCentre + position + volumeHeightDir;
            Handles.color = Color.white;
            if (Vector3.Dot(camDirection, volumePosition - camPosition) > 0)//only display label when facade is facing camera
            {
                Handles.Label(volumePosition + (Vector3.up * (handleSize * 0.1f)), "volume " + s, whiteLabelStyle);
            }
        }
        whiteLabelStyle.normal.textColor = Color.white;
        whiteLabelStyle.fontStyle        = FontStyle.Normal;

        for (int p = 0; p < selectedVolumeSize; p++)
        {
            int     point    = selectedVolume.points[p];
            Vector3 pointPos = plan.points[point].vector3;

            List <Vector3> verts               = new List <Vector3>();
            int            indexB              = (p < selectedVolumeSize - 1) ? p + 1 : 0;
            Vector3        floorHeightVector   = Vector3.up * (selectedFloor * data.floorHeight);
            Vector3        ceilingHeightVector = Vector3.up * ((selectedFloor + 1) * data.floorHeight);
            Vector3        p0 = pointPos + position;
            Vector3        p1 = plan.points[selectedVolume.points[indexB]].vector3 + position;
            verts.Add(pointPos + position);
            verts.Add(plan.points[selectedVolume.points[indexB]].vector3 + position);
            verts.Add(verts[1] + floorHeightVector);
            verts.Add(verts[0] + floorHeightVector);
            Handles.color = BuildrColours.RED;
            Handles.DrawLine(p0 + floorHeightVector, p1 + floorHeightVector);
            Handles.DrawLine(p0 + ceilingHeightVector, p1 + ceilingHeightVector);
            Handles.DrawLine(p0 + floorHeightVector, p0 + ceilingHeightVector);
            if (_editMode.showFacadeMarkers)
            {
                Handles.color = Color.white;
                Vector3 facadeDirection = Vector3.Cross((verts[0] - verts[1]), Vector3.up);
                Vector3 centerPos       = (verts[0] + verts[1]) * 0.5f;
                bool    camVisible      = Vector3.Dot(camDirection, centerPos - camPosition) > 0;
                bool    facadeVisible   = Vector3.Dot(camDirection, facadeDirection) < 0;
                if (camVisible && facadeVisible)//only display label when facade is facing camera and is in camera view
                {
                    Vector3 labelPos = centerPos + facadeDirection.normalized;
                    Handles.Label(labelPos, "facade " + facadeCounter, whiteLabelStyle);
                    Handles.DrawLine(centerPos, labelPos);
                }
            }
            facadeCounter++;
        }
    }
Beispiel #6
0
    //private static BuildrData data;

    public static void InspectorGUI(BuildrEditMode editMode, BuildrData _data)
    {
        //ensure that the model exists in the scene
        if (editMode.fullMesh == null)
        {
            editMode.UpdateRender();
        }

        Undo.RecordObject(_data, "Building Modified");
        //texture library string array
        BuildrTexture[] textures         = _data.textures.ToArray();
        int             numberOfTextures = textures.Length;

        string[] textureNames = new string[numberOfTextures];
        for (int t = 0; t < numberOfTextures; t++)
        {
            textureNames[t] = textures[t].name;
        }

        //Render a full version version
        EditorGUILayout.LabelField("Building Generation Types");
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUI.BeginDisabledGroup(editMode.renderMode == BuildrEditMode.renderModes.full);
        if (GUILayout.Button("Full Detail", GUILayout.Height(28)))
        {
            editMode.UpdateRender(BuildrEditMode.renderModes.full);
        }
        EditorGUI.EndDisabledGroup();

        //Render a low detail version
        EditorGUI.BeginDisabledGroup(editMode.renderMode == BuildrEditMode.renderModes.lowDetail);
        if (GUILayout.Button("Low Detail", GUILayout.Height(28)))
        {
            editMode.UpdateRender(BuildrEditMode.renderModes.lowDetail);
        }
        EditorGUI.EndDisabledGroup();

        //Render a box version
        EditorGUI.BeginDisabledGroup(editMode.renderMode == BuildrEditMode.renderModes.box);
        if (GUILayout.Button("Box Outline", GUILayout.Height(28)))
        {
            editMode.UpdateRender(BuildrEditMode.renderModes.box);
        }
        EditorGUI.EndDisabledGroup();
        EditorGUILayout.EndHorizontal();

        //Toggle showing the wireframe when we have selected the model.
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUILayout.LabelField("Show Wireframe");
        editMode.showWireframe = EditorGUILayout.Toggle(editMode.showWireframe, GUILayout.Width(15));
        EditorGUILayout.EndHorizontal();

        //Tangent calculation
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUI.BeginDisabledGroup(editMode.fullMesh.hasTangents);
        if (GUILayout.Button("Build Tangents", GUILayout.Height(38)))
        {
            if (editMode.fullMesh != null)
            {
                editMode.fullMesh.SolveTangents();
            }
            if (editMode.detailMesh != null)
            {
                editMode.detailMesh.SolveTangents();
            }
            GUI.changed = false;
        }
        EditorGUI.EndDisabledGroup();
        if (!editMode.fullMesh.hasTangents)
        {
            EditorGUILayout.HelpBox("The model doesn't have tangents", MessageType.Warning);
        }
        EditorGUILayout.EndHorizontal();

        //Lightmap rendering
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUI.BeginDisabledGroup(editMode.fullMesh.lightmapUvsCalculated);
        if (GUILayout.Button("Build Lightmap UVs", GUILayout.Height(38)))
        {
//            Undo.RegisterSceneUndo("Build Lightmap UVs");
            if (editMode.fullMesh != null)
            {
                for (int i = 0; i < editMode.fullMesh.meshCount; i++)
                {
                    Unwrapping.GenerateSecondaryUVSet(editMode.fullMesh[i].mesh);
                }
            }
            editMode.fullMesh.lightmapUvsCalculated = true;
            if (editMode.detailMesh != null)
            {
                for (int i = 0; i < editMode.detailMesh.meshCount; i++)
                {
                    Unwrapping.GenerateSecondaryUVSet(editMode.detailMesh[i].mesh);
                }
                editMode.detailMesh.lightmapUvsCalculated = true;
            }
            int numberOfInteriors = editMode.interiorMeshes.Count;
            for (int i = 0; i < numberOfInteriors; i++)
            {
                DynamicMeshGenericMultiMaterialMesh interiorMesh = editMode.interiorMeshes[i];
                for (int j = 0; j < interiorMesh.meshCount; j++)
                {
                    Unwrapping.GenerateSecondaryUVSet(interiorMesh[j].mesh);
                }
                interiorMesh.lightmapUvsCalculated = true;
            }
            GUI.changed = false;
        }
        EditorGUI.EndDisabledGroup();
        if (!editMode.fullMesh.lightmapUvsCalculated)
        {
            EditorGUILayout.HelpBox("The model doesn't have lightmap UVs", MessageType.Warning);
        }
        EditorGUILayout.EndHorizontal();

        //Mesh Optimisation
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUI.BeginDisabledGroup(editMode.fullMesh.optimised);
        if (GUILayout.Button("Optimise Mesh For Runtime", GUILayout.Height(38)))
        {
//            Undo.RegisterSceneUndo("Optimise Mesh");
            if (editMode.fullMesh != null)
            {
                for (int i = 0; i < editMode.fullMesh.meshCount; i++)
                {
                    MeshUtility.Optimize(editMode.fullMesh[i].mesh);
                }
                editMode.fullMesh.optimised = true;
            }

            if (editMode.detailMesh != null)
            {
                for (int i = 0; i < editMode.detailMesh.meshCount; i++)
                {
                    MeshUtility.Optimize(editMode.detailMesh[i].mesh);
                }
                editMode.detailMesh.optimised = true;
            }
            GUI.changed = false;
        }
        EditorGUI.EndDisabledGroup();
        if (!editMode.fullMesh.optimised)
        {
            EditorGUILayout.HelpBox("The model is currently fully optimised for runtime", MessageType.Warning);
        }
        EditorGUILayout.EndHorizontal();

        //Underside render toggle
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUILayout.LabelField("Render Underside of Building");
        bool drawUnderside = EditorGUILayout.Toggle(_data.drawUnderside, GUILayout.Width(15));

        if (drawUnderside != _data.drawUnderside)
        {
            _data.drawUnderside = drawUnderside;
        }
        EditorGUILayout.EndHorizontal();

        //Define the height of foundations if you need them
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUILayout.LabelField("Foundation Height", GUILayout.Width(120));
        _data.foundationHeight = EditorGUILayout.Slider(_data.foundationHeight, 0, 25);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Foundation Texture", GUILayout.Width(120));
        _data.foundationTexture = EditorGUILayout.Popup(_data.foundationTexture, textureNames, GUILayout.Width(260));
        EditorGUILayout.EndHorizontal();

        //Collider mesh
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUILayout.LabelField("Generate Collider");
        _data.generateCollider = (BuildrData.ColliderGenerationModes)EditorGUILayout.EnumPopup(_data.generateCollider);
        EditorGUILayout.EndHorizontal();

        //One draw call mesh  -TODO
//        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
//        EditorGUILayout.LabelField("One Draw Call");
//        _data.oneDrawCall = EditorGUILayout.Toggle(_data.oneDrawCall);
//        EditorGUILayout.EndHorizontal();

        for (int i = 0; i < editMode.fullMesh.meshCount; i++)
        {
            EditorUtility.SetSelectedWireframeHidden(editMode.meshHolders[i].GetComponent <Renderer>(), !editMode.showWireframe);
        }
    }
    //private static BuildrData data;

    public static void InspectorGUI(BuildrEditMode editMode, BuildrData _data)
    {
        //ensure that the model exists in the scene
        if (editMode.fullMesh == null)
            editMode.UpdateRender();

        Undo.RecordObject(_data, "Building Modified");
        //texture library string array
        BuildrTexture[] textures = _data.textures.ToArray();
        int numberOfTextures = textures.Length;
        string[] textureNames = new string[numberOfTextures];
        for (int t = 0; t < numberOfTextures; t++)
            textureNames[t] = textures[t].name;

        //Render a full version version
        EditorGUILayout.LabelField("Building Generation Types");
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUI.BeginDisabledGroup(editMode.renderMode == BuildrEditMode.renderModes.full);
        if (GUILayout.Button("Full Detail", GUILayout.Height(28)))
        {
            editMode.UpdateRender(BuildrEditMode.renderModes.full);
        }
        EditorGUI.EndDisabledGroup();

        //Render a low detail version
        EditorGUI.BeginDisabledGroup(editMode.renderMode == BuildrEditMode.renderModes.lowDetail);
        if (GUILayout.Button("Low Detail", GUILayout.Height(28)))
        {
            editMode.UpdateRender(BuildrEditMode.renderModes.lowDetail);
        }
        EditorGUI.EndDisabledGroup();

        //Render a box version
        EditorGUI.BeginDisabledGroup(editMode.renderMode == BuildrEditMode.renderModes.box);
        if (GUILayout.Button("Box Outline", GUILayout.Height(28)))
        {
            editMode.UpdateRender(BuildrEditMode.renderModes.box);
        }
        EditorGUI.EndDisabledGroup();
        EditorGUILayout.EndHorizontal();

        //Toggle showing the wireframe when we have selected the model.
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUILayout.LabelField("Show Wireframe");
        editMode.showWireframe = EditorGUILayout.Toggle(editMode.showWireframe, GUILayout.Width(15));
        EditorGUILayout.EndHorizontal();

        //Tangent calculation
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUI.BeginDisabledGroup(editMode.fullMesh.hasTangents);
        if (GUILayout.Button("Build Tangents", GUILayout.Height(38)))
        {
            if (editMode.fullMesh != null)
                editMode.fullMesh.SolveTangents();
            if(editMode.detailMesh != null)
                editMode.detailMesh.SolveTangents();
            GUI.changed = false;
        }
        EditorGUI.EndDisabledGroup();
        if (!editMode.fullMesh.hasTangents)
            EditorGUILayout.HelpBox("The model doesn't have tangents", MessageType.Warning);
        EditorGUILayout.EndHorizontal();

        //Lightmap rendering
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUI.BeginDisabledGroup(editMode.fullMesh.lightmapUvsCalculated);
        if (GUILayout.Button("Build Lightmap UVs", GUILayout.Height(38)))
        {
//            Undo.RegisterSceneUndo("Build Lightmap UVs");
            if(editMode.fullMesh != null)
            {
                for (int i = 0; i < editMode.fullMesh.meshCount; i++)
                    Unwrapping.GenerateSecondaryUVSet(editMode.fullMesh[i].mesh);}
                editMode.fullMesh.lightmapUvsCalculated = true;
            if(editMode.detailMesh != null)
            {
                for (int i = 0; i < editMode.detailMesh.meshCount; i++)
                    Unwrapping.GenerateSecondaryUVSet(editMode.detailMesh[i].mesh);
                editMode.detailMesh.lightmapUvsCalculated = true;
            }
            int numberOfInteriors = editMode.interiorMeshes.Count;
            for(int i = 0; i < numberOfInteriors; i++)
            {
                DynamicMeshGenericMultiMaterialMesh interiorMesh = editMode.interiorMeshes[i];
                for (int j = 0; j < interiorMesh.meshCount; j++)
                    Unwrapping.GenerateSecondaryUVSet(interiorMesh[j].mesh);
                interiorMesh.lightmapUvsCalculated = true;
            }
            GUI.changed = false;
        }
        EditorGUI.EndDisabledGroup();
        if (!editMode.fullMesh.lightmapUvsCalculated)
            EditorGUILayout.HelpBox("The model doesn't have lightmap UVs", MessageType.Warning);
        EditorGUILayout.EndHorizontal();

        //Mesh Optimisation
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUI.BeginDisabledGroup(editMode.fullMesh.optimised);
        if (GUILayout.Button("Optimise Mesh For Runtime", GUILayout.Height(38)))
        {
//            Undo.RegisterSceneUndo("Optimise Mesh");
            if (editMode.fullMesh != null)
            {
                for (int i = 0; i < editMode.fullMesh.meshCount; i++)
                    MeshUtility.Optimize(editMode.fullMesh[i].mesh);
                editMode.fullMesh.optimised = true;
            }

            if (editMode.detailMesh != null)
            {
                for(int i = 0; i < editMode.detailMesh.meshCount; i++)
                    MeshUtility.Optimize(editMode.detailMesh[i].mesh);
                editMode.detailMesh.optimised = true;
            }
            GUI.changed = false;
        }
        EditorGUI.EndDisabledGroup();
        if (!editMode.fullMesh.optimised)
            EditorGUILayout.HelpBox("The model is currently fully optimised for runtime", MessageType.Warning);
        EditorGUILayout.EndHorizontal();

        //Underside render toggle
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUILayout.LabelField("Render Underside of Building");
        bool drawUnderside = EditorGUILayout.Toggle(_data.drawUnderside, GUILayout.Width(15));
        if(drawUnderside != _data.drawUnderside)
        {
            _data.drawUnderside = drawUnderside;
        }
        EditorGUILayout.EndHorizontal();

        //Define the height of foundations if you need them
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUILayout.LabelField("Foundation Height", GUILayout.Width(120));
        _data.foundationHeight = EditorGUILayout.Slider(_data.foundationHeight, 0, 25);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Foundation Texture", GUILayout.Width(120));
        _data.foundationTexture = EditorGUILayout.Popup(_data.foundationTexture, textureNames, GUILayout.Width(260));
        EditorGUILayout.EndHorizontal();

        //Collider mesh
        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUILayout.LabelField("Generate Collider");
        _data.generateCollider = (BuildrData.ColliderGenerationModes)EditorGUILayout.EnumPopup(_data.generateCollider);
        EditorGUILayout.EndHorizontal();

        //One draw call mesh  -TODO
//        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
//        EditorGUILayout.LabelField("One Draw Call");
//        _data.oneDrawCall = EditorGUILayout.Toggle(_data.oneDrawCall);
//        EditorGUILayout.EndHorizontal();

        for (int i = 0; i < editMode.fullMesh.meshCount; i++)
            EditorUtility.SetSelectedWireframeHidden(editMode.meshHolders[i].GetComponent<Renderer>(), !editMode.showWireframe);
    }
    public static void InspectorGUI(BuildrEditMode editMode, BuildrData _data)
    {

        data = _data;
        Undo.RecordObject(data, "Interior Modified");

        BuildrTexture[] textures = data.textures.ToArray();
        int numberOfTextures = textures.Length;
        string[] textureNames = new string[numberOfTextures];
        for (int t = 0; t < numberOfTextures; t++)
            textureNames[t] = textures[t].name;

        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUILayout.LabelField("Render Interior of Building");
        bool renderInterior = EditorGUILayout.Toggle(_data.renderInteriors, GUILayout.Width(15));
        if (renderInterior != _data.renderInteriors)
        {
            _data.renderInteriors = renderInterior;
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUILayout.LabelField("Cull All Building Bays");
        bool cullBays = EditorGUILayout.Toggle(_data.cullBays, GUILayout.Width(15));
        if (cullBays != _data.cullBays)
        {
            _data.cullBays = cullBays;
        }
        EditorGUILayout.EndHorizontal();

        //Floor Height
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Floor height", GUILayout.Width(200));
        float newFloorHeight = EditorGUILayout.FloatField(data.floorHeight, GUILayout.Width(50));
        if (newFloorHeight != data.floorHeight)
        {
            data.floorHeight = newFloorHeight;
        }
        EditorGUILayout.LabelField("metres", GUILayout.Width(50));
        EditorGUILayout.EndHorizontal();

        EditorGUI.BeginDisabledGroup(!renderInterior);

        //Ceiling Height
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Interior Ceiling Height", GUILayout.Width(200));
        float newCeilingHeight = EditorGUILayout.Slider(data.interiorCeilingHeight, 0, 1);
        if (newCeilingHeight != data.interiorCeilingHeight)
        {
            data.interiorCeilingHeight = newCeilingHeight;
        }
        EditorGUILayout.EndHorizontal();

        BuildrPlan plan = data.plan;
        int numberOfVolumes = plan.numberOfVolumes;
        int[] volumeSeletionsList = new int[numberOfVolumes];
        string[] volumeSeletionsStringList = new string[numberOfVolumes];
        for (int s = 0; s < numberOfVolumes; s++)
        {
            volumeSeletionsStringList[s] = ("volume " + s);
            volumeSeletionsList[s] = (s);
        }
        selectedVolumeIndex = EditorGUILayout.IntPopup("Selected Volume", selectedVolumeIndex, volumeSeletionsStringList, volumeSeletionsList, GUILayout.Width(400));
        BuildrVolume volume = plan.volumes[selectedVolumeIndex];


        //Stairs
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Generate Stairs", GUILayout.Width(110));
        volume.generateStairs = EditorGUILayout.Toggle(volume.generateStairs);
        EditorGUILayout.EndHorizontal();

        if(plan.cores.Count == 0)
            EditorGUILayout.HelpBox("There are no building cores defined. Go to floorplan to define one so you can generate a stairwell", MessageType.Error);

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Stair Width", GUILayout.Width(110));
        volume.staircaseWidth = EditorGUILayout.Slider(volume.staircaseWidth, 0.5f, 5.0f);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Minimum Step Riser Value", GUILayout.Width(150));
        volume.stepHeight = EditorGUILayout.Slider(volume.stepHeight, 0.05f, 0.5f);
        EditorGUILayout.EndHorizontal();

        EditorGUI.BeginDisabledGroup(!volume.generateStairs);
        EditorGUILayout.BeginVertical("box");
        EditorGUILayout.LabelField("Stairwell Textures");

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Wall Texture", GUILayout.Width(120));
        volume.stairwellWallTexture = EditorGUILayout.Popup(volume.stairwellWallTexture, textureNames);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Floor Texture", GUILayout.Width(120));
        volume.stairwellFloorTexture = EditorGUILayout.Popup(volume.stairwellFloorTexture, textureNames);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Ceiling Texture", GUILayout.Width(120));
        volume.stairwellCeilingTexture = EditorGUILayout.Popup(volume.stairwellCeilingTexture, textureNames);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Step Texture", GUILayout.Width(120));
        volume.stairwellStepTexture = EditorGUILayout.Popup(volume.stairwellStepTexture, textureNames);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.EndVertical();
        EditorGUI.EndDisabledGroup();

        //Basement floors
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Basement Floors", GUILayout.Width(110));
        EditorGUILayout.LabelField(volume.numberOfBasementFloors.ToString("F0"), GUILayout.Width(40));
        EditorGUI.BeginDisabledGroup(volume.numberOfBasementFloors < 1);
        if (GUILayout.Button("-"))
            volume.numberOfBasementFloors--;
        EditorGUI.EndDisabledGroup();
        if (GUILayout.Button("+"))
            volume.numberOfBasementFloors++;
        EditorGUILayout.EndHorizontal();

        int numberOfFloors = volume.numberOfFloors;
        int numberOfBasementFloors = volume.numberOfBasementFloors;
        int totalNumberOfFloors = numberOfBasementFloors + numberOfFloors;
        int[] floorSeletionsList = new int[totalNumberOfFloors];
        string[] floorSeletionsStringList = new string[totalNumberOfFloors];
        for (int f = -numberOfBasementFloors; f < numberOfFloors; f++)
        {
            int index = f + numberOfBasementFloors;
            if(f>0)
                floorSeletionsStringList[index] = "floor " + f;
            else if(f<0)
                floorSeletionsStringList[index] = "basement " + -f;
            else
                floorSeletionsStringList[index] = "ground floor ";
            floorSeletionsList[index] = (f);
        }
        selectedFloor = EditorGUILayout.IntPopup("Selected Floor", selectedFloor, floorSeletionsStringList, floorSeletionsList, GUILayout.Width(400));
        
        EditorGUILayout.LabelField("Interior Textures");
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Floor Texture", GUILayout.Width(120));
        volume.FloorTexture(selectedFloor, EditorGUILayout.Popup(volume.FloorTexture(selectedFloor), textureNames));
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Wall Texture", GUILayout.Width(120));
        volume.WallTexture(selectedFloor, EditorGUILayout.Popup(volume.WallTexture(selectedFloor), textureNames));
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Ceiling Texture", GUILayout.Width(120));
        volume.CeilingTexture(selectedFloor, EditorGUILayout.Popup(volume.CeilingTexture(selectedFloor), textureNames));
        EditorGUILayout.EndHorizontal();

        if(GUILayout.Button("Use Values for All Floors"))
        {
            int useFloorTextureIndex = volume.FloorTexture(selectedFloor);
            int useWallTextureIndex = volume.WallTexture(selectedFloor);
            int useCeilingTextureIndex = volume.CeilingTexture(selectedFloor);
            for(int f = 0; f < numberOfFloors; f++)
            {
                volume.FloorTexture(f, useFloorTextureIndex);
                volume.WallTexture(f, useWallTextureIndex);
                volume.CeilingTexture(f, useCeilingTextureIndex);
            }
        }

        if (GUILayout.Button("Use Values for Entire Building"))
        {
            int useFloorTextureIndex = volume.FloorTexture(selectedFloor);
            int useWallTextureIndex = volume.WallTexture(selectedFloor);
            int useCeilingTextureIndex = volume.CeilingTexture(selectedFloor);

            for (int v = 0; v < numberOfVolumes; v++)
            {
                BuildrVolume thisvolume = plan.volumes[v];
                int numberOfFloorsToModifiy = thisvolume.numberOfFloors;
                for (int f = 0; f < numberOfFloorsToModifiy; f++)
                {
                    thisvolume.FloorTexture(f, useFloorTextureIndex);
                    thisvolume.WallTexture(f, useWallTextureIndex);
                    thisvolume.CeilingTexture(f, useCeilingTextureIndex);
                }
            }
        }

        EditorGUI.EndDisabledGroup();
    }
    public static void InspectorGUI(BuildrEditMode editMode, BuildrData _data)
    {
        int helpWidth = 20;

        data = _data;

        Undo.RecordObject(data, "Facade Modified");

        BuildrFacadeDesign[] facades = data.facades.ToArray();
        int numberOfFacades = facades.Length;
        selectedFacade = Mathf.Clamp(selectedFacade, 0, numberOfFacades - 1);

        if (numberOfFacades == 0)
        {
            EditorGUILayout.HelpBox("There are no facade designs to show", MessageType.Info);
            return;
        }

        bool hasUnusedFacades = false;
        int unusedIndex = 0;
        //Check all facades have een used and warn if there are unused ones
        for(int i = 0; i < numberOfFacades; i++)
        {
            bool facadeUnused = true;
            foreach(BuildrVolume volume in data.plan.volumes)
            {
                if(volume.ContainsFacade(i))
                {
                    facadeUnused = false;
                    break;
                }
            }
            if(facadeUnused)
            {
                hasUnusedFacades = true;
                unusedIndex = i;
                break;
            }
        }
        if (hasUnusedFacades)
            EditorGUILayout.HelpBox("There are facade designs that are not applied to your building and are unused.\nGo to the Building section to apply them to a facade.\nCheck facade design \""+facades[unusedIndex].name+"\"", MessageType.Warning);

        //Facade Selector
        EditorGUILayout.BeginVertical("box");
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Facade Design:", GUILayout.Width(145));
        string[] facadeNames = new string[numberOfFacades];
        for (int f = 0; f < numberOfFacades; f++)
            facadeNames[f] = facades[f].name;
        selectedFacade = EditorGUILayout.Popup(selectedFacade, facadeNames);
        BuildrFacadeDesign bFacade = facades[selectedFacade];
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();

        if (GUILayout.Button("Add", GUILayout.Width(60)))
        {
            data.facades.Add(new BuildrFacadeDesign("new facade " + numberOfFacades));
            facades = data.facades.ToArray();
            numberOfFacades++;
            selectedFacade = numberOfFacades - 1;
        }

        if (GUILayout.Button("Duplicate", GUILayout.Width(90)))
        {
            data.facades.Add(bFacade.Duplicate());
            facades = data.facades.ToArray();
            numberOfFacades++;
            selectedFacade = numberOfFacades - 1;
        }

        if (GUILayout.Button("Delete", GUILayout.Width(70)))
        {
            if (EditorUtility.DisplayDialog("Deleting Facade Design Entry", "Are you sure you want to delete this facade?", "Delete", "Cancel"))
            {
                data.RemoveFacadeDesign(bFacade);
                selectedFacade = 0;
                GUI.changed = true;

                return;
            }
        }

        if (GUILayout.Button("Import", GUILayout.Width(71)))
        {
            string xmlPath = EditorUtility.OpenFilePanel("Select the XML file...", "Assets/BuildR/Exported/", "xml");
            if (xmlPath == "")
                return;
            BuildrXMLImporter.ImportFacades(xmlPath, _data);
            facades = _data.facades.ToArray();
            selectedFacade = 0;
            GUI.changed = true;
        }

        if (GUILayout.Button("Export", GUILayout.Width(71)))
        {
            string xmlPath = EditorUtility.SaveFilePanel("Export as...", "Assets/BuildR/Exported/", _data.name + "_facadeLibrary", "xml");
            if (xmlPath == "")
                return;
            BuildrXMLExporter.ExportFacades(xmlPath, _data);
            GUI.changed = true;
        }
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.Space();
        EditorGUILayout.EndVertical();

        bFacade = facades[selectedFacade];//reassign
        bFacade.name = EditorGUILayout.TextField("Facade Name: ", bFacade.name);

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Facade Design Type:", GUILayout.Width(145));
        bFacade.type = (BuildrFacadeDesign.types)EditorGUILayout.EnumPopup(bFacade.type);
        if (GUILayout.Button("?", GUILayout.Width(helpWidth)))
        {
            string helpTitle = "Help - Design Type";
            string helpBody = "This allows you to select the type of design you're using.\n" +
                "Simple - the facade openings will be uniform\n" +
                "Patterned - the facade openings will follow a pattern of defined dimensions and textures\n";
            EditorUtility.DisplayDialog(helpTitle, helpBody, "close");
        }
        EditorGUILayout.EndHorizontal();

        int numberOfTextures = data.textures.Count;
        string[] textureNames = new string[numberOfTextures];
        for (int t = 0; t < numberOfTextures; t++)
            textureNames[t] = data.textures[t].name;

        bFacade.hasWindows = EditorGUILayout.Toggle("Facade Has Bays", bFacade.hasWindows);

        if (bFacade.hasWindows)
        {
            if (bFacade.type == BuildrFacadeDesign.types.simple)
            {
                BuildrBay bbay = bFacade.simpleBay;

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("Render Bay", GUILayout.Width(146));
                bool renderBayBack = EditorGUILayout.Toggle(bbay.renderBack);
                if (renderBayBack != bbay.renderBack)
                {
                    bbay.renderBack = renderBayBack;
                }
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("Bay Model", GUILayout.Width(146));
                bbay.bayModel = (GameObject)EditorGUILayout.ObjectField(bbay.bayModel, typeof(GameObject), false);
                if (GUILayout.Button("Clear", GUILayout.Width(70)))
                    bbay.bayModel = null;
                EditorGUILayout.EndHorizontal();

                float bbayopeningWidth = Mathf.Max(EditorGUILayout.FloatField("Opening Width", bbay.openingWidth), 0);
                if (bbayopeningWidth != bbay.openingWidth)
                {
                    bbay.openingWidth = bbayopeningWidth;
                }
                float bbayopeningHeight = Mathf.Max(EditorGUILayout.FloatField("Opening Height", bbay.openingHeight), 0);
                if (bbayopeningHeight > data.floorHeight)
                    bbayopeningHeight = data.floorHeight;
                if (bbayopeningHeight != bbay.openingHeight)
                {
                    bbay.openingHeight = bbayopeningHeight;
                }
                float bbayminimumBayWidth = Mathf.Max(EditorGUILayout.FloatField("Min. Spacing", bbay.minimumBayWidth), 0);
                if (bbayminimumBayWidth != bbay.minimumBayWidth)
                {
                    bbay.minimumBayWidth = bbayminimumBayWidth;
                }

                float bbayopeningWidthRatio = EditorGUILayout.Slider("Horizontal Space Ratio", bbay.openingWidthRatio, 0, 1);
                if(bbayopeningWidthRatio != bbay.openingWidthRatio)
                {
                    bbay.openingWidthRatio = bbayopeningWidthRatio;
                }
                float bbayopeningHeightRatio = EditorGUILayout.Slider("Vertical Space Ratio", bbay.openingHeightRatio, 0, 1);
                if (bbayopeningHeightRatio != bbay.openingHeightRatio)
                {
                    bbay.openingHeightRatio = bbayopeningHeightRatio;
                }

                float bbayopeningDepth = EditorGUILayout.Slider("Opening Depth", bbay.openingDepth, -depth, depth);
                if (bbayopeningDepth != bbay.openingDepth)
                {
                    bbay.openingDepth = bbayopeningDepth;
                }
                float bbaycolumnDepth = EditorGUILayout.Slider("Column Depth", bbay.columnDepth, -depth, depth);
                if (bbaycolumnDepth != bbay.columnDepth)
                {
                    bbay.columnDepth = bbaycolumnDepth;
                }
                float bbayrowDepth = EditorGUILayout.Slider("Row Depth", bbay.rowDepth, -depth, depth);
                if (bbayrowDepth != bbay.rowDepth)
                {
                    bbay.rowDepth = bbayrowDepth;
                }
                float bbaycrossDepth = EditorGUILayout.Slider("Cross Depth", bbay.crossDepth, -depth, depth);
                if (bbaycrossDepth != bbay.crossDepth)
                {
                    bbay.crossDepth = bbaycrossDepth;
                }

                int numberOfTextureSlots = bbay.numberOfTextures;
                string[] titles = new string[numberOfTextureSlots];
                for (int bft = 0; bft < numberOfTextureSlots; bft++)
                {
                    titles[bft] = ((BuildrBay.TextureNames)(bft)).ToString();
                }

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("Wall Surface:", GUILayout.Width(75));
                editTextureOnFacade = EditorGUILayout.Popup(editTextureOnFacade, titles);
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("Wall Texture:", GUILayout.Width(75));
                int newFacadeTextureID = EditorGUILayout.Popup(bbay.textureValues[editTextureOnFacade], textureNames);
                if (newFacadeTextureID != bbay.textureValues[editTextureOnFacade])
                {
                    bbay.textureValues[editTextureOnFacade] = newFacadeTextureID;
                }
                EditorGUILayout.EndHorizontal();
                BuildrTexture bTexture = data.textures[bbay.textureValues[editTextureOnFacade]];
                Texture2D texture = bTexture.texture;
                EditorGUILayout.BeginHorizontal();

                if (texture != null)
                    GUILayout.Label(texture, GUILayout.Width(100), GUILayout.Height(100));
                else
                    EditorGUILayout.HelpBox("No texture assigned for '" + textureNames[bbay.textureValues[editTextureOnFacade]] + "', assign one in the Textures menu above", MessageType.Warning);

                bbay.flipValues[editTextureOnFacade] = EditorGUILayout.Toggle("Flip 90\u00B0", bbay.flipValues[editTextureOnFacade]);

                EditorGUILayout.EndHorizontal();
            }
            else
            {
                //Patterned design GUI

                int numberOfBays = bFacade.bayPattern.Count;
                int numberOfBayDesigns = data.bays.Count;

                EditorGUILayout.BeginHorizontal();
                GUILayout.BeginHorizontal("box");
                if (GUILayout.Button("Add New Bay Design"))
                {
                    BuildrBay newBay = new BuildrBay("new bay design " + (numberOfBayDesigns + 1));
                    data.bays.Add(newBay);
                    bFacade.bayPattern.Add(numberOfBayDesigns);
                    numberOfBays++;
                    selectedBayPatternIndex = numberOfBays - 1;
                    numberOfBayDesigns++;
                    GUI.changed = true;
                }
                EditorGUILayout.EndHorizontal();
                if (numberOfBays == 0 || data.bays.Count == 0)
                {
                    EditorGUILayout.HelpBox("There are no bay designs to show", MessageType.Info);
        //                    EditorGUILayout.EndHorizontal();
                    EditorGUILayout.EndVertical();
                    return;
                }

                BuildrBay[] bays = new BuildrBay[numberOfBays];
                for (int i = 0; i < numberOfBays; i++)
                {
                    bays[i] = data.bays[bFacade.bayPattern[i]];
                }
                selectedBayPatternIndex = Mathf.Clamp(selectedBayPatternIndex, 0, numberOfBays - 1);

                EditorGUILayout.EndHorizontal();
                EditorGUILayout.BeginHorizontal();
                GUILayout.BeginHorizontal("box");
                string[] bayDesignNames = new string[data.bays.Count];
                for (int i = 0; i < numberOfBayDesigns; i++)
                {
                    bayDesignNames[i] = data.bays[i].name;
                }
                selectedBayDesign = EditorGUILayout.Popup(selectedBayDesign, bayDesignNames);
                if (GUILayout.Button("Add Selected"))
                {
                    bFacade.bayPattern.Add(selectedBayDesign);
                    GUI.changed = true;
                }
                if (GUILayout.Button("Duplicate Selected"))
                {
                    BuildrBay newBay = data.bays[selectedBayDesign].Duplicate();
                    data.bays.Add(newBay);
                    bFacade.bayPattern.Add(numberOfBayDesigns);
                    numberOfBays++;
                    selectedBayPatternIndex = numberOfBays - 1;
                    numberOfBayDesigns++;
                    GUI.changed = true;
                }
                EditorGUILayout.EndHorizontal();
                EditorGUILayout.EndHorizontal();

                GUILayout.BeginVertical("box");
                EditorGUILayout.LabelField("Bay Design Order:");
                var scrollbarHStyle = new GUIStyle(GUI.skin.horizontalScrollbar);
                var scrollbarBackStyle = new GUIStyle();
                var scrollbarVStyle = new GUIStyle(GUI.skin.verticalScrollbar);
                scrollbarVStyle.fixedHeight = scrollbarVStyle.fixedWidth = 0;
                bayDesignPatternScrollView = EditorGUILayout.BeginScrollView(bayDesignPatternScrollView, false, false, scrollbarHStyle, scrollbarVStyle, scrollbarBackStyle, GUILayout.Height(40));
                List<string> bayNames = new List<string>();
                foreach (int bayIndex in bFacade.bayPattern)
                {
                    bayNames.Add(data.bays[bayIndex].name);
                }
                selectedBayPatternIndex = GUILayout.Toolbar(selectedBayPatternIndex, bayNames.ToArray());
                EditorGUILayout.EndScrollView();
                BuildrBay bBay = data.bays[bFacade.bayPattern[selectedBayPatternIndex]];

                EditorGUILayout.BeginHorizontal();

                EditorGUI.BeginDisabledGroup(selectedBayPatternIndex == 0);
                if (GUILayout.Button("<<", GUILayout.Width(40)))
                {
                    int bayDesignIndex = bFacade.bayPattern[selectedBayPatternIndex];
                    bFacade.bayPattern.RemoveAt(selectedBayPatternIndex);
                    bFacade.bayPattern.Insert(selectedBayPatternIndex - 1, bayDesignIndex);
                    selectedBayPatternIndex--;
                    GUI.changed = true;
                }
                EditorGUI.EndDisabledGroup();
                if (GUILayout.Button("Remove"))
                {
                    bFacade.bayPattern.RemoveAt(selectedBayPatternIndex);
                    GUI.changed = true;
                }
                if (GUILayout.Button("Delete"))
                {
                    if (EditorUtility.DisplayDialog("Deleting Bay Design Entry", "Are you sure you want to delete this bay?", "Delete", "Cancel"))
                    {
                        int deletedBayDesignIndex = bFacade.bayPattern[selectedBayPatternIndex];
                        Debug.Log("Delete Bay Design " + deletedBayDesignIndex);
                        Debug.Log("Delete Bay Design " + data.bays[deletedBayDesignIndex].name);
                        data.bays.RemoveAt(deletedBayDesignIndex);
                        int numberOfFacadeDesigns = data.facades.Count;
                        for (int i = 0; i < numberOfFacadeDesigns; i++)
                        {
                            BuildrFacadeDesign checkFacade = data.facades[i];
                            int bayPatternSize = checkFacade.bayPattern.Count;
                            for (int j = 0; j < bayPatternSize; j++)
                            {
                                if (checkFacade.bayPattern[j] == deletedBayDesignIndex)
                                {
                                    checkFacade.bayPattern.RemoveAt(j);
                                    j--;
                                    bayPatternSize--;
                                }
                                else if (checkFacade.bayPattern[j] > deletedBayDesignIndex)
                                    checkFacade.bayPattern[j]--;
                            }
                        }
                        GUI.changed = true;
                    }
                }
                EditorGUI.BeginDisabledGroup(selectedBayPatternIndex == numberOfBays - 1);
                if (GUILayout.Button(">>", GUILayout.Width(40)))
                {
                    int bayDesignIndex = bFacade.bayPattern[selectedBayPatternIndex];
                    bFacade.bayPattern.Insert(selectedBayPatternIndex + 2, bayDesignIndex);
                    bFacade.bayPattern.RemoveAt(selectedBayPatternIndex);
                    selectedBayPatternIndex++;
                    GUI.changed = true;
                }
                EditorGUI.EndDisabledGroup();
                EditorGUILayout.EndHorizontal();
                EditorGUILayout.EndVertical();

                GUILayout.Space(10);
                EditorGUILayout.BeginVertical("box");
                bBay.name = EditorGUILayout.TextField("Name: ", bBay.name);
                bool bBayisOpening = EditorGUILayout.Toggle("Has Opening", bBay.isOpening);
                if(bBayisOpening != bBay.isOpening)
                {
                    bBay.isOpening = bBayisOpening;
                }

                bool bBayRenderBack = EditorGUILayout.Toggle("Render Back", bBay.renderBack);
                if (bBayRenderBack != bBay.renderBack)
                {
                    bBay.renderBack = bBayRenderBack;
                }

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("Bay Model", GUILayout.Width(146));
                bBay.bayModel = (GameObject)EditorGUILayout.ObjectField(bBay.bayModel, typeof(GameObject), false);
                if (GUILayout.Button("Clear", GUILayout.Width(70)))
                    bBay.bayModel = null;
                EditorGUILayout.EndHorizontal();

                float bBayopeningWidth = Mathf.Max(EditorGUILayout.FloatField("Opening Width", bBay.openingWidth), 0);
                if (bBayopeningWidth != bBay.openingWidth)
                {
                    bBay.openingWidth = bBayopeningWidth;
                }
                float bBayopeningHeight = Mathf.Clamp(EditorGUILayout.FloatField("Opening Height", bBay.openingHeight), 0, data.floorHeight);
                if (bBayopeningHeight != bBay.openingHeight)
                {
                    bBay.openingHeight = bBayopeningHeight;
                }

                float bBayminimumBayWidth = Mathf.Max(EditorGUILayout.FloatField("Bay Spacing Width", bBay.minimumBayWidth), 0);
                if (bBayminimumBayWidth != bBay.minimumBayWidth)
                {
                    bBay.minimumBayWidth = bBayminimumBayWidth;
                }

                float bBayopeningWidthRatio = EditorGUILayout.Slider("Horizontal Space Ratio", bBay.openingWidthRatio, 0, 1);
                if (bBayopeningWidthRatio != bBay.openingWidthRatio)
                {
                    bBay.openingWidthRatio = bBayopeningWidthRatio;
                }
                float bBayopeningHeightRatio = EditorGUILayout.Slider("Vertical Space Ratio", bBay.openingHeightRatio, 0, 1);
                if (bBayopeningHeightRatio != bBay.openingHeightRatio)
                {
                    bBay.openingHeightRatio = bBayopeningHeightRatio;
                }

                float bBayopeningDepth = EditorGUILayout.Slider("Opening Depth", bBay.openingDepth, -depth, depth);
                if (bBayopeningDepth != bBay.openingDepth)
                {
                    bBay.openingDepth = bBayopeningDepth;
                }
                float bBaycolumnDepth = EditorGUILayout.Slider("Column depth", bBay.columnDepth, -depth, depth);
                if (bBaycolumnDepth != bBay.columnDepth)
                {
                    bBay.columnDepth = bBaycolumnDepth;
                }
                float bBayrowDepth = EditorGUILayout.Slider("Row depth", bBay.rowDepth, -depth, depth);
                if (bBayrowDepth != bBay.rowDepth)
                {
                    bBay.rowDepth = bBayrowDepth;
                }
                float bBaycrossDepth = EditorGUILayout.Slider("Cross depth", bBay.crossDepth, -depth, depth);
                if (bBaycrossDepth != bBay.crossDepth)
                {
                    bBay.crossDepth = bBaycrossDepth;
                }

                //BAY TEXTURES

                int numberOfTextureSlots = bBay.numberOfTextures;
                string[] titles = new string[numberOfTextureSlots];
                for (int bft = 0; bft < numberOfTextureSlots; bft++)
                {
                    titles[bft] = ((BuildrBay.TextureNames)(bft)).ToString();
                }

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("Surface:", GUILayout.Width(75));
                editTextureOnFacade = EditorGUILayout.Popup(editTextureOnFacade, titles);
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("Texture:", GUILayout.Width(75));
                bBay.textureValues[editTextureOnFacade] = EditorGUILayout.Popup(bBay.textureValues[editTextureOnFacade], textureNames);
                EditorGUILayout.EndHorizontal();
                BuildrTexture bTexture = data.textures[bBay.textureValues[editTextureOnFacade]];
                Texture2D texture = bTexture.texture;
                EditorGUILayout.BeginHorizontal();

                if (texture != null)
                    GUILayout.Label(texture, GUILayout.Width(100), GUILayout.Height(100));
                else
                    EditorGUILayout.HelpBox("No texture assigned for '" + textureNames[bBay.textureValues[editTextureOnFacade]] + "', assign one in the Textures menu above", MessageType.Warning);

                bFacade.flipValues[editTextureOnFacade] = EditorGUILayout.Toggle("Flip 90\u00B0", bFacade.flipValues[editTextureOnFacade]);

                EditorGUILayout.EndHorizontal();
                EditorGUILayout.EndVertical();
            }
        }
        else
        {
            editTextureOnFacade = 7;
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Surface:", GUILayout.Width(75));
            EditorGUILayout.LabelField("Wall");
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Texture:", GUILayout.Width(75));
            int newFacadeTexture = EditorGUILayout.Popup(bFacade.simpleBay.textureValues[editTextureOnFacade], textureNames);
            if (newFacadeTexture != bFacade.simpleBay.textureValues[editTextureOnFacade])
            {
                bFacade.simpleBay.textureValues[editTextureOnFacade] = newFacadeTexture;
            }
            EditorGUILayout.EndHorizontal();
            BuildrTexture bTexture = data.textures[bFacade.simpleBay.textureValues[editTextureOnFacade]];
            Texture2D texture = bTexture.texture;
            EditorGUILayout.BeginHorizontal();

            if (texture != null)
                GUILayout.Label(texture, GUILayout.Width(100), GUILayout.Height(100));
            else
                EditorGUILayout.HelpBox("No texture assigned for '" + textureNames[bFacade.simpleBay.textureValues[editTextureOnFacade]] + "', assign one in the Textures menu above", MessageType.Warning);

            bFacade.simpleBay.flipValues[editTextureOnFacade] = EditorGUILayout.Toggle("Flip 90\u00B0", bFacade.simpleBay.flipValues[editTextureOnFacade]);

            EditorGUILayout.EndHorizontal();
        }
    }
    void OnEnable()
    {
        if (target != null)
        {
            _editMode = (BuildrEditMode)target;
            _data = _editMode.data;
        }

        bool editing = (_data != null) ? _data.editing : true;
        if (!editing)
        {
            BuildrGenerateModeEditor.OnEnable();
        }
    }
    public static void InspectorGUI(BuildrEditMode editMode, BuildrData _data)
    {
        data = _data;
        Undo.RecordObject(data, "Building Modified");
        BuildrPlan plan = data.plan;
        int numberOfFacadeFaces = 0;
        int numberOfVolumes = plan.numberOfVolumes;
        int numberOfFacadeDesigns = data.facades.Count;

        if (numberOfVolumes == 0)
        {
            EditorGUILayout.HelpBox("There are no defined volumes, go to Floorplan and define one", MessageType.Error);
            return;
        }

        int numberOfFacades = data.facades.Count;
        int numberOfRoofs = data.roofs.Count;
        int numberOfTextures = data.textures.Count;

        bool legalBuilding = true;
        if (numberOfFacades == 0)
        {
            EditorGUILayout.HelpBox("There are no facade designs to render building, go to Facades to define a default one", MessageType.Error);
            legalBuilding = false;
        }
        if (numberOfRoofs == 0)
        {
            EditorGUILayout.HelpBox("There are no roof designs to render building, go to Facades to define a default one", MessageType.Error);
            legalBuilding = false;
        }
        if (numberOfTextures == 0)
        {
            EditorGUILayout.HelpBox("There are no textures to render building, go to Textures to define a default one", MessageType.Error);
            legalBuilding = false;
        }

        if (!legalBuilding)
            return;

        //Building Name
        EditorGUILayout.Space();
        EditorGUILayout.Space();
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Name", GUILayout.Width(200));
        data.name = EditorGUILayout.TextField(data.name, GUILayout.Width(200));
        EditorGUILayout.EndHorizontal();

        //Floor Height
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Floor height", GUILayout.Width(200));
        data.floorHeight = EditorGUILayout.FloatField(data.floorHeight, GUILayout.Width(50));
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Number of Floors", GUILayout.Width(200));
        int[] volumeSeletionsList = new int[numberOfVolumes];
        string[] volumeSeletionsStringList = new string[numberOfVolumes];
        for (int s = 0; s < numberOfVolumes; s++)
        {
            volumeSeletionsStringList[s] = ("volume " + s);
            volumeSeletionsList[s] = (s);
        }

        selectedFloorNumberVolume = EditorGUILayout.IntPopup(selectedFloorNumberVolume, volumeSeletionsStringList, volumeSeletionsList, GUILayout.Width(100));
        int numberOfFloors = EditorGUILayout.IntField(data.plan.volumes[selectedFloorNumberVolume].numberOfFloors);
        if (GUILayout.Button("^"))
            numberOfFloors++;
        if (GUILayout.Button("v"))
            numberOfFloors--;
        data.plan.volumes[selectedFloorNumberVolume].numberOfFloors = Mathf.Max(numberOfFloors, 1);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Show Facade Markers", GUILayout.Width(200));
        editMode.showFacadeMarkers = EditorGUILayout.Toggle(editMode.showFacadeMarkers, GUILayout.Width(200));
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.Space();

        GUIStyle titlesyle = new GUIStyle(GUI.skin.label);
        titlesyle.fixedHeight = 60;
        titlesyle.fixedWidth = 400;
        titlesyle.alignment = TextAnchor.UpperCenter;
        titlesyle.fontStyle = FontStyle.Bold;
        titlesyle.normal.textColor = Color.white;

        EditorGUILayout.LabelField("Facade Design", titlesyle);
        Texture2D facadeTexture = new Texture2D(1, 1);
        facadeTexture.SetPixel(0, 0, BuildrColours.MAGENTA);
        facadeTexture.Apply();
        Rect sqrPos = new Rect(0, 0, 0, 0);
        if (Event.current.type == EventType.Repaint)
            sqrPos = GUILayoutUtility.GetLastRect();
        GUI.DrawTexture(sqrPos, facadeTexture);
        EditorGUI.LabelField(sqrPos, "Facade Design", titlesyle);

        //create/display the facade selector
        List<int> facadeSeletionsList = new List<int>();
        List<int> facadeRenderList = new List<int>();
        List<string> facadeSeletionsStringList = new List<string>();
        for (int s = 0; s < numberOfVolumes; s++)
        {
            int numberOfPoints = plan.volumes[s].Count;
            numberOfFacadeFaces += numberOfPoints;
            for (int p = 0; p < numberOfPoints; p++)
            {
                int index = facadeSeletionsList.Count;
                facadeSeletionsStringList.Add("facade " + index);
                facadeSeletionsList.Add(index);
                facadeRenderList.Add(p);
            }
        }
        int[] facadeSelections = facadeSeletionsList.ToArray();
        string[] facadeSelectionString = facadeSeletionsStringList.ToArray();

        selectedFacade = EditorGUILayout.IntPopup("Selected Facade", selectedFacade, facadeSelectionString, facadeSelections, GUILayout.Width(400));

        //grab the selected facade
        int facadeCount = 0;
        int selectedVolumePoint = 0;
        for (int s = 0; s < numberOfVolumes; s++)
        {
            int numberOfPoints = plan.volumes[s].Count;
            for (int p = 0; p < numberOfPoints; p++)
            {
                if (selectedFacade == facadeCount)
                {
                    selectedVolume = s;
                    selectedVolumePoint = p;
                    selectedPoint = plan.volumes[s].points[p];
                }
                facadeCount++;
            }
        }

        BuildrVolume volume = plan.volumes[selectedVolume];
        BuildrVolumeStylesUnit[] styles = volume.styles.GetContents();

        bool renderFacade = volume.renderFacade[selectedVolumePoint];
        volume.renderFacade[selectedVolumePoint] = EditorGUILayout.Toggle("Render Facade", renderFacade);

        //ensure the selected style isn't out of bounds
        int numberOfStyles = styles.Length;
        if (selectedStyle >= numberOfStyles)
            selectedStyle = 0;

        //compose a list of style ids from the volume style library
        List<int> entryNum = new List<int>();
        for (int s = 0; s < numberOfStyles; s++)
        {
            if (selectedPoint == styles[s].facadeID)
                entryNum.Add(s);
        }

        int numberOfFacadeStyles = entryNum.Count;

        if (GUILayout.Button("Add style to facade", GUILayout.Width(400)))
            volume.styles.AddStyle(0, selectedPoint, 1);

        GUILayout.BeginHorizontal("box");
        GUILayout.BeginHorizontal("box");
        EditorGUILayout.LabelField("Style", GUILayout.Width(160));
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal("box");
        GUILayout.Label("Floors", GUILayout.Width(78));
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal("box");
        GUILayout.Label("Position", GUILayout.Width(54));
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal("box");
        GUILayout.Label(" ", GUILayout.Width(55));
        GUILayout.EndHorizontal();
        GUILayout.EndHorizontal();

        for (int s = 0; s < numberOfFacadeStyles; s++)
        {
            int index = entryNum[s];
            BuildrVolumeStylesUnit styleUnit = styles[index];

            GUILayout.BeginHorizontal("box");
            GUILayout.BeginHorizontal("box");
            string[] facadeNames = new string[numberOfFacadeDesigns];
            for (int f = 0; f < numberOfFacadeDesigns; f++)
                facadeNames[f] = data.facades[f].name;
            int selectedFacadeDesign = EditorGUILayout.Popup(styleUnit.styleID, facadeNames, GUILayout.Width(160));
            if (selectedFacadeDesign != styleUnit.styleID)
            {
                volume.styles.ModifyStyle(index, selectedFacadeDesign);
            }
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal("box");
            int currentFloors = styleUnit.floors;

            currentFloors = EditorGUILayout.IntField(currentFloors, GUILayout.Width(20));
            if (GUILayout.Button("+", GUILayout.Width(25)))
                currentFloors++;
            EditorGUI.BeginDisabledGroup(currentFloors < 2);
            if (GUILayout.Button("-", GUILayout.Width(25)))
                currentFloors--;
            EditorGUI.EndDisabledGroup();
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal("box");
            EditorGUI.BeginDisabledGroup((s < 1));
            {
                if (GUILayout.Button("^", GUILayout.Width(25)))
                {
                    volume.styles.MoveEntry(entryNum[s], entryNum[s - 1] + 1);
                    GUI.changed = true;
                }
            }
            EditorGUI.EndDisabledGroup();
            EditorGUI.BeginDisabledGroup((s > numberOfFacadeStyles - 2));
            {
                if (GUILayout.Button("v", GUILayout.Width(25)))
                {
                    volume.styles.MoveEntry(entryNum[s], entryNum[s + 1] + 1);
                    GUI.changed = true;
                }
            }
            EditorGUI.EndDisabledGroup();
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal("box");
            if (GUILayout.Button("remove", GUILayout.Width(55)))
            {
                volume.styles.RemoveStyle(index);
            }
            GUILayout.EndHorizontal();
            GUILayout.EndHorizontal();

            if (currentFloors != styleUnit.floors)
            {
                volume.styles.ModifyFloors(index, currentFloors);
                GUI.changed = true;
            }
        }
        EditorGUILayout.Space();

        titlesyle = new GUIStyle(GUI.skin.label);
        titlesyle.fixedHeight = 60;
        titlesyle.fixedWidth = 400;
        titlesyle.alignment = TextAnchor.UpperCenter;
        titlesyle.fontStyle = FontStyle.Bold;
        titlesyle.normal.textColor = Color.black;

        EditorGUILayout.LabelField("Roof Design", titlesyle);
        facadeTexture = new Texture2D(1, 1);
        facadeTexture.SetPixel(0, 0, BuildrColours.CYAN);
        facadeTexture.Apply();
        sqrPos = new Rect(0, 0, 0, 0);
        if (Event.current.type == EventType.Repaint)
            sqrPos = GUILayoutUtility.GetLastRect();
        GUI.DrawTexture(sqrPos, facadeTexture);
        EditorGUI.LabelField(sqrPos, "Roof Design", titlesyle);

        //create/display the roof selector
        volumeSeletionsList = new int[numberOfVolumes];
        volumeSeletionsStringList = new string[numberOfVolumes];
        for (int s = 0; s < numberOfVolumes; s++)
        {
            volumeSeletionsStringList[s] = ("volume " + s);
            volumeSeletionsList[s] = (s);
        }

        selectedRoofVolume = EditorGUILayout.IntPopup("Selected Volume", selectedRoofVolume, volumeSeletionsStringList, volumeSeletionsList, GUILayout.Width(400));

        string[] roofNames = new string[numberOfRoofs];
        int[] roofList = new int[numberOfRoofs];
        for (int r = 0; r < numberOfRoofs; r++)
        {
            roofList[r] = r;
            roofNames[r] = data.roofs[r].name;
        }

        volume = data.plan.volumes[selectedRoofVolume];
        volume.roofDesignID = EditorGUILayout.IntPopup("Selected Roof Design", volume.roofDesignID, roofNames, roofList, GUILayout.Width(400));
    }
Beispiel #12
0
    public static void SceneGUI(BuildrEditMode editMode, BuildrData data, bool shouldSnap, float handleSize)
    {
        if (data.details.Count == 0)
        {
            return;
        }
        Undo.RecordObject(data, "Detail Modified");

        int numberOfFacades  = data.facades.Count;
        int numberOfRoofs    = data.roofs.Count;
        int numberOfTextures = data.textures.Count;

        if (numberOfFacades == 0 || numberOfRoofs == 0 || numberOfTextures == 0)
        {
            return;
        }

        Vector3 position = editMode.transform.position;

        BuildrPlan   plan            = data.plan;
        int          numberOfVolumes = plan.numberOfVolumes;
        BuildrDetail bDetail         = data.details[selectedDetail];
        float        volumeHeight    = 0;
        Vector3      baseLeft        = Vector3.zero;
        Vector3      baseRight       = Vector3.zero;
        int          faceIndex       = bDetail.face;

        int facadeCounter = 0;

        for (int v = 0; v < numberOfVolumes; v++)
        {
            BuildrVolume volume      = data.plan.volumes[v];
            int          volumeSize  = volume.Count;
            Vector3      floorCentre = Vector3.zero;
            Handles.color = Color.white;

            for (int p = 0; p < volumeSize; p++)
            {
                int     point  = volume.points[p];
                int     indexB = volume.points[(p + 1) % volumeSize];
                Vector3 fb0    = plan.points[point].vector3;
                Vector3 fb1    = plan.points[indexB].vector3;
                if (bDetail.face == facadeCounter && bDetail.type == BuildrDetail.Types.Facade)
                {
                    baseLeft  = fb0;
                    baseRight = fb1;
                }
                floorCentre += baseLeft;

                List <Vector3> verts = new List <Vector3>();
                volumeHeight = (volume.numberOfFloors * data.floorHeight);
                Vector3 volumeHeightVector = Vector3.up * volumeHeight;
                verts.Add(fb0 + position);
                verts.Add(fb1 + position);
                verts.Add(verts[1] + volumeHeightVector);
                verts.Add(verts[0] + volumeHeightVector);
                if (bDetail.face == facadeCounter && bDetail.type == BuildrDetail.Types.Facade)
                {
                    //display something to highlight this facade
                    Handles.DrawSolidRectangleWithOutline(verts.ToArray(), Color.clear, BuildrColours.MAGENTA);
                }
                Handles.color = BuildrColours.CYAN;
                if (v == bDetail.face && bDetail.type == BuildrDetail.Types.Roof)
                {
                    Handles.DrawLine(verts[2], verts[3]);
                }
                if (editMode.showFacadeMarkers)
                {
                    Handles.color = Color.white;
                    Vector3  camDirection     = Camera.current.transform.forward;
                    Vector3  facadeDirection  = Vector3.Cross((verts[0] - verts[1]), Vector3.up);
                    GUIStyle facadeLabelStyle = new GUIStyle();
                    facadeLabelStyle.normal.textColor = Color.white;
                    facadeLabelStyle.alignment        = TextAnchor.MiddleCenter;
                    facadeLabelStyle.fixedWidth       = 75.0f;
                    if (Vector3.Dot(camDirection, facadeDirection) < 0)//only display label when facade is facing camera
                    {
                        Vector3 centerPos = (verts[0] + verts[1]) * 0.5f;
                        Vector3 labelPos  = centerPos + facadeDirection.normalized;
                        Handles.Label(labelPos, "facade " + facadeCounter, facadeLabelStyle);
                        Handles.DrawLine(centerPos, labelPos);
                    }
                }
                facadeCounter++;
            }
        }

        Vector3    handlePosition = bDetail.worldPosition + position;// new Vector3(basePos.x, volumeHeight * bDetail.faceUv.y, basePos.z);
        Vector3    baseDir        = (baseRight - baseLeft).normalized;
        Vector3    baseCross      = Vector3.Cross(Vector3.up, baseDir);
        Quaternion currentRot     = Quaternion.Euler(bDetail.userRotation);
        Quaternion faceRotation   = (bDetail.type == BuildrDetail.Types.Facade) ? Quaternion.LookRotation(baseCross) : Quaternion.identity;

        switch (Tools.current)
        {
        case Tool.Move:
            Vector3 dirX, dirY, dirZ;
            if (bDetail.type == BuildrDetail.Types.Facade)
            {
                dirX = baseDir;
                dirY = baseCross;
                dirZ = Vector3.up;
            }
            else
            {
                dirX = Vector3.right;
                dirY = Vector3.up;
                dirZ = Vector3.forward;
            }
            Vector3 newSliderPos;
            Handles.color = BuildrColours.RED;
            newSliderPos  = Handles.Slider(handlePosition, dirX, handleSize * 0.666f, Handles.ArrowCap, 0.0f);
            Handles.color = BuildrColours.BLUE;
            newSliderPos  = Handles.Slider(newSliderPos, dirZ, handleSize * 0.666f, Handles.ArrowCap, 0.0f);
            Handles.color = BuildrColours.GREEN;
            newSliderPos  = Handles.Slider(newSliderPos, dirY, handleSize * 0.666f, Handles.ArrowCap, 0.0f);
            Vector3 sliderDiff = newSliderPos - handlePosition;

            if (sliderDiff != Vector3.zero)
            {
                float newXUV = 0, newYUV = 0, newHeight = bDetail.faceHeight;
                if (bDetail.type == BuildrDetail.Types.Facade)
                {
                    float facadeWidth = Vector3.Distance(baseLeft, baseRight);
                    float sliderDiffX = Mathf.Sqrt(sliderDiff.x * sliderDiff.x + sliderDiff.z * sliderDiff.z) * Mathf.Sign(Vector3.Dot(baseDir, sliderDiff));
                    newXUV = sliderDiffX / facadeWidth + bDetail.faceUv.x;
                    newYUV = sliderDiff.y / volumeHeight + bDetail.faceUv.y;
                }
                else
                {
                    BuildrVolume volume = plan.volumes[faceIndex];
                    int          numberOfVolumePoints = volume.points.Count;
                    Vector3      minPoint             = plan.points[volume.points[0]].vector3;
                    Vector3      maxPoint             = plan.points[volume.points[0]].vector3;
                    for (int p = 1; p < numberOfVolumePoints; p++)
                    {
                        Vector3 fp0 = plan.points[volume.points[p]].vector3;
                        if (fp0.x < minPoint.x)
                        {
                            minPoint.x = fp0.x;
                        }
                        if (fp0.z < minPoint.z)
                        {
                            minPoint.z = fp0.z;
                        }
                        if (fp0.x > maxPoint.x)
                        {
                            maxPoint.x = fp0.x;
                        }
                        if (fp0.z > maxPoint.z)
                        {
                            maxPoint.z = fp0.z;
                        }
                    }
                    float roofWidth = maxPoint.x - minPoint.x;
                    float roofDepth = maxPoint.z - minPoint.z;
                    newXUV     = sliderDiff.x / roofWidth + bDetail.faceUv.x;
                    newYUV     = sliderDiff.z / roofDepth + bDetail.faceUv.y;
                    newHeight += sliderDiff.y;
                }
                bDetail.faceUv     = new Vector2(newXUV, newYUV);
                bDetail.faceHeight = newHeight;
            }
            break;

        case Tool.Rotate:
            currentRot           = Handles.RotationHandle(currentRot, handlePosition);
            bDetail.userRotation = currentRot.eulerAngles;
            break;

        case Tool.Scale:
            bDetail.scale = Handles.ScaleHandle(bDetail.scale, handlePosition, currentRot * faceRotation, handleSize * 0.666f);

            break;
        }

        //draw mesh bounds
        if (bDetail.mesh != null)
        {
            Bounds     meshBounds = bDetail.mesh.bounds;
            Quaternion rotation   = bDetail.worldRotation;
            Vector3    p0         = rotation * (new Vector3(meshBounds.min.x, meshBounds.min.y, meshBounds.min.z)) + bDetail.worldPosition;
            Vector3    p1         = rotation * (new Vector3(meshBounds.max.x, meshBounds.min.y, meshBounds.min.z)) + bDetail.worldPosition;
            Vector3    p2         = rotation * (new Vector3(meshBounds.min.x, meshBounds.min.y, meshBounds.max.z)) + bDetail.worldPosition;
            Vector3    p3         = rotation * (new Vector3(meshBounds.max.x, meshBounds.min.y, meshBounds.max.z)) + bDetail.worldPosition;
            Vector3    p4         = rotation * (new Vector3(meshBounds.min.x, meshBounds.max.y, meshBounds.min.z)) + bDetail.worldPosition;
            Vector3    p5         = rotation * (new Vector3(meshBounds.max.x, meshBounds.max.y, meshBounds.min.z)) + bDetail.worldPosition;
            Vector3    p6         = rotation * (new Vector3(meshBounds.min.x, meshBounds.max.y, meshBounds.max.z)) + bDetail.worldPosition;
            Vector3    p7         = rotation * (new Vector3(meshBounds.max.x, meshBounds.max.y, meshBounds.max.z)) + bDetail.worldPosition;

            Handles.color = BuildrColours.BLUE;
            Handles.DrawLine(p0, p1);
            Handles.DrawLine(p0, p2);
            Handles.DrawLine(p1, p3);
            Handles.DrawLine(p2, p3);
            Handles.DrawLine(p0, p4);
            Handles.DrawLine(p1, p5);
            Handles.DrawLine(p2, p6);
            Handles.DrawLine(p3, p7);
            Handles.DrawLine(p4, p5);
            Handles.DrawLine(p4, p6);
            Handles.DrawLine(p5, p7);
            Handles.DrawLine(p6, p7);

            if (clickPlace)
            {
                Vector3 planeBase   = Vector3.zero;
                Vector3 planeNormal = Vector3.up;
                Vector3 planeSize   = Vector3.zero;
                if (bDetail.type == BuildrDetail.Types.Facade)
                {
                    //find facade
                    int  facadeCount = 0;
                    bool facadeFound = false;
                    for (int s = 0; s < numberOfVolumes; s++)
                    {
                        BuildrVolume volume = plan.volumes[s];
                        int          numberOfVolumePoints = volume.points.Count;
                        for (int p = 0; p < numberOfVolumePoints; p++)
                        {
                            if (facadeCount == faceIndex)
                            {
                                int     indexA = p;
                                int     indexB = (p + 1) % numberOfVolumePoints;
                                Vector3 fp0    = plan.points[volume.points[indexA]].vector3;
                                Vector3 fp1    = plan.points[volume.points[indexB]].vector3;
                                planeBase   = fp0;
                                planeNormal = Vector3.Cross(Vector3.up, fp1 - fp0).normalized;
                                planeSize.x = Vector3.Distance(fp0, fp1);
                                planeSize.y = volume.numberOfFloors * data.floorHeight;
                                facadeFound = true;
                                break;
                            }
                            facadeCount++;
                        }
                        if (facadeFound)
                        {
                            break;
                        }
                    }
                }
                else
                {
                    BuildrVolume volume = plan.volumes[faceIndex];
                    int          numberOfVolumePoints = volume.points.Count;
                    Vector3      minPoint             = plan.points[volume.points[0]].vector3;
                    Vector3      maxPoint             = plan.points[volume.points[0]].vector3;
                    for (int p = 1; p < numberOfVolumePoints; p++)
                    {
                        Vector3 fp0 = plan.points[volume.points[p]].vector3;
                        if (fp0.x < minPoint.x)
                        {
                            minPoint.x = fp0.x;
                        }
                        if (fp0.z < minPoint.z)
                        {
                            minPoint.z = fp0.z;
                        }
                        if (fp0.x > maxPoint.x)
                        {
                            maxPoint.x = fp0.x;
                        }
                        if (fp0.z > maxPoint.z)
                        {
                            maxPoint.z = fp0.z;
                        }
                    }
                    planeSize.x = maxPoint.x - minPoint.x;
                    planeSize.z = maxPoint.z - minPoint.z;
                    planeBase   = minPoint;
                    planeBase.y = (data.floorHeight * volume.numberOfFloors);
                }
                float distance;
                Plane buildingPlane = new Plane(planeNormal, planeBase);
                Ray   ray           = Camera.current.ScreenPointToRay(new Vector3(Event.current.mousePosition.x, Screen.height - Event.current.mousePosition.y - 30, 0));
                if (buildingPlane.Raycast(ray, out distance))
                {
                    Vector3    mousePlanePoint    = ray.GetPoint(distance);
                    Quaternion mouseLookDirection = Quaternion.LookRotation(buildingPlane.normal);

                    if (Handles.Button(mousePlanePoint, mouseLookDirection, handleSize * 0.1f, handleSize * 0.1f, Handles.CircleCap))
                    {
                        float xUv, yUv;
                        if (bDetail.type == BuildrDetail.Types.Facade)
                        {
                            Vector3 facadeBaseMousePoint = new Vector3(mousePlanePoint.x, 0, mousePlanePoint.z);
                            xUv = Vector3.Distance(planeBase, facadeBaseMousePoint) / planeSize.x;
                            yUv = (mousePlanePoint.y - planeBase.y) / planeSize.y;
                        }
                        else
                        {
                            xUv = (mousePlanePoint.x - planeBase.x) / planeSize.x;
                            yUv = (mousePlanePoint.z - planeBase.z) / planeSize.z;
                        }
                        bDetail.faceUv = new Vector2(xUv, yUv);
                        clickPlace     = false;
                        GUI.changed    = true;
                    }
                }
            }
        }


        if (GUI.changed)
        {
            EditorUtility.SetDirty(editMode);
            EditorUtility.SetDirty(data);
            editMode.UpdateRender();
        }
    }
Beispiel #13
0
    public static void InspectorGUI(BuildrEditMode editMode, BuildrData data)
    {
        BuildrDetail[] details         = data.details.ToArray();
        int            numberOfDetails = details.Length;

        selectedDetail = Mathf.Clamp(selectedDetail, 0, numberOfDetails - 1);

        if (numberOfDetails == 0)
        {
            EditorGUILayout.HelpBox("There are no details to show", MessageType.Info);
            if (GUILayout.Button("Add New"))
            {
                data.details.Add(new BuildrDetail("new detail " + numberOfDetails));
                numberOfDetails++;
                selectedDetail = numberOfDetails - 1;
            }
            return;
        }

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Detail", GUILayout.Width(75));
        string[] detailNames = new string[numberOfDetails];
        for (int t = 0; t < numberOfDetails; t++)
        {
            detailNames[t] = details[t].name;
        }
        selectedDetail = EditorGUILayout.Popup(selectedDetail, detailNames);
        EditorGUILayout.EndHorizontal();

        BuildrDetail bDetail = details[selectedDetail];

        EditorGUILayout.BeginHorizontal();

        EditorGUILayout.Space();

        if (GUILayout.Button("Add New", GUILayout.Width(81)))
        {
            data.details.Add(new BuildrDetail("new detail " + numberOfDetails));
            numberOfDetails++;
            selectedDetail = numberOfDetails - 1;
        }


        if (GUILayout.Button("Duplicate", GUILayout.Width(90)))
        {
            data.details.Add(bDetail.Duplicate());
            numberOfDetails++;
            selectedDetail = numberOfDetails - 1;
        }

        if (GUILayout.Button("Delete", GUILayout.Width(71)))
        {
            if (EditorUtility.DisplayDialog("Deleting Building Detail Entry", "Are you sure you want to delete this detail?", "Delete", "Cancel"))
            {
                data.details.Remove(bDetail);
                selectedDetail = 0;
                GUI.changed    = true;

                return;
            }
        }
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.Space();

        details     = data.details.ToArray();
        detailNames = new string[numberOfDetails];
        for (int t = 0; t < numberOfDetails; t++)
        {
            detailNames[t] = details[t].name;
        }
        bDetail = details[selectedDetail];//reassign

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.BeginVertical();

        bDetail.name = EditorGUILayout.TextField("Name", bDetail.name);

        bDetail.mesh = (Mesh)EditorGUILayout.ObjectField("Mesh", bDetail.mesh, typeof(Mesh), false);
        EditorGUIUtility.LookLikeControls();
        bDetail.material.mainTexture = (Texture)EditorGUILayout.ObjectField("Texture", bDetail.material.mainTexture, typeof(Texture), false, GUILayout.Height(140));

        if (bDetail.material.mainTexture != null)
        {
            string          texturePath     = AssetDatabase.GetAssetPath(bDetail.material.mainTexture);
            TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(texturePath);

            if (!textureImporter.isReadable)
            {
                EditorGUILayout.HelpBox("The texture you have selected is not readable." +
                                        "\nPlease select the readable checkbox under advanced texture settings." +
                                        "\nOr move this texture to the BuildR texture folder and reimport.",
                                        MessageType.Error);
            }
        }

        BuildrPlan    plan                    = data.plan;
        int           numberOfVolumes         = plan.numberOfVolumes;
        int           numberOfFaces           = 0;
        List <int>    faceSeletionsList       = new List <int>();
        List <string> faceSeletionsStringList = new List <string>();

        if (bDetail.type == BuildrDetail.Types.Facade)
        {
            for (int s = 0; s < numberOfVolumes; s++)
            {
                int numberOfPoints = plan.volumes[s].Count;
                numberOfFaces += numberOfPoints;
                for (int p = 0; p < numberOfPoints; p++)
                {
                    int index = faceSeletionsList.Count;
                    faceSeletionsStringList.Add("facade " + index);
                    faceSeletionsList.Add(index);
                }
            }
        }
        else
        {
            bDetail.face = Mathf.Clamp(0, numberOfVolumes - 1, bDetail.face);
            for (int s = 0; s < numberOfVolumes; s++)
            {
                int index = faceSeletionsList.Count;
                faceSeletionsStringList.Add("roof " + index);
                faceSeletionsList.Add(index);
            }
        }

        if (!clickPlace)
        {
            if (GUILayout.Button("Place Detail with Mouse"))
            {
                clickPlace = true;
            }
        }
        else
        {
            if (GUILayout.Button("Cancel Place Detail"))
            {
                clickPlace = false;
            }
        }

        BuildrDetail.Types bDetailtype = (BuildrDetail.Types)EditorGUILayout.EnumPopup("Face Type", bDetail.type);
        if (bDetailtype != bDetail.type)
        {
            bDetail.type = bDetailtype;
        }
        int[]    faceSelections      = faceSeletionsList.ToArray();
        string[] faceSelectionString = faceSeletionsStringList.ToArray();
        int      bDetailface         = EditorGUILayout.IntPopup("Selected Face", bDetail.face, faceSelectionString, faceSelections);

        if (bDetailface != bDetail.face)
        {
            bDetail.face = bDetailface;
        }

        Vector2 bDetailfaceUv = EditorGUILayout.Vector2Field("Face UV", bDetail.faceUv);

        if (bDetailfaceUv != bDetail.faceUv)
        {
            bDetail.faceUv = bDetailfaceUv;
        }
        float bDetailfaceHeight = EditorGUILayout.FloatField("Face Height", bDetail.faceHeight);

        if (bDetailfaceHeight != bDetail.faceHeight)
        {
            bDetail.faceHeight = bDetailfaceHeight;
        }
        Vector3 bDetailuserRotation = EditorGUILayout.Vector3Field("Rotation", bDetail.userRotation);

        if (bDetailuserRotation != bDetail.userRotation)
        {
            bDetail.userRotation = bDetailuserRotation;
        }
        Vector3 bDetailscale = EditorGUILayout.Vector3Field("Object Scale", bDetail.scale);

        if (bDetailscale != bDetail.scale)
        {
            bDetail.scale = bDetailscale;
        }

        EditorGUILayout.EndVertical();
        EditorGUILayout.BeginVertical(GUILayout.Width(120));
        if (bDetail.mesh != null)
        {
            Texture2D previewMeshImage = AssetPreview.GetAssetPreview(bDetail.mesh);
            GUILayout.Label(previewMeshImage);
        }
        else
        {
            Texture2D previewMeshImage = new Texture2D(118, 118);
            GUILayout.Label(previewMeshImage);
            GUILayout.Label("No Mesh Selected");
        }

        if (bDetail.material.mainTexture != null)
        {
            Texture previewMeshImage = bDetail.material.mainTexture;
            GUILayout.Label(previewMeshImage, GUILayout.Width(128), GUILayout.Height(128));
        }
        else
        {
            Texture2D previewMeshImage = new Texture2D(118, 118);
            GUILayout.Label(previewMeshImage);
            GUILayout.Label("No Texture Selected");
        }
        EditorGUILayout.EndVertical();
        EditorGUILayout.EndHorizontal();
    }
Beispiel #14
0
    public static void InspectorGUI(BuildrEditMode editMode, BuildrData _data)
    {
        data = _data;
        Undo.RecordObject(data, "Roof Modified");

        BuildrRoofDesign[] roofs = data.roofs.ToArray();
        int numberOfRoofs        = roofs.Length;

        selectedRoof = Mathf.Clamp(selectedRoof, 0, numberOfRoofs - 1);

        if (GUILayout.Button("Add new roof design"))
        {
            data.roofs.Add(new BuildrRoofDesign("new roof " + numberOfRoofs));
            roofs = data.roofs.ToArray();
            numberOfRoofs++;
            selectedRoof = numberOfRoofs - 1;
        }
        if (numberOfRoofs == 0)
        {
            EditorGUILayout.HelpBox("There are no roof designs to show", MessageType.Info);
            return;
        }

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Design: ", GUILayout.Width(75));
        string[] roofNames = new string[numberOfRoofs];
        for (int f = 0; f < numberOfRoofs; f++)
        {
            roofNames[f] = roofs[f].name;
        }
        selectedRoof = EditorGUILayout.Popup(selectedRoof, roofNames);

        BuildrRoofDesign bRoof = roofs[selectedRoof];

        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        if (GUILayout.Button("Delete", GUILayout.Width(75)))
        {
            if (EditorUtility.DisplayDialog("Deleting Roof Design Entry", "Are you sure you want to delete this roof?", "Delete", "Cancel"))
            {
                data.RemoveRoofDesign(bRoof);
                selectedRoof = 0;
                GUI.changed  = true;

                return;
            }
        }

        if (GUILayout.Button("Import", GUILayout.Width(71)))
        {
            string xmlPath = EditorUtility.OpenFilePanel("Select the XML file...", "Assets/BuildR/Exported/", "xml");
            if (xmlPath == "")
            {
                return;
            }
            BuildrXMLImporter.ImportRoofs(xmlPath, _data);
            GUI.changed = true;
        }

        if (GUILayout.Button("Export", GUILayout.Width(71)))
        {
            string xmlPath = EditorUtility.SaveFilePanel("Export as...", "Assets/BuildR/Exported/", _data.name + "_roofLibrary", "xml");
            if (xmlPath == "")
            {
                return;
            }
            BuildrXMLExporter.ExportRoofs(xmlPath, _data);
            GUI.changed = true;
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Name: ", GUILayout.Width(75));
        bRoof.name = EditorGUILayout.TextField(bRoof.name);
        EditorGUILayout.EndHorizontal();

        //ROOF STYLE
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Style: ", GUILayout.Width(75));
        BuildrRoofDesign.styles bRoofstyle = (BuildrRoofDesign.styles)EditorGUILayout.EnumPopup(bRoof.style);
        if (bRoofstyle != bRoof.style)
        {
            bRoof.style = bRoofstyle;
        }
        EditorGUILayout.EndHorizontal();

        if (bRoof.style != BuildrRoofDesign.styles.flat && bRoof.style != BuildrRoofDesign.styles.mansard && bRoof.style != BuildrRoofDesign.styles.steepled && bRoof.style != BuildrRoofDesign.styles.hipped)
        {
            EditorGUILayout.HelpBox("Please note that this design can only be used on sections with 4 points." +
                                    "\nComplex sections can only use the Flat, Mansard and Steeple designs.", MessageType.Warning);
        }

        if (bRoof.style != BuildrRoofDesign.styles.flat)
        {
            bRoof.height = Mathf.Max(EditorGUILayout.FloatField("Height", bRoof.height), 0);
        }

        if (bRoof.style == BuildrRoofDesign.styles.mansard)
        {
            bRoof.floorDepth = Mathf.Max(EditorGUILayout.FloatField("Base Depth", bRoof.floorDepth), 0);
            bRoof.depth      = Mathf.Max(EditorGUILayout.FloatField("Top Depth", bRoof.depth), 0);
        }

        if (bRoof.style == BuildrRoofDesign.styles.barrel)
        {
            bRoof.barrelSegments = Mathf.Max(EditorGUILayout.IntField("Barrel Segments", bRoof.barrelSegments), 3);
        }

        if (bRoof.style == BuildrRoofDesign.styles.barrel || bRoof.style == BuildrRoofDesign.styles.gabled || bRoof.style == BuildrRoofDesign.styles.hipped)
        {
            //two directions of the ridge
            bRoof.direction = Mathf.Clamp(bRoof.direction, 0, 1);
            string[] options = new string[2] {
                "short", "long"
            };
            bRoof.direction = EditorGUILayout.Popup(bRoof.direction, options);
        }

        if (bRoof.style == BuildrRoofDesign.styles.leanto || bRoof.style == BuildrRoofDesign.styles.sawtooth)
        {
            //four directions of the ridge
            bRoof.direction = Mathf.Clamp(bRoof.direction, 0, 3);
            string[] options = new string[4] {
                "left", "up", "right", "down"
            };
            bRoof.direction = EditorGUILayout.Popup(bRoof.direction, options);
        }

        if (bRoof.style == BuildrRoofDesign.styles.sawtooth)
        {
            bRoof.sawtoothTeeth = Mathf.Max(EditorGUILayout.IntField("Number of 'teeth'", bRoof.sawtoothTeeth), 2);
        }

        //PARAPET
        bool bRoofparapet = EditorGUILayout.Toggle("Has Parapet", bRoof.parapet);

        if (bRoofparapet != bRoof.parapet)
        {
            bRoof.parapet = bRoofparapet;
        }
        if (bRoof.parapet)
        {
            float bRoofparapetHeight = Mathf.Max(EditorGUILayout.FloatField("Parapet Width", bRoof.parapetHeight), 0);
            if (bRoofparapetHeight != bRoof.parapetHeight)
            {
                bRoof.parapetHeight = bRoofparapetHeight;
            }
            float bRoofparapetFrontDepth = Mathf.Max(EditorGUILayout.FloatField("Parapet Front Depth", bRoof.parapetFrontDepth), 0);
            if (bRoofparapetFrontDepth != bRoof.parapetFrontDepth)
            {
                bRoof.parapetFrontDepth = bRoofparapetFrontDepth;
            }
            float bRoofparapetBackDepth = Mathf.Max(EditorGUILayout.FloatField("Parapet Back Depth", bRoof.parapetBackDepth), 0);
            if (bRoofparapetBackDepth != bRoof.parapetBackDepth)
            {
                bRoof.parapetBackDepth = bRoofparapetBackDepth;
            }

            if (bRoof.parapetStyle == BuildrRoofDesign.parapetStyles.fancy)//NOT IMPLMENTED...YET...
            {
                EditorGUILayout.HelpBox("This allows you to specify a model mesh that will be used to create a parapet." +
                                        "\nIt should not repeat as Buildr will attempt to repeat the style to fit the length of the facade.", MessageType.Info);
                bRoof.parapetDesign      = (Mesh)EditorGUILayout.ObjectField("Parapet Mesh", bRoof.parapetDesign, typeof(Mesh), false);
                bRoof.parapetDesignWidth = Mathf.Max(EditorGUILayout.FloatField("Parapet Design Width", bRoof.parapetDesignWidth), 0);
            }
        }

        //DORMERS
        if (bRoof.style == BuildrRoofDesign.styles.mansard)
        {
            bool bRoofhasDormers = EditorGUILayout.Toggle("Has Dormers", bRoof.hasDormers);
            if (bRoofhasDormers != bRoof.hasDormers)
            {
                bRoof.hasDormers = bRoofhasDormers;
            }
            if (bRoof.hasDormers)
            {
                float bRoofdormerWidth = Mathf.Max(EditorGUILayout.FloatField("Dormer Width", bRoof.dormerWidth), 0);
                if (bRoofdormerWidth != bRoof.dormerWidth)
                {
                    bRoof.dormerWidth = bRoofdormerWidth;
                }
                float bRoofdormerHeight = Mathf.Clamp(EditorGUILayout.FloatField("Dormer Height", bRoof.dormerHeight), 0, bRoof.height);
                if (bRoofdormerHeight != bRoof.dormerHeight)
                {
                    bRoof.dormerHeight = bRoofdormerHeight;
                }
                float bRoofdormerRoofHeight = Mathf.Clamp(EditorGUILayout.FloatField("Dormer Roof Height", bRoof.dormerRoofHeight), 0, bRoof.dormerHeight);
                if (bRoofdormerRoofHeight != bRoof.dormerRoofHeight)
                {
                    bRoof.dormerRoofHeight = bRoofdormerRoofHeight;
                }
                float bRoofminimumDormerSpacing = Mathf.Max(EditorGUILayout.FloatField("Dormer Minimum Spacing", bRoof.minimumDormerSpacing), 0);
                if (bRoofminimumDormerSpacing != bRoof.minimumDormerSpacing)
                {
                    bRoof.minimumDormerSpacing = bRoofminimumDormerSpacing;
                }
                float bRoofdormerHeightRatio = EditorGUILayout.Slider("Dormer Height Ratio", bRoof.dormerHeightRatio, 0, 1);
                if (bRoofdormerHeightRatio != bRoof.dormerHeightRatio)
                {
                    bRoof.dormerHeightRatio = bRoofdormerHeightRatio;
                }
            }
        }

        //TEXTURES
        int numberOfTextures = data.textures.Count;

        string[] textureNames = new string[numberOfTextures];
        for (int t = 0; t < numberOfTextures; t++)
        {
            textureNames[t] = data.textures[t].name;
        }

        int numberOfTextureSlots = bRoof.numberOfTextures;

        string[] titles = new string[numberOfTextureSlots];
        for (int brt = 0; brt < numberOfTextureSlots; brt++)
        {
            titles[brt] = ((BuildrRoofDesign.textureNames)(brt)).ToString();
        }

        editTextureOnRoof = EditorGUILayout.Popup("Texture Surface:", editTextureOnRoof, titles);

        int selectedRoofTexture = EditorGUILayout.Popup("Selected Texture:", bRoof.textureValues[editTextureOnRoof], textureNames);

        if (selectedRoofTexture != bRoof.textureValues[editTextureOnRoof])
        {
            bRoof.textureValues[editTextureOnRoof] = selectedRoofTexture;
        }
        BuildrTexture bTexture = data.textures[bRoof.textureValues[editTextureOnRoof]];
        Texture2D     texture  = bTexture.texture;

        EditorGUILayout.BeginHorizontal();

        if (texture != null)
        {
            GUILayout.Label(texture, GUILayout.Width(100), GUILayout.Height(100));
        }
        else
        {
            EditorGUILayout.HelpBox("No texture assigned for '" + textureNames[bRoof.textureValues[editTextureOnRoof]] + "', assign one in the Textures menu above", MessageType.Warning);
        }

        bRoof.flipValues[editTextureOnRoof] = EditorGUILayout.Toggle("Flip 90\u00B0", bRoof.flipValues[editTextureOnRoof]);

        EditorGUILayout.EndHorizontal();
    }
    public static void InspectorGUI(BuildrEditMode editMode, BuildrPlan plan)
    {
        EditorGUILayout.Space();

        Undo.RecordObject(plan, "Floorplan Modified");

        editMode.showDimensionLines = EditorGUILayout.Toggle("Show Wall Dimensions", editMode.showDimensionLines);
        if (editMode.mode != BuildrEditMode.modes.floorplan)
        {
            EditorGUILayout.LabelField("Current Mode: " + editMode.mode.ToString());
            if (GUILayout.Button("Cancel"))
            {
                editMode.SetMode(BuildrEditMode.modes.floorplan);
                UpdateGUI();
            }
        }

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Snap to Grid", GUILayout.Width(100));
        bool editModesnapFloorplanToGrid = EditorGUILayout.Toggle(editMode.snapFloorplanToGrid);
        if(editModesnapFloorplanToGrid != editMode.snapFloorplanToGrid)
        {
            //Snapping modified
            editMode.snapFloorplanToGrid = editModesnapFloorplanToGrid;
            if(editModesnapFloorplanToGrid)
            {
                int numberOfPoints = plan.points.Count;
                for (int i = 0; i < numberOfPoints; i++)
                {
                    Vector2z point = plan.points[i];
                    Vector3 snappedPoint = point.vector3;
                    snappedPoint.x -= snappedPoint.x % editMode.floorplanGridSize;
                    snappedPoint.z -= snappedPoint.z % editMode.floorplanGridSize;
                    point.vector3 = snappedPoint;
                }
            }
        }
        EditorGUI.BeginDisabledGroup(!editMode.snapFloorplanToGrid);
        EditorGUILayout.LabelField("Grid Size", GUILayout.Width(100));
        editMode.floorplanGridSize = EditorGUILayout.FloatField(editMode.floorplanGridSize);
        EditorGUILayout.LabelField("metres", GUILayout.Width(60));
        EditorGUI.EndDisabledGroup();
        EditorGUILayout.EndHorizontal();

        if(GUILayout.Button("Recenter Floorplan to Origin"))
        {
            Vector3 currentCenter = Vector3.zero;
            int numberOfPoints = plan.points.Count;
            for (int i = 0; i < numberOfPoints; i++)
                currentCenter += plan.points[i].vector3;
            currentCenter *= (1.0f / numberOfPoints);
            for (int i = 0; i < numberOfPoints; i++)
                plan.points[i].vector3 += -currentCenter;
            int numberOfCores = plan.cores.Count;
            for(int i = 0; i < numberOfCores; i++)
            {
                Rect core = plan.cores[i];
                plan.cores[i] = new Rect(core.xMin - currentCenter.x, core.yMin - currentCenter.z, core.width, core.height);
            }
        }

        if (GUILayout.Button("Recenter Origin to Floorplan"))
        {
            Vector3 currentCenter = Vector3.zero;
            int numberOfPoints = plan.points.Count;
            for (int i = 0; i < numberOfPoints; i++)
                currentCenter += plan.points[i].vector3;
            currentCenter *= (1.0f / numberOfPoints);
            for (int i = 0; i < numberOfPoints; i++)
                plan.points[i].vector3 += -currentCenter;
            int numberOfCores = plan.cores.Count;
            for (int i = 0; i < numberOfCores; i++)
            {
                Rect core = plan.cores[i];
                plan.cores[i] = new Rect(core.xMin - currentCenter.x, core.yMin - currentCenter.z, core.width, core.height);
            }
            editMode.transform.position += currentCenter;
        }

        EditorGUILayout.LabelField("New Volume Plans");
        if (GUILayout.Button("Add New Volume Square"))
        {
            editMode.SetMode(BuildrEditMode.modes.addNewVolume);
            UpdateGUI();
        }

        if (GUILayout.Button("Add New Volume By Drawing Rectangle"))
        {
            editMode.SetMode(BuildrEditMode.modes.addNewVolumeByDraw);
            UpdateGUI();
        }

        if (GUILayout.Button("Add New Volume By Drawing Points"))
        {
            editMode.SetMode(BuildrEditMode.modes.addNewVolumeByPoints);
            UpdateGUI();
        }

        if (GUILayout.Button("Add New Volume By Extending Wall"))
        {
            editMode.SetMode(BuildrEditMode.modes.addVolumeByWall);
            UpdateGUI();
        }

        if (GUILayout.Button("Merge Volumes"))
        {
            editMode.SetMode(BuildrEditMode.modes.mergeVolumes);
            UpdateGUI();
        }

        if (GUILayout.Button("Split Volumes"))
        {
            editMode.SetMode(BuildrEditMode.modes.splitVolume);
            UpdateGUI();
        }

        if (GUILayout.Button("Remove Volume"))
        {
            editMode.SetMode(BuildrEditMode.modes.removeVolume);
            UpdateGUI();
        }

        EditorGUILayout.LabelField("Volume Plan Modification");
        if (GUILayout.Button("Split Wall"))
        {
            editMode.SetMode(BuildrEditMode.modes.splitwall);
            UpdateGUI();
        }

        if (GUILayout.Button("Add Point To Volume"))
        {
            editMode.SetMode(BuildrEditMode.modes.addPointToVolume);
            UpdateGUI();
        }

        if (GUILayout.Button("Remove Wall Point"))
        {
            editMode.SetMode(BuildrEditMode.modes.removewall);
            UpdateGUI();
        }

        if (GUILayout.Button("Extrude Wall"))
        {
            editMode.SetMode(BuildrEditMode.modes.extrudewallselect);
            UpdateGUI();
        }

        EditorGUILayout.LabelField("Core Modification");
        if (GUILayout.Button("Add Building Core"))
        {
            editMode.SetMode(BuildrEditMode.modes.addNewCore);
            UpdateGUI();
        }

        if (GUILayout.Button("Remove Building Core"))
        {
            editMode.SetMode(BuildrEditMode.modes.removeCore);
            UpdateGUI();
        }
    }
    public static void SceneGUI(BuildrEditMode editMode, BuildrPlan plan, bool shouldSnap, float handleSize)
    {
        Vector3 position = editMode.transform.position;
        Plane buildingPlane = new Plane(Vector3.up, position);
        float distance;
        Vector3 mousePlanePoint = Vector3.zero;
        Camera sceneCamera = Camera.current;
        Ray ray = sceneCamera.ScreenPointToRay(new Vector3(Event.current.mousePosition.x, Screen.height - Event.current.mousePosition.y - 30, 0));
        if (buildingPlane.Raycast(ray, out distance))
        {
            mousePlanePoint = ray.GetPoint(distance);
        }
        Quaternion mouseLookDirection = Quaternion.LookRotation(-ray.direction);

        //Draw the floorplan outline
        int numberOfVolumes = plan.numberOfVolumes;
        for (int s = 0; s < numberOfVolumes; s++)
        {
            BuildrVolume volumeLinks = plan.volumes[s];
            int volumeSize = volumeLinks.Count;

            for (int l = 0; l < volumeSize; l++)
            {
                Handles.color = Color.white;
                Vector3[] wallPositions = plan.GetWallVectors(s, l);
                Handles.DrawLine(wallPositions[0] + position, wallPositions[1] + position);
            }
        }

        //draw outlines of building cores
        int numberOfCores = plan.cores.Count;
        for(int c = 0; c < numberOfCores; c++)
        {
            Rect coreOutline = plan.cores[c];
            Vector3 coreCenter = new Vector3(coreOutline.center.x,0,coreOutline.center.y);
            Handles.Label(coreCenter + position, "Core " + (c + 1));
            Vector3 coreBL = new Vector3(coreOutline.xMin,0, coreOutline.yMin) + position;
            Vector3 coreBR = new Vector3(coreOutline.xMax,0, coreOutline.yMin) + position;
            Vector3 coreTL = new Vector3(coreOutline.xMin,0, coreOutline.yMax) + position;
            Vector3 coreTR = new Vector3(coreOutline.xMax,0, coreOutline.yMax) + position;
            Handles.DrawLine(coreBL,coreBR);
            Handles.DrawLine(coreBR,coreTR);
            Handles.DrawLine(coreTR,coreTL);
            Handles.DrawLine(coreTL,coreBL);
        }

        //Draw red lines over illegal point/lines
        int numberOfIllegalPoints = plan.numberOfIllegalPoints;
        if (numberOfIllegalPoints > 0)
        {
            Handles.color = Color.red;
            Vector2z[] illegalPoints = plan.illegalPoints;
            for (int i = 0; i < numberOfIllegalPoints - 1; i += 2)
            {
                Vector3 a, b;
                a = illegalPoints[i].vector3 + position;
                b = illegalPoints[i + 1].vector3 + position;
                Handles.DrawLine(a, b);
            }
        }

        SceneView.focusedWindow.wantsMouseMove = false;
        Vector3 vertA;
        Vector3 vertB;
        int selectedPoint;
        switch (editMode.mode)
        {

            case BuildrEditMode.modes.floorplan:
                Vector3 sliderPos = Vector3.zero;
                int numberOfPoints = plan.points.Count;
                int numberOfSelectedPoints = editMode.selectedPoints.Count;

                //Per point scene gui
                for (int i = 0; i < numberOfPoints; i++)
                {
                    Vector2z point = plan.points[i];
                    Vector3 pointPos = point.vector3 + position;
                    float pointHandleSize = HandleUtility.GetHandleSize(pointPos);
                    bool selected = editMode.selectedPoints.Contains(i);
                    if (selected)
                    {
                        Handles.color = Color.green;
                        //Handles.Label(pointPos, "point "+i);
                        sliderPos += point.vector3;
                        if (Handles.Button(pointPos, Quaternion.identity, pointHandleSize * 0.1f, pointHandleSize * 0.1f, Handles.DotCap))
                        {
                            editMode.selectedPoints.Remove(i);
                        }

                    }
                    else
                    {
                        Handles.color = Color.white;
                        if (Handles.Button(pointPos, Quaternion.identity, pointHandleSize * 0.05f, pointHandleSize * 0.05f, Handles.DotCap))
                        {
                            if (!shouldSnap)
                                editMode.selectedPoints.Clear();
                            editMode.selectedPoints.Add(i);
                        }
                    }

                    float pointDot = Vector3.Dot(sceneCamera.transform.forward, pointPos - sceneCamera.transform.position);
                    if(pointDot > 0.0f)
                    {
                        Handles.color = Color.white;
                        GUIStyle pointLabelStyle = new GUIStyle();
                        pointLabelStyle.normal.textColor = Color.white;
                        pointLabelStyle.fontStyle = FontStyle.Bold;
                        pointLabelStyle.alignment = TextAnchor.MiddleCenter;
                        pointLabelStyle.fixedWidth = 50.0f;
                        Handles.Label(pointPos + Vector3.up * 2, "point " + i, pointLabelStyle);
                    }
                }

                //draw plan dimensions
                if (editMode.showDimensionLines)
                {
                    Handles.color = Color.white;
                    for (int v = 0; v < numberOfVolumes; v++)
                    {
                        BuildrVolume volume = plan.volumes[v];
                        int volumeSize = volume.Count;
                        for (int l = 0; l < volumeSize; l++)
                        {
                            if (plan.GetConnectingVolumeIndex(v, volume.points[l], volume.points[(l + 1) % volumeSize]) != -1)
                                continue;
                            vertA = plan.points[volume.points[l]].vector3 + position;
                            vertB = plan.points[volume.points[(l + 1) % volumeSize]].vector3 + position;
                            float wallWidth = Vector3.Distance(vertA, vertB);
                            Vector3 facadeDirection = Vector3.Cross((vertA - vertB), Vector3.up).normalized;
                            Vector3 labelPos = (vertA + vertB) * 0.5f + facadeDirection;
                            GUIStyle widthStyle = new GUIStyle();
                            widthStyle.normal.textColor = Color.white;
                            widthStyle.alignment = TextAnchor.MiddleCenter;
                            widthStyle.fixedWidth = 50.0f;
                            Handles.Label(labelPos, wallWidth.ToString("F2") + "m", widthStyle);
                            if (wallWidth > 3)//draw guidelines
                            {
                                float gapSpace = (HandleUtility.GetHandleSize(labelPos) * 0.5f) / wallWidth;
                                Vector3 lineStopA = Vector3.Lerp(vertA, vertB, (0.5f - gapSpace)) + facadeDirection;
                                Vector3 lineStopB = Vector3.Lerp(vertA, vertB, (0.5f + gapSpace)) + facadeDirection;
                                Handles.DrawLine(vertA + facadeDirection, lineStopA);
                                Handles.DrawLine(vertA + facadeDirection, vertA);
                                Handles.DrawLine(vertB + facadeDirection, lineStopB);
                                Handles.DrawLine(vertB + facadeDirection, vertB);
                            }
                        }
                    }
                }

                //selected point scene gui
                if (numberOfSelectedPoints > 0)
                {
        //                    Undo.SetSnapshotTarget(plan, "Floorplan Node Moved");
                    sliderPos /= numberOfSelectedPoints;
                    Vector3 dirX = (sliderPos.x < 0) ? Vector3.right : Vector3.left;
                    Vector3 dirZ = (sliderPos.z < 0) ? Vector3.forward : Vector3.back;
                    sliderPos += position;
                    Vector3 newSliderPos;
                    Handles.color = Color.red;
                    newSliderPos = Handles.Slider(sliderPos, dirX, HandleUtility.GetHandleSize(sliderPos) * 0.666f, Handles.ArrowCap, 0.0f);
                    Handles.color = Color.blue;
                    newSliderPos = Handles.Slider(newSliderPos, dirZ, HandleUtility.GetHandleSize(newSliderPos) * 0.666f, Handles.ArrowCap, 0.0f);

                    Vector3 sliderDiff = newSliderPos - sliderPos;

                    for (int i = 0; i < numberOfPoints; i++)
                    {
                        if (editMode.selectedPoints.Contains(i))
                        {
                            if(sliderDiff != Vector3.zero)
                            {
                                Vector2z point = plan.points[i];
                                point.vector3 += sliderDiff;

                                if(editMode.snapFloorplanToGrid)
                                {
                                    Vector3 snappedPoint = point.vector3;
                                    snappedPoint.x -= snappedPoint.x % editMode.floorplanGridSize;
                                    snappedPoint.z -= snappedPoint.z % editMode.floorplanGridSize;
                                    point.vector3 = snappedPoint;
                                }
                            }
                        }
                    }
                }

                //core gui
                for(int c = 0; c < numberOfCores; c++)
                {
        //                    Undo.SetSnapshotTarget(plan, "Core Node Moved");
                    Rect coreOutline = plan.cores[c];

                    Vector3 coreLeft = new Vector3(coreOutline.xMin, 0, (coreOutline.yMin + coreOutline.yMax)/2);
                    Vector3 coreRight = new Vector3(coreOutline.xMax, 0, (coreOutline.yMin + coreOutline.yMax)/2);
                    Vector3 coreBottom = new Vector3((coreOutline.xMin + coreOutline.xMax) / 2, 0, coreOutline.yMin);
                    Vector3 coreTop = new Vector3((coreOutline.xMin + coreOutline.xMax) / 2, 0, coreOutline.yMax);

                    Vector3 newCoreLeft = Handles.Slider(coreLeft + position, Vector3.left, HandleUtility.GetHandleSize(coreLeft) * 0.666f, Handles.ArrowCap, 0.0f);
                    Vector3 newCoreRight = Handles.Slider(coreRight + position, Vector3.right, HandleUtility.GetHandleSize(coreLeft) * 0.666f, Handles.ArrowCap, 0.0f);
                    Vector3 newCoreBottom = Handles.Slider(coreBottom + position, Vector3.back, HandleUtility.GetHandleSize(coreLeft) * 0.666f, Handles.ArrowCap, 0.0f);
                    Vector3 newCoreTop = Handles.Slider(coreTop + position, Vector3.forward, HandleUtility.GetHandleSize(coreLeft) * 0.666f, Handles.ArrowCap, 0.0f);

                    newCoreLeft -= position;
                    newCoreRight -= position;
                    newCoreBottom -= position;
                    newCoreTop -= position;

                    if (coreLeft != newCoreLeft)
                        coreOutline.xMin = Mathf.Min(newCoreLeft.x, coreOutline.xMax - 1.0f);
                    if (coreRight != newCoreRight)
                        coreOutline.xMax = Mathf.Max(newCoreRight.x, coreOutline.xMin + 1.0f);
                    if (coreBottom != newCoreBottom)
                        coreOutline.yMin = Mathf.Min(newCoreBottom.z, coreOutline.yMax - 1.0f);
                    if (coreTop != newCoreTop)
                        coreOutline.yMax = Mathf.Max(newCoreTop.z, coreOutline.yMin + 1.0f);

                    plan.cores[c] = coreOutline;
                }

                break;

            case BuildrEditMode.modes.addNewVolume:
                Vector3 basePoint = mousePlanePoint;
                Vector3 width = Vector3.right * 10;
                Vector3 height = Vector3.forward * 10;
                Vector3[] verts = new Vector3[4] { basePoint - width - height, basePoint + width - height, basePoint + width + height, basePoint + height - width };

                Handles.DrawSolidRectangleWithOutline(verts, new Color(0.2f, 0.4f, 0.9f, 0.5f), new Color(0.1f, 0.2f, 1.0f, 0.85f));
                Handles.Label(mousePlanePoint, "Click to place a new volume");
                if (Handles.Button(basePoint, Quaternion.identity, 0, 10, Handles.CircleCap))
                {
        //                    Undo.RegisterUndo(plan.GetUndoObjects(), "Add new volume");
                    plan.AddVolume(verts, -position);
                    editMode.SetMode(BuildrEditMode.modes.floorplan);
                    EditorUtility.SetDirty(plan);
                }

                break;

            case BuildrEditMode.modes.addNewVolumeByDraw:

                if (editMode.startVolumeDraw == Vector3.zero)
                {
                    Handles.Label(mousePlanePoint, "Click to select the start point of this volume");
                    if (Handles.Button(mousePlanePoint, Quaternion.identity, handleSize * 0.1f, handleSize * 0.1f, Handles.CircleCap))
                    {
                        editMode.startVolumeDraw = mousePlanePoint;
                    }
                }
                else
                {
                    Vector3 baseDrawPoint = editMode.startVolumeDraw;
                    Vector3 finishDrawPoint = mousePlanePoint;
                    Vector3[] drawVerts = new Vector3[4];
                    drawVerts[0] = new Vector3(baseDrawPoint.x, 0, baseDrawPoint.z);
                    drawVerts[1] = new Vector3(finishDrawPoint.x, 0, baseDrawPoint.z);
                    drawVerts[2] = new Vector3(finishDrawPoint.x, 0, finishDrawPoint.z);
                    drawVerts[3] = new Vector3(baseDrawPoint.x, 0, finishDrawPoint.z);

                    Handles.DrawSolidRectangleWithOutline(drawVerts, new Color(0.2f, 0.4f, 0.9f, 0.5f), new Color(0.1f, 0.2f, 1.0f, 0.85f));
                    Handles.Label(mousePlanePoint, "Click to finish and add a new volume");
                    if (Handles.Button(mousePlanePoint, Quaternion.identity, 0, 10, Handles.CircleCap))
                    {
        //                        Undo.RegisterUndo(plan.GetUndoObjects(), "Add new volume");
                        plan.AddVolume(drawVerts, -position);
                        editMode.SetMode(BuildrEditMode.modes.floorplan);
                        EditorUtility.SetDirty(plan);
                    }
                }
                break;

            case BuildrEditMode.modes.addNewVolumeByPoints:

                int numberOfDrawnPoints = editMode.volumeDrawPoints.Count;
                bool allowNewPoint = true;
                for (int p = 0; p < numberOfDrawnPoints; p++)
                {
                    Vector3 point = editMode.volumeDrawPoints[p];
                    if (p == 0 && Vector3.Distance(point, mousePlanePoint) < 3 && numberOfDrawnPoints >= 3)
                    {
                        allowNewPoint = false;//hovering over the first point - don't add a new point - ready to complete the volume plan
                        Handles.color = Color.green;
                    }
                    Vector3 lookDirection = -(point - Camera.current.transform.position);

                    int p2 = (p + 1) % numberOfDrawnPoints;
                    if (p < numberOfDrawnPoints - 1 || !allowNewPoint)//don't draw last line
                        Handles.DrawLine(point, editMode.volumeDrawPoints[p2]);
                    float pointhandleSize = HandleUtility.GetHandleSize(point);
                    if (Handles.Button(point, Quaternion.LookRotation(lookDirection), pointhandleSize * 0.1f, pointhandleSize * 0.1f, Handles.DotCap))
                    {
                        if (p == 0 && numberOfDrawnPoints >= 3)
                        {
                            plan.AddVolume(editMode.volumeDrawPoints.ToArray(), -position);
                            editMode.SetMode(BuildrEditMode.modes.floorplan);
                            EditorUtility.SetDirty(plan);
                            GUI.changed = true;
                            return;
                        }
                    }
                }

                if (allowNewPoint)
                {

                    bool isLegal = true;
                    if (numberOfDrawnPoints >= 1)
                    {
                        Vector2z newPoint = new Vector2z(mousePlanePoint);
                        Vector2z lastPoint = new Vector2z(editMode.volumeDrawPoints[numberOfDrawnPoints - 1]);
                        for (int op = 0; op < numberOfDrawnPoints - 1; op++)//don't do the final line
                        {
                            int op2 = (op + 1) % numberOfDrawnPoints;

                            if (BuildrUtils.FastLineIntersection(newPoint, lastPoint, new Vector2z(editMode.volumeDrawPoints[op]), new Vector2z(editMode.volumeDrawPoints[op2])))
                                isLegal = false;
                        }
                        for (int v = 0; v < numberOfVolumes; v++)
                        {
                            BuildrVolume volume = plan.volumes[v];
                            int volumeSize = volume.Count;
                            for (int l = 0; l < volumeSize; l++)
                            {
                                int vp1 = l;
                                int vp2 = (l + 1) % volumeSize;

                                Vector2z v2zPos = new Vector2z(position);
                                Vector2z p1 = newPoint - v2zPos;
                                Vector2z p2 = lastPoint - v2zPos;
                                Vector2z p3 = plan.points[volume.points[vp1]];
                                Vector2z p4 = plan.points[volume.points[vp2]];

                                if (BuildrUtils.FastLineIntersection(p1, p2, p3, p4))
                                    isLegal = false;
                            }
                        }

                        Handles.Label(mousePlanePoint, "Click to add another point to the volume wall");

                        if (!isLegal)
                            Handles.color = Color.red;

                        Handles.DrawLine(lastPoint.vector3, newPoint.vector3);
                    }
                    else
                    {
                        Handles.Label(mousePlanePoint, "Click to add the first point in this volume wall");
                    }

                    Handles.color = Color.white;
                    if (Handles.Button(mousePlanePoint, mouseLookDirection, 0, 10, Handles.CircleCap))
                    {
                        if (isLegal)
                        {
        //                            Undo.RegisterUndo(plan.GetUndoObjects(), "Add new wall line for new volume");
                            editMode.volumeDrawPoints.Add(mousePlanePoint);
                            EditorUtility.SetDirty(plan);
                        }
                        else
                        {
                            EditorUtility.DisplayDialog("Error", "Wall lines cannot intersect other wall lines", "ok, sorry");
                        }
                    }
                }
                else
                {
                    Handles.Label(mousePlanePoint, "Click to complete the volume wall plan");
                }

                break;

            case BuildrEditMode.modes.removeVolume:

                for (int v = 0; v < numberOfVolumes; v++)
                {
                    BuildrVolume volume = plan.volumes[v];
                    int volumeSize = volume.Count;
                    Vector3 centerPoint = Vector3.zero;
                    for (int l = 0; l < volumeSize; l++)
                    {
                        centerPoint += plan.points[volume.points[l]].vector3;
                    }
                    centerPoint /= volumeSize;
                    centerPoint += position;

                    Handles.color = Color.red;
                    float centerPointHandleSize = HandleUtility.GetHandleSize(centerPoint);
                    if (Handles.Button(centerPoint, Quaternion.identity, centerPointHandleSize * 0.1f, centerPointHandleSize * 0.1f, Handles.DotCap))
                    {
        //                        Undo.RegisterUndo(plan.GetUndoObjects(), "Remove volume");
        //                        Undo.RegisterSceneUndo("Remove Volume");
                        plan.RemoveVolume(volume);
                        numberOfVolumes--;
                        v--;
                        editMode.SetMode(BuildrEditMode.modes.floorplan);
                        EditorUtility.SetDirty(plan);
                    }
                }

                break;

            case BuildrEditMode.modes.mergeVolumes:

                List<int> usedPointsA = new List<int>();
                List<int> usedPointsB = new List<int>();
                for (int v = 0; v < numberOfVolumes; v++)
                {
                    BuildrVolume volume = plan.volumes[v];
                    int volumeSize = volume.Count;
                    for (int p = 0; p < volumeSize; p++)
                    {
                        int a = volume.points[p];
                        int b = volume.points[(p + 1) % volumeSize];

                        bool alreadyDrawn = false;
                        foreach (int pa in usedPointsA)
                        {
                            if (pa == a || pa == b)
                            {
                                int pb = usedPointsB[usedPointsA.IndexOf(pa)];
                                if (pb == a || pb == b)
                                {
                                    alreadyDrawn = true;
                                    break;
                                }
                            }
                        }

                        if (!alreadyDrawn)
                        {

                            usedPointsA.Add(a);
                            usedPointsA.Add(b);
                            usedPointsB.Add(b);
                            usedPointsB.Add(a);

                            int otherV = plan.GetConnectingVolumeIndex(v, a, b);
                            if (otherV == -1)
                                continue;//it's not connected to another volume

                            vertA = plan.points[a].vector3 + position;
                            vertB = plan.points[b].vector3 + position;
                            Vector3 diff = vertA - vertB;
                            Vector3 facadeDirection = Vector3.Cross(diff, Vector3.up).normalized;
                            Vector3 midPoint = Vector3.Lerp(vertA, vertB, 0.5f);

                            float mergeHandleSize = HandleUtility.GetHandleSize(midPoint) * 0.1f;
                            Vector3 outPointA = midPoint + (facadeDirection * mergeHandleSize * 6);
                            Vector3 outPointB = midPoint - (facadeDirection * mergeHandleSize * 6);
                            Handles.ArrowCap(0, outPointA, Quaternion.LookRotation(-facadeDirection), mergeHandleSize * 4);
                            Handles.ArrowCap(0, outPointB, Quaternion.LookRotation(facadeDirection), mergeHandleSize * 4);

                            GUIStyle pointLabelStyle = new GUIStyle();
                            pointLabelStyle.normal.textColor = Color.white;
                            pointLabelStyle.fontStyle = FontStyle.Bold;
                            pointLabelStyle.alignment = TextAnchor.MiddleCenter;
                            pointLabelStyle.fixedWidth = 50.0f;
                            Handles.Label(midPoint + Vector3.up * mergeHandleSize * 3, "Merge", pointLabelStyle);

                            if (Handles.Button(midPoint, Quaternion.identity, mergeHandleSize, mergeHandleSize, Handles.DotCap))
                            {
        //                                Undo.RegisterSceneUndo("Merge Volume");
                                int otherVolume = plan.GetConnectingVolumeIndex(v, a, b);
                                plan.MergeVolumes(v, otherVolume);
                                numberOfVolumes--;
                                editMode.SetMode(BuildrEditMode.modes.floorplan);
                                EditorUtility.SetDirty(plan);
                            }
                        }
                    }
                }

                break;

            //SUB VOLUME FUNCTIONS

            case BuildrEditMode.modes.splitwall:

                SceneView.focusedWindow.wantsMouseMove = true;
                float pointDistance = 999;
                int wallIndex = -1;
                int volumeIndex = -1;
                Vector3 closestPoint = Vector3.zero;
                Vector3 usePoint = Vector3.zero;
                vertA = Vector3.zero;
                vertB = Vector3.zero;

                for (int s = 0; s < numberOfVolumes; s++)
                {
                    BuildrVolume volumeLinks = plan.volumes[s];
                    int volumeSize = volumeLinks.Count;

                    for (int l = 0; l < volumeSize; l++)
                    {
                        Vector3[] wallVectors = plan.GetWallVectors(s, l);
                        closestPoint = BuildrUtils.ClosestPointOnLine(wallVectors[0] + position, wallVectors[1] + position, mousePlanePoint);
                        float thisDist = Vector3.Distance(closestPoint, mousePlanePoint);
                        if (thisDist < pointDistance)
                        {
                            wallIndex = l;
                            volumeIndex = s;
                            vertA = wallVectors[0];
                            vertB = wallVectors[1];
                            usePoint = closestPoint;
                            pointDistance = thisDist;
                            editMode.selectedPoints.Clear();
                        }

                        Handles.color = Color.white;
                        float wallHandleSize = HandleUtility.GetHandleSize(wallVectors[0] + position);
                        Handles.DotCap(0, wallVectors[0] + position, Quaternion.identity, wallHandleSize * 0.05f);
                    }
                }

                if (wallIndex != -1 && pointDistance < 5 && volumeIndex != -1)
                {
                    float pointHandleSize = HandleUtility.GetHandleSize(usePoint);
                    if (Handles.Button(usePoint, Quaternion.identity, pointHandleSize * 0.1f, pointHandleSize * 0.1f, Handles.DotCap))
                    {
        //                        Undo.RegisterUndo(plan.GetUndoObjects(), "Split Wall");
                        int newPointID = plan.AddWallPoint(usePoint - position, wallIndex, volumeIndex);
                        editMode.selectedPoints.Clear();
                        editMode.selectedPoints.Add(newPointID);
                        editMode.SetMode(BuildrEditMode.modes.floorplan);
                        EditorUtility.SetDirty(plan);
                    }

                    Handles.color = Color.white;
                    GUIStyle widthStyle = new GUIStyle();
                    widthStyle.normal.textColor = Color.white;
                    widthStyle.alignment = TextAnchor.MiddleCenter;
                    widthStyle.fixedWidth = 50.0f;
                    Vector3 facadeDirection = Vector3.Cross((vertA - vertB), Vector3.up).normalized;

                    float wallWidthA = Vector3.Distance(vertA, usePoint);
                    Vector3 labelPosA = (vertA + usePoint) * 0.5f + facadeDirection;
                    Handles.Label(labelPosA, wallWidthA.ToString("F2") + "m", widthStyle);
                    if (wallWidthA > 3)//draw guidelines
                    {
                        float gapSpace = (pointHandleSize * 0.5f) / wallWidthA;
                        Vector3 lineStopA = Vector3.Lerp(vertA, usePoint, (0.5f - gapSpace)) + facadeDirection;
                        Vector3 lineStopB = Vector3.Lerp(vertA, usePoint, (0.5f + gapSpace)) + facadeDirection;
                        Handles.DrawLine(vertA + facadeDirection, lineStopA);
                        Handles.DrawLine(vertA + facadeDirection, vertA);
                        Handles.DrawLine(usePoint + facadeDirection, lineStopB);
                        Handles.DrawLine(usePoint + facadeDirection, usePoint);
                    }

                    float wallWidthB = Vector3.Distance(usePoint, vertB);
                    Vector3 labelPosB = (usePoint + vertB) * 0.5f + facadeDirection;
                    Handles.Label(labelPosB, wallWidthB.ToString("F2") + "m", widthStyle);
                    if (wallWidthB > 3)//draw guidelines
                    {
                        float gapSpace = (pointHandleSize * 0.5f) / wallWidthB;
                        Vector3 lineStopA = Vector3.Lerp(vertB, usePoint, (0.5f - gapSpace)) + facadeDirection;
                        Vector3 lineStopB = Vector3.Lerp(vertB, usePoint, (0.5f + gapSpace)) + facadeDirection;
                        Handles.DrawLine(vertB + facadeDirection, lineStopA);
                        Handles.DrawLine(vertB + facadeDirection, vertB);
                        Handles.DrawLine(usePoint + facadeDirection, lineStopB);
                        Handles.DrawLine(usePoint + facadeDirection, usePoint);
                    }
                }
                Handles.color = Color.white;
                break;

            case BuildrEditMode.modes.removewall:

                int index = 0;
                foreach (Vector2z point in plan.points)
                {
                    Handles.color = Color.white;
                    Vector3 pointPos = point.vector3 + position;
                    float pointHandleSize = HandleUtility.GetHandleSize(pointPos);
                    if (Handles.Button(pointPos, Quaternion.identity, pointHandleSize * 0.1f, pointHandleSize * 0.1f, Handles.DotCap))
                    {
        //                        Undo.RegisterSceneUndo("Delete Wall Point");
                        plan.RemovePoint(index);
                        editMode.SetMode(BuildrEditMode.modes.floorplan);
                        break;
                    }

                    index++;
                }

                break;

            case BuildrEditMode.modes.extrudewallselect:

                Handles.color = Color.blue;
                for (int s = 0; s < numberOfVolumes; s++)
                {
                    BuildrVolume volume = plan.volumes[s];
                    int volumeSize = volume.Count;

                    for (int l = 0; l < volumeSize; l++)
                    {
                        int a = volume.points[l];
                        int b = (l < volume.points.Count - 1) ? volume.points[l + 1] : volume.points[0];
                        if (plan.GetConnectingVolumeIndex(s, a, b) == -1)//if the volume wall has not been connected to two volumes yet...
                        {
                            Vector3[] pIndexes = plan.GetWallVectors(s, l);
                            Vector3 pA = pIndexes[0];
                            Vector3 pB = pIndexes[1];
                            Vector3 pC = (pA + pB) / 2 + position;
                            float pointHandleSize = HandleUtility.GetHandleSize(pC);

                            if (Handles.Button(pC, Quaternion.identity, pointHandleSize * 0.1f, pointHandleSize * 0.1f, Handles.DotCap))
                            {
        //                                Undo.RegisterSceneUndo("Extrude wall");
                                int wallIndexA = l;
                                int newPointAIndex = plan.AddWallPoint(pA, wallIndexA, s);
                                int wallIndexB = l + 1;

                                int newPointBIndex = plan.AddWallPoint(pB, wallIndexB, s);

                                editMode.SetMode(BuildrEditMode.modes.floorplan);

                                editMode.selectedPoints.Clear();
                                editMode.selectedPoints.Add(newPointAIndex);
                                editMode.selectedPoints.Add(newPointBIndex);
                                break;
                            }
                        }
                    }
                }

                Handles.color = Color.white;

                break;

            case BuildrEditMode.modes.addVolumeByPoint:

                Handles.color = Color.blue;
                for (int s = 0; s < numberOfVolumes; s++)
                {
                    BuildrVolume volume = plan.volumes[s];
                    int volumeSize = volume.Count;

                    for (int l = 0; l < volumeSize; l++)
                    {
                        int a = volume.points[l];
                        int b = (l < volume.points.Count - 1) ? volume.points[l + 1] : volume.points[0];
                        if (plan.GetConnectingVolumeIndex(s, a, b) == -1)//if the volume wall has not been connected to two volumes yet...
                        {
                            Vector3[] pointVectors = plan.GetWallVectors(s, l);
                            Vector3 pA = pointVectors[0];
                            Vector3 pB = pointVectors[1];
                            Vector3 pC = (pA + pB) / 2 + position;
                            float pointHandleSize = HandleUtility.GetHandleSize(pC);
                            if (Handles.Button(pC, Quaternion.identity, pointHandleSize * 0.1f, pointHandleSize * 0.1f, Handles.DotCap))
                            {
                                Vector2z[] newPoints = new Vector2z[1];
                                float pointDist = Vector3.Distance(pA, pB);
                                Vector3 newPointPos = Vector3.Cross(pA - pB, Vector3.up).normalized * pointDist;
                                newPoints[0] = new Vector2z(pC + newPointPos);
                                int indexa, indexb;
                                indexa = volume.points[l];
                                if (l < volumeSize - 1)
                                    indexb = volume.points[l + 1];
                                else
                                    indexb = volume.points[0];
                                plan.AddVolume(indexa, indexb, newPoints);

                                editMode.SetMode(BuildrEditMode.modes.floorplan);
                                break;
                            }
                        }
                    }
                }
                Handles.color = Color.white;
                break;

            case BuildrEditMode.modes.addVolumeByWall:

                Handles.color = Color.blue;
                for (int s = 0; s < numberOfVolumes; s++)
                {
                    BuildrVolume volume = plan.volumes[s];
                    int volumeSize = volume.Count;

                    for (int l = 0; l < volumeSize; l++)
                    {
                        int a = volume.points[l];
                        int b = (l < volume.points.Count - 1) ? volume.points[l + 1] : volume.points[0];
                        if (plan.GetConnectingVolumeIndex(s, a, b) == -1)
                        {
                            Vector3[] pIndexes = plan.GetWallVectors(s, l);
                            Vector3 pA = pIndexes[0];
                            Vector3 pB = pIndexes[1];
                            Vector3 pC = (pA + pB) / 2 + position;
                            float pointHandleSize = HandleUtility.GetHandleSize(pC);
                            if (Handles.Button(pC, Quaternion.identity, pointHandleSize * 0.1f, pointHandleSize * 0.1f, Handles.DotCap))
                            {
        //                                Undo.RegisterSceneUndo("Add volume by wall");
                                Vector2z[] newPoints = new Vector2z[2];
                                float pointDist = Vector3.Distance(pA, pB);
                                Vector3 newPointPos = Vector3.Cross(pA - pB, Vector3.up).normalized * pointDist;
                                newPoints[0] = new Vector2z(pA + newPointPos);
                                newPoints[1] = new Vector2z(pB + newPointPos);
                                int indexa, indexb;
                                indexa = volume.points[l];
                                if (l < volumeSize - 1)
                                    indexb = volume.points[l + 1];
                                else
                                    indexb = volume.points[0];
                                plan.AddVolume(indexa, indexb, newPoints);

                                editMode.SetMode(BuildrEditMode.modes.floorplan);
                                break;
                            }
                        }
                    }
                }
                Handles.color = Color.white;
                break;

            case BuildrEditMode.modes.addPointToVolume:

                numberOfPoints = plan.numberOfPoints;
                if (editMode.selectedPoint == -1)
                {
                    for (int p = 0; p < numberOfPoints; p++)
                    {
                        Vector2z point = plan.points[p];
                        Handles.color = Color.white;
                        Vector3 pointPos = point.vector3 + position;
                        float pointhandleSize = HandleUtility.GetHandleSize(pointPos);
                        if (Handles.Button(pointPos, Quaternion.identity, pointhandleSize * 0.1f, pointhandleSize * 0.1f, Handles.DotCap))
                        {
        //                            Undo.RegisterSceneUndo("Select Wall Point");
                            editMode.selectedPoint = p;
                            break;
                        }
                    }
                }
                else
                {

                    selectedPoint = editMode.selectedPoint;
                    Vector2z startPoint = plan.points[selectedPoint];
                    Vector2z endPoint = new Vector2z(mousePlanePoint - position);

                    bool isLegal = true;
                    for (int s = 0; s < numberOfVolumes; s++)
                    {
                        BuildrVolume volume = plan.volumes[s];
                        if (!volume.Contains(selectedPoint))
                            continue;
                        int volumeSize = volume.Count;

                        for (int l = 0; l < volumeSize; l++)
                        {
                            int a = volume.points[l];
                            int b = volume.points[(l + 1) % volumeSize];

                            if (a == selectedPoint || b == selectedPoint)
                                continue;

                            if (BuildrUtils.FastLineIntersection(startPoint, endPoint, plan.points[a], plan.points[b]))
                                isLegal = false;
                        }
                    }

                    Handles.color = isLegal ? Color.white : Color.red;
                    Handles.DrawLine(startPoint.vector3 + position, endPoint.vector3 + position);

                }

                break;

            case BuildrEditMode.modes.splitVolume:

                numberOfPoints = plan.numberOfPoints;
                selectedPoint = editMode.selectedPoint;
                if (selectedPoint == -1)
                {
                    for (int p = 0; p < numberOfPoints; p++)
                    {
                        Vector2z point = plan.points[p];
                        Handles.color = Color.white;
                        Vector3 pointPos = point.vector3 + position;
                        float pointhandleSize = HandleUtility.GetHandleSize(pointPos);

                        if (Handles.Button(pointPos, Quaternion.identity, pointhandleSize * 0.1f, pointhandleSize * 0.1f, Handles.DotCap))
                        {
        //                            Undo.RegisterSceneUndo("Select Wall Point");
                            editMode.selectedPoint = p;
                            break;
                        }
                    }
                }
                else
                {

                    for (int s = 0; s < numberOfVolumes; s++)
                    {
                        BuildrVolume volume = plan.volumes[s];
                        if (!volume.Contains(selectedPoint))
                            continue;
                        int volumeSize = volume.Count;

                        for (int l = 0; l < volumeSize; l++)
                        {

                            int o = volume.points[l];
                            int a = selectedPoint;
                            int selectedVolumePoint = volume.IndexOf(selectedPoint);
                            int b = volume.points[(selectedVolumePoint + 1) % volumeSize];
                            int volb = (selectedVolumePoint - 1) % volumeSize;
                            if (volb == -1) volb = volumeSize - 1;
                            int c = volume.points[volb];

                            if (o == a || o == b || o == c)
                                continue;

                            Vector3 pointPos = plan.points[o].vector3 + position;

                            bool isLegal = true;
                            for (int j = 0; j < volumeSize; j++)
                            {
                                int ob = volume.points[j];
                                int oc = volume.points[(j + 1) % volumeSize];
                                if (ob == selectedPoint || oc == selectedPoint || ob == o || oc == o)
                                    continue;
                                if (BuildrUtils.FastLineIntersection(plan.points[selectedPoint], plan.points[o], plan.points[ob], plan.points[oc]))
                                    isLegal = false;
                            }

                            Vector2z pA = plan.points[a];
                            Vector2z pB = plan.points[b];
                            Vector2z pC = plan.points[c];
                            Vector2z pO = plan.points[o];

                            float startAng, endAng, mouseAng, ang;
                            Vector3 cross;
                            Vector2z diff;

                            diff = pC - pA;
                            ang = Vector2.Angle(Vector2.up, diff.vector2);
                            cross = Vector3.Cross(Vector3.forward, diff.vector3);
                            startAng = (cross.y > 0) ? ang : 360 - ang;

                            diff = pB - pA;
                            ang = Vector2.Angle(Vector2.up, diff.vector2);
                            cross = Vector3.Cross(Vector3.forward, diff.vector3);
                            endAng = (cross.y > 0) ? ang : 360 - ang;

                            diff = pO - pA;
                            ang = Vector2.Angle(Vector2.up, diff.vector2);
                            cross = Vector3.Cross(Vector3.forward, diff.vector3);
                            mouseAng = (cross.y > 0) ? ang : 360 - ang;

                            mouseAng = (360 + (mouseAng % 360)) % 360;
                            startAng = (3600000 + startAng) % 360;
                            endAng = (3600000 + endAng) % 360;

                            bool isBetween = false;
                            if (startAng < endAng)
                                isBetween = startAng <= mouseAng && mouseAng <= endAng;
                            else
                                isBetween = startAng <= mouseAng || mouseAng <= endAng;

                            if (isLegal && !isBetween)
                                isLegal = false;

                            if (isLegal)
                            {
                                Handles.color = Color.white;
                                float pointhandleSize = HandleUtility.GetHandleSize(pointPos);
                                if (Handles.Button(pointPos, Quaternion.identity, pointhandleSize * 0.1f, pointhandleSize * 0.1f, Handles.DotCap))
                                {
        //                                    Undo.RegisterSceneUndo("Split Volume");
                                    plan.SplitVolume(s, a, o);
                                    editMode.selectedPoint = -1;
                                    editMode.SetMode(BuildrEditMode.modes.floorplan);
                                    return;
                                }
                                Handles.color = new Color(1, 0, 0, 0.25f);
                                Handles.DrawLine(plan.points[selectedPoint].vector3 + position, plan.points[o].vector3 + position);
                            }
                        }
                    }
                }

                break;

                case BuildrEditMode.modes.addNewCore:

                SceneView.focusedWindow.wantsMouseMove = true;
                Vector3 coreBasePoint = mousePlanePoint;
                Vector3 coreWidth = Vector3.right * 2.5f;
                Vector3 coreHeight = Vector3.forward * 2.5f;
                Vector3[] coreVerts = new Vector3[4] { coreBasePoint - coreWidth - coreHeight, coreBasePoint + coreWidth - coreHeight, coreBasePoint + coreWidth + coreHeight, coreBasePoint + coreHeight - coreWidth };

                Color newCoreColour = BuildrColours.RED;
                newCoreColour.a = 0.5f;
                Handles.DrawSolidRectangleWithOutline(coreVerts, newCoreColour, BuildrColours.YELLOW);
                Handles.Label(mousePlanePoint, "Click to place a new core");
                if (Handles.Button(coreBasePoint, Quaternion.identity, 0, 10, Handles.CircleCap))
                {
        //                    Undo.RegisterSceneUndo("Add new core");
                    Vector3 coreBase = coreBasePoint - position;
                    Rect newCoreRect = new Rect(coreBase.x - 2.5f, coreBase.z - 2.5f, 5.0f, 5.0f);
                    plan.cores.Add(newCoreRect);
                    editMode.SetMode(BuildrEditMode.modes.floorplan);
                    EditorUtility.SetDirty(plan);
                }

                break;

                case BuildrEditMode.modes.removeCore:

                for (int c = 0; c < numberOfCores; c++)
                {
                    Rect core = plan.cores[c];
                    Vector3 centerPoint = new Vector3(core.center.x, 0, core.center.y) + position;

                    Handles.color = Color.red;
                    float centerPointHandleSize = HandleUtility.GetHandleSize(centerPoint);
                    if (Handles.Button(centerPoint, Quaternion.identity, centerPointHandleSize * 0.1f, centerPointHandleSize * 0.1f, Handles.DotCap))
                    {
        //                        Undo.RegisterSceneUndo("Remove Core");
                        plan.cores.RemoveAt(c);
                        numberOfCores--;
                        c--;
                        editMode.SetMode(BuildrEditMode.modes.floorplan);
                        EditorUtility.SetDirty(plan);
                    }
                }

                break;
        }

        bool clickedOutside = false;
        if (Event.current.isMouse)
        {
            RaycastHit hitInfo;
            clickedOutside = true;
            if (Physics.Raycast(ray, out hitInfo))
            {
                if (hitInfo.collider.gameObject == editMode.gameObject)
                    clickedOutside = false;
            }
        }

        if (clickedOutside)
            editMode.selectedPoints.Clear();

        if (GUI.changed)
        {
            plan.CheckPlan();
            EditorUtility.SetDirty(editMode);
            EditorUtility.SetDirty(plan);
            editMode.UpdateRender();
        }
    }
    public static void InspectorGUI(BuildrEditMode editMode, BuildrData _data)
    {
        data = _data;
        Undo.RecordObject(data, "Roof Modified");

        BuildrRoofDesign[] roofs = data.roofs.ToArray();
        int numberOfRoofs = roofs.Length;
        selectedRoof = Mathf.Clamp(selectedRoof, 0, numberOfRoofs - 1);

        if (GUILayout.Button("Add new roof design"))
        {
            data.roofs.Add(new BuildrRoofDesign("new roof " + numberOfRoofs));
            roofs = data.roofs.ToArray();
            numberOfRoofs++;
            selectedRoof = numberOfRoofs - 1;

        }
        if (numberOfRoofs == 0)
        {
            EditorGUILayout.HelpBox("There are no roof designs to show", MessageType.Info);
            return;
        }

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Design: ", GUILayout.Width(75));
        string[] roofNames = new string[numberOfRoofs];
        for (int f = 0; f < numberOfRoofs; f++)
            roofNames[f] = roofs[f].name;
        selectedRoof = EditorGUILayout.Popup(selectedRoof, roofNames);

        BuildrRoofDesign bRoof = roofs[selectedRoof];
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        if (GUILayout.Button("Delete", GUILayout.Width(75)))
        {
            if (EditorUtility.DisplayDialog("Deleting Roof Design Entry", "Are you sure you want to delete this roof?", "Delete", "Cancel"))
            {
                data.RemoveRoofDesign(bRoof);
                selectedRoof = 0;
                GUI.changed = true;

                return;
            }
        }

        if (GUILayout.Button("Import", GUILayout.Width(71)))
        {
            string xmlPath = EditorUtility.OpenFilePanel("Select the XML file...", "Assets/BuildR/Exported/", "xml");
            if (xmlPath == "")
                return;
            BuildrXMLImporter.ImportRoofs(xmlPath, _data);
            GUI.changed = true;
        }

        if (GUILayout.Button("Export", GUILayout.Width(71)))
        {
            string xmlPath = EditorUtility.SaveFilePanel("Export as...", "Assets/BuildR/Exported/", _data.name + "_roofLibrary", "xml");
            if (xmlPath == "")
                return;
            BuildrXMLExporter.ExportRoofs(xmlPath, _data);
            GUI.changed = true;
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Name: ", GUILayout.Width(75));
        bRoof.name = EditorGUILayout.TextField(bRoof.name);
        EditorGUILayout.EndHorizontal();

        //ROOF STYLE
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Style: ", GUILayout.Width(75));
        BuildrRoofDesign.styles bRoofstyle = (BuildrRoofDesign.styles)EditorGUILayout.EnumPopup(bRoof.style);
        if(bRoofstyle != bRoof.style)
        {
            bRoof.style = bRoofstyle;
        }
        EditorGUILayout.EndHorizontal();

        if (bRoof.style != BuildrRoofDesign.styles.flat && bRoof.style != BuildrRoofDesign.styles.mansard && bRoof.style != BuildrRoofDesign.styles.steepled && bRoof.style != BuildrRoofDesign.styles.hipped)
        {
            EditorGUILayout.HelpBox("Please note that this design can only be used on sections with 4 points." +
                "\nComplex sections can only use the Flat, Mansard and Steeple designs.", MessageType.Warning);
        }

        if (bRoof.style != BuildrRoofDesign.styles.flat)
            bRoof.height = Mathf.Max(EditorGUILayout.FloatField("Height", bRoof.height), 0);

        if (bRoof.style == BuildrRoofDesign.styles.mansard)
        {
            bRoof.floorDepth = Mathf.Max(EditorGUILayout.FloatField("Base Depth", bRoof.floorDepth), 0);
            bRoof.depth = Mathf.Max(EditorGUILayout.FloatField("Top Depth", bRoof.depth), 0);
        }

        if (bRoof.style == BuildrRoofDesign.styles.barrel)
            bRoof.barrelSegments = Mathf.Max(EditorGUILayout.IntField("Barrel Segments", bRoof.barrelSegments), 3);

        if (bRoof.style == BuildrRoofDesign.styles.barrel || bRoof.style == BuildrRoofDesign.styles.gabled || bRoof.style == BuildrRoofDesign.styles.hipped)
        {
            //two directions of the ridge
            bRoof.direction = Mathf.Clamp(bRoof.direction, 0, 1);
            string[] options = new string[2] { "short", "long" };
            bRoof.direction = EditorGUILayout.Popup(bRoof.direction, options);
        }

        if (bRoof.style == BuildrRoofDesign.styles.leanto || bRoof.style == BuildrRoofDesign.styles.sawtooth)
        {
            //four directions of the ridge
            bRoof.direction = Mathf.Clamp(bRoof.direction, 0, 3);
            string[] options = new string[4] { "left", "up", "right", "down" };
            bRoof.direction = EditorGUILayout.Popup(bRoof.direction, options);
        }

        if (bRoof.style == BuildrRoofDesign.styles.sawtooth)
            bRoof.sawtoothTeeth = Mathf.Max(EditorGUILayout.IntField("Number of 'teeth'", bRoof.sawtoothTeeth), 2);

        //PARAPET
        bool bRoofparapet = EditorGUILayout.Toggle("Has Parapet", bRoof.parapet);
        if(bRoofparapet != bRoof.parapet)
        {
            bRoof.parapet = bRoofparapet;
        }
        if (bRoof.parapet)
        {
            float bRoofparapetHeight = Mathf.Max(EditorGUILayout.FloatField("Parapet Width", bRoof.parapetHeight), 0);
            if(bRoofparapetHeight != bRoof.parapetHeight)
            {
                bRoof.parapetHeight = bRoofparapetHeight;
            }
            float bRoofparapetFrontDepth = Mathf.Max(EditorGUILayout.FloatField("Parapet Front Depth", bRoof.parapetFrontDepth), 0);
            if (bRoofparapetFrontDepth != bRoof.parapetFrontDepth)
            {
                bRoof.parapetFrontDepth = bRoofparapetFrontDepth;
            }
            float bRoofparapetBackDepth = Mathf.Max(EditorGUILayout.FloatField("Parapet Back Depth", bRoof.parapetBackDepth), 0);
            if (bRoofparapetBackDepth != bRoof.parapetBackDepth)
            {
                bRoof.parapetBackDepth = bRoofparapetBackDepth;
            }

            if (bRoof.parapetStyle == BuildrRoofDesign.parapetStyles.fancy)//NOT IMPLMENTED...YET...
            {
                EditorGUILayout.HelpBox("This allows you to specify a model mesh that will be used to create a parapet." +
                    "\nIt should not repeat as Buildr will attempt to repeat the style to fit the length of the facade.", MessageType.Info);
                bRoof.parapetDesign = (Mesh)EditorGUILayout.ObjectField("Parapet Mesh", bRoof.parapetDesign, typeof(Mesh), false);
                bRoof.parapetDesignWidth = Mathf.Max(EditorGUILayout.FloatField("Parapet Design Width", bRoof.parapetDesignWidth), 0);
            }
        }

        //DORMERS
        if (bRoof.style == BuildrRoofDesign.styles.mansard)
        {
            bool bRoofhasDormers = EditorGUILayout.Toggle("Has Dormers", bRoof.hasDormers);
            if(bRoofhasDormers != bRoof.hasDormers)
            {
                bRoof.hasDormers = bRoofhasDormers;
            }
            if (bRoof.hasDormers)
            {
                float bRoofdormerWidth = Mathf.Max(EditorGUILayout.FloatField("Dormer Width", bRoof.dormerWidth), 0);
                if (bRoofdormerWidth != bRoof.dormerWidth)
                {
                    bRoof.dormerWidth = bRoofdormerWidth;
                }
                float bRoofdormerHeight = Mathf.Clamp(EditorGUILayout.FloatField("Dormer Height", bRoof.dormerHeight), 0, bRoof.height);
                if (bRoofdormerHeight != bRoof.dormerHeight)
                {
                    bRoof.dormerHeight = bRoofdormerHeight;
                }
                float bRoofdormerRoofHeight = Mathf.Clamp(EditorGUILayout.FloatField("Dormer Roof Height", bRoof.dormerRoofHeight), 0, bRoof.dormerHeight);
                if (bRoofdormerRoofHeight != bRoof.dormerRoofHeight)
                {
                    bRoof.dormerRoofHeight = bRoofdormerRoofHeight;
                }
                float bRoofminimumDormerSpacing = Mathf.Max(EditorGUILayout.FloatField("Dormer Minimum Spacing", bRoof.minimumDormerSpacing), 0);
                if (bRoofminimumDormerSpacing != bRoof.minimumDormerSpacing)
                {
                    bRoof.minimumDormerSpacing = bRoofminimumDormerSpacing;
                }
                float bRoofdormerHeightRatio = EditorGUILayout.Slider("Dormer Height Ratio", bRoof.dormerHeightRatio, 0, 1);
                if (bRoofdormerHeightRatio != bRoof.dormerHeightRatio)
                {
                    bRoof.dormerHeightRatio = bRoofdormerHeightRatio;
                }
            }
        }

        //TEXTURES
        int numberOfTextures = data.textures.Count;
        string[] textureNames = new string[numberOfTextures];
        for (int t = 0; t < numberOfTextures; t++)
            textureNames[t] = data.textures[t].name;

        int numberOfTextureSlots = bRoof.numberOfTextures;
        string[] titles = new string[numberOfTextureSlots];
        for (int brt = 0; brt < numberOfTextureSlots; brt++)
        {
            titles[brt] = ((BuildrRoofDesign.textureNames)(brt)).ToString();
        }

        editTextureOnRoof = EditorGUILayout.Popup("Texture Surface:", editTextureOnRoof, titles);

        int selectedRoofTexture = EditorGUILayout.Popup("Selected Texture:", bRoof.textureValues[editTextureOnRoof], textureNames);
        if(selectedRoofTexture != bRoof.textureValues[editTextureOnRoof])
        {
            bRoof.textureValues[editTextureOnRoof] = selectedRoofTexture;
        }
        BuildrTexture bTexture = data.textures[bRoof.textureValues[editTextureOnRoof]];
        Texture2D texture = bTexture.texture;
        EditorGUILayout.BeginHorizontal();

        if (texture != null)
            GUILayout.Label(texture, GUILayout.Width(100), GUILayout.Height(100));
        else
            EditorGUILayout.HelpBox("No texture assigned for '" + textureNames[bRoof.textureValues[editTextureOnRoof]] + "', assign one in the Textures menu above", MessageType.Warning);

        bRoof.flipValues[editTextureOnRoof] = EditorGUILayout.Toggle("Flip 90\u00B0", bRoof.flipValues[editTextureOnRoof]);

        EditorGUILayout.EndHorizontal();
    }
Beispiel #18
0
    public static void InspectorGUI(BuildrEditMode editMode, BuildrData _data)
    {
        data = _data;
        Undo.RecordObject(data, "Building Modified");
        BuildrPlan plan = data.plan;
        int        numberOfFacadeFaces   = 0;
        int        numberOfVolumes       = plan.numberOfVolumes;
        int        numberOfFacadeDesigns = data.facades.Count;

        if (numberOfVolumes == 0)
        {
            EditorGUILayout.HelpBox("There are no defined volumes, go to Floorplan and define one", MessageType.Error);
            return;
        }

        int numberOfFacades  = data.facades.Count;
        int numberOfRoofs    = data.roofs.Count;
        int numberOfTextures = data.textures.Count;

        bool legalBuilding = true;

        if (numberOfFacades == 0)
        {
            EditorGUILayout.HelpBox("There are no facade designs to render building, go to Facades to define a default one", MessageType.Error);
            legalBuilding = false;
        }
        if (numberOfRoofs == 0)
        {
            EditorGUILayout.HelpBox("There are no roof designs to render building, go to Facades to define a default one", MessageType.Error);
            legalBuilding = false;
        }
        if (numberOfTextures == 0)
        {
            EditorGUILayout.HelpBox("There are no textures to render building, go to Textures to define a default one", MessageType.Error);
            legalBuilding = false;
        }

        if (!legalBuilding)
        {
            return;
        }

        //Building Name
        EditorGUILayout.Space();
        EditorGUILayout.Space();
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Name", GUILayout.Width(200));
        data.name = EditorGUILayout.TextField(data.name, GUILayout.Width(200));
        EditorGUILayout.EndHorizontal();

        //Floor Height
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Floor height", GUILayout.Width(200));
        data.floorHeight = EditorGUILayout.FloatField(data.floorHeight, GUILayout.Width(50));
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Number of Floors", GUILayout.Width(200));
        int[]    volumeSeletionsList       = new int[numberOfVolumes];
        string[] volumeSeletionsStringList = new string[numberOfVolumes];
        for (int s = 0; s < numberOfVolumes; s++)
        {
            volumeSeletionsStringList[s] = ("volume " + s);
            volumeSeletionsList[s]       = (s);
        }

        selectedFloorNumberVolume = EditorGUILayout.IntPopup(selectedFloorNumberVolume, volumeSeletionsStringList, volumeSeletionsList, GUILayout.Width(100));
        int numberOfFloors = EditorGUILayout.IntField(data.plan.volumes[selectedFloorNumberVolume].numberOfFloors);

        if (GUILayout.Button("^"))
        {
            numberOfFloors++;
        }
        if (GUILayout.Button("v"))
        {
            numberOfFloors--;
        }
        data.plan.volumes[selectedFloorNumberVolume].numberOfFloors = Mathf.Max(numberOfFloors, 1);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Show Facade Markers", GUILayout.Width(200));
        editMode.showFacadeMarkers = EditorGUILayout.Toggle(editMode.showFacadeMarkers, GUILayout.Width(200));
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.Space();

        GUIStyle titlesyle = new GUIStyle(GUI.skin.label);

        titlesyle.fixedHeight      = 60;
        titlesyle.fixedWidth       = 400;
        titlesyle.alignment        = TextAnchor.UpperCenter;
        titlesyle.fontStyle        = FontStyle.Bold;
        titlesyle.normal.textColor = Color.white;

        EditorGUILayout.LabelField("Facade Design", titlesyle);
        Texture2D facadeTexture = new Texture2D(1, 1);

        facadeTexture.SetPixel(0, 0, BuildrColours.MAGENTA);
        facadeTexture.Apply();
        Rect sqrPos = new Rect(0, 0, 0, 0);

        if (Event.current.type == EventType.Repaint)
        {
            sqrPos = GUILayoutUtility.GetLastRect();
        }
        GUI.DrawTexture(sqrPos, facadeTexture);
        EditorGUI.LabelField(sqrPos, "Facade Design", titlesyle);

        //create/display the facade selector
        List <int>    facadeSeletionsList       = new List <int>();
        List <int>    facadeRenderList          = new List <int>();
        List <string> facadeSeletionsStringList = new List <string>();

        for (int s = 0; s < numberOfVolumes; s++)
        {
            int numberOfPoints = plan.volumes[s].Count;
            numberOfFacadeFaces += numberOfPoints;
            for (int p = 0; p < numberOfPoints; p++)
            {
                int index = facadeSeletionsList.Count;
                facadeSeletionsStringList.Add("facade " + index);
                facadeSeletionsList.Add(index);
                facadeRenderList.Add(p);
            }
        }
        int[]    facadeSelections      = facadeSeletionsList.ToArray();
        string[] facadeSelectionString = facadeSeletionsStringList.ToArray();

        selectedFacade = EditorGUILayout.IntPopup("Selected Facade", selectedFacade, facadeSelectionString, facadeSelections, GUILayout.Width(400));

        //grab the selected facade
        int facadeCount         = 0;
        int selectedVolumePoint = 0;

        for (int s = 0; s < numberOfVolumes; s++)
        {
            int numberOfPoints = plan.volumes[s].Count;
            for (int p = 0; p < numberOfPoints; p++)
            {
                if (selectedFacade == facadeCount)
                {
                    selectedVolume      = s;
                    selectedVolumePoint = p;
                    selectedPoint       = plan.volumes[s].points[p];
                }
                facadeCount++;
            }
        }

        BuildrVolume volume = plan.volumes[selectedVolume];

        BuildrVolumeStylesUnit[] styles = volume.styles.GetContents();

        bool renderFacade = volume.renderFacade[selectedVolumePoint];

        volume.renderFacade[selectedVolumePoint] = EditorGUILayout.Toggle("Render Facade", renderFacade);

        //ensure the selected style isn't out of bounds
        int numberOfStyles = styles.Length;

        if (selectedStyle >= numberOfStyles)
        {
            selectedStyle = 0;
        }

        //compose a list of style ids from the volume style library
        List <int> entryNum = new List <int>();

        for (int s = 0; s < numberOfStyles; s++)
        {
            if (selectedPoint == styles[s].facadeID)
            {
                entryNum.Add(s);
            }
        }

        int numberOfFacadeStyles = entryNum.Count;

        if (GUILayout.Button("Add style to facade", GUILayout.Width(400)))
        {
            volume.styles.AddStyle(0, selectedPoint, 1);
        }

        GUILayout.BeginHorizontal("box");
        GUILayout.BeginHorizontal("box");
        EditorGUILayout.LabelField("Style", GUILayout.Width(160));
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal("box");
        GUILayout.Label("Floors", GUILayout.Width(78));
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal("box");
        GUILayout.Label("Position", GUILayout.Width(54));
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal("box");
        GUILayout.Label(" ", GUILayout.Width(55));
        GUILayout.EndHorizontal();
        GUILayout.EndHorizontal();

        for (int s = 0; s < numberOfFacadeStyles; s++)
        {
            int index = entryNum[s];
            BuildrVolumeStylesUnit styleUnit = styles[index];

            GUILayout.BeginHorizontal("box");
            GUILayout.BeginHorizontal("box");
            string[] facadeNames = new string[numberOfFacadeDesigns];
            for (int f = 0; f < numberOfFacadeDesigns; f++)
            {
                facadeNames[f] = data.facades[f].name;
            }
            int selectedFacadeDesign = EditorGUILayout.Popup(styleUnit.styleID, facadeNames, GUILayout.Width(160));
            if (selectedFacadeDesign != styleUnit.styleID)
            {
                volume.styles.ModifyStyle(index, selectedFacadeDesign);
            }
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal("box");
            int currentFloors = styleUnit.floors;

            currentFloors = EditorGUILayout.IntField(currentFloors, GUILayout.Width(20));
            if (GUILayout.Button("+", GUILayout.Width(25)))
            {
                currentFloors++;
            }
            EditorGUI.BeginDisabledGroup(currentFloors < 2);
            if (GUILayout.Button("-", GUILayout.Width(25)))
            {
                currentFloors--;
            }
            EditorGUI.EndDisabledGroup();
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal("box");
            EditorGUI.BeginDisabledGroup((s < 1));
            {
                if (GUILayout.Button("^", GUILayout.Width(25)))
                {
                    volume.styles.MoveEntry(entryNum[s], entryNum[s - 1] + 1);
                    GUI.changed = true;
                }
            }
            EditorGUI.EndDisabledGroup();
            EditorGUI.BeginDisabledGroup((s > numberOfFacadeStyles - 2));
            {
                if (GUILayout.Button("v", GUILayout.Width(25)))
                {
                    volume.styles.MoveEntry(entryNum[s], entryNum[s + 1] + 1);
                    GUI.changed = true;
                }
            }
            EditorGUI.EndDisabledGroup();
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal("box");
            if (GUILayout.Button("remove", GUILayout.Width(55)))
            {
                volume.styles.RemoveStyle(index);
            }
            GUILayout.EndHorizontal();
            GUILayout.EndHorizontal();

            if (currentFloors != styleUnit.floors)
            {
                volume.styles.ModifyFloors(index, currentFloors);
                GUI.changed = true;
            }
        }
        EditorGUILayout.Space();

        titlesyle                  = new GUIStyle(GUI.skin.label);
        titlesyle.fixedHeight      = 60;
        titlesyle.fixedWidth       = 400;
        titlesyle.alignment        = TextAnchor.UpperCenter;
        titlesyle.fontStyle        = FontStyle.Bold;
        titlesyle.normal.textColor = Color.black;

        EditorGUILayout.LabelField("Roof Design", titlesyle);
        facadeTexture = new Texture2D(1, 1);
        facadeTexture.SetPixel(0, 0, BuildrColours.CYAN);
        facadeTexture.Apply();
        sqrPos = new Rect(0, 0, 0, 0);
        if (Event.current.type == EventType.Repaint)
        {
            sqrPos = GUILayoutUtility.GetLastRect();
        }
        GUI.DrawTexture(sqrPos, facadeTexture);
        EditorGUI.LabelField(sqrPos, "Roof Design", titlesyle);



        //create/display the roof selector
        volumeSeletionsList       = new int[numberOfVolumes];
        volumeSeletionsStringList = new string[numberOfVolumes];
        for (int s = 0; s < numberOfVolumes; s++)
        {
            volumeSeletionsStringList[s] = ("volume " + s);
            volumeSeletionsList[s]       = (s);
        }

        selectedRoofVolume = EditorGUILayout.IntPopup("Selected Volume", selectedRoofVolume, volumeSeletionsStringList, volumeSeletionsList, GUILayout.Width(400));

        string[] roofNames = new string[numberOfRoofs];
        int[]    roofList  = new int[numberOfRoofs];
        for (int r = 0; r < numberOfRoofs; r++)
        {
            roofList[r]  = r;
            roofNames[r] = data.roofs[r].name;
        }

        volume = data.plan.volumes[selectedRoofVolume];
        volume.roofDesignID = EditorGUILayout.IntPopup("Selected Roof Design", volume.roofDesignID, roofNames, roofList, GUILayout.Width(400));
    }
Beispiel #19
0
    public static void InspectorGUI(BuildrEditMode editMode, BuildrData data)
    {
        if (data.plan == null || data.plan.numberOfVolumes == 0)
        {
            EditorGUILayout.HelpBox("There are no defined volumes, go to Floorplan and define one", MessageType.Error);
            return;
        }

        const int guiWidth    = 400;
        const int textWidth   = 348;
        const int toggleWidth = 25;
        const int helpWidth   = 20;

        CURRENT_TRANSFORM = editMode.transform;
        EditorGUILayout.Space();
        EditorGUILayout.Space();
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Filename", GUILayout.Width(225));
        data.exportFilename = EditorGUILayout.TextField(data.exportFilename, GUILayout.Width(175));
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.Space();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Filetype", GUILayout.Width(350));
        data.filetype = (BuildrData.filetypes)EditorGUILayout.EnumPopup(data.filetype, GUILayout.Width(50));
        switch (data.filetype)
        {
        case BuildrData.filetypes.obj:
            FILE_EXTENTION = ".obj";
            break;

        case BuildrData.filetypes.fbx:
            FILE_EXTENTION = ".fbx";
            break;
        }
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.Space();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Export Full Mesh", GUILayout.Width(textWidth));
        data.fullmesh = EditorGUILayout.Toggle(data.fullmesh, GUILayout.Width(toggleWidth));
        if (GUILayout.Button("?", GUILayout.Width(helpWidth)))
        {
            string helpTitle = "Help - Export Full Mesh";
            string helpBody  = "Select this checkbox if you want your export the full detail model.";
            EditorUtility.DisplayDialog(helpTitle, helpBody, "close");
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Place Exported Model Into Scene", GUILayout.Width(textWidth));
        data.placeIntoScene = EditorGUILayout.Toggle(data.placeIntoScene, GUILayout.Width(toggleWidth));
        if (GUILayout.Button("?", GUILayout.Width(helpWidth)))
        {
            string helpTitle = "Help - Place Exported Model Into Scene";
            string helpBody  = "Select this checkbox if you want your exported models to be copied into your scene." +
                               "\nThese will be positioned correctly and will include colliders and LOD models if you opt to export them also.";
            EditorUtility.DisplayDialog(helpTitle, helpBody, "close");
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Copy Textures into Export Folder", GUILayout.Width(textWidth));
        data.copyTexturesIntoExportFolder = EditorGUILayout.Toggle(data.copyTexturesIntoExportFolder, GUILayout.Width(toggleWidth));
        if (GUILayout.Button("?", GUILayout.Width(helpWidth)))
        {
            string helpTitle = "Help - Copy Textures into Export Folder";
            string helpBody  = "Check this box if you want to copy the textures you are using into the export folder." +
                               "\nThis is useful if you plan to use the exported model elsewhere. Having the model and the textures in one folder will allow you to move this model with ease.";
            EditorUtility.DisplayDialog(helpTitle, helpBody, "close");
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Export Collider");
        data.generateCollider = (BuildrData.ColliderGenerationModes)EditorGUILayout.EnumPopup(data.generateCollider, GUILayout.Width(80));
        if (GUILayout.Button("?", GUILayout.Width(helpWidth)))
        {
            string helpTitle = "Help - Export Collider Mesh";
            string helpBody  = "Check this box if you wish to generate a collider mesh for your model." +
                               "\nThis will generate a mesh to be used with colliders.";
            EditorUtility.DisplayDialog(helpTitle, helpBody, "close");
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Export as Prefab", GUILayout.Width(textWidth));
        data.createPrefabOnExport = EditorGUILayout.Toggle(data.createPrefabOnExport, GUILayout.Width(toggleWidth));
        if (GUILayout.Button("?", GUILayout.Width(helpWidth)))
        {
            string helpTitle = "Help - Export as Prefab";
            string helpBody  = "Select this if you wish to create a prefab of your model." +
                               "\nThis is recommended if you're exporting a collider so they will get packaged together.";
            EditorUtility.DisplayDialog(helpTitle, helpBody, "close");
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Export a Low Detail Version", GUILayout.Width(textWidth));
        data.exportLowLOD = EditorGUILayout.Toggle(data.exportLowLOD, GUILayout.Width(toggleWidth));
        if (GUILayout.Button("?", GUILayout.Width(helpWidth)))
        {
            string helpTitle = "Help - Export a Low Detail Version";
            string helpBody  = "Check this box to export a simplified model of your building." +
                               "\nIdeal to use as a low level of detail version of your model." +
                               "\nGeometry will be significantly reduced." +
                               "\nFacades will flat and exported as a single atlased texture" +
                               "\nThe model will use 1 draw call and will have around 10% of the triangles and verticies";
            EditorUtility.DisplayDialog(helpTitle, helpBody, "close");
        }
        EditorGUILayout.EndHorizontal();


        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Export with tangents", GUILayout.Width(textWidth));
        data.includeTangents = EditorGUILayout.Toggle(data.includeTangents, GUILayout.Width(toggleWidth));
        if (GUILayout.Button("?", GUILayout.Width(helpWidth)))
        {
            string helpTitle = "Help - with tangents";
            string helpBody  = "Export the models with calculated tangents." +
                               "\nSome shaders require tangents to be calculated on the model." +
                               "\nUnity will do this automatically on all imported meshes so it's not neccessary here." +
                               "/nBut you might want them if you're taking them to another program.";
            EditorUtility.DisplayDialog(helpTitle, helpBody, "close");
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.Space();

        bool   unreadableTextures    = false;
        bool   nullTextures          = false;
        string unreadableTextureList = "";

        foreach (BuildrTexture bTexture in data.textures)//check texture readablility
        {
            if (bTexture.type == BuildrTexture.Types.Substance)
            {
                continue;//substances are preset in BuildrTexture class
            }
            if (bTexture.texture != null)
            {
                string          texturePath     = AssetDatabase.GetAssetPath(bTexture.texture);
                TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(texturePath);
                if (!textureImporter.isReadable)
                {
                    unreadableTextures = true;
                    if (unreadableTextureList.Length > 0)
                    {
                        unreadableTextureList += ", ";
                    }
                    unreadableTextureList += "'" + bTexture.name + "'";
                }
            }
            else
            {
                nullTextures = true;
            }
        }

        if (unreadableTextures)
        {
            EditorGUILayout.HelpBox("Unreadable Texture Error." +
                                    "\nThe following textures you are useing are not readable." +
                                    "\n" + unreadableTextureList + "." +
                                    "\nPlease select the readable checkbox under advanced texture settings." +
                                    "\nOr move this texture to the BuildR texture folder and reimport.",
                                    MessageType.Error);
        }

        if (nullTextures)
        {
            EditorGUILayout.HelpBox("Null Texture Error" +
                                    "\nSome of the textures have not been set" +
                                    "\nEnsure you are not using null textures to proceed.",
                                    MessageType.Error);
        }

        bool usingSubstances = false;

        foreach (BuildrTexture bTexture in data.textures)
        {
            if (bTexture.type == BuildrTexture.Types.Substance)
            {
                usingSubstances = true;
                break;
            }
        }
        if (usingSubstances)
        {
            EditorGUILayout.HelpBox("Model uses Substance textures." +
                                    "\nExporting model to " + data.filetype + " will lose references to this texture and it will be rendered white.",
                                    MessageType.Warning);
        }

        EditorGUI.BeginDisabledGroup(unreadableTextures || nullTextures);

        if (GUILayout.Button("Export", GUILayout.Width(guiWidth), GUILayout.Height(40)))
        {
            ExportModel(data);
        }

        if (GUILayout.Button("Export Data to XML", GUILayout.Width(guiWidth)))
        {
            BuildrXMLExporter.Export(ROOT_FOLDER + data.exportFilename + "/", data.exportFilename, data);
            AssetDatabase.Refresh();
        }

        EditorGUI.EndDisabledGroup();

        CURRENT_TRANSFORM = null;
    }
    public static void SceneGUI(BuildrEditMode editMode, BuildrData _data, bool shouldSnap, float handleSize)
    {
        data = _data;
        Vector3 camDirection = Camera.current.transform.forward;
        Vector3 camPosition = Camera.current.transform.position;

        int numberOfFacades = data.facades.Count;
        int numberOfRoofs = data.roofs.Count;
        int numberOfTextures = data.textures.Count;

        if (numberOfFacades == 0 || numberOfRoofs == 0 || numberOfTextures == 0)
            return;

        Vector3 position = editMode.transform.position;
        float floorHeight = data.floorHeight;

        BuildrPlan area = data.plan;
        int numberOfVolumes = area.numberOfVolumes;

        int facadeCounter = 0;
        for (int s = 0; s < numberOfVolumes; s++)
        {
            BuildrVolume volume = data.plan.volumes[s];
            int volumeSize = volume.Count;
            Vector3 floorCentre = Vector3.zero;
            Handles.color = Color.white;

            for (int p = 0; p < volumeSize; p++)
            {
                int point = volume.points[p];
                Vector3 pointPos = area.points[point].vector3;
                floorCentre += pointPos;

                List<Vector3> verts = new List<Vector3>();
                int indexB = (p < volumeSize - 1) ? p + 1 : 0;
                Vector3 volumeHeight = Vector3.up * (volume.numberOfFloors * data.floorHeight);
                verts.Add(pointPos + position);
                verts.Add(area.points[volume.points[indexB]].vector3 + position);
                verts.Add(verts[1] + volumeHeight);
                verts.Add(verts[0] + volumeHeight);
                if (s == selectedVolume && point == selectedPoint)
                    //display something to highlight this facade
                    Handles.DrawSolidRectangleWithOutline(verts.ToArray(), Color.clear, BuildrColours.MAGENTA);
                Handles.color = BuildrColours.CYAN;
                if (s == selectedRoofVolume)
                    Handles.DrawLine(verts[2], verts[3]);
                if (editMode.showFacadeMarkers)
                {
                    Handles.color = Color.white;
                    Vector3 facadeDirection = Vector3.Cross((verts[0] - verts[1]), Vector3.up);
                    GUIStyle facadeLabelStyle = new GUIStyle();
                    facadeLabelStyle.normal.textColor = Color.white;
                    facadeLabelStyle.alignment = TextAnchor.MiddleCenter;
                    facadeLabelStyle.fixedWidth = 75.0f;
                    Vector3 centerPos = (verts[0] + verts[1]) * 0.5f;
                    bool camVisible = Vector3.Dot(camDirection, centerPos - camPosition) > 0;
                    bool facadeVisible = Vector3.Dot(camDirection, facadeDirection) < 0;
                    if (camVisible && facadeVisible)//only display label when facade is facing camera and is in camera view
                    {
                        Vector3 labelPos = centerPos + facadeDirection.normalized;
                        Handles.Label(labelPos, "facade " + facadeCounter, facadeLabelStyle);
                        Handles.DrawLine(centerPos, labelPos);
                    }
                }
                facadeCounter++;
            }
            floorCentre /= volumeSize;

            //Volume height/floor number slider
            Vector3 volumeHeightDir = Vector3.up * (volume.numberOfFloors * data.floorHeight);
            Vector3 volumePosition = floorCentre + position + volumeHeightDir;
            if (Vector3.Dot(camDirection, volumePosition - camPosition) > 0)//only display label when facade is facing camera
            {
                Handles.Label(volumePosition + (Vector3.up * (handleSize * 0.1f)), "volume " + s);
                Handles.Label(volumePosition, "number of floors " + volume.numberOfFloors);
            }
            Handles.color = Color.green;
            volume.height = Handles.Slider(volumePosition, Vector3.up).y - position.y;
            if (volume.height < data.floorHeight)
                volume.height = data.floorHeight;

            volume.numberOfFloors = Mathf.RoundToInt(volume.height / floorHeight);
        }
    }
Beispiel #21
0
    public static void InspectorGUI(BuildrEditMode _editMode, BuildrData _data)
    {
        data = _data;
        BuildrTexture[] textures         = data.textures.ToArray();
        int             numberOfTextures = textures.Length;

        selectedTexture = Mathf.Clamp(selectedTexture, 0, numberOfTextures - 1);
        int currentSelectedTexture = selectedTexture;//keep tack of what we had selected to reset fields if changed

        Undo.RecordObject(data, "Texture Modified");

        if (numberOfTextures == 0)
        {
            EditorGUILayout.HelpBox("There are no textures to show", MessageType.Info);
            if (GUILayout.Button("Add New"))
            {
                data.textures.Add(new BuildrTexture("new texture " + numberOfTextures));
                numberOfTextures++;
                selectedTexture = numberOfTextures - 1;
            }
            return;
        }

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Texture", GUILayout.Width(75));
        string[] textureNames = new string[numberOfTextures];
        for (int t = 0; t < numberOfTextures; t++)
        {
            textureNames[t] = textures[t].name;
        }
        selectedTexture = EditorGUILayout.Popup(selectedTexture, textureNames);
        EditorGUILayout.EndHorizontal();

        BuildrTexture bTexture = textures[selectedTexture];

        EditorGUILayout.BeginHorizontal();

        EditorGUILayout.Space();

        if (GUILayout.Button("Add New", GUILayout.Width(81)))
        {
            data.textures.Add(new BuildrTexture("new texture " + numberOfTextures));
            numberOfTextures++;
            selectedTexture = numberOfTextures - 1;
        }


        if (GUILayout.Button("Duplicate", GUILayout.Width(90)))
        {
            data.textures.Add(bTexture.Duplicate());
            numberOfTextures++;
            selectedTexture = numberOfTextures - 1;
        }

        if (GUILayout.Button("Delete", GUILayout.Width(71)))
        {
            if (EditorUtility.DisplayDialog("Deleting Texture Entry", "Are you sure you want to delete this texture?", "Delete", "Cancel"))
            {
                data.RemoveTexture(bTexture);
                selectedTexture = 0;
                GUI.changed     = true;

                return;
            }
        }

        if (GUILayout.Button("Import", GUILayout.Width(71)))
        {
            string xmlPath = EditorUtility.OpenFilePanel("Select the XML file...", "Assets/BuildR/Exported/", "xml");
            if (xmlPath == "")
            {
                return;
            }
            BuildrXMLImporter.ImportTextures(xmlPath, _data);
            textures        = data.textures.ToArray();
            selectedTexture = 0;
            GUI.changed     = true;
        }

        if (GUILayout.Button("Export", GUILayout.Width(71)))
        {
            string xmlPath = EditorUtility.SaveFilePanel("Export as...", "Assets/BuildR/Exported/", _data.name + "_textureLibrary", "xml");
            if (xmlPath == "")
            {
                return;
            }
            BuildrXMLExporter.ExportTextures(xmlPath, _data);
            GUI.changed = true;
        }
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.Space();

        textures     = data.textures.ToArray();
        textureNames = new string[numberOfTextures];
        for (int t = 0; t < numberOfTextures; t++)
        {
            textureNames[t] = textures[t].name;
        }
        bTexture = textures[selectedTexture];//reassign

        string   textureName = bTexture.name;
        GUIStyle redText     = new GUIStyle(GUI.skin.textField);

        if (textureName.Contains(" "))
        {
            redText.focused.textColor = Color.red;
            textureName = EditorGUILayout.TextField("Name", textureName, redText);
        }
        else
        {
            redText.focused.textColor = defaultCol;
            textureName = EditorGUILayout.TextField("Name", textureName, redText);
        }
        bTexture.name = textureName;

        bool conflictingName = false;

        for (int i = 0; i < textureNames.Length; i++)
        {
            if (selectedTexture != i)
            {
                if (textureNames[i] == bTexture.name)
                {
                    conflictingName = true;
                }
            }
        }

        if (conflictingName)
        {
            EditorGUILayout.HelpBox("You have named this texture the same as another.", MessageType.Warning);
        }


        if (currentSelectedTexture != selectedTexture)
        {
            GUIUtility.hotControl      = 0;
            GUIUtility.keyboardControl = 0;
        }

        bTexture.type = (BuildrTexture.Types)EditorGUILayout.EnumPopup("Type", bTexture.type);

        switch (bTexture.type)
        {
        case BuildrTexture.Types.Basic:

            if (bTexture.texture != null)
            {
                string          texturePath     = AssetDatabase.GetAssetPath(bTexture.texture);
                TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(texturePath);

                if (!textureImporter.isReadable)
                {
                    EditorGUILayout.HelpBox("The texture you have selected is not readable." + "\nPlease select the readable checkbox under advanced texture settings." + "\nOr move this texture to the BuildR texture folder and reimport.", MessageType.Error);
                }
            }

            //Shader Time
            Shader[]      tempshaders = (Shader[])Resources.FindObjectsOfTypeAll(typeof(Shader));
            List <string> shaderNames = new List <string>(ShaderProperties.NAMES);
            foreach (Shader shader in tempshaders)
            {
                if (!string.IsNullOrEmpty(shader.name) && !shader.name.StartsWith("__") && !shader.name.Contains("hidden"))
                {
                    shaderNames.Add(shader.name);
                }
            }
            int selectedShaderIndex    = shaderNames.IndexOf(bTexture.material.shader.name);
            int newSelectedShaderIndex = EditorGUILayout.Popup("Shader", selectedShaderIndex, shaderNames.ToArray());
            if (selectedShaderIndex != newSelectedShaderIndex)
            {
                bTexture.material.shader = Shader.Find(shaderNames[newSelectedShaderIndex]);
            }

            Shader selectedShader = bTexture.material.shader;
            int    propertyCount  = ShaderUtil.GetPropertyCount(selectedShader);

            for (int s = 0; s < propertyCount; s++)
            {
                ShaderUtil.ShaderPropertyType propertyTpe = ShaderUtil.GetPropertyType(selectedShader, s);
                string shaderPropertyName = ShaderUtil.GetPropertyName(selectedShader, s);
                switch (propertyTpe)
                {
                case ShaderUtil.ShaderPropertyType.TexEnv:
                    Texture shaderTexture    = bTexture.material.GetTexture(shaderPropertyName);
                    Texture newShaderTexture = (Texture)EditorGUILayout.ObjectField(shaderPropertyName, shaderTexture, typeof(Texture), false);
                    if (shaderTexture != newShaderTexture)
                    {
                        bTexture.material.SetTexture(shaderPropertyName, newShaderTexture);
                    }
                    break;

                case ShaderUtil.ShaderPropertyType.Color:
                    Color shaderColor    = bTexture.material.GetColor(shaderPropertyName);
                    Color newShaderColor = EditorGUILayout.ColorField(shaderPropertyName, shaderColor);
                    if (shaderColor != newShaderColor)
                    {
                        bTexture.material.SetColor(shaderPropertyName, newShaderColor);
                    }
                    break;

                case ShaderUtil.ShaderPropertyType.Float:
                    float shaderFloat    = bTexture.material.GetFloat(shaderPropertyName);
                    float newShaderFloat = EditorGUILayout.FloatField(shaderPropertyName, shaderFloat);
                    if (shaderFloat != newShaderFloat)
                    {
                        bTexture.material.SetFloat(shaderPropertyName, newShaderFloat);
                    }
                    break;

                case ShaderUtil.ShaderPropertyType.Range:
                    float shaderRange    = bTexture.material.GetFloat(shaderPropertyName);
                    float rangeMin       = ShaderUtil.GetRangeLimits(selectedShader, s, 1);
                    float rangeMax       = ShaderUtil.GetRangeLimits(selectedShader, s, 2);
                    float newShaderRange = EditorGUILayout.Slider(shaderPropertyName, shaderRange, rangeMin, rangeMax);
                    if (shaderRange != newShaderRange)
                    {
                        bTexture.material.SetFloat(shaderPropertyName, newShaderRange);
                    }
                    break;

                case ShaderUtil.ShaderPropertyType.Vector:
                    Vector3 shaderVector    = bTexture.material.GetVector(shaderPropertyName);
                    Vector3 newShaderVector = EditorGUILayout.Vector3Field(shaderPropertyName, shaderVector);
                    if (shaderVector != newShaderVector)
                    {
                        bTexture.material.SetVector(shaderPropertyName, newShaderVector);
                    }
                    break;
                }
            }

            bool tiled = EditorGUILayout.Toggle("Is Tiled", bTexture.tiled);
            if (tiled != bTexture.tiled)
            {
                bTexture.tiled = tiled;
            }
            if (bTexture.tiled)
            {
                bool patterned = EditorGUILayout.Toggle("Has Pattern", bTexture.patterned);
                if (patterned != bTexture.patterned)
                {
                    bTexture.patterned = patterned;
                }
            }
            else
            {
                bTexture.patterned = false;
            }

            if (bTexture.texture == null)
            {
                return;
            }

            Vector2 textureUnitSize = bTexture.textureUnitSize;
            if (bTexture.tiled)
            {
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("texture width", GUILayout.Width(75)); //, GUILayout.Width(42));
                textureUnitSize.x = EditorGUILayout.FloatField(bTexture.textureUnitSize.x, GUILayout.Width(25));
                EditorGUILayout.LabelField("metres", GUILayout.Width(40));        //, GUILayout.Width(42));
                EditorGUILayout.EndHorizontal();
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("texture height", GUILayout.Width(75));//, GUILayout.Width(42));
                textureUnitSize.y = EditorGUILayout.FloatField(bTexture.textureUnitSize.y, GUILayout.Width(25));
                EditorGUILayout.LabelField("metres", GUILayout.Width(40));
                EditorGUILayout.EndHorizontal();
                if (bTexture.textureUnitSize != textureUnitSize)
                {
                    bTexture.textureUnitSize = textureUnitSize;
                }
            }

            Vector2 tileUnitSize = bTexture.tileUnitUV;
            if (bTexture.patterned)
            {
                float minWidth  = 2 / bTexture.texture.width;
                float minHeight = 2 / bTexture.texture.height;

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("unit width", GUILayout.Width(75));
                float tileUnitSizex = EditorGUILayout.Slider(tileUnitSize.x, minWidth, 1.0f);
                if (tileUnitSizex != tileUnitSize.x)
                {
                    tileUnitSize.x = tileUnitSizex;
                }
                EditorGUILayout.EndHorizontal();
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("unit height", GUILayout.Width(75));
                float tileUnitSizey = EditorGUILayout.Slider(tileUnitSize.y, minHeight, 1.0f);
                if (tileUnitSizey != tileUnitSize.y)
                {
                    tileUnitSize.y = tileUnitSizey;
                }
                EditorGUILayout.EndHorizontal();
                bTexture.tileUnitUV = tileUnitSize;

                EditorGUILayout.Space();
            }

            const int previewTextureUnitSize = 120;
            const int previewTileUnitSize    = 59;
            const int previewTileUnitPadding = 2;
            const int previewPadding         = 25;

            EditorGUILayout.BeginHorizontal();
            if (bTexture.tiled)
            {
                EditorGUILayout.LabelField("1 Metre Squared", GUILayout.Width(previewTextureUnitSize));
            }
            GUILayout.Space(previewPadding);
            if (bTexture.patterned)
            {
                EditorGUILayout.LabelField("Texture Pattern Units", GUILayout.Width(previewTileUnitSize * 2));
            }
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.Space();


            if (Event.current.type == EventType.Repaint)
            {
                texturePreviewPostion = GUILayoutUtility.GetLastRect();
            }

            if (bTexture.tiled)
            {
                Rect previewRect = new Rect(texturePreviewPostion.x, texturePreviewPostion.y, previewTextureUnitSize, previewTextureUnitSize);
                Rect sourceRect  = new Rect(0, 0, (1.0f / textureUnitSize.x), (1.0f / textureUnitSize.y));

                Graphics.DrawTexture(previewRect, bTexture.texture, sourceRect, 0, 0, 0, 0);
            }

            if (bTexture.patterned)
            {
                Rect previewRect = new Rect(previewTextureUnitSize + previewPadding, 0, previewTileUnitSize, previewTileUnitSize);
                Rect sourceRect  = new Rect(0, tileUnitSize.y, tileUnitSize.x, tileUnitSize.y);

                previewRect.x += texturePreviewPostion.x;
                previewRect.y += texturePreviewPostion.y;

                Graphics.DrawTexture(previewRect, bTexture.texture, sourceRect, 0, 0, 0, 0);

                sourceRect.x  += tileUnitSize.x;
                previewRect.x += previewTileUnitSize + previewTileUnitPadding;

                Graphics.DrawTexture(previewRect, bTexture.texture, sourceRect, 0, 0, 0, 0);

                sourceRect.x  += -tileUnitSize.x;
                sourceRect.y  += -tileUnitSize.y;
                previewRect.x += -(previewTileUnitSize + previewTileUnitPadding);
                previewRect.y += previewTileUnitSize + previewTileUnitPadding;

                Graphics.DrawTexture(previewRect, bTexture.texture, sourceRect, 0, 0, 0, 0);

                sourceRect.x  += tileUnitSize.x;
                previewRect.x += previewTileUnitSize + previewTileUnitPadding;

                Graphics.DrawTexture(previewRect, bTexture.texture, sourceRect, 0, 0, 0, 0);
            }

            if (!bTexture.tiled)
            {
                EditorGUILayout.LabelField("Tile texture");

                EditorGUILayout.BeginHorizontal();
                int currentXTiles = bTexture.tiledX;
                GUILayout.Label("tile x", GUILayout.Width(38));
                currentXTiles = EditorGUILayout.IntField(currentXTiles, GUILayout.Width(20));
                if (GUILayout.Button("+", GUILayout.Width(25)))
                {
                    currentXTiles++;
                }
                EditorGUI.BeginDisabledGroup(currentXTiles < 2);
                if (GUILayout.Button("-", GUILayout.Width(25)))
                {
                    currentXTiles--;
                }
                EditorGUI.EndDisabledGroup();
                bTexture.tiledX = currentXTiles;

                int currentYTiles = bTexture.tiledY;
                GUILayout.Label("tile y", GUILayout.Width(38));
                currentYTiles = EditorGUILayout.IntField(currentYTiles, GUILayout.Width(20));
                if (GUILayout.Button("+", GUILayout.Width(25)))
                {
                    currentYTiles++;
                }
                EditorGUI.BeginDisabledGroup(currentYTiles < 2);
                if (GUILayout.Button("-", GUILayout.Width(25)))
                {
                    currentYTiles--;
                }
                EditorGUI.EndDisabledGroup();
                bTexture.tiledY = currentYTiles;
                EditorGUILayout.EndHorizontal();

                GUILayout.Space(10);
                EditorGUILayout.Space();
                if (Event.current.type == EventType.Repaint)
                {
                    texturePreviewPostion = GUILayoutUtility.GetLastRect();
                }

                Rect previewRect = new Rect(texturePreviewPostion.x, texturePreviewPostion.y, previewTextureUnitSize, previewTextureUnitSize);
                Rect sourceRect  = new Rect(0, 0, currentXTiles, currentYTiles);

                Graphics.DrawTexture(previewRect, bTexture.texture, sourceRect, 0, 0, 0, 0);
            }

            GUILayout.Space(previewTextureUnitSize);

            break;

        case BuildrTexture.Types.Substance:

            bTexture.proceduralMaterial = (ProceduralMaterial)EditorGUILayout.ObjectField("Procedural Material", bTexture.proceduralMaterial, typeof(ProceduralMaterial), false);

            if (bTexture.proceduralMaterial != null)
            {
                ProceduralMaterial pMat = bTexture.proceduralMaterial;
                GUILayout.Label(pMat.GetGeneratedTexture(pMat.mainTexture.name), GUILayout.Width(400));
            }
            else
            {
                EditorGUILayout.HelpBox("There is no substance material set.", MessageType.Error);
            }
            break;

        case BuildrTexture.Types.User:
            bTexture.userMaterial = (Material)EditorGUILayout.ObjectField("User Material", bTexture.userMaterial, typeof(Material), false);

            if (bTexture.userMaterial != null)
            {
                Material mat = bTexture.userMaterial;
                GUILayout.Label(mat.mainTexture, GUILayout.Width(400));
            }
            else
            {
                EditorGUILayout.HelpBox("There is no substance material set.", MessageType.Error);
            }
            break;
        }
    }
    public static void SceneGUI(BuildrEditMode editMode, BuildrData data, bool shouldSnap, float handleSize)
    {
        switch (mode)
        {
        case EditModes.general:
            //No scene actions
            break;

        case EditModes.floorplan:
            BuildrEditModeFloorplan.SceneGUI(editMode, data.plan, false, handleSize);
            break;
        }

        if (constraints.constrainPlanByArea)
        {
            Rect    area     = constraints.area;
            Vector3 position = editMode.transform.position;

            Vector3 areaLeft   = new Vector3(area.xMin, 0, (area.yMin + area.yMax) / 2);
            Vector3 areaRight  = new Vector3(area.xMax, 0, (area.yMin + area.yMax) / 2);
            Vector3 areaBottom = new Vector3((area.xMin + area.xMax) / 2, 0, area.yMin);
            Vector3 areaTop    = new Vector3((area.xMin + area.xMax) / 2, 0, area.yMax);

            Vector3 newAreaLeft   = Handles.Slider(areaLeft + position, Vector3.left, HandleUtility.GetHandleSize(areaLeft) * 0.666f, Handles.ArrowCap, 0.0f);
            Vector3 newAreaRight  = Handles.Slider(areaRight + position, Vector3.right, HandleUtility.GetHandleSize(areaLeft) * 0.666f, Handles.ArrowCap, 0.0f);
            Vector3 newAreaBottom = Handles.Slider(areaBottom + position, Vector3.back, HandleUtility.GetHandleSize(areaLeft) * 0.666f, Handles.ArrowCap, 0.0f);
            Vector3 newAreaTop    = Handles.Slider(areaTop + position, Vector3.forward, HandleUtility.GetHandleSize(areaLeft) * 0.666f, Handles.ArrowCap, 0.0f);

            newAreaLeft   -= position;
            newAreaRight  -= position;
            newAreaBottom -= position;
            newAreaTop    -= position;

            if (areaLeft != newAreaLeft)
            {
                area.xMin = Mathf.Min(newAreaLeft.x, area.xMax - 1.0f);
            }
            if (areaRight != newAreaRight)
            {
                area.xMax = Mathf.Max(newAreaRight.x, area.xMin + 1.0f);
            }
            if (areaBottom != newAreaBottom)
            {
                area.yMin = Mathf.Min(newAreaBottom.z, area.yMax - 1.0f);
            }
            if (areaTop != newAreaTop)
            {
                area.yMax = Mathf.Max(newAreaTop.z, area.yMin + 1.0f);
            }

            constraints.area = area;

            Vector3 coreBL = new Vector3(area.xMin, 0, area.yMin) + position;
            Vector3 coreBR = new Vector3(area.xMax, 0, area.yMin) + position;
            Vector3 coreTL = new Vector3(area.xMin, 0, area.yMax) + position;
            Vector3 coreTR = new Vector3(area.xMax, 0, area.yMax) + position;
            Handles.DrawLine(coreBL, coreBR);
            Handles.DrawLine(coreBR, coreTR);
            Handles.DrawLine(coreTR, coreTL);
            Handles.DrawLine(coreTL, coreBL);
        }
    }
Beispiel #23
0
    public static void SceneGUI(BuildrEditMode editMode, BuildrData _data, bool shouldSnap, float handleSize)
    {
        data = _data;
        Vector3 camDirection = Camera.current.transform.forward;
        Vector3 camPosition  = Camera.current.transform.position;

        int numberOfFacades  = data.facades.Count;
        int numberOfRoofs    = data.roofs.Count;
        int numberOfTextures = data.textures.Count;

        if (numberOfFacades == 0 || numberOfRoofs == 0 || numberOfTextures == 0)
        {
            return;
        }

        Vector3 position    = editMode.transform.position;
        float   floorHeight = data.floorHeight;

        BuildrPlan area            = data.plan;
        int        numberOfVolumes = area.numberOfVolumes;

        int facadeCounter = 0;

        for (int s = 0; s < numberOfVolumes; s++)
        {
            BuildrVolume volume      = data.plan.volumes[s];
            int          volumeSize  = volume.Count;
            Vector3      floorCentre = Vector3.zero;
            Handles.color = Color.white;

            for (int p = 0; p < volumeSize; p++)
            {
                int     point    = volume.points[p];
                Vector3 pointPos = area.points[point].vector3;
                floorCentre += pointPos;

                List <Vector3> verts        = new List <Vector3>();
                int            indexB       = (p < volumeSize - 1) ? p + 1 : 0;
                Vector3        volumeHeight = Vector3.up * (volume.numberOfFloors * data.floorHeight);
                verts.Add(pointPos + position);
                verts.Add(area.points[volume.points[indexB]].vector3 + position);
                verts.Add(verts[1] + volumeHeight);
                verts.Add(verts[0] + volumeHeight);
                if (s == selectedVolume && point == selectedPoint)
                {
                    //display something to highlight this facade
                    Handles.DrawSolidRectangleWithOutline(verts.ToArray(), Color.clear, BuildrColours.MAGENTA);
                }
                Handles.color = BuildrColours.CYAN;
                if (s == selectedRoofVolume)
                {
                    Handles.DrawLine(verts[2], verts[3]);
                }
                if (editMode.showFacadeMarkers)
                {
                    Handles.color = Color.white;
                    Vector3  facadeDirection  = Vector3.Cross((verts[0] - verts[1]), Vector3.up);
                    GUIStyle facadeLabelStyle = new GUIStyle();
                    facadeLabelStyle.normal.textColor = Color.white;
                    facadeLabelStyle.alignment        = TextAnchor.MiddleCenter;
                    facadeLabelStyle.fixedWidth       = 75.0f;
                    Vector3 centerPos     = (verts[0] + verts[1]) * 0.5f;
                    bool    camVisible    = Vector3.Dot(camDirection, centerPos - camPosition) > 0;
                    bool    facadeVisible = Vector3.Dot(camDirection, facadeDirection) < 0;
                    if (camVisible && facadeVisible)//only display label when facade is facing camera and is in camera view
                    {
                        Vector3 labelPos = centerPos + facadeDirection.normalized;
                        Handles.Label(labelPos, "facade " + facadeCounter, facadeLabelStyle);
                        Handles.DrawLine(centerPos, labelPos);
                    }
                }
                facadeCounter++;
            }
            floorCentre /= volumeSize;

            //Volume height/floor number slider
            Vector3 volumeHeightDir = Vector3.up * (volume.numberOfFloors * data.floorHeight);
            Vector3 volumePosition  = floorCentre + position + volumeHeightDir;
            if (Vector3.Dot(camDirection, volumePosition - camPosition) > 0)//only display label when facade is facing camera
            {
                Handles.Label(volumePosition + (Vector3.up * (handleSize * 0.1f)), "volume " + s);
                Handles.Label(volumePosition, "number of floors " + volume.numberOfFloors);
            }
            Handles.color = Color.green;
            volume.height = Handles.Slider(volumePosition, Vector3.up).y - position.y;
            if (volume.height < data.floorHeight)
            {
                volume.height = data.floorHeight;
            }

            volume.numberOfFloors = Mathf.RoundToInt(volume.height / floorHeight);
        }
    }
Beispiel #24
0
 public static void SceneGUI(BuildrEditMode editMode, BuildrData data, bool shouldSnap, float handleSize)
 {
 }
    public static void SceneGUI(BuildrEditMode _editMode, BuildrData _data, bool shouldSnap, float handleSize)
    {
        Vector3 camDirection = Camera.current.transform.forward;
        Vector3 camPosition = Camera.current.transform.position;
        Vector3 position = _editMode.transform.position;
        data = _data;
        BuildrPlan plan = data.plan;
        BuildrVolume selectedVolume = plan.volumes[selectedVolumeIndex];
        int selectedVolumeSize = selectedVolume.Count;
        Handles.color = Color.white;
        int facadeCounter = 0;

        GUIStyle whiteLabelStyle = new GUIStyle();
        whiteLabelStyle.normal.textColor = Color.white;
        whiteLabelStyle.alignment = TextAnchor.MiddleCenter;
        whiteLabelStyle.fixedWidth = 75.0f;

        int numberOfVolumes = plan.numberOfVolumes;
        for (int s = 0; s < numberOfVolumes; s++)
        {
            BuildrVolume volume = data.plan.volumes[s];
            int volumeSize = volume.Count;
            Vector3 floorCentre = Vector3.zero;

            for (int p = 0; p < volumeSize; p++)
            {
                int point = volume.points[p];
                Vector3 pointPos = plan.points[point].vector3;
                floorCentre += pointPos;
            }
            floorCentre /= volumeSize;

            if(s==selectedVolumeIndex)
            {
                whiteLabelStyle.normal.textColor = BuildrColours.RED;
                whiteLabelStyle.fontStyle = FontStyle.Bold;
            }
            else
            {
                whiteLabelStyle.normal.textColor = Color.white;
                whiteLabelStyle.fontStyle = FontStyle.Normal;
            }

            //Volume height/floor number slider
            Vector3 volumeHeightDir = Vector3.up * (volume.numberOfFloors * data.floorHeight);
            Vector3 volumePosition = floorCentre + position + volumeHeightDir;
            Handles.color = Color.white;
            if (Vector3.Dot(camDirection, volumePosition - camPosition) > 0)//only display label when facade is facing camera
            {
                Handles.Label(volumePosition + (Vector3.up * (handleSize * 0.1f)), "volume " + s, whiteLabelStyle);
            }
        }
        whiteLabelStyle.normal.textColor = Color.white;
        whiteLabelStyle.fontStyle = FontStyle.Normal;

        for (int p = 0; p < selectedVolumeSize; p++)
        {
            int point = selectedVolume.points[p];
            Vector3 pointPos = plan.points[point].vector3;

            List<Vector3> verts = new List<Vector3>();
            int indexB = (p < selectedVolumeSize - 1) ? p + 1 : 0;
            Vector3 floorHeightVector = Vector3.up * (selectedFloor * data.floorHeight);
            Vector3 ceilingHeightVector = Vector3.up * ((selectedFloor+1) * data.floorHeight);
            Vector3 p0 = pointPos + position;
            Vector3 p1 = plan.points[selectedVolume.points[indexB]].vector3 + position;
            verts.Add(pointPos + position);
            verts.Add(plan.points[selectedVolume.points[indexB]].vector3 + position);
            verts.Add(verts[1] + floorHeightVector);
            verts.Add(verts[0] + floorHeightVector);
            Handles.color = BuildrColours.RED;
            Handles.DrawLine(p0 + floorHeightVector, p1 + floorHeightVector);
            Handles.DrawLine(p0 + ceilingHeightVector, p1 + ceilingHeightVector);
            Handles.DrawLine(p0 + floorHeightVector, p0 + ceilingHeightVector);
            if (_editMode.showFacadeMarkers)
            {
                Handles.color = Color.white;
                Vector3 facadeDirection = Vector3.Cross((verts[0] - verts[1]), Vector3.up);
                Vector3 centerPos = (verts[0] + verts[1]) * 0.5f;
                bool camVisible = Vector3.Dot(camDirection, centerPos - camPosition) > 0;
                bool facadeVisible = Vector3.Dot(camDirection, facadeDirection) < 0;
                if (camVisible && facadeVisible)//only display label when facade is facing camera and is in camera view
                {
                    Vector3 labelPos = centerPos + facadeDirection.normalized;
                    Handles.Label(labelPos, "facade " + facadeCounter, whiteLabelStyle);
                    Handles.DrawLine(centerPos, labelPos);
                }
            }
            facadeCounter++;
        }
    }
Beispiel #26
0
    public static void InspectorGUI(BuildrEditMode editMode, BuildrData _data)
    {
        int helpWidth = 20;

        data = _data;

        Undo.RecordObject(data, "Facade Modified");

        BuildrFacadeDesign[] facades = data.facades.ToArray();
        int numberOfFacades          = facades.Length;

        selectedFacade = Mathf.Clamp(selectedFacade, 0, numberOfFacades - 1);

        if (numberOfFacades == 0)
        {
            EditorGUILayout.HelpBox("There are no facade designs to show", MessageType.Info);
            return;
        }

        bool hasUnusedFacades = false;
        int  unusedIndex      = 0;

        //Check all facades have een used and warn if there are unused ones
        for (int i = 0; i < numberOfFacades; i++)
        {
            bool facadeUnused = true;
            foreach (BuildrVolume volume in data.plan.volumes)
            {
                if (volume.ContainsFacade(i))
                {
                    facadeUnused = false;
                    break;
                }
            }
            if (facadeUnused)
            {
                hasUnusedFacades = true;
                unusedIndex      = i;
                break;
            }
        }
        if (hasUnusedFacades)
        {
            EditorGUILayout.HelpBox("There are facade designs that are not applied to your building and are unused.\nGo to the Building section to apply them to a facade.\nCheck facade design \"" + facades[unusedIndex].name + "\"", MessageType.Warning);
        }

        //Facade Selector
        EditorGUILayout.BeginVertical("box");
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Facade Design:", GUILayout.Width(145));
        string[] facadeNames = new string[numberOfFacades];
        for (int f = 0; f < numberOfFacades; f++)
        {
            facadeNames[f] = facades[f].name;
        }
        selectedFacade = EditorGUILayout.Popup(selectedFacade, facadeNames);
        BuildrFacadeDesign bFacade = facades[selectedFacade];

        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();

        if (GUILayout.Button("Add", GUILayout.Width(60)))
        {
            data.facades.Add(new BuildrFacadeDesign("new facade " + numberOfFacades));
            facades = data.facades.ToArray();
            numberOfFacades++;
            selectedFacade = numberOfFacades - 1;
        }

        if (GUILayout.Button("Duplicate", GUILayout.Width(90)))
        {
            data.facades.Add(bFacade.Duplicate());
            facades = data.facades.ToArray();
            numberOfFacades++;
            selectedFacade = numberOfFacades - 1;
        }

        if (GUILayout.Button("Delete", GUILayout.Width(70)))
        {
            if (EditorUtility.DisplayDialog("Deleting Facade Design Entry", "Are you sure you want to delete this facade?", "Delete", "Cancel"))
            {
                data.RemoveFacadeDesign(bFacade);
                selectedFacade = 0;
                GUI.changed    = true;

                return;
            }
        }

        if (GUILayout.Button("Import", GUILayout.Width(71)))
        {
            string xmlPath = EditorUtility.OpenFilePanel("Select the XML file...", "Assets/BuildR/Exported/", "xml");
            if (xmlPath == "")
            {
                return;
            }
            BuildrXMLImporter.ImportFacades(xmlPath, _data);
            facades        = _data.facades.ToArray();
            selectedFacade = 0;
            GUI.changed    = true;
        }

        if (GUILayout.Button("Export", GUILayout.Width(71)))
        {
            string xmlPath = EditorUtility.SaveFilePanel("Export as...", "Assets/BuildR/Exported/", _data.name + "_facadeLibrary", "xml");
            if (xmlPath == "")
            {
                return;
            }
            BuildrXMLExporter.ExportFacades(xmlPath, _data);
            GUI.changed = true;
        }
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.Space();
        EditorGUILayout.EndVertical();

        bFacade      = facades[selectedFacade];//reassign
        bFacade.name = EditorGUILayout.TextField("Facade Name: ", bFacade.name);


        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Facade Design Type:", GUILayout.Width(145));
        bFacade.type = (BuildrFacadeDesign.types)EditorGUILayout.EnumPopup(bFacade.type);
        if (GUILayout.Button("?", GUILayout.Width(helpWidth)))
        {
            string helpTitle = "Help - Design Type";
            string helpBody  = "This allows you to select the type of design you're using.\n" +
                               "Simple - the facade openings will be uniform\n" +
                               "Patterned - the facade openings will follow a pattern of defined dimensions and textures\n";
            EditorUtility.DisplayDialog(helpTitle, helpBody, "close");
        }
        EditorGUILayout.EndHorizontal();

        int numberOfTextures = data.textures.Count;

        string[] textureNames = new string[numberOfTextures];
        for (int t = 0; t < numberOfTextures; t++)
        {
            textureNames[t] = data.textures[t].name;
        }

        bFacade.hasWindows = EditorGUILayout.Toggle("Facade Has Bays", bFacade.hasWindows);

        if (bFacade.hasWindows)
        {
            if (bFacade.type == BuildrFacadeDesign.types.simple)
            {
                BuildrBay bbay = bFacade.simpleBay;

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("Render Bay", GUILayout.Width(146));
                bool renderBayBack = EditorGUILayout.Toggle(bbay.renderBack);
                if (renderBayBack != bbay.renderBack)
                {
                    bbay.renderBack = renderBayBack;
                }
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("Bay Model", GUILayout.Width(146));
                bbay.bayModel = (GameObject)EditorGUILayout.ObjectField(bbay.bayModel, typeof(GameObject), false);
                if (GUILayout.Button("Clear", GUILayout.Width(70)))
                {
                    bbay.bayModel = null;
                }
                EditorGUILayout.EndHorizontal();

                float bbayopeningWidth = Mathf.Max(EditorGUILayout.FloatField("Opening Width", bbay.openingWidth), 0);
                if (bbayopeningWidth != bbay.openingWidth)
                {
                    bbay.openingWidth = bbayopeningWidth;
                }
                float bbayopeningHeight = Mathf.Max(EditorGUILayout.FloatField("Opening Height", bbay.openingHeight), 0);
                if (bbayopeningHeight > data.floorHeight)
                {
                    bbayopeningHeight = data.floorHeight;
                }
                if (bbayopeningHeight != bbay.openingHeight)
                {
                    bbay.openingHeight = bbayopeningHeight;
                }
                float bbayminimumBayWidth = Mathf.Max(EditorGUILayout.FloatField("Min. Spacing", bbay.minimumBayWidth), 0);
                if (bbayminimumBayWidth != bbay.minimumBayWidth)
                {
                    bbay.minimumBayWidth = bbayminimumBayWidth;
                }

                float bbayopeningWidthRatio = EditorGUILayout.Slider("Horizontal Space Ratio", bbay.openingWidthRatio, 0, 1);
                if (bbayopeningWidthRatio != bbay.openingWidthRatio)
                {
                    bbay.openingWidthRatio = bbayopeningWidthRatio;
                }
                float bbayopeningHeightRatio = EditorGUILayout.Slider("Vertical Space Ratio", bbay.openingHeightRatio, 0, 1);
                if (bbayopeningHeightRatio != bbay.openingHeightRatio)
                {
                    bbay.openingHeightRatio = bbayopeningHeightRatio;
                }

                float bbayopeningDepth = EditorGUILayout.Slider("Opening Depth", bbay.openingDepth, -depth, depth);
                if (bbayopeningDepth != bbay.openingDepth)
                {
                    bbay.openingDepth = bbayopeningDepth;
                }
                float bbaycolumnDepth = EditorGUILayout.Slider("Column Depth", bbay.columnDepth, -depth, depth);
                if (bbaycolumnDepth != bbay.columnDepth)
                {
                    bbay.columnDepth = bbaycolumnDepth;
                }
                float bbayrowDepth = EditorGUILayout.Slider("Row Depth", bbay.rowDepth, -depth, depth);
                if (bbayrowDepth != bbay.rowDepth)
                {
                    bbay.rowDepth = bbayrowDepth;
                }
                float bbaycrossDepth = EditorGUILayout.Slider("Cross Depth", bbay.crossDepth, -depth, depth);
                if (bbaycrossDepth != bbay.crossDepth)
                {
                    bbay.crossDepth = bbaycrossDepth;
                }

                int      numberOfTextureSlots = bbay.numberOfTextures;
                string[] titles = new string[numberOfTextureSlots];
                for (int bft = 0; bft < numberOfTextureSlots; bft++)
                {
                    titles[bft] = ((BuildrBay.TextureNames)(bft)).ToString();
                }

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("Wall Surface:", GUILayout.Width(75));
                editTextureOnFacade = EditorGUILayout.Popup(editTextureOnFacade, titles);
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("Wall Texture:", GUILayout.Width(75));
                int newFacadeTextureID = EditorGUILayout.Popup(bbay.textureValues[editTextureOnFacade], textureNames);
                if (newFacadeTextureID != bbay.textureValues[editTextureOnFacade])
                {
                    bbay.textureValues[editTextureOnFacade] = newFacadeTextureID;
                }
                EditorGUILayout.EndHorizontal();
                BuildrTexture bTexture = data.textures[bbay.textureValues[editTextureOnFacade]];
                Texture2D     texture  = bTexture.texture;
                EditorGUILayout.BeginHorizontal();

                if (texture != null)
                {
                    GUILayout.Label(texture, GUILayout.Width(100), GUILayout.Height(100));
                }
                else
                {
                    EditorGUILayout.HelpBox("No texture assigned for '" + textureNames[bbay.textureValues[editTextureOnFacade]] + "', assign one in the Textures menu above", MessageType.Warning);
                }

                bbay.flipValues[editTextureOnFacade] = EditorGUILayout.Toggle("Flip 90\u00B0", bbay.flipValues[editTextureOnFacade]);

                EditorGUILayout.EndHorizontal();
            }
            else
            {
                //Patterned design GUI

                int numberOfBays       = bFacade.bayPattern.Count;
                int numberOfBayDesigns = data.bays.Count;

                EditorGUILayout.BeginHorizontal();
                GUILayout.BeginHorizontal("box");
                if (GUILayout.Button("Add New Bay Design"))
                {
                    BuildrBay newBay = new BuildrBay("new bay design " + (numberOfBayDesigns + 1));
                    data.bays.Add(newBay);
                    bFacade.bayPattern.Add(numberOfBayDesigns);
                    numberOfBays++;
                    selectedBayPatternIndex = numberOfBays - 1;
                    numberOfBayDesigns++;
                    GUI.changed = true;
                }
                EditorGUILayout.EndHorizontal();
                if (numberOfBays == 0 || data.bays.Count == 0)
                {
                    EditorGUILayout.HelpBox("There are no bay designs to show", MessageType.Info);
//                    EditorGUILayout.EndHorizontal();
                    EditorGUILayout.EndVertical();
                    return;
                }

                BuildrBay[] bays = new BuildrBay[numberOfBays];
                for (int i = 0; i < numberOfBays; i++)
                {
                    bays[i] = data.bays[bFacade.bayPattern[i]];
                }
                selectedBayPatternIndex = Mathf.Clamp(selectedBayPatternIndex, 0, numberOfBays - 1);

                EditorGUILayout.EndHorizontal();
                EditorGUILayout.BeginHorizontal();
                GUILayout.BeginHorizontal("box");
                string[] bayDesignNames = new string[data.bays.Count];
                for (int i = 0; i < numberOfBayDesigns; i++)
                {
                    bayDesignNames[i] = data.bays[i].name;
                }
                selectedBayDesign = EditorGUILayout.Popup(selectedBayDesign, bayDesignNames);
                if (GUILayout.Button("Add Selected"))
                {
                    bFacade.bayPattern.Add(selectedBayDesign);
                    GUI.changed = true;
                }
                if (GUILayout.Button("Duplicate Selected"))
                {
                    BuildrBay newBay = data.bays[selectedBayDesign].Duplicate();
                    data.bays.Add(newBay);
                    bFacade.bayPattern.Add(numberOfBayDesigns);
                    numberOfBays++;
                    selectedBayPatternIndex = numberOfBays - 1;
                    numberOfBayDesigns++;
                    GUI.changed = true;
                }
                EditorGUILayout.EndHorizontal();
                EditorGUILayout.EndHorizontal();

                GUILayout.BeginVertical("box");
                EditorGUILayout.LabelField("Bay Design Order:");
                var scrollbarHStyle    = new GUIStyle(GUI.skin.horizontalScrollbar);
                var scrollbarBackStyle = new GUIStyle();
                var scrollbarVStyle    = new GUIStyle(GUI.skin.verticalScrollbar);
                scrollbarVStyle.fixedHeight = scrollbarVStyle.fixedWidth = 0;
                bayDesignPatternScrollView  = EditorGUILayout.BeginScrollView(bayDesignPatternScrollView, false, false, scrollbarHStyle, scrollbarVStyle, scrollbarBackStyle, GUILayout.Height(40));
                List <string> bayNames = new List <string>();
                foreach (int bayIndex in bFacade.bayPattern)
                {
                    bayNames.Add(data.bays[bayIndex].name);
                }
                selectedBayPatternIndex = GUILayout.Toolbar(selectedBayPatternIndex, bayNames.ToArray());
                EditorGUILayout.EndScrollView();
                BuildrBay bBay = data.bays[bFacade.bayPattern[selectedBayPatternIndex]];

                EditorGUILayout.BeginHorizontal();

                EditorGUI.BeginDisabledGroup(selectedBayPatternIndex == 0);
                if (GUILayout.Button("<<", GUILayout.Width(40)))
                {
                    int bayDesignIndex = bFacade.bayPattern[selectedBayPatternIndex];
                    bFacade.bayPattern.RemoveAt(selectedBayPatternIndex);
                    bFacade.bayPattern.Insert(selectedBayPatternIndex - 1, bayDesignIndex);
                    selectedBayPatternIndex--;
                    GUI.changed = true;
                }
                EditorGUI.EndDisabledGroup();
                if (GUILayout.Button("Remove"))
                {
                    bFacade.bayPattern.RemoveAt(selectedBayPatternIndex);
                    GUI.changed = true;
                }
                if (GUILayout.Button("Delete"))
                {
                    if (EditorUtility.DisplayDialog("Deleting Bay Design Entry", "Are you sure you want to delete this bay?", "Delete", "Cancel"))
                    {
                        int deletedBayDesignIndex = bFacade.bayPattern[selectedBayPatternIndex];
                        Debug.Log("Delete Bay Design " + deletedBayDesignIndex);
                        Debug.Log("Delete Bay Design " + data.bays[deletedBayDesignIndex].name);
                        data.bays.RemoveAt(deletedBayDesignIndex);
                        int numberOfFacadeDesigns = data.facades.Count;
                        for (int i = 0; i < numberOfFacadeDesigns; i++)
                        {
                            BuildrFacadeDesign checkFacade = data.facades[i];
                            int bayPatternSize             = checkFacade.bayPattern.Count;
                            for (int j = 0; j < bayPatternSize; j++)
                            {
                                if (checkFacade.bayPattern[j] == deletedBayDesignIndex)
                                {
                                    checkFacade.bayPattern.RemoveAt(j);
                                    j--;
                                    bayPatternSize--;
                                }
                                else if (checkFacade.bayPattern[j] > deletedBayDesignIndex)
                                {
                                    checkFacade.bayPattern[j]--;
                                }
                            }
                        }
                        GUI.changed = true;
                    }
                }
                EditorGUI.BeginDisabledGroup(selectedBayPatternIndex == numberOfBays - 1);
                if (GUILayout.Button(">>", GUILayout.Width(40)))
                {
                    int bayDesignIndex = bFacade.bayPattern[selectedBayPatternIndex];
                    bFacade.bayPattern.Insert(selectedBayPatternIndex + 2, bayDesignIndex);
                    bFacade.bayPattern.RemoveAt(selectedBayPatternIndex);
                    selectedBayPatternIndex++;
                    GUI.changed = true;
                }
                EditorGUI.EndDisabledGroup();
                EditorGUILayout.EndHorizontal();
                EditorGUILayout.EndVertical();

                GUILayout.Space(10);
                EditorGUILayout.BeginVertical("box");
                bBay.name = EditorGUILayout.TextField("Name: ", bBay.name);
                bool bBayisOpening = EditorGUILayout.Toggle("Has Opening", bBay.isOpening);
                if (bBayisOpening != bBay.isOpening)
                {
                    bBay.isOpening = bBayisOpening;
                }

                bool bBayRenderBack = EditorGUILayout.Toggle("Render Back", bBay.renderBack);
                if (bBayRenderBack != bBay.renderBack)
                {
                    bBay.renderBack = bBayRenderBack;
                }

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("Bay Model", GUILayout.Width(146));
                bBay.bayModel = (GameObject)EditorGUILayout.ObjectField(bBay.bayModel, typeof(GameObject), false);
                if (GUILayout.Button("Clear", GUILayout.Width(70)))
                {
                    bBay.bayModel = null;
                }
                EditorGUILayout.EndHorizontal();

                float bBayopeningWidth = Mathf.Max(EditorGUILayout.FloatField("Opening Width", bBay.openingWidth), 0);
                if (bBayopeningWidth != bBay.openingWidth)
                {
                    bBay.openingWidth = bBayopeningWidth;
                }
                float bBayopeningHeight = Mathf.Clamp(EditorGUILayout.FloatField("Opening Height", bBay.openingHeight), 0, data.floorHeight);
                if (bBayopeningHeight != bBay.openingHeight)
                {
                    bBay.openingHeight = bBayopeningHeight;
                }

                float bBayminimumBayWidth = Mathf.Max(EditorGUILayout.FloatField("Bay Spacing Width", bBay.minimumBayWidth), 0);
                if (bBayminimumBayWidth != bBay.minimumBayWidth)
                {
                    bBay.minimumBayWidth = bBayminimumBayWidth;
                }

                float bBayopeningWidthRatio = EditorGUILayout.Slider("Horizontal Space Ratio", bBay.openingWidthRatio, 0, 1);
                if (bBayopeningWidthRatio != bBay.openingWidthRatio)
                {
                    bBay.openingWidthRatio = bBayopeningWidthRatio;
                }
                float bBayopeningHeightRatio = EditorGUILayout.Slider("Vertical Space Ratio", bBay.openingHeightRatio, 0, 1);
                if (bBayopeningHeightRatio != bBay.openingHeightRatio)
                {
                    bBay.openingHeightRatio = bBayopeningHeightRatio;
                }

                float bBayopeningDepth = EditorGUILayout.Slider("Opening Depth", bBay.openingDepth, -depth, depth);
                if (bBayopeningDepth != bBay.openingDepth)
                {
                    bBay.openingDepth = bBayopeningDepth;
                }
                float bBaycolumnDepth = EditorGUILayout.Slider("Column depth", bBay.columnDepth, -depth, depth);
                if (bBaycolumnDepth != bBay.columnDepth)
                {
                    bBay.columnDepth = bBaycolumnDepth;
                }
                float bBayrowDepth = EditorGUILayout.Slider("Row depth", bBay.rowDepth, -depth, depth);
                if (bBayrowDepth != bBay.rowDepth)
                {
                    bBay.rowDepth = bBayrowDepth;
                }
                float bBaycrossDepth = EditorGUILayout.Slider("Cross depth", bBay.crossDepth, -depth, depth);
                if (bBaycrossDepth != bBay.crossDepth)
                {
                    bBay.crossDepth = bBaycrossDepth;
                }

                //BAY TEXTURES

                int      numberOfTextureSlots = bBay.numberOfTextures;
                string[] titles = new string[numberOfTextureSlots];
                for (int bft = 0; bft < numberOfTextureSlots; bft++)
                {
                    titles[bft] = ((BuildrBay.TextureNames)(bft)).ToString();
                }

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("Surface:", GUILayout.Width(75));
                editTextureOnFacade = EditorGUILayout.Popup(editTextureOnFacade, titles);
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("Texture:", GUILayout.Width(75));
                bBay.textureValues[editTextureOnFacade] = EditorGUILayout.Popup(bBay.textureValues[editTextureOnFacade], textureNames);
                EditorGUILayout.EndHorizontal();
                BuildrTexture bTexture = data.textures[bBay.textureValues[editTextureOnFacade]];
                Texture2D     texture  = bTexture.texture;
                EditorGUILayout.BeginHorizontal();

                if (texture != null)
                {
                    GUILayout.Label(texture, GUILayout.Width(100), GUILayout.Height(100));
                }
                else
                {
                    EditorGUILayout.HelpBox("No texture assigned for '" + textureNames[bBay.textureValues[editTextureOnFacade]] + "', assign one in the Textures menu above", MessageType.Warning);
                }

                bFacade.flipValues[editTextureOnFacade] = EditorGUILayout.Toggle("Flip 90\u00B0", bFacade.flipValues[editTextureOnFacade]);

                EditorGUILayout.EndHorizontal();
                EditorGUILayout.EndVertical();
            }
        }
        else
        {
            editTextureOnFacade = 7;
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Surface:", GUILayout.Width(75));
            EditorGUILayout.LabelField("Wall");
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Texture:", GUILayout.Width(75));
            int newFacadeTexture = EditorGUILayout.Popup(bFacade.simpleBay.textureValues[editTextureOnFacade], textureNames);
            if (newFacadeTexture != bFacade.simpleBay.textureValues[editTextureOnFacade])
            {
                bFacade.simpleBay.textureValues[editTextureOnFacade] = newFacadeTexture;
            }
            EditorGUILayout.EndHorizontal();
            BuildrTexture bTexture = data.textures[bFacade.simpleBay.textureValues[editTextureOnFacade]];
            Texture2D     texture  = bTexture.texture;
            EditorGUILayout.BeginHorizontal();

            if (texture != null)
            {
                GUILayout.Label(texture, GUILayout.Width(100), GUILayout.Height(100));
            }
            else
            {
                EditorGUILayout.HelpBox("No texture assigned for '" + textureNames[bFacade.simpleBay.textureValues[editTextureOnFacade]] + "', assign one in the Textures menu above", MessageType.Warning);
            }

            bFacade.simpleBay.flipValues[editTextureOnFacade] = EditorGUILayout.Toggle("Flip 90\u00B0", bFacade.simpleBay.flipValues[editTextureOnFacade]);

            EditorGUILayout.EndHorizontal();
        }
    }
 public static void SceneGUI(BuildrEditMode editMode, BuildrData data, bool shouldSnap, float handleSize)
 {
 }
    public static void InspectorGUI(BuildrEditMode _editMode, BuildrData _data)
    {
        data = _data;
        BuildrTexture[] textures = data.textures.ToArray();
        int numberOfTextures = textures.Length;
        selectedTexture = Mathf.Clamp(selectedTexture, 0, numberOfTextures - 1);
        int currentSelectedTexture = selectedTexture;//keep tack of what we had selected to reset fields if changed

        Undo.RecordObject(data, "Texture Modified");

        if(numberOfTextures == 0)
        {
            EditorGUILayout.HelpBox("There are no textures to show", MessageType.Info);
            if(GUILayout.Button("Add New"))
            {
                data.textures.Add(new BuildrTexture("new texture " + numberOfTextures));
                numberOfTextures++;
                selectedTexture = numberOfTextures - 1;
            }
            return;
        }

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Texture", GUILayout.Width(75));
        string[] textureNames = new string[numberOfTextures];
        for(int t = 0; t < numberOfTextures; t++)
            textureNames[t] = textures[t].name;
        selectedTexture = EditorGUILayout.Popup(selectedTexture, textureNames);
        EditorGUILayout.EndHorizontal();

        BuildrTexture bTexture = textures[selectedTexture];

        EditorGUILayout.BeginHorizontal();

        EditorGUILayout.Space();

        if(GUILayout.Button("Add New", GUILayout.Width(81)))
        {
            data.textures.Add(new BuildrTexture("new texture " + numberOfTextures));
            numberOfTextures++;
            selectedTexture = numberOfTextures - 1;
        }

        if(GUILayout.Button("Duplicate", GUILayout.Width(90)))
        {
            data.textures.Add(bTexture.Duplicate());
            numberOfTextures++;
            selectedTexture = numberOfTextures - 1;

        }

        if(GUILayout.Button("Delete", GUILayout.Width(71)))
        {
            if(EditorUtility.DisplayDialog("Deleting Texture Entry", "Are you sure you want to delete this texture?", "Delete", "Cancel"))
            {
                data.RemoveTexture(bTexture);
                selectedTexture = 0;
                GUI.changed = true;

                return;
            }
        }

        if (GUILayout.Button("Import", GUILayout.Width(71)))
        {
            string xmlPath = EditorUtility.OpenFilePanel("Select the XML file...", "Assets/BuildR/Exported/", "xml");
            if (xmlPath == "")
                return;
            BuildrXMLImporter.ImportTextures(xmlPath, _data);
            textures = data.textures.ToArray();
            selectedTexture = 0;
            GUI.changed = true;
        }

        if (GUILayout.Button("Export", GUILayout.Width(71)))
        {
            string xmlPath = EditorUtility.SaveFilePanel("Export as...", "Assets/BuildR/Exported/", _data.name + "_textureLibrary", "xml");
            if (xmlPath == "")
                return;
            BuildrXMLExporter.ExportTextures(xmlPath, _data);
            GUI.changed = true;
        }
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.Space();

        textures = data.textures.ToArray();
        textureNames = new string[numberOfTextures];
        for(int t = 0; t < numberOfTextures; t++)
            textureNames[t] = textures[t].name;
        bTexture = textures[selectedTexture];//reassign

        string textureName = bTexture.name;
        GUIStyle redText = new GUIStyle(GUI.skin.textField);
        if(textureName.Contains(" "))
        {
            redText.focused.textColor = Color.red;
            textureName = EditorGUILayout.TextField("Name", textureName, redText);
        }
        else
        {
            redText.focused.textColor = defaultCol;
            textureName = EditorGUILayout.TextField("Name", textureName, redText);
        }
        bTexture.name = textureName;

        bool conflictingName = false;
        for(int i = 0; i < textureNames.Length; i++)
        {
            if(selectedTexture != i)
            {
                if(textureNames[i] == bTexture.name)
                    conflictingName = true;
            }
        }

        if(conflictingName)
            EditorGUILayout.HelpBox("You have named this texture the same as another.", MessageType.Warning);

        if(currentSelectedTexture != selectedTexture)
        {
            GUIUtility.hotControl = 0;
            GUIUtility.keyboardControl = 0;
        }

        bTexture.type = (BuildrTexture.Types)EditorGUILayout.EnumPopup("Type", bTexture.type);

        switch(bTexture.type)
        {
            case BuildrTexture.Types.Basic:

            if(bTexture.texture != null)
            {
                string texturePath = AssetDatabase.GetAssetPath(bTexture.texture);
                TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(texturePath);

                if(!textureImporter.isReadable)
                {
                    EditorGUILayout.HelpBox("The texture you have selected is not readable." + "\nPlease select the readable checkbox under advanced texture settings." + "\nOr move this texture to the BuildR texture folder and reimport.", MessageType.Error);
                }
            }

            //Shader Time
            Shader[] tempshaders = (Shader[])Resources.FindObjectsOfTypeAll(typeof(Shader));
            List<string> shaderNames = new List<string>(ShaderProperties.NAMES);
            foreach(Shader shader in tempshaders)
            {
                if(!string.IsNullOrEmpty(shader.name) && !shader.name.StartsWith("__") && !shader.name.Contains("hidden"))
                    shaderNames.Add(shader.name);
            }
            int selectedShaderIndex = shaderNames.IndexOf(bTexture.material.shader.name);
            int newSelectedShaderIndex = EditorGUILayout.Popup("Shader", selectedShaderIndex, shaderNames.ToArray());
            if(selectedShaderIndex != newSelectedShaderIndex)
            {
                bTexture.material.shader = Shader.Find(shaderNames[newSelectedShaderIndex]);
            }

            Shader selectedShader = bTexture.material.shader;
            int propertyCount = ShaderUtil.GetPropertyCount(selectedShader);

            for(int s = 0; s < propertyCount; s++)
            {
                ShaderUtil.ShaderPropertyType propertyTpe = ShaderUtil.GetPropertyType(selectedShader, s);
                string shaderPropertyName = ShaderUtil.GetPropertyName(selectedShader, s);
                switch(propertyTpe)
                {
                    case ShaderUtil.ShaderPropertyType.TexEnv:
                        Texture shaderTexture = bTexture.material.GetTexture(shaderPropertyName);
                        Texture newShaderTexture = (Texture)EditorGUILayout.ObjectField(shaderPropertyName, shaderTexture, typeof(Texture), false);
                        if(shaderTexture != newShaderTexture)
                        {
                            bTexture.material.SetTexture(shaderPropertyName, newShaderTexture);
                        }
                        break;

                    case ShaderUtil.ShaderPropertyType.Color:
                        Color shaderColor = bTexture.material.GetColor(shaderPropertyName);
                        Color newShaderColor = EditorGUILayout.ColorField(shaderPropertyName, shaderColor);
                        if(shaderColor != newShaderColor)
                        {
                            bTexture.material.SetColor(shaderPropertyName, newShaderColor);
                        }
                        break;

                    case ShaderUtil.ShaderPropertyType.Float:
                        float shaderFloat = bTexture.material.GetFloat(shaderPropertyName);
                        float newShaderFloat = EditorGUILayout.FloatField(shaderPropertyName, shaderFloat);
                        if(shaderFloat != newShaderFloat)
                        {
                            bTexture.material.SetFloat(shaderPropertyName, newShaderFloat);
                        }
                        break;

                    case ShaderUtil.ShaderPropertyType.Range:
                        float shaderRange = bTexture.material.GetFloat(shaderPropertyName);
                        float rangeMin = ShaderUtil.GetRangeLimits(selectedShader, s, 1);
                        float rangeMax = ShaderUtil.GetRangeLimits(selectedShader, s, 2);
                        float newShaderRange = EditorGUILayout.Slider(shaderPropertyName, shaderRange, rangeMin, rangeMax);
                        if(shaderRange != newShaderRange)
                        {
                            bTexture.material.SetFloat(shaderPropertyName, newShaderRange);
                        }
                        break;

                    case ShaderUtil.ShaderPropertyType.Vector:
                        Vector3 shaderVector = bTexture.material.GetVector(shaderPropertyName);
                        Vector3 newShaderVector = EditorGUILayout.Vector3Field(shaderPropertyName, shaderVector);
                        if(shaderVector != newShaderVector)
                        {
                            bTexture.material.SetVector(shaderPropertyName, newShaderVector);
                        }
                        break;
                }
            }

            bool tiled = EditorGUILayout.Toggle("Is Tiled", bTexture.tiled);
            if(tiled != bTexture.tiled)
            {
                bTexture.tiled = tiled;
            }
            if(bTexture.tiled)
            {
                bool patterned = EditorGUILayout.Toggle("Has Pattern", bTexture.patterned);
                if(patterned != bTexture.patterned)
                {
                    bTexture.patterned = patterned;
                }
            }
            else
                bTexture.patterned = false;

            if(bTexture.texture == null)
                return;

            Vector2 textureUnitSize = bTexture.textureUnitSize;
            if(bTexture.tiled)
            {
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("texture width", GUILayout.Width(75));//, GUILayout.Width(42));
                textureUnitSize.x = EditorGUILayout.FloatField(bTexture.textureUnitSize.x, GUILayout.Width(25));
                EditorGUILayout.LabelField("metres", GUILayout.Width(40));//, GUILayout.Width(42));
                EditorGUILayout.EndHorizontal();
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("texture height", GUILayout.Width(75));//, GUILayout.Width(42));
                textureUnitSize.y = EditorGUILayout.FloatField(bTexture.textureUnitSize.y, GUILayout.Width(25));
                EditorGUILayout.LabelField("metres", GUILayout.Width(40));
                EditorGUILayout.EndHorizontal();
                if(bTexture.textureUnitSize != textureUnitSize)
                {
                    bTexture.textureUnitSize = textureUnitSize;
                }
            }

            Vector2 tileUnitSize = bTexture.tileUnitUV;
            if(bTexture.patterned)
            {
                float minWidth = 2 / bTexture.texture.width;
                float minHeight = 2 / bTexture.texture.height;

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("unit width", GUILayout.Width(75));
                float tileUnitSizex = EditorGUILayout.Slider(tileUnitSize.x, minWidth, 1.0f);
                if(tileUnitSizex != tileUnitSize.x)
                {
                    tileUnitSize.x = tileUnitSizex;
                }
                EditorGUILayout.EndHorizontal();
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("unit height", GUILayout.Width(75));
                float tileUnitSizey = EditorGUILayout.Slider(tileUnitSize.y, minHeight, 1.0f);
                if(tileUnitSizey != tileUnitSize.y)
                {
                    tileUnitSize.y = tileUnitSizey;
                }
                EditorGUILayout.EndHorizontal();
                bTexture.tileUnitUV = tileUnitSize;

                EditorGUILayout.Space();
            }

            const int previewTextureUnitSize = 120;
            const int previewTileUnitSize = 59;
            const int previewTileUnitPadding = 2;
            const int previewPadding = 25;

            EditorGUILayout.BeginHorizontal();
            if(bTexture.tiled)
            {
                EditorGUILayout.LabelField("1 Metre Squared", GUILayout.Width(previewTextureUnitSize));
            }
            GUILayout.Space(previewPadding);
            if(bTexture.patterned)
            {
                EditorGUILayout.LabelField("Texture Pattern Units", GUILayout.Width(previewTileUnitSize * 2));
            }
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.Space();

            if(Event.current.type == EventType.Repaint)
                texturePreviewPostion = GUILayoutUtility.GetLastRect();

            if(bTexture.tiled)
            {
                Rect previewRect = new Rect(texturePreviewPostion.x, texturePreviewPostion.y, previewTextureUnitSize, previewTextureUnitSize);
                Rect sourceRect = new Rect(0, 0, (1.0f / textureUnitSize.x), (1.0f / textureUnitSize.y));

                Graphics.DrawTexture(previewRect, bTexture.texture, sourceRect, 0, 0, 0, 0);
            }

            if(bTexture.patterned)
            {
                Rect previewRect = new Rect(previewTextureUnitSize + previewPadding, 0, previewTileUnitSize, previewTileUnitSize);
                Rect sourceRect = new Rect(0, tileUnitSize.y, tileUnitSize.x, tileUnitSize.y);

                previewRect.x += texturePreviewPostion.x;
                previewRect.y += texturePreviewPostion.y;

                Graphics.DrawTexture(previewRect, bTexture.texture, sourceRect, 0, 0, 0, 0);

                sourceRect.x += tileUnitSize.x;
                previewRect.x += previewTileUnitSize + previewTileUnitPadding;

                Graphics.DrawTexture(previewRect, bTexture.texture, sourceRect, 0, 0, 0, 0);

                sourceRect.x += -tileUnitSize.x;
                sourceRect.y += -tileUnitSize.y;
                previewRect.x += -(previewTileUnitSize + previewTileUnitPadding);
                previewRect.y += previewTileUnitSize + previewTileUnitPadding;

                Graphics.DrawTexture(previewRect, bTexture.texture, sourceRect, 0, 0, 0, 0);

                sourceRect.x += tileUnitSize.x;
                previewRect.x += previewTileUnitSize + previewTileUnitPadding;

                Graphics.DrawTexture(previewRect, bTexture.texture, sourceRect, 0, 0, 0, 0);
            }

            if(!bTexture.tiled)
            {
                EditorGUILayout.LabelField("Tile texture");

                EditorGUILayout.BeginHorizontal();
                int currentXTiles = bTexture.tiledX;
                GUILayout.Label("tile x", GUILayout.Width(38));
                currentXTiles = EditorGUILayout.IntField(currentXTiles, GUILayout.Width(20));
                if(GUILayout.Button("+", GUILayout.Width(25)))
                {
                    currentXTiles++;
                }
                EditorGUI.BeginDisabledGroup(currentXTiles < 2);
                if(GUILayout.Button("-", GUILayout.Width(25)))
                {
                    currentXTiles--;
                }
                EditorGUI.EndDisabledGroup();
                bTexture.tiledX = currentXTiles;

                int currentYTiles = bTexture.tiledY;
                GUILayout.Label("tile y", GUILayout.Width(38));
                currentYTiles = EditorGUILayout.IntField(currentYTiles, GUILayout.Width(20));
                if(GUILayout.Button("+", GUILayout.Width(25)))
                {
                    currentYTiles++;
                }
                EditorGUI.BeginDisabledGroup(currentYTiles < 2);
                if(GUILayout.Button("-", GUILayout.Width(25)))
                {
                    currentYTiles--;
                }
                EditorGUI.EndDisabledGroup();
                bTexture.tiledY = currentYTiles;
                EditorGUILayout.EndHorizontal();

                GUILayout.Space(10);
                EditorGUILayout.Space();
                if(Event.current.type == EventType.Repaint)
                    texturePreviewPostion = GUILayoutUtility.GetLastRect();

                Rect previewRect = new Rect(texturePreviewPostion.x, texturePreviewPostion.y, previewTextureUnitSize, previewTextureUnitSize);
                Rect sourceRect = new Rect(0, 0, currentXTiles, currentYTiles);

                Graphics.DrawTexture(previewRect, bTexture.texture, sourceRect, 0, 0, 0, 0);
            }

            GUILayout.Space(previewTextureUnitSize);

            break;
        case BuildrTexture.Types.Substance:

            bTexture.proceduralMaterial = (ProceduralMaterial)EditorGUILayout.ObjectField("Procedural Material", bTexture.proceduralMaterial, typeof(ProceduralMaterial), false);

            if(bTexture.proceduralMaterial != null)
            {
                ProceduralMaterial pMat = bTexture.proceduralMaterial;
                GUILayout.Label(pMat.GetGeneratedTexture(pMat.mainTexture.name), GUILayout.Width(400));
            }
            else
            {
                EditorGUILayout.HelpBox("There is no substance material set.", MessageType.Error);
            }
            break;

        case BuildrTexture.Types.User:
            bTexture.userMaterial = (Material)EditorGUILayout.ObjectField("User Material", bTexture.userMaterial, typeof(Material), false);

            if (bTexture.userMaterial != null)
            {
                Material mat = bTexture.userMaterial;
                GUILayout.Label(mat.mainTexture, GUILayout.Width(400));
            }
            else
                EditorGUILayout.HelpBox("There is no substance material set.", MessageType.Error);
            break;
        }
    }
    public static void InspectorGUI(BuildrEditMode editMode, BuildrData data)
    {
        if (data.plan==null || data.plan.numberOfVolumes == 0)
        {
            EditorGUILayout.HelpBox("There are no defined volumes, go to Floorplan and define one", MessageType.Error);
            return;
        }

        const int guiWidth = 400;
        const int textWidth = 348;
        const int toggleWidth = 25;
        const int helpWidth = 20;

        CURRENT_TRANSFORM = editMode.transform;
        EditorGUILayout.Space();
        EditorGUILayout.Space();
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Filename", GUILayout.Width(225));
        data.exportFilename = EditorGUILayout.TextField(data.exportFilename, GUILayout.Width(175));
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.Space();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Filetype", GUILayout.Width(350));
        data.filetype = (BuildrData.filetypes)EditorGUILayout.EnumPopup(data.filetype, GUILayout.Width(50));
        switch (data.filetype)
        {
            case BuildrData.filetypes.obj:
                FILE_EXTENTION = ".obj";
                break;
            case BuildrData.filetypes.fbx:
                FILE_EXTENTION = ".fbx";
                break;
        }
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.Space();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Export Full Mesh", GUILayout.Width(textWidth));
        data.fullmesh = EditorGUILayout.Toggle(data.fullmesh, GUILayout.Width(toggleWidth));
        if (GUILayout.Button("?", GUILayout.Width(helpWidth)))
        {
            string helpTitle = "Help - Export Full Mesh";
            string helpBody = "Select this checkbox if you want your export the full detail model.";
            EditorUtility.DisplayDialog(helpTitle, helpBody, "close");
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Place Exported Model Into Scene", GUILayout.Width(textWidth));
        data.placeIntoScene = EditorGUILayout.Toggle(data.placeIntoScene, GUILayout.Width(toggleWidth));
        if (GUILayout.Button("?", GUILayout.Width(helpWidth)))
        {
            string helpTitle = "Help - Place Exported Model Into Scene";
            string helpBody = "Select this checkbox if you want your exported models to be copied into your scene." +
                "\nThese will be positioned correctly and will include colliders and LOD models if you opt to export them also.";
            EditorUtility.DisplayDialog(helpTitle, helpBody, "close");
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Copy Textures into Export Folder", GUILayout.Width(textWidth));
        data.copyTexturesIntoExportFolder = EditorGUILayout.Toggle(data.copyTexturesIntoExportFolder, GUILayout.Width(toggleWidth));
        if (GUILayout.Button("?", GUILayout.Width(helpWidth)))
        {
            string helpTitle = "Help - Copy Textures into Export Folder";
            string helpBody = "Check this box if you want to copy the textures you are using into the export folder." +
                "\nThis is useful if you plan to use the exported model elsewhere. Having the model and the textures in one folder will allow you to move this model with ease.";
            EditorUtility.DisplayDialog(helpTitle, helpBody, "close");
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Export Collider");
        data.generateCollider = (BuildrData.ColliderGenerationModes)EditorGUILayout.EnumPopup(data.generateCollider, GUILayout.Width(80));
        if (GUILayout.Button("?", GUILayout.Width(helpWidth)))
        {
            string helpTitle = "Help - Export Collider Mesh";
            string helpBody = "Check this box if you wish to generate a collider mesh for your model." +
                "\nThis will generate a mesh to be used with colliders.";
            EditorUtility.DisplayDialog(helpTitle, helpBody, "close");
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Export as Prefab", GUILayout.Width(textWidth));
        data.createPrefabOnExport = EditorGUILayout.Toggle(data.createPrefabOnExport, GUILayout.Width(toggleWidth));
        if (GUILayout.Button("?", GUILayout.Width(helpWidth)))
        {
            string helpTitle = "Help - Export as Prefab";
            string helpBody = "Select this if you wish to create a prefab of your model." +
                "\nThis is recommended if you're exporting a collider so they will get packaged together.";
            EditorUtility.DisplayDialog(helpTitle, helpBody, "close");
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Export a Low Detail Version", GUILayout.Width(textWidth));
        data.exportLowLOD = EditorGUILayout.Toggle(data.exportLowLOD, GUILayout.Width(toggleWidth));
        if (GUILayout.Button("?", GUILayout.Width(helpWidth)))
        {
            string helpTitle = "Help - Export a Low Detail Version";
            string helpBody = "Check this box to export a simplified model of your building." +
                "\nIdeal to use as a low level of detail version of your model." +
                "\nGeometry will be significantly reduced." +
                "\nFacades will flat and exported as a single atlased texture" +
                "\nThe model will use 1 draw call and will have around 10% of the triangles and verticies";
            EditorUtility.DisplayDialog(helpTitle, helpBody, "close");
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Export with tangents", GUILayout.Width(textWidth));
        data.includeTangents = EditorGUILayout.Toggle(data.includeTangents, GUILayout.Width(toggleWidth));
        if (GUILayout.Button("?", GUILayout.Width(helpWidth)))
        {
            string helpTitle = "Help - with tangents";
            string helpBody = "Export the models with calculated tangents." +
                "\nSome shaders require tangents to be calculated on the model." +
                "\nUnity will do this automatically on all imported meshes so it's not neccessary here." +
                "/nBut you might want them if you're taking them to another program.";
            EditorUtility.DisplayDialog(helpTitle, helpBody, "close");
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.Space();

        bool unreadableTextures = false;
        bool nullTextures = false;
        string unreadableTextureList = "";
        foreach (BuildrTexture bTexture in data.textures)//check texture readablility
        {
            if(bTexture.type == BuildrTexture.Types.Substance)
                continue;//substances are preset in BuildrTexture class
            if (bTexture.texture != null)
            {
                string texturePath = AssetDatabase.GetAssetPath(bTexture.texture);
                TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(texturePath);
                if (!textureImporter.isReadable)
                {
                    unreadableTextures = true;
                    if (unreadableTextureList.Length > 0)
                        unreadableTextureList += ", ";
                    unreadableTextureList += "'" + bTexture.name + "'";
                }
            }
            else
            {
                nullTextures = true;
            }
        }

        if (unreadableTextures)
        {
            EditorGUILayout.HelpBox("Unreadable Texture Error." +
                "\nThe following textures you are useing are not readable." +
                "\n" + unreadableTextureList + "." +
                "\nPlease select the readable checkbox under advanced texture settings." +
                "\nOr move this texture to the BuildR texture folder and reimport.",
                MessageType.Error);
        }

        if (nullTextures)
        {
            EditorGUILayout.HelpBox("Null Texture Error" +
                "\nSome of the textures have not been set" +
                "\nEnsure you are not using null textures to proceed.",
                MessageType.Error);
        }

        bool usingSubstances = false;
        foreach(BuildrTexture bTexture in data.textures)
        {
            if(bTexture.type == BuildrTexture.Types.Substance)
            {
                usingSubstances = true;
                break;
            }
        }
        if (usingSubstances)
        {
            EditorGUILayout.HelpBox("Model uses Substance textures." +
                "\nExporting model to " + data.filetype + " will lose references to this texture and it will be rendered white.",
                MessageType.Warning);
        }

        EditorGUI.BeginDisabledGroup(unreadableTextures || nullTextures);

        if (GUILayout.Button("Export", GUILayout.Width(guiWidth), GUILayout.Height(40)))
        {
            ExportModel(data);
        }

        if (GUILayout.Button("Export Data to XML", GUILayout.Width(guiWidth)))
        {
            BuildrXMLExporter.Export(ROOT_FOLDER + data.exportFilename + "/", data.exportFilename, data);
            AssetDatabase.Refresh();
        }

        EditorGUI.EndDisabledGroup();

        CURRENT_TRANSFORM = null;
    }
 public static void SceneGUI(BuildrEditMode editMode, BuildrData data, bool shouldSnap, float handleSize)
 {
     if (GUI.changed)
     {
         EditorUtility.SetDirty(editMode);
         EditorUtility.SetDirty(data);
         editMode.UpdateRender();
     }
 }
    public static void SceneGUI(BuildrEditMode editMode, BuildrData data, bool shouldSnap, float handleSize)
    {
        if (data.details.Count == 0)
            return;
        Undo.RecordObject(data, "Detail Modified");

        int numberOfFacades = data.facades.Count;
        int numberOfRoofs = data.roofs.Count;
        int numberOfTextures = data.textures.Count;

        if (numberOfFacades == 0 || numberOfRoofs == 0 || numberOfTextures == 0)
            return;

        Vector3 position = editMode.transform.position;

        BuildrPlan plan = data.plan;
        int numberOfVolumes = plan.numberOfVolumes;
        BuildrDetail bDetail = data.details[selectedDetail];
        float volumeHeight = 0;
        Vector3 baseLeft = Vector3.zero;
        Vector3 baseRight = Vector3.zero;
        int faceIndex = bDetail.face;

        int facadeCounter = 0;
        for (int v = 0; v < numberOfVolumes; v++)
        {
            BuildrVolume volume = data.plan.volumes[v];
            int volumeSize = volume.Count;
            Vector3 floorCentre = Vector3.zero;
            Handles.color = Color.white;

            for (int p = 0; p < volumeSize; p++)
            {
                int point = volume.points[p];
                int indexB = volume.points[(p + 1) % volumeSize];
                Vector3 fb0 = plan.points[point].vector3;
                Vector3 fb1 = plan.points[indexB].vector3;
                if (bDetail.face == facadeCounter && bDetail.type == BuildrDetail.Types.Facade)
                {
                    baseLeft = fb0;
                    baseRight = fb1;
                }
                floorCentre += baseLeft;

                List<Vector3> verts = new List<Vector3>();
                volumeHeight = (volume.numberOfFloors * data.floorHeight);
                Vector3 volumeHeightVector = Vector3.up * volumeHeight;
                verts.Add(fb0 + position);
                verts.Add(fb1 + position);
                verts.Add(verts[1] + volumeHeightVector);
                verts.Add(verts[0] + volumeHeightVector);
                if (bDetail.face == facadeCounter && bDetail.type == BuildrDetail.Types.Facade)
                    //display something to highlight this facade
                    Handles.DrawSolidRectangleWithOutline(verts.ToArray(), Color.clear, BuildrColours.MAGENTA);
                Handles.color = BuildrColours.CYAN;
                if (v == bDetail.face && bDetail.type == BuildrDetail.Types.Roof)
                    Handles.DrawLine(verts[2], verts[3]);
                if (editMode.showFacadeMarkers)
                {
                    Handles.color = Color.white;
                    Vector3 camDirection = Camera.current.transform.forward;
                    Vector3 facadeDirection = Vector3.Cross((verts[0] - verts[1]), Vector3.up);
                    GUIStyle facadeLabelStyle = new GUIStyle();
                    facadeLabelStyle.normal.textColor = Color.white;
                    facadeLabelStyle.alignment = TextAnchor.MiddleCenter;
                    facadeLabelStyle.fixedWidth = 75.0f;
                    if (Vector3.Dot(camDirection, facadeDirection) < 0)//only display label when facade is facing camera
                    {
                        Vector3 centerPos = (verts[0] + verts[1]) * 0.5f;
                        Vector3 labelPos = centerPos + facadeDirection.normalized;
                        Handles.Label(labelPos, "facade " + facadeCounter, facadeLabelStyle);
                        Handles.DrawLine(centerPos, labelPos);
                    }
                }
                facadeCounter++;
            }
        }

        Vector3 handlePosition = bDetail.worldPosition + position;// new Vector3(basePos.x, volumeHeight * bDetail.faceUv.y, basePos.z);
        Vector3 baseDir = (baseRight - baseLeft).normalized;
                Vector3 baseCross = Vector3.Cross(Vector3.up, baseDir);
        Quaternion currentRot = Quaternion.Euler(bDetail.userRotation);
        Quaternion faceRotation = (bDetail.type == BuildrDetail.Types.Facade) ? Quaternion.LookRotation(baseCross) : Quaternion.identity;

        switch (Tools.current)
        {
            case Tool.Move:
                Vector3 dirX, dirY, dirZ;
                if (bDetail.type == BuildrDetail.Types.Facade)
                {
                    dirX = baseDir;
                    dirY = baseCross;
                    dirZ = Vector3.up;
                }
                else
                {
                    dirX = Vector3.right;
                    dirY = Vector3.up;
                    dirZ = Vector3.forward;
                }
                Vector3 newSliderPos;
                Handles.color = BuildrColours.RED;
                newSliderPos = Handles.Slider(handlePosition, dirX, handleSize * 0.666f, Handles.ArrowCap, 0.0f);
                Handles.color = BuildrColours.BLUE;
                newSliderPos = Handles.Slider(newSliderPos, dirZ, handleSize * 0.666f, Handles.ArrowCap, 0.0f);
                Handles.color = BuildrColours.GREEN;
                newSliderPos = Handles.Slider(newSliderPos, dirY, handleSize * 0.666f, Handles.ArrowCap, 0.0f);
                Vector3 sliderDiff = newSliderPos - handlePosition;

                if (sliderDiff != Vector3.zero)
                {
                    float newXUV = 0, newYUV = 0, newHeight = bDetail.faceHeight;
                    if (bDetail.type == BuildrDetail.Types.Facade)
                    {
                        float facadeWidth = Vector3.Distance(baseLeft, baseRight);
                        float sliderDiffX = Mathf.Sqrt(sliderDiff.x * sliderDiff.x + sliderDiff.z * sliderDiff.z) * Mathf.Sign(Vector3.Dot(baseDir, sliderDiff));
                        newXUV = sliderDiffX / facadeWidth + bDetail.faceUv.x;
                        newYUV = sliderDiff.y / volumeHeight + bDetail.faceUv.y;
                    }
                    else
                    {
                        BuildrVolume volume = plan.volumes[faceIndex];
                        int numberOfVolumePoints = volume.points.Count;
                        Vector3 minPoint = plan.points[volume.points[0]].vector3;
                        Vector3 maxPoint = plan.points[volume.points[0]].vector3;
                        for (int p = 1; p < numberOfVolumePoints; p++)
                        {
                            Vector3 fp0 = plan.points[volume.points[p]].vector3;
                            if (fp0.x < minPoint.x) minPoint.x = fp0.x;
                            if (fp0.z < minPoint.z) minPoint.z = fp0.z;
                            if (fp0.x > maxPoint.x) maxPoint.x = fp0.x;
                            if (fp0.z > maxPoint.z) maxPoint.z = fp0.z;
                        }
                        float roofWidth = maxPoint.x - minPoint.x;
                        float roofDepth = maxPoint.z - minPoint.z;
                        newXUV = sliderDiff.x / roofWidth + bDetail.faceUv.x;
                        newYUV = sliderDiff.z / roofDepth + bDetail.faceUv.y;
                        newHeight += sliderDiff.y;
                    }
                    bDetail.faceUv = new Vector2(newXUV, newYUV);
                    bDetail.faceHeight = newHeight;
                }
                break;

                case Tool.Rotate:
                currentRot = Handles.RotationHandle(currentRot, handlePosition);
                bDetail.userRotation = currentRot.eulerAngles;
                break;

                case Tool.Scale:
                bDetail.scale = Handles.ScaleHandle(bDetail.scale, handlePosition, currentRot * faceRotation, handleSize * 0.666f);

                break;
        }

        //draw mesh bounds
        if (bDetail.mesh != null)
        {
            Bounds meshBounds = bDetail.mesh.bounds;
            Quaternion rotation = bDetail.worldRotation;
            Vector3 p0 = rotation * (new Vector3(meshBounds.min.x, meshBounds.min.y, meshBounds.min.z)) + bDetail.worldPosition;
            Vector3 p1 = rotation * (new Vector3(meshBounds.max.x, meshBounds.min.y, meshBounds.min.z)) + bDetail.worldPosition;
            Vector3 p2 = rotation * (new Vector3(meshBounds.min.x, meshBounds.min.y, meshBounds.max.z)) + bDetail.worldPosition;
            Vector3 p3 = rotation * (new Vector3(meshBounds.max.x, meshBounds.min.y, meshBounds.max.z)) + bDetail.worldPosition;
            Vector3 p4 = rotation * (new Vector3(meshBounds.min.x, meshBounds.max.y, meshBounds.min.z)) + bDetail.worldPosition;
            Vector3 p5 = rotation * (new Vector3(meshBounds.max.x, meshBounds.max.y, meshBounds.min.z)) + bDetail.worldPosition;
            Vector3 p6 = rotation * (new Vector3(meshBounds.min.x, meshBounds.max.y, meshBounds.max.z)) + bDetail.worldPosition;
            Vector3 p7 = rotation * (new Vector3(meshBounds.max.x, meshBounds.max.y, meshBounds.max.z)) + bDetail.worldPosition;

            Handles.color = BuildrColours.BLUE;
            Handles.DrawLine(p0, p1);
            Handles.DrawLine(p0, p2);
            Handles.DrawLine(p1, p3);
            Handles.DrawLine(p2, p3);
            Handles.DrawLine(p0, p4);
            Handles.DrawLine(p1, p5);
            Handles.DrawLine(p2, p6);
            Handles.DrawLine(p3, p7);
            Handles.DrawLine(p4, p5);
            Handles.DrawLine(p4, p6);
            Handles.DrawLine(p5, p7);
            Handles.DrawLine(p6, p7);

            if (clickPlace)
            {
                Vector3 planeBase = Vector3.zero;
                Vector3 planeNormal = Vector3.up;
                Vector3 planeSize = Vector3.zero;
                if (bDetail.type == BuildrDetail.Types.Facade)
                {
                    //find facade
                    int facadeCount = 0;
                    bool facadeFound = false;
                    for (int s = 0; s < numberOfVolumes; s++)
                    {
                        BuildrVolume volume = plan.volumes[s];
                        int numberOfVolumePoints = volume.points.Count;
                        for (int p = 0; p < numberOfVolumePoints; p++)
                        {
                            if (facadeCount == faceIndex)
                            {
                                int indexA = p;
                                int indexB = (p + 1) % numberOfVolumePoints;
                                Vector3 fp0 = plan.points[volume.points[indexA]].vector3;
                                Vector3 fp1 = plan.points[volume.points[indexB]].vector3;
                                planeBase = fp0;
                                planeNormal = Vector3.Cross(Vector3.up, fp1 - fp0).normalized;
                                planeSize.x = Vector3.Distance(fp0, fp1);
                                planeSize.y = volume.numberOfFloors * data.floorHeight;
                                facadeFound = true;
                                break;
                            }
                            facadeCount++;
                        }
                        if (facadeFound)
                            break;
                    }
                }
                else
                {
                    BuildrVolume volume = plan.volumes[faceIndex];
                    int numberOfVolumePoints = volume.points.Count;
                    Vector3 minPoint = plan.points[volume.points[0]].vector3;
                    Vector3 maxPoint = plan.points[volume.points[0]].vector3;
                    for (int p = 1; p < numberOfVolumePoints; p++)
                    {
                        Vector3 fp0 = plan.points[volume.points[p]].vector3;
                        if (fp0.x < minPoint.x) minPoint.x = fp0.x;
                        if (fp0.z < minPoint.z) minPoint.z = fp0.z;
                        if (fp0.x > maxPoint.x) maxPoint.x = fp0.x;
                        if (fp0.z > maxPoint.z) maxPoint.z = fp0.z;
                    }
                    planeSize.x = maxPoint.x - minPoint.x;
                    planeSize.z = maxPoint.z - minPoint.z;
                    planeBase = minPoint;
                    planeBase.y = (data.floorHeight * volume.numberOfFloors);
                }
                float distance;
                Plane buildingPlane = new Plane(planeNormal, planeBase);
                Ray ray = Camera.current.ScreenPointToRay(new Vector3(Event.current.mousePosition.x, Screen.height - Event.current.mousePosition.y - 30, 0));
                if (buildingPlane.Raycast(ray, out distance))
                {
                    Vector3 mousePlanePoint = ray.GetPoint(distance);
                    Quaternion mouseLookDirection = Quaternion.LookRotation(buildingPlane.normal);

                    if (Handles.Button(mousePlanePoint, mouseLookDirection, handleSize * 0.1f, handleSize * 0.1f, Handles.CircleCap))
                    {
                        float xUv, yUv;
                        if (bDetail.type == BuildrDetail.Types.Facade)
                        {
                            Vector3 facadeBaseMousePoint = new Vector3(mousePlanePoint.x, 0, mousePlanePoint.z);
                            xUv = Vector3.Distance(planeBase, facadeBaseMousePoint) / planeSize.x;
                            yUv = (mousePlanePoint.y - planeBase.y) / planeSize.y;
                        }
                        else
                        {
                            xUv = (mousePlanePoint.x - planeBase.x) / planeSize.x;
                            yUv = (mousePlanePoint.z - planeBase.z) / planeSize.z;
                        }
                        bDetail.faceUv = new Vector2(xUv, yUv);
                        clickPlace = false;
                        GUI.changed = true;
                    }
                }
            }
        }

        if (GUI.changed)
        {
            EditorUtility.SetDirty(editMode);
            EditorUtility.SetDirty(data);
            editMode.UpdateRender();
        }
    }
    public static void InspectorGUI(BuildrEditMode editMode, BuildrData data)
    {
        BuildrDetail[] details = data.details.ToArray();
        int numberOfDetails = details.Length;
        selectedDetail = Mathf.Clamp(selectedDetail, 0, numberOfDetails - 1);

        if (numberOfDetails == 0)
        {
            EditorGUILayout.HelpBox("There are no details to show", MessageType.Info);
            if (GUILayout.Button("Add New"))
            {
                data.details.Add(new BuildrDetail("new detail " + numberOfDetails));
                numberOfDetails++;
                selectedDetail = numberOfDetails - 1;
            }
            return;
        }

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Detail", GUILayout.Width(75));
        string[] detailNames = new string[numberOfDetails];
        for (int t = 0; t < numberOfDetails; t++)
            detailNames[t] = details[t].name;
        selectedDetail = EditorGUILayout.Popup(selectedDetail, detailNames);
        EditorGUILayout.EndHorizontal();

        BuildrDetail bDetail = details[selectedDetail];

        EditorGUILayout.BeginHorizontal();

        EditorGUILayout.Space();

        if (GUILayout.Button("Add New", GUILayout.Width(81)))
        {
            data.details.Add(new BuildrDetail("new detail " + numberOfDetails));
            numberOfDetails++;
            selectedDetail = numberOfDetails - 1;
        }

        if (GUILayout.Button("Duplicate", GUILayout.Width(90)))
        {
            data.details.Add(bDetail.Duplicate());
            numberOfDetails++;
            selectedDetail = numberOfDetails - 1;

        }

        if (GUILayout.Button("Delete", GUILayout.Width(71)))
        {
            if (EditorUtility.DisplayDialog("Deleting Building Detail Entry", "Are you sure you want to delete this detail?", "Delete", "Cancel"))
            {
                data.details.Remove(bDetail);
                selectedDetail = 0;
                GUI.changed = true;

                return;
            }
        }
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.Space();

        details = data.details.ToArray();
        detailNames = new string[numberOfDetails];
        for (int t = 0; t < numberOfDetails; t++)
            detailNames[t] = details[t].name;
        bDetail = details[selectedDetail];//reassign

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.BeginVertical();

        bDetail.name = EditorGUILayout.TextField("Name", bDetail.name);

        bDetail.mesh = (Mesh)EditorGUILayout.ObjectField("Mesh", bDetail.mesh, typeof(Mesh), false);
        EditorGUIUtility.LookLikeControls();
        bDetail.material.mainTexture = (Texture)EditorGUILayout.ObjectField("Texture", bDetail.material.mainTexture, typeof(Texture), false, GUILayout.Height(140));

        if (bDetail.material.mainTexture != null)
        {
            string texturePath = AssetDatabase.GetAssetPath(bDetail.material.mainTexture);
            TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(texturePath);

            if (!textureImporter.isReadable)
            {
                EditorGUILayout.HelpBox("The texture you have selected is not readable." +
                    "\nPlease select the readable checkbox under advanced texture settings." +
                    "\nOr move this texture to the BuildR texture folder and reimport.",
                    MessageType.Error);
            }
        }

        BuildrPlan plan = data.plan;
        int numberOfVolumes = plan.numberOfVolumes;
        int numberOfFaces = 0;
        List<int> faceSeletionsList = new List<int>();
        List<string> faceSeletionsStringList = new List<string>();
        if (bDetail.type == BuildrDetail.Types.Facade)
        {
            for (int s = 0; s < numberOfVolumes; s++)
            {
                int numberOfPoints = plan.volumes[s].Count;
                numberOfFaces += numberOfPoints;
                for (int p = 0; p < numberOfPoints; p++)
                {
                    int index = faceSeletionsList.Count;
                    faceSeletionsStringList.Add("facade " + index);
                    faceSeletionsList.Add(index);
                }
            }
        }
        else
        {
            bDetail.face = Mathf.Clamp(0, numberOfVolumes - 1, bDetail.face);
            for (int s = 0; s < numberOfVolumes; s++)
            {
                int index = faceSeletionsList.Count;
                faceSeletionsStringList.Add("roof " + index);
                faceSeletionsList.Add(index);
            }
        }

        if (!clickPlace)
        {
            if (GUILayout.Button("Place Detail with Mouse"))
            {
                clickPlace = true;
            }
        }
        else
        {
            if (GUILayout.Button("Cancel Place Detail"))
            {
                clickPlace = false;
            }
        }

        BuildrDetail.Types bDetailtype = (BuildrDetail.Types)EditorGUILayout.EnumPopup("Face Type", bDetail.type);
        if(bDetailtype != bDetail.type)
        {
            bDetail.type = bDetailtype;
        }
        int[] faceSelections = faceSeletionsList.ToArray();
        string[] faceSelectionString = faceSeletionsStringList.ToArray();
        int bDetailface = EditorGUILayout.IntPopup("Selected Face", bDetail.face, faceSelectionString, faceSelections);
        if(bDetailface != bDetail.face)
        {
            bDetail.face = bDetailface;
        }

        Vector2 bDetailfaceUv = EditorGUILayout.Vector2Field("Face UV", bDetail.faceUv);
        if(bDetailfaceUv != bDetail.faceUv)
        {
            bDetail.faceUv = bDetailfaceUv;
        }
        float bDetailfaceHeight = EditorGUILayout.FloatField("Face Height", bDetail.faceHeight);
        if(bDetailfaceHeight != bDetail.faceHeight)
        {
            bDetail.faceHeight = bDetailfaceHeight;
        }
        Vector3 bDetailuserRotation = EditorGUILayout.Vector3Field("Rotation", bDetail.userRotation);
        if(bDetailuserRotation != bDetail.userRotation)
        {
            bDetail.userRotation = bDetailuserRotation;
        }
        Vector3 bDetailscale = EditorGUILayout.Vector3Field("Object Scale", bDetail.scale);
        if(bDetailscale != bDetail.scale)
        {
            bDetail.scale = bDetailscale;
        }

        EditorGUILayout.EndVertical();
        EditorGUILayout.BeginVertical(GUILayout.Width(120));
        if (bDetail.mesh != null)
        {
            Texture2D previewMeshImage = AssetPreview.GetAssetPreview(bDetail.mesh);
            GUILayout.Label(previewMeshImage);
        }
        else
        {
            Texture2D previewMeshImage = new Texture2D(118, 118);
            GUILayout.Label(previewMeshImage);
            GUILayout.Label("No Mesh Selected");
        }

        if (bDetail.material.mainTexture != null)
        {
            Texture previewMeshImage = bDetail.material.mainTexture;
            GUILayout.Label(previewMeshImage, GUILayout.Width(128), GUILayout.Height(128));
        }
        else
        {
            Texture2D previewMeshImage = new Texture2D(118, 118);
            GUILayout.Label(previewMeshImage);
            GUILayout.Label("No Texture Selected");
        }
        EditorGUILayout.EndVertical();
        EditorGUILayout.EndHorizontal();
    }
Beispiel #33
0
    public static void SceneGUI(BuildrEditMode editMode, BuildrData data, bool shouldSnap, float handleSize)
    {
        if (editMode.fullMesh == null)
        {
            return;
        }

        Rect HUDRect = new Rect(0, 0, 300, 300);

        Handles.BeginGUI();
        GUILayout.BeginArea(HUDRect);

        EditorGUILayout.LabelField("Buildr");
        EditorGUILayout.LabelField("Vertices: " + editMode.fullMesh.vertexCount);
        EditorGUILayout.LabelField("Triangles " + editMode.fullMesh.triangleCount / 3);

        GUILayout.EndArea();
        Handles.EndGUI();

        bool isLegal = !(data.plan.illegalPoints.Length > 0);

        if (isLegal)
        {
            isLegal = editMode.transform.localScale == Vector3.one;
        }

        if (isLegal)
        {
            return;
        }

        int numberOfFacades  = data.facades.Count;
        int numberOfRoofs    = data.roofs.Count;
        int numberOfTextures = data.textures.Count;

        if (numberOfFacades == 0 || numberOfRoofs == 0 || numberOfTextures == 0)
        {
            return;
        }

        Vector3 position = editMode.transform.position;

        BuildrPlan area            = data.plan;
        int        numberOfVolumes = area.numberOfVolumes;

        int facadeCounter = 0;

        for (int s = 0; s < numberOfVolumes; s++)
        {
            BuildrVolume volume      = data.plan.volumes[s];
            int          volumeSize  = volume.Count;
            Vector3      floorCentre = Vector3.zero;
            Handles.color = Color.red;

            for (int p = 0; p < volumeSize; p++)
            {
                int     point    = volume.points[p];
                Vector3 pointPos = area.points[point].vector3;
                floorCentre += pointPos;

                List <Vector3> verts        = new List <Vector3>();
                int            indexB       = (p < volumeSize - 1) ? p + 1 : 0;
                Vector3        volumeHeight = Vector3.up * (volume.numberOfFloors * data.floorHeight);
                verts.Add(pointPos + position);
                verts.Add(area.points[volume.points[indexB]].vector3 + position);
                verts.Add(verts[1] + volumeHeight);
                verts.Add(verts[0] + volumeHeight);
                Handles.DrawSolidRectangleWithOutline(verts.ToArray(), new Color(1, 0, 0, 0.2f), Color.red);
                Handles.DrawLine(verts[2], verts[3]);
                facadeCounter++;
            }
        }
    }
Beispiel #34
0
    public static void InspectorGUI(BuildrEditMode editMode, BuildrData _data)
    {
        data = _data;
        Undo.RecordObject(data, "Interior Modified");

        BuildrTexture[] textures         = data.textures.ToArray();
        int             numberOfTextures = textures.Length;

        string[] textureNames = new string[numberOfTextures];
        for (int t = 0; t < numberOfTextures; t++)
        {
            textureNames[t] = textures[t].name;
        }

        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUILayout.LabelField("Render Interior of Building");
        bool renderInterior = EditorGUILayout.Toggle(_data.renderInteriors, GUILayout.Width(15));

        if (renderInterior != _data.renderInteriors)
        {
            _data.renderInteriors = renderInterior;
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal(GUILayout.Width(400));
        EditorGUILayout.LabelField("Cull All Building Bays");
        bool cullBays = EditorGUILayout.Toggle(_data.cullBays, GUILayout.Width(15));

        if (cullBays != _data.cullBays)
        {
            _data.cullBays = cullBays;
        }
        EditorGUILayout.EndHorizontal();

        //Floor Height
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Floor height", GUILayout.Width(200));
        float newFloorHeight = EditorGUILayout.FloatField(data.floorHeight, GUILayout.Width(50));

        if (newFloorHeight != data.floorHeight)
        {
            data.floorHeight = newFloorHeight;
        }
        EditorGUILayout.LabelField("metres", GUILayout.Width(50));
        EditorGUILayout.EndHorizontal();

        EditorGUI.BeginDisabledGroup(!renderInterior);

        //Ceiling Height
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Interior Ceiling Height", GUILayout.Width(200));
        float newCeilingHeight = EditorGUILayout.Slider(data.interiorCeilingHeight, 0, 1);

        if (newCeilingHeight != data.interiorCeilingHeight)
        {
            data.interiorCeilingHeight = newCeilingHeight;
        }
        EditorGUILayout.EndHorizontal();

        BuildrPlan plan            = data.plan;
        int        numberOfVolumes = plan.numberOfVolumes;

        int[]    volumeSeletionsList       = new int[numberOfVolumes];
        string[] volumeSeletionsStringList = new string[numberOfVolumes];
        for (int s = 0; s < numberOfVolumes; s++)
        {
            volumeSeletionsStringList[s] = ("volume " + s);
            volumeSeletionsList[s]       = (s);
        }
        selectedVolumeIndex = EditorGUILayout.IntPopup("Selected Volume", selectedVolumeIndex, volumeSeletionsStringList, volumeSeletionsList, GUILayout.Width(400));
        BuildrVolume volume = plan.volumes[selectedVolumeIndex];


        //Stairs
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Generate Stairs", GUILayout.Width(110));
        volume.generateStairs = EditorGUILayout.Toggle(volume.generateStairs);
        EditorGUILayout.EndHorizontal();

        if (plan.cores.Count == 0)
        {
            EditorGUILayout.HelpBox("There are no building cores defined. Go to floorplan to define one so you can generate a stairwell", MessageType.Error);
        }

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Stair Width", GUILayout.Width(110));
        volume.staircaseWidth = EditorGUILayout.Slider(volume.staircaseWidth, 0.5f, 5.0f);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Minimum Step Riser Value", GUILayout.Width(150));
        volume.stepHeight = EditorGUILayout.Slider(volume.stepHeight, 0.05f, 0.5f);
        EditorGUILayout.EndHorizontal();

        EditorGUI.BeginDisabledGroup(!volume.generateStairs);
        EditorGUILayout.BeginVertical("box");
        EditorGUILayout.LabelField("Stairwell Textures");

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Wall Texture", GUILayout.Width(120));
        volume.stairwellWallTexture = EditorGUILayout.Popup(volume.stairwellWallTexture, textureNames);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Floor Texture", GUILayout.Width(120));
        volume.stairwellFloorTexture = EditorGUILayout.Popup(volume.stairwellFloorTexture, textureNames);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Ceiling Texture", GUILayout.Width(120));
        volume.stairwellCeilingTexture = EditorGUILayout.Popup(volume.stairwellCeilingTexture, textureNames);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Step Texture", GUILayout.Width(120));
        volume.stairwellStepTexture = EditorGUILayout.Popup(volume.stairwellStepTexture, textureNames);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.EndVertical();
        EditorGUI.EndDisabledGroup();

        //Basement floors
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Basement Floors", GUILayout.Width(110));
        EditorGUILayout.LabelField(volume.numberOfBasementFloors.ToString("F0"), GUILayout.Width(40));
        EditorGUI.BeginDisabledGroup(volume.numberOfBasementFloors < 1);
        if (GUILayout.Button("-"))
        {
            volume.numberOfBasementFloors--;
        }
        EditorGUI.EndDisabledGroup();
        if (GUILayout.Button("+"))
        {
            volume.numberOfBasementFloors++;
        }
        EditorGUILayout.EndHorizontal();

        int numberOfFloors         = volume.numberOfFloors;
        int numberOfBasementFloors = volume.numberOfBasementFloors;
        int totalNumberOfFloors    = numberOfBasementFloors + numberOfFloors;

        int[]    floorSeletionsList       = new int[totalNumberOfFloors];
        string[] floorSeletionsStringList = new string[totalNumberOfFloors];
        for (int f = -numberOfBasementFloors; f < numberOfFloors; f++)
        {
            int index = f + numberOfBasementFloors;
            if (f > 0)
            {
                floorSeletionsStringList[index] = "floor " + f;
            }
            else if (f < 0)
            {
                floorSeletionsStringList[index] = "basement " + -f;
            }
            else
            {
                floorSeletionsStringList[index] = "ground floor ";
            }
            floorSeletionsList[index] = (f);
        }
        selectedFloor = EditorGUILayout.IntPopup("Selected Floor", selectedFloor, floorSeletionsStringList, floorSeletionsList, GUILayout.Width(400));

        EditorGUILayout.LabelField("Interior Textures");
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Floor Texture", GUILayout.Width(120));
        volume.FloorTexture(selectedFloor, EditorGUILayout.Popup(volume.FloorTexture(selectedFloor), textureNames));
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Wall Texture", GUILayout.Width(120));
        volume.WallTexture(selectedFloor, EditorGUILayout.Popup(volume.WallTexture(selectedFloor), textureNames));
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Ceiling Texture", GUILayout.Width(120));
        volume.CeilingTexture(selectedFloor, EditorGUILayout.Popup(volume.CeilingTexture(selectedFloor), textureNames));
        EditorGUILayout.EndHorizontal();

        if (GUILayout.Button("Use Values for All Floors"))
        {
            int useFloorTextureIndex   = volume.FloorTexture(selectedFloor);
            int useWallTextureIndex    = volume.WallTexture(selectedFloor);
            int useCeilingTextureIndex = volume.CeilingTexture(selectedFloor);
            for (int f = 0; f < numberOfFloors; f++)
            {
                volume.FloorTexture(f, useFloorTextureIndex);
                volume.WallTexture(f, useWallTextureIndex);
                volume.CeilingTexture(f, useCeilingTextureIndex);
            }
        }

        if (GUILayout.Button("Use Values for Entire Building"))
        {
            int useFloorTextureIndex   = volume.FloorTexture(selectedFloor);
            int useWallTextureIndex    = volume.WallTexture(selectedFloor);
            int useCeilingTextureIndex = volume.CeilingTexture(selectedFloor);

            for (int v = 0; v < numberOfVolumes; v++)
            {
                BuildrVolume thisvolume = plan.volumes[v];
                int          numberOfFloorsToModifiy = thisvolume.numberOfFloors;
                for (int f = 0; f < numberOfFloorsToModifiy; f++)
                {
                    thisvolume.FloorTexture(f, useFloorTextureIndex);
                    thisvolume.WallTexture(f, useWallTextureIndex);
                    thisvolume.CeilingTexture(f, useCeilingTextureIndex);
                }
            }
        }

        EditorGUI.EndDisabledGroup();
    }