Search Unity

Runtime File Browser

Discussion in 'Made With Unity' started by inventor2010, Sep 24, 2011.

  1. inventor2010

    inventor2010

    Joined:
    Nov 3, 2010
    Posts:
    124
    Hi,

    So, I've been working on a runtime world editor for months now. I just recently had enough in my editor to implement a saving and loading routine, so I did. Had to learn how first, but I went with System.IO and just parsing my own text file (I don't really mind if the user can change it so it works for me).

    Any way, I wanted the user to be able to organize their saved creations how ever they see fit (in folders). So I made the following script. It's a columns view file browser (inspired by OS X Finder). Currently it doesn't have the ability to move files or folders, but it can: view them, open them, save them, and create new folders.

    The window can be resized at the bottom right, every column can be resized for easier viewing, and it the scrolling functions like Pre-Lion Finder.

    If you just want to play with the GUI code, and not worry about integrating it into your game... just grab the script at the bottom and uncomment the Start function at the top, that will basically just open the browser and let you browse your Application.dataPath (your Project view if you just run it in Unity). Otherwise read on...

    All you need do to set it up is, find the comment about a third the way down and add a single line to call what ever function you already have for opening save files. Then just place the script in an object you can reference. Just call:
    Code (csharp):
    1. Browser.OpenFile( The_Path_To_Your_MainSaves_Folder );
    To allow the user to access any file or folder in the directory you pass to the OpenFile function.

    Then for saving files you have to run what ever saving script you have to get a file (or folder) you can pass to this function, sorry no player prefs, you need to give it a path. Then the user will basically pick where they want to move that file and what they want to call it, if the click cancel it will delete the temporary save file for you. This way you can just do your saving routine, and pass the output to this script and let it do its thing (no need to wait for it with coroutines or anything).

    So basically pass it the path to your main saves folder, and the path to the temporary save file your scripts will create, like this:
    Code (csharp):
    1. Browser.SaveFile(Temporary_Path_Of_The_Save_File, The_Path_To_Your_MainSaves_Folder);
    Note: this will overwrite any files with the same name that the user picks, and wont warn them.

    WARNING!!! Make sure that you do not pass a directory to Temporary_Path_Of_The_Save_File that you do not want to lose, as if the user clicks cancel, it will be instantly deleted without warning! This is normal behavior as it is meant to be a temporary file, I designed browser so other coders could implement it with only 2 lines of code, but I can not predict how you wish to save files, so all browser does is move them, if the user clicks cancel then the temporary file is deleted without the user knowing of it's existence.

    I'll probably update this soon and make it a little more capable, but heres what I have so far. Let me know what you think! :D

    PHP:
    // Browser.cs
    // Basic Columns view file browser for saveing and loading save games at runtime.
    // Created Sep 17 by Charlie Mehlenbeck
    // Contact me here for any questions: http://forum.unity3d.com/members/27746-inventor2010
    using UnityEngine;
    using System.Collections;
    using System;
    using System.IO;

    public class 
    Browser MonoBehaviour
    {
        public 
    int defaultWidth 100;
        public 
    int minWidth 50;
        public 
    GUISkin skin;
       
        
    bool WindowOpen false;
        
    WindowType WinType;
        
    String MainFolder "";
        
    String FileToSave "";
        
    String NameOfFileToSave "";
        
    Path[] PathTree = new Path[0];
        
    String[] OpenPaths = new String[0];
        
    String[] OpenPaths_Reduced = new String[0];
        
    String WindowName "";
        
    Vector2 OuterScrollPosition Vector2.zero;
        
    Vector2[] ScrollPositions = new Vector2[0];
        
    int[] Widths = new int[0];
        
    Drag DragStat;
        
    bool creatingFolder false;
        
    String folderName "";
        
    Vector2 minWindowScale = new Vector2(455150);
       
        static 
    Rect BrowserRect = new Rect(2020500400);

        public 
    void OpenFile(String mainFolder)
        {
            if(
    Directory.Exists(mainFolder))
            {
                
    WindowOpen true;
                
    WinType WindowType.Open;
                
    DragStat.Dragging false;    // Ensure nothing is being draged.
           
                
    MainFolder mainFolder// example: Application.dataPath/Saves;
                
    GetAllSubDirectoriesAndFilesMainFolder );
               
                
    AddWidth();
                
    AddScrollPosition(0);
                
    AddPath(MainFolder0);
            }
            else
            {
                if(
    File.Exists(mainFolder)) Debug.LogError("I need a main directory, not a file!");
                else 
    Debug.LogError("I need a path for a main directory that actually exists!");
            }
        }

        public 
    void SaveFile(String FilePathString mainFolder)
        {
            if(
    Directory.Exists(mainFolder))
            {
                if(
    File.Exists(FilePath) || Directory.Exists(FilePath))
                {
                    
    WindowOpen true;
                    
    WinType WindowType.Save;
                    
    DragStat.Dragging false;    // Ensure nothing is being draged.
                   
                    
    FileToSave FilePath;
                   
                    
    MainFolder mainFolder// example: Application.dataPath/Saves;
                    
    GetAllSubDirectoriesAndFilesMainFolder );
                   
                    
    AddWidth();
                    
    AddScrollPosition(0);
                    
    AddPath(MainFolder0);
                }
                else 
    Debug.LogError("I need a path for a temporary save file that actually exists!");
            }
            else
            {
                if(
    File.Exists(mainFolder)) Debug.LogError("I need a main directory, not a file!");
                else 
    Debug.LogError("I need a path for a main directory that actually exists!");
            }
        }
       
        
    void OnGUI()
        {
            if(
    WindowOpen)
            {
                
    GUI.skin skin;
                
    BrowserRect GUI.Window(0BrowserRectDrawBrowserWindowName);
            }
        }
       
        
    void DrawBrowser(int windowID)
        {
            
    Event E Event.current;
            
    Rect bottom = new Rect(5BrowserRect.height-40BrowserRect.width-104);
            
    GUI.Box(bottom"");
            
    bottom.x=10;    //Get bottom bar rect.
            
    bottom.y+=10;
            
    bottom.width 120;
            
    bottom.height 20;
            if(
    creatingFolder// Folder creation tool.
            
    {
                
    folderName GUI.TextField(bottomfolderName);
                
    bottom.+= bottom.width+5;
                
    bottom.width 52;
                if(
    GUI.Button(bottom"Create"))
                {
                    
    String newDirectory;
                    if( 
    Directory.Exists(OpenPaths[OpenPaths.Length-1]) )
                        
    newDirectory OpenPaths[OpenPaths.Length-1] + "/" folderName;
                    else
                        
    newDirectory OpenPaths[OpenPaths.Length-2] + "/" folderName;
                   
                    if(!
    Directory.Exists(newDirectory))
                    {
                        
    Directory.CreateDirectory(newDirectory);
                        
    GetAllSubDirectoriesAndFilesMainFolder );
                    }
                    
    creatingFolder false;
                }
            } else
            if(
    GUI.Button(bottom"Create New Folder"))
            {
                
    folderName "";
                
    creatingFolder true;
            }
           
            
    bottom.width 12// Draw resize handle
            
    bottom.height 12;
            
    bottom.BrowserRect.width-bottom.width-5;
            
    bottom.y+=12;
            
    GUI.Box(bottom"");
            
    Rect realBottom bottom;
            
    realBottom.+= BrowserRect.x;
            
    realBottom.+= BrowserRect.y;
            if( 
    Input.GetMouseButtonDown(0)  realBottom.Contains(GetMouseCord()) )
            {
                
    DragStat.Dragging true;
                
    DragStat.startMouse GetMouseCord();
                
    DragStat.startPosition = new Vector2(BrowserRect.widthBrowserRect.height);
                
    DragStat.type DragType.WindowScaler;
            } else
            if(
    DragStat.Dragging  DragStat.type==DragType.WindowScaler)
            {
                
    Vector2 MouseCord GetMouseCord();
                
    Vector2 newScale DragStat.startPosition - new Vector2(    DragStat.startMouse.MouseCord.x,
                                                                            
    DragStat.startMouse.MouseCord.y);
                
    BrowserRect.width newScale.x;
                
    BrowserRect.height newScale.y;
                if(
    BrowserRect.width minWindowScale.xBrowserRect.width minWindowScale.x;
                if(
    BrowserRect.height minWindowScale.yBrowserRect.height minWindowScale.y;
            }
           
            
    // Draw Open/Save Cancel buttons, and make them function:
            
    bottom.y-=12;
            
    bottom.height 20;
            
    bottom.width 42;
            
    bottom.-= bottom.width+5;
            if(
    WinType == WindowType.Open  GUI.Button(bottom"Open"))
            {
                
    String FileToOpen OpenPaths[OpenPaths.Length-1];
                if(
    File.Exists(FileToOpen) || Directory.Exists(FileToOpen))
                {
                    
    //////////////////////////////////////////////////////////////////////////////////////////////////////////
                    //                                                                                                      //
                    //    Run Your Open file code here! Have your open file code in a function that accepts a path (string) //
                    //                                    and pass to it: FileToOpen.                                       //
                    //                                                                                                      //
                    //////////////////////////////////////////////////////////////////////////////////////////////////////////
                    
    Debug.Log("Opening File: " FileToOpen);
                }
                else 
    Debug.LogError("The File you are trying to open must have gotten moved, or deleated.");
               
                
    WindowOpen false;
            }
            if(
    WinType == WindowType.Save  GUI.Button(bottom"Save"))
            {
                if(
    File.Exists(FileToSave) || Directory.Exists(FileToSave))
                {
                    
    //NameOfFileToSave
                    
    String SaveLocation OpenPaths[OpenPaths.Length-1];
                    if(
    Directory.ExistsSaveLocation ))
                        
    OverwriteDuplicates(FileToSaveSaveLocation+"/"+NameOfFileToSave);
                    else
                    {
                        if(
    File.Exists(SaveLocation)) // If the user chooses a file instead of a folder the parent folder will be used.
                        
    {
                            
    SaveLocation = (new FileInfo(SaveLocation)).DirectoryName;
                            
    OverwriteDuplicates(FileToSaveSaveLocation+"/"+NameOfFileToSave);
                        }
                        else 
    Debug.LogError("The directory you're trying to save in no longer exists");
                    }
                }
                else 
    Debug.LogError("The file/folder your trying to save no longer exists.");
                
    WindowOpen false;
            }
            
    bottom.width 52;
            
    bottom.-= bottom.width+5;
            if(
    GUI.Button(bottom"Cancel"))
            {
                if(
    WinType == WindowType.Save)
                {
                    if(
    File.Exists(FileToSave))
                        
    File.Delete(FileToSave); // Deleate FileToSave if the user chooses cancel.
                    
    if(Directory.Exists(FileToSave))
                        
    Directory.Delete(FileToSavetrue); // Deleate FileToSave if the user chooses cancel.
                    
    Debug.Log("Deleate: " FileToSave);
                }
                    
    //Directory.Delete(FileToSave, true); // Deleate the file to save if the user chooses cancel.
                
    WindowOpen false;
            }
            if(
    WinType == WindowType.Save)
            {
                
    bottom.width 130;
                
    bottom.-= bottom.width+5;
                
    NameOfFileToSave GUI.TextField(bottomNameOfFileToSave);
            }
           
            
    //////////////////////////////////////////////////////////////////
            // The rest of OnGUI is to draw the columns part of the window. //
            //////////////////////////////////////////////////////////////////
            
    const int verticalSpace 2;
            const 
    int horiznontalSpace 10;
           
            
    Rect OuterPosition BrowserRect;
            
    OuterPosition.x=5;
            
    OuterPosition.y=20;
            
    OuterPosition.width-=10;
            
    OuterPosition.height-=67;
            
    Rect OuterViewRect OuterPosition;
           
            
    OuterViewRect.height-=17;
            
    OuterViewRect.width 0;
            for(
    int i=0i<ScrollPositions.Length; ++iOuterViewRect.width += horiznontalSpace+Widths[i];
            
    OuterViewRect.width += 15;
            
    //OuterPosition.width = 0;
            //for(int i=0; i<Widths.Length; ++i) OuterPosition.width += 12+Widths[i];
           
            // Makes scroll wheel on columns view scroll horizontally, as well allowing vertical scrolling in each column.
            
    if(!Input.GetMouseButton(0))
            {
                
    DragStat.Dragging false;
               
                
    Rect realOuterPosition OuterPosition;
                
    realOuterPosition.+= BrowserRect.x;
                
    realOuterPosition.+= BrowserRect.y;
                if( 
    realOuterPosition.Contains(GetMouseCord())  E.type == EventType.ScrollWheel )
                    
    OuterScrollPosition.+= Mathf.Clamp(E.delta.x,-2f,2f)*20;
            }
           
            if(
    OuterPosition.width >= OuterViewRect.width)
            {
                
    OuterPosition.height+=20;
                
    OuterViewRect.height+=20;
            }
            
    OuterScrollPosition GUI.BeginScrollView (OuterPositionOuterScrollPositionOuterViewRect);
            
    GUI.BeginGroup (OuterViewRect);
           
                for(
    int i=0i<ScrollPositions.Length; ++i)
                {
                    
    int ButtonHeight 20;
                    
    int[] PathIndexes GetPathIndexesAtOpenPaths[i] );
                    
    Rect Position GetRect(ihoriznontalSpace, (int)OuterViewRect.height);
                    
    Rect viewRect Position;
                    
    viewRect.height PathIndexes.Length*ButtonHeight + (PathIndexes.Length-1)*verticalSpace;
                    
    viewRect.width -=17;
                    
    viewRect.0;
                    
    viewRect.0;
                    
    // Make the buttons fill the space available:
                    
    if(PathIndexes.Length*ButtonHeight + (PathIndexes.Length-1)*verticalSpace <= Position.heightviewRect.width += 15;
                   
                    
    ScrollPositions[i] = GUI.BeginScrollView (PositionScrollPositions[i], viewRect); // Draw Column i.
                        
    viewRect.height ButtonHeight;
                        for(
    int j=0j<PathIndexes.Length; ++j)
                        {
                            
    int index PathIndexes[j];
                           
                            if(
    i+1<OpenPaths_Reduced.Length  PathTree[index].Name == OpenPaths_Reduced[i+1]) GUI.backgroundColor Color.blue;
                            else 
    GUI.backgroundColor Color.white;
                           
                            
    Vector2 posbackup ScrollPositions[i]; // Prevent it from scrolling to the top on button click.
                            
    if(GUI.Button(viewRectPathTree[index].Name))
                            {
                                
    OuterScrollPosition.Mathf.Infinity// Scroll to end of outer scroll view.
                                
    if(PathTree[index].File)
                                {
                                    if(
    i==OpenPaths.Length-1AddWidth();
                                    
    AddScrollPosition(i);
                                }
                                else
                                {
                                    if(
    i==OpenPaths.Length-1AddWidth();
                                    
    AddScrollPosition(i+1);
                                }
                                
    AddPath(PathTree[index].Parent "/" PathTree[index].Namei+1);
                            }
                            
    ScrollPositions[i] = posbackup;
                            
    viewRect.+= ButtonHeight+verticalSpace;
                        }
                    
    GUI.EndScrollView();
                   
                    
    Position.+= Position.width;            // Draw Column Resizer Bar:
                    
    Position.width horiznontalSpace-2;
                    
    GUI.Box(Position"");
                    
    Rect realPosition Position;            // Make it function:
                    
    realPosition.-= OuterScrollPosition.OuterPosition.x-2;
                    
    //realPosition.y -= OuterScrollPosition.y;
                    
    realPosition.+= BrowserRect.x;
                    
    realPosition.+= BrowserRect.y;
                    if( 
    Input.GetMouseButtonDown(0)  realPosition.Contains(GetMouseCord()) )
                    {
                        
    DragStat.Dragging true;
                        
    DragStat.startMouse Input.mousePosition;
                        
    DragStat.startPosition = new Vector2(Widths[i], 0);
                        
    DragStat.type DragType.Column;
                        
    DragStat.column i;
                    } else
                    if(
    DragStat.Dragging  DragStat.type==DragType.Column  DragStat.column==i)
                    {
                        if(
    realPosition.BrowserRect.x+BrowserRect.widthBrowserRect.width realPosition.x-BrowserRect.x;
                        
    int newWidth = (int)(DragStat.startPosition.DragStat.startMouse.Input.mousePosition.x);
                        if(
    newWidth minWidthnewWidth=minWidth;
                        
    Widths[i] = newWidth;
                    }
                }
            
    GUI.EndGroup ();
            
    GUI.EndScrollView();
           
            
    //GUI.Button(new Rect(10, 20, 400, 20), "Can't drag me");
            //GUI.DragWindow();
           
            
    if(Input.GetMouseButtonDown(0))
            {
                
    Rect topBar BrowserRect;
                
    topBar.height 15;
                if( 
    topBar.Contains(GetMouseCord()) )
                {
                    
    DragStat.Dragging true;
                    
    DragStat.startMouse GetMouseCord();
                    
    DragStat.startPosition = new Vector2(BrowserRect.xBrowserRect.y);
                    
    DragStat.type DragType.Window;
                }
            }
            if(
    DragStat.Dragging  DragStat.type==DragType.Window)
            {
                
    Vector2 MouseCord GetMouseCord();
                
    Vector2 newPos DragStat.startPosition - new Vector2(    DragStat.startMouse.MouseCord.x,
                                                                        
    DragStat.startMouse.MouseCord.y);
                
    BrowserRect.newPos.x;
                
    BrowserRect.newPos.y;
            }
        }
       
        
    Rect GetRect(int indexint spaceint height)
        {
            
    int x 10;
            for(
    int i=0i<index; ++i+= space+Widths[i];
            return new 
    Rect(x0Widths[index], height);
        }
       
        
    int[] GetPathIndexesAt(string Parent)
        {
            
    int[] Temp = new int[PathTree.Length];
            
    int n 0// Number of paths found at Parent.
            
    for(int i=0i<PathTree.Length; ++i)
            {
                if(
    System.IO.Path.GetFullPath(PathTree[i].Parent) == System.IO.Path.GetFullPath(Parent))
                {
                    
    Temp[n] = i;
                    
    n++;
                }
            }
            
    int[] OUT = new int[n];
            for(
    int i=0i<OUT.Length; ++i)
            {
                
    OUT[i] = Temp[i];
            }
            return 
    OUT;
        }
       
        
    void GetAllSubDirectoriesAndFiles(String MainDirectory)
        {
            
    PathTree = new Path[0];
            
    WalkTheTree( new DirectoryInfo(MainDirectory) );
        }

        
    void WalkTheTree(DirectoryInfo DI)
        {
            
    String PARENT DI.FullName;
            
    DirectoryInfo[] diArr DI.GetDirectories();
            
    FileInfo[] fiArr DI.GetFiles();
           
            
    //Debug
            
    Path[] PathTreeTemp = new PathdiArr.Length fiArr.Length ];
            for (
    int i=0i<diArr.Length; ++i)
            {
                
    //Debug.Log(diArr[i].Name);
                
    PathTreeTemp[i].Name diArr[i].Name;
                
    PathTreeTemp[i].Parent PARENT;
                
    PathTreeTemp[i].File false;
            }
            
    int diArrLength diArr.Length;
            for (
    int i=diArrLengthi<PathTreeTemp.Length; ++i)
            {
                
    PathTreeTemp[i].Name fiArr[i-diArrLength].Name;
                
    PathTreeTemp[i].Parent PARENT;
                
    PathTreeTemp[i].File true;
            }
           
            
    PathTree AddPathArraysPathTreePathTreeTemp);
           
            foreach (
    DirectoryInfo di in diArr)
                
    WalkTheTreedi );
        }
       
       
       
        
    void OverwriteDuplicates(String FTSString FL)
        {
            if(
    Directory.Exists(FL)) Directory.Delete(FLtrue);
            else if (
    File.Exists(FL)) File.Delete(FL);
            
    Directory.Move(FTSFL);
        }
       
        
    void AddPath(String addint indexOfAdd)
        {
            
    String[] Temp = new String[indexOfAdd+1];
            for(
    int i=0i<indexOfAdd; ++iTemp[i] = OpenPaths[i];
            
    Temp[Temp.Length-1] = add;
            
    OpenPaths Temp;
           
            
    Temp = new String[indexOfAdd+1];
            for(
    int i=0i<indexOfAdd; ++iTemp[i] = OpenPaths_Reduced[i];
            
    Temp[Temp.Length-1] = (new DirectoryInfo(add)).Name;
            
    OpenPaths_Reduced Temp;
           
            
    WindowName ""// Get the Name of the window.
            
    for(int i=0i<OpenPaths_Reduced.Length; ++iWindowName += "/"+OpenPaths_Reduced[i];
        }
       
        
    void AddWidth()
        {
            
    int[] Temp = new int[Widths.Length+1];
            
    Widths.CopyTo(Temp0);
            
    Temp[Temp.Length-1] = defaultWidth;
            
    Widths Temp;
        }
       
        
    void AddScrollPosition(int indexOfAdd)
        {
            
    Vector2[] Temp = new Vector2[indexOfAdd+1];
            for(
    int i=0i<indexOfAdd; ++iTemp[i] = ScrollPositions[i];
            
    Temp[Temp.Length-1] = Vector2.zero;
            
    ScrollPositions Temp;
        }
       
        
    Path[] AddPathArrays(Path[] IN1Path[] IN2)
        {
            
    Path[] Temp = new Path[IN1.Length IN2.Length];
            
    IN1.CopyTo(Temp0);
            
    IN2.CopyTo(TempIN1.Length);
            return 
    Temp;
        }
       
        
    Vector2 GetMouseCord()
        {
            
    Vector2 mouse Input.mousePosition;
            
    mouse.Screen.height-mouse.y;
            return 
    mouse;
        }
    }

    struct Path
    {
        public 
    String Parent;
        public 
    String Name;
        public 
    bool File// If false, it's a folder.
    }

    struct Drag
    {
        public 
    bool Dragging;
        public 
    Vector2 startMouse;
        public 
    Vector2 startPosition;
        public 
    DragType type;
        public 
    int column;
    }

    enum DragType
    {
        
    Column,
        
    Window,
        
    WindowScaler
    }

    enum WindowType
    {
        
    Open,
        
    Save
    }
     
    Last edited: Oct 1, 2016
  2. bigkahuna

    bigkahuna

    Joined:
    Apr 30, 2006
    Posts:
    5,434
  3. inventor2010

    inventor2010

    Joined:
    Nov 3, 2010
    Posts:
    124
    Thank you bigkahuna, just finished adding it here.

    First time using a wiki. :)

    Hope it helps some one!
     
  4. inventor2010

    inventor2010

    Joined:
    Nov 3, 2010
    Posts:
    124
    To any one who has looked at this before and had to contend with the
    Code (csharp):
    1. Assets/Script/Browser.cs(134,74): error CS0103: The name `Fun' does not exist in the current context
    error, I apologize. I thought that I removed all dependency on other scripts that I have in my project, but apparently I didn't test that.

    Fun is just short for functions, its just a script I wrote with a bunch of standard functions I use regularly like MouseCord which just inverts the y position provided by Input.mousePosition.

    This script will work on its own now, I edited my original post, and I actually tested it in a separate project this time ;)

    Thanks to Michele for bringing that to my attention!

    I will probably update this script soon as well, I've just been really busy with school.
     
  5. Ryuuguu

    Ryuuguu

    Joined:
    Apr 14, 2007
    Posts:
    391
    Has anyone used this on Windows stand alone build. It works great in my mac editor and my Mac build but it shows no directory on WindowsXP for me.

    cheers,
    Grant
     
  6. suppenhuhn

    suppenhuhn

    Joined:
    Dec 15, 2011
    Posts:
    37
    hi!

    great thing - exactly what i was looking for the last few weeks!! thank you for sharing!
    i have only one problem: i don't get it running :(
    think because i'm the worst programmer on earth - is there a demo scene on the wiki available also?

    merry christmas!
     
  7. inventor2010

    inventor2010

    Joined:
    Nov 3, 2010
    Posts:
    124
    Thnaks ryuuguu and suppenhuhn,

    ryuuguu,
    Sorry I haven't gotten back to you on this sooner, I've been busy with school and working on an in-game editor (the in-game editor being the reason why I made this script). I'm almost ready to release the editor on the Asset Store, and now that I'm on break I'm going to work with this script further. I'm going to go see whats wrong with the windows build right now. Even when I release my editor though, I will keep updating this script as I improve it, to help the community.

    suppenhuhn,
    Are you also trying to run it on windows?
    In either case I'll post a demo project of it in a few min.

    Merry christmas to you too!
     
  8. suppenhuhn

    suppenhuhn

    Joined:
    Dec 15, 2011
    Posts:
    37
    yes, i'm working on a windows machine - win7 64bit. yeah, a short demoscene would be great!

    but now for me it's time to go sleeping .. gn8!
     
  9. inventor2010

    inventor2010

    Joined:
    Nov 3, 2010
    Posts:
    124
    ...Several hours after a few min, I figured out the problem Browser was having on windows and I made a demo Project.

    Here is the demo project: View attachment $Browser Demo Project.unitypackage . Just load it into a empty project and run. There is no "Read Me" file, but there are several lengthy comments in "Browser Test window.js" that you may want to read to understand whats actually going on.

    Any way, for any one who is curious, the problem Browser was having on windows was... Windows... (can tell I'm a mac person here :D ). But seriously, theres a line in Browser where 2 paths need to be checked to see if they are identical or not, but in windows sometimes it would give forward slashes as the separators between folder names, and sometimes it would give backward slashes.
    example: "C:/folder/bla"=="C:\folder\bla"
    So basically even when the paths are in fact identical, the strings representing them were not, so it wouldn't execute any of the code that draws the file names on the screen.

    Solution: pass both of the strings into "System.IO.Path.GetFullPath( String )" before checking if they are identical, "GetFullPath" always returns paths with the same slashes for separators.

    I've updated the browser script here and on the wiki accordingly. I also fixed a minor bug with the new folder button not working when a file is selected and not a folder.

    Enjoy, and mary christmas! :D
     
  10. gads

    gads

    Joined:
    Oct 10, 2008
    Posts:
    34
    I've download this code asset and tried it in my project.
    I don't know what's happened or why, but when I tried to Save File to my project's folder it just erase it, causing me to lost several days of work... (yes, last time I used Time Machine to backup my files was a week ago).

    So, as far as I'm concerned, this code asset is a public menace :p
     
  11. inventor2010

    inventor2010

    Joined:
    Nov 3, 2010
    Posts:
    124
    public menace? :(

    I'm sorry gads for what happened, I'm just coding in my free time and sharing a few things that I learn as I go, I never meant to harm anyone, it's just an honest mistake.

    Most of what you see there is just interface, and a few functions and classes for walking a directory tree.

    The save function....
    Code (csharp):
    1. SaveFile(String FilePath, String mainFolder)
    is the only thing that even has a deleate command in it...

    I never even thought about it, but your suppose to pass that function a file that you want it to save, and then the directory you wish to restrict the user to. If the user cancels, the file that you passed it to save is deleted to prevent a pile up of temporary files.

    I guess if you reverse it and put your project into "FilePath" by mistake it would delete your project, believing it was a file you wanted the user to be able to save.

    I'm sorry for the inconvenience, I didn't even think that this thing could do something like that.

    I'll add a warning for now, and get to work on a dummy window "Are you sure you want to delete file ___?"
     
  12. inventor2010

    inventor2010

    Joined:
    Nov 3, 2010
    Posts:
    124
    I'm sorry gads... This is my fault, I thought it may be due to user error, but it's my instructions.

    I reversed it in my initial description:

    It should be:
    Again, this is my fault, honest mistake, I can't imagine you'd want to use it now, but it should work if you reverse those 2 variables... Please try it on an empty project though! Let me know if you have any other issues!

    I've updated the tutorial, will go update the wiki now, I've added a warning as well, hopefully no one has to go through what you did again. The demo project I have in the 6th post down doesn't have this mistake so that should be safe.

    I'll try and figure out how to prevent it from doing this, just in case, maybe block the deletion of any folder called "assets". But it's suppose to be that you create a save file and use browser to move it, to the user it looks like they are saving normally, if they click cancel, they shouldn't even know of the temporary file, so having a warning "are you sure you want to delete ___" is kinda awkward.

    Please, from now on though, use an empty project for any kind of testing of third party plugins, its not your fault, but to be on the safe side next time, I'm still learning too (as every one always is) mistakes happen, please prepare your self for them.
     
  13. gads

    gads

    Joined:
    Oct 10, 2008
    Posts:
    34
    Hi inventor2010,

    Yes, it was a bad feeling when I saw my project vanish in the void... However I remembered later that I had enabled OSX Lion Versions system that keeps documents' changes in disc and and it does not require that the backup disc has to be connected to the laptop. It allowed me to recover all my work :D
    Hurray for Lion Versions :D

    About you plugin.
    I don't quite remember what were the arguments that I sent to the SaveFile function. I think it was SaveFile(Temporary_Path_Of_The_Save_File_Inside_Project_Folder, The_Path_To_My_Project_Folder);

    Since the plugin is an interface for navigating through directories, probably it makes more sense to code it so it would return the selected path, instead of creating a temporary file (I don't quite understand why you are doing it).


    cheers,
     
  14. inventor2010

    inventor2010

    Joined:
    Nov 3, 2010
    Posts:
    124
    Great!

    Glad to know nothing was lost, in the end! And to think, I still like Snow Leopard more. :eek:

    It's been a while since I coded it, but If I remember right, I didn't return a path because theres an unpredictable amount of time where the user is naming, moving files, and picking their save location. I wasn't sure how to simply return a chosen path, If you have any suggestions I'd be more than happy to hear them, may speed up some other programming I'm doing, but without accessing pointers or something I'm unsure how to have it return a path after x time.

    I guess it could be modified to be incorporated with your code, call a specific function when the user is done, but I wanted to keep it as plug and play as possible (void load and void save).
     
  15. WOOYU

    WOOYU

    Joined:
    Jul 7, 2014
    Posts:
    2
  16. agarama

    agarama

    Joined:
    May 27, 2015
    Posts:
    1
    tiny file dialogs on sourceforge is a single C / C++ file that provides cross-platform file dialogs. It has no init and no main loop.
     
    Last edited: May 29, 2015
  17. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    It's great of the community to provide this. I think it would work pretty well for save-game purposes.

    It doesn't work so well for more general purposes; e.g., if I were making some sort of model browser, I need to let people navigate to anywhere on their hard drive to select a model. This script only lets you browse files under one subdirectory; there's no way to go up, and if you try to start it at root, it hangs while it tries to preload every directory on the disk!

    Does anybody know of any good alternatives to this script?
     
  18. inventor2010

    inventor2010

    Joined:
    Nov 3, 2010
    Posts:
    124
    Hehe, Yeah... I remember that! :p

    Your right, it does not work well with large directory tree's!

    I (or anyone) could probably implement an incremental loading of the tree as the user browses though.

    But, as you noted, it's good for save-game purposes, which was all I was focused on at the time.

    If you wanted to mod it, I would love to see it added to the community again! :D The primary variable that needs to be refracted appears to be PathTree, which is a rather deceptive name, because I quite lazily made it an ordinary array since I was more focused on the UI at the time.

    I might update it. But I'm a bit focused on other things atm (like getting a new job). :p
     
  19. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    No problem... I ended up going with File Chooser Dialog Box, which isn't perfect either, but is close enough for my current project.

    I might revisit this in the future, though... I have pretty strong feelings about file dialogs. :)

    Good luck with the job search!
     
  20. Oleszek

    Oleszek

    Joined:
    Aug 21, 2015
    Posts:
    5
    It's very small on a screen of smartfon on Android. Is there an easy way to make window and fonts independent of screen resolution?