Yann's Forum Posts

  • zatyka

    I do agree that the plugin's interface is a bit clunky and I would have liked for it to be simpler and more straight forward. However, I wouldn't bet on a reworking of the engine anytime soon.

    Hopefully, I do think that with it, you can do everything you can do with a basic javascript object (well almost... you can't copy an object by reference... yet :3)

    In any case, the JSON plugin's topic is always opened for suggestion =)

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • vtrix

    First there's never been any JSON.Key(...) expression, with or without parameters.

    Getting the key at a specific path doesn't mean much thing, because the key would be the last part of the path you are setting.

    Key(0,"my","path") should return "path". Key(0) shouldn't return anything (although it's "root" in javascript, but this implementation detail needs to be hidden from the user)

    Mabye the only use I could think of is Key(1) that would return the last component of the CurrentPath, but you should already know it in your code somehow.

    The only place where you could be unable to know the CurrentPath is in the foreach loop, that's why CurrentKey is set here.

    Otherwise, Value(0,"my","path") is already returning the value at the given path, and Value(1,"my","path") as well but relatively to CurrentPath.

    The difference between v1.0 and v1.1 is just the addition of CurrentValue which is an alias to Value(1).

    The other change I made was to reset the CurrentPath to what it should be at the begining of each loop iteration, and reset it to what it was before the foreach loop when you exit it.

    I was thinking about providing an alias like ValueFromRoot("my","path") and ValueFromCurrent("my","path") to make things more clear (maybe someone has a better idea)

    So, to summarize, I fail to see where a `Key` expression would be usefull, and the `Value` expression already works as expected, isn't it?

    And as far as CurrentKey and CurrentValue goes I prefer them to be simple. They are more or less the equivalent of the Dictionary counterpart.

  • vtrix

    thanks nice finding, I was doing

    delete array[0];[/code:1o8zrg4h]
    but this doesn't change the size of the array so javascript set it to undefined (which is transformed to null on export)
    I have to do [code:1o8zrg4h]array.splice(0,1);[/code:1o8zrg4h]
  • vtrix

    Well... The problem is a mix between javascript ambiguity, striving for simplicity (nice way to say laziness) and giving as much control as possible

    In javascript, you usually loop through array elements like this:

    for (var i = 0; i < myArray.length; i++) {
          // do things with myArray[i]
    }[/code:3sbiy7t4]
    and you loop through objects members like this:[code:3sbiy7t4]for (var m in myObject) {
          // do things with myObject[m]
    }[/code:3sbiy7t4]
    
    Thing is, in javascript arrays are also some kind of objects. So looping using a for-in works.
    However there are few differences.
      - With the first solution you have an index that increments. So expected ordering is ensured and you only explore the range between 0 and size-1
      - With the second you treat array indexes as object properties, so if you did weird things like adding a value to an array using a non positive integer (like -1) or a key as an index (c2 doesn't prevent that), you would, at least, be able to loop through it using For each property. However, if I'm not wrong the JSON exporting will just export the array part, so overall adding properties to an array should be discouraged)
      - If you skip array indexes, like for example set a value at index 10 on an less than 9-elements array, the first loop will allow you to loop through all the indexes from 0 to 10 (the inbetweens will return undefined and the JSON export will be padded with null), whereas if you use the second loop (for... in) you'll only loop through existing indexes (skipping the inbetweens)
    
    So my idea was to leave as much possibilities as the user might want (so internally choosed "for .. in") while avoiding confusion (there's only one type of loop)
    This way:
    [ul]
    	[li]If you want to loop through arrays like an object (for... in), use For each property[/li]
    	[li]otherwise, use a for/repeat loop like this:[code:3sbiy7t4]+ System: repeat JSON.Size(0,"path","to","array")[/li]
    [/ul]   -> Browser: log JSON.Value(0,"path","to","array",loopindex)[/code:3sbiy7t4]which is equivalent to for(var i = 0; i < arr.length, i++) {...}
    
    As for the necessity to cast currentKey to int... it's because I return currentKey as a string, I should probably return it as an "any" type (meaning string or number).
  • vtrix , shinkan (mostly highlighting you since you were the most active (: )

    New version: JSON v1.1

    The first post documentation has been updated to reflect this change

    ChangeLog

    v1.1 - 2014-04-17

      - implement save/load/debugger
      • ToJson deprecated and replaced by AsJson for overall coherence
      • change the brackets syntax for a less confusing one (I hope) before: root["Wizard","stats","hp"]
      after: root@"Wizard","stats","hp"[/code:2i4wuwdv]- change Length for Size and handle object/array return -1 for anything else
      • isEmpty condition and Clear action for array and object
      • add a CurrentValue property
      • in foreach loop reset the current path to the path given at the begining on each iteration, this way we can mess with this current path to our heart content within the loop
      • more reliable logData

    Have fun testing

    If all go well, I'll probably move it to completed plugin.

  • vtrix

    Ok very interesting. At first I thought it was just a simple misuse, but it turned out there were a very peculiar issue.

    So first for the misuse, which is more of a design flaw for now, is that the foreach loop is actually modifying the current path to point to the property being foreached ( which doesn't work properly if you loop using an root based path (the loop will ignore the path <_<)). So, if you modify the current path inside the foreach loop, everything can get fucked up (:

    Here is one example case:

    considering this object:

    { "Wizard": {
          "stats":{
             "hp":100,
             "mp":80,
             "int":120,
             "dex":20,
             "str": 10
          },
          "buffs": {
             "hp":10,
             "mp":15,
             "int":10,
             "dex":3,
             "str": 2
          }
       }
    }[/code:2xof0hjw]
    
    Let say we want to loop through all the property and display their stats + buffs. It could be done like that:
    [code:2xof0hjw]
    -> System: set Current Path to root["Wizard","stats"]
    + JSON: foreach current[]  // using foreach root["Wizard","stats"] is broken
      Local text property = ""
      Local number value = 0
      -> System: set property to JSON.CurrentKey
      -> System: set value to JSON.Value(1,CurrentKey)
      -> System: set Current Path to root["Wizard","buffs"] // here you are modifying the looping path
      -> Text: Set text to property & ":" & value& " + " & JSON.Value(1) & " = " & value+ JSON.Value(1)[/code:2xof0hjw]
    
    Here is what will be output in the text object:
    [code:2xof0hjw]hp:100 + 10 = 110
    mp:15 + 15 = 30
    int:10 + 10 = 20
    dex:3 + 3 = 6
    str:2 + 2 = 4[/code:2xof0hjw]
    As you can see, after the first iteration, the loop is in fact looking into the buffs path
    and if you doesn't have the same properties in the two path you'll get some NaN or undefined values.
    
    I see two possible solutions to this problem:
     1. have a separated Current Path and Loop Path. As much as it makes sense now, I think it's a very confusing solution. What would be the current[]  in this situation? or maybe I should have root/current/loop... And what happens with nested loops? should I name those path like it's done with for loops and loopindex?... So yeah I'm not too sure about this idea
     2. have the loop reset the Current Path to the original path after each iterations. Good thing is, it's simple and straightforward to implement and use. Bad thing is, any change to the current path you do inside a loop will be lost at the end of the iteration (cannot be saved for later). But I think it's a very specific case and I can easily find a work around using an array in C2 and making a "savePath" and "buildPath" function.[code:2xof0hjw]// Function.Call("loadPath")
    + Function: On "loadPath"
       -> JSON: Set Current Path to root[]
       + Array: For each X element
          -> JSON: Set Current Path to current[Array.CurValue][/code:2xof0hjw][code:2xof0hjw]// Function.Call("savePath","path","you","want","to","save",...)
    + Function: On "savePath"
       -> Array: Set size to (0,1,1)
       + System: Repeat Function.ParamCount times
          -> Array: Push back Function.Param(loopindex) on X axis[/code:2xof0hjw]
    Though one weakness is that you can't dynamically save the path because you have no way, during a foreach loop, to know the entire path, you just know the CurrentKey. If you are recursively inspecting an entire unknown JSON it's harder to save a spacific path (probably doable if you save the path constantly during the recursion...)
    Maybe I could add a "foreach Node in the path"condition you could call in savePath instead of passing parameters.
    
    Anyway, now, for the real interesting stuff I discovered thanks to your capx:
    1. The list of parameters you pass in set Current Path to root["template","folder"], which is internally an array, is in fact built just once, and the same array object is passed over and over each time C2 reaches this action (at least during a given tick).
    And the plugin was using this very same array as a current path, and this array was modified when going through your two first foreach.
    That's why when you execute the run function a second time, you are already at root["template","folder","object1","path"] instead of root["template","folder"]. The array of argument was modified during the previous run.
    Hopefully this is easily solvable by using a copy of this array.
    2. A the end you logged properties (0, 1, 2, 3, 4 ,5 ,6)  that didn't really make sense since there were no array in your JSON. And the reason for that is that, in the second run, your first foreach was looping through the value at ["template","folder","object1","path"] which was actually the string "folder2". Javascript often consider strings as arrays of character, so you where looping through the 7 letters and was logging their indices. (which is more an unexpected feature than a bug )
  • vtrix

    it will obviously (:

  • vtrix

    Not sure I understand all that you are saying, an example capx to illustrate your case would be better.

    Anyway, a simple capx showing how to simply go from array to the JSON plugin:

    arrayToJSONplugin.capx

  • vtrix

    You guessed right, when I do

    JSON.ToJson(0,"Star1")[/code:2v4ltxd4]in javascript I in fact do[code:2v4ltxd4]JSON.stringify(this.root["Star1"]);[/code:2v4ltxd4](well not exactly since I loop through the arguments provided to go through the path, but in a nutshell that's what I do)
    
    So yeah, if you already have the JSON string as a template, instead of copying one object into another with that[code:2v4ltxd4]-> JSON: Load JSON at root["Star2"] to JSON.ToJson(0,"Star1")[/code:2v4ltxd4]Doing that:[code:2v4ltxd4]-> JSON: Load JSON at root["Star2"] to myTemplate[/code:2v4ltxd4] (with myTemplate containing the JSON string for your... template) 
    would be slightly more efficient but you still will do a javascript JSON.parse(myTemplate) which can potentially be a bit slow as well (meaning slower than just passing references in javascript)
    
    If I rename the Length property I would probably not use ObjectSize but just Size, so you could use it for arrays or objects. (Note that your projects using Length will break when I'll make this change... or I can just set it to deprecated for a while to give you the opportunity to change it)
    
    Not sure I get your thing about ID. If you want to reference a JSON object using some kind of numbering, an array seems ok, you just need that numbering to be consecutive. (well in theory, javascript allows non consecutive indexing but when generating a JSON from that, in chrome at least, you get an array with the holes filled with null)
    For example you could do:[code:2v4ltxd4]-> JSON: Create new array at root[]
    -> JSON: Create new object at root[2]
    -> JSON: Create new object at root[4][/code:2v4ltxd4]but then if you want to get back the JSON you'll get something like[code:2v4ltxd4][null,null,{},null,{}][/code:2v4ltxd4]The other possibility would be to reference them in an object using the ID as a key.
  • shinkan

    You can't do that kind of thing in any language I know of.

    JSON objects (a.k.a. dictionnary or hashtables) are values indexed using a key.

    The only way to change the key, for a given value, is, as you did, copying to another key and deleting the previous one.

    In javascript it wouldn't be a big deal because you would probably just swap objects references (the new key will point to the same object, hence no copy). But since, in construct2, you don't have access to any value type other than strings and number, it's not possible.

    To be clear, you would have that in javascript:

    // this creates an empty object
    // and put its reference in the variable root
    var root = {};
    
    // this creates an object with "name" and "size"
    // and  put its reference in the "Star1" property of root
    root["Star1"] = {"name":"somename","size":"somesize"};
    
    // "Star1" and "Star2" properties point to the same exact object
    root["Star2"] = root["Star1"];
    
    // for example:
    root["Star1"]["name"] = "plop";
    root["Star2"]["name"] == "plop"; // this will return true ("==" means "is equal?")
    
    // then to finish things up, in javascript you would do:
    delete root["Star1"];[/code:3clgjt1x]
    
    Now, the closest thing you can do with the current JSON plugin is:[code:3clgjt1x]-> JSON: Set Value at root["Star1"] to "{""name"":""somename"",""size"":""somesize""}"
    -> JSON: Load JSON JSON.ToJson(0,"Star1") at root["Star2"] // the copy
    -> JSON: delete root["Star1"][/code:3clgjt1x]
    as you notice it's almost the same
    The only difference is that after the copy (and before the delete) if you modify the object in "Star1", the one in "Star2" will be left untouched because it's not a reference but a copy.
    
    Modifying the key this way is totally fine, but you have to be carefull because copy is slower than just passing references. And going from an object to a JSON string to a new object is even slower than if you just copied each properties one by one. But it's a lot simpler (:
  • vtrix

    Thing is, even in javascript you have no property/function to get the number of properties in an object. An object has no length per se.

    The way you can answer this question is to usually count them manually

    var count = 0;
    for (var p in myObject) {
        if(myObject.hasOwnProperty(p) {
             count++;
        }
    }[/code:1eqcbou2]
    I could implement that, but I'm not sure if it's a good idea to blend the boundaries between array and object. If the user can get the property count (which shouldn't really be called length) they might be tempted to believe they could loop through properties using indices... well still thinking about it.
    
    Hmm, yeah I might add that as well as "isEmpty" and "Clear" function for array and object. We'll see. Maybe renaming "Length" to "ElementCount" or something more general to cover array and objects with the same function... 
    Hmm according to json.org, objects contain "members" whereas arrays contain "elements"... not sure how far I should stick to the vocabulary.
    Hmm... "Size" might be better then.
  • zenox98

    What's uploaded to the arcade is just the event sheet structure. The arcade concatenates this with the whole runtime.

    If there's a bug, I would guess it's in the common javascript used in the arcade that's causing it. Somehow it probably became out of date with how firefox 28 works... not sure.

    I could maybe solve the problem by doing a new export, but I'm not even sure where is the last capx or if it would still work (nope I'm not lazy... not at all!)

    So... meh... maybe on one rainny day.

    Looking at it closely, the problem comes from the fact that firefox changed they renamed "noteOn" and "noteOff" function of the AudioContext's BufferSource object for "start" and "stop".

    So I guess I'm probably not the only one who should reexport their game. Or maybe better, scirra arcade should update its code to correct all the bugs in one place =) (dunno how hard it would be)

  • In my case events looked a lot like:

    Three: Create scene "myScene"
    Three: Create camera "myCamera" (fov:30, aspect:windowWidth/windowHeight)
    Three: Create CubGeometry "myCube" (10,10,10,1,1,1)
    Three: Create BasicMaterial "myMat" diffuse: "0xff0000"
    Three: Create Mesh "myMesh" with geometry "myCube" and material "myMat"
    Three: Create PointLight "myLight" intensity: "1.0"
    Three: Position object "myMesh" at (1,0,2)
    Three: Position object "myLight" at (2,5,2)
    Three: Position object "myCamera" at (2,5,-2)
    Three: Camera "myCamera" lookAt (1,0,2)
    Three: add object "myCamera" to scene "myScene"
    Three: add object "myMesh" to scene "myScene"
    Three: add object "myLight" to scene "myScene"
    Three: Render scene with camera "myCamera" and scene "myScene"[/code:1vgphv7x]
    At some point I think it's easier to do in javascript directly.... You lose almost all of c2's advantages.
  • TikTik

    I'm not sure I understand what you are saying

    But your browser blocking pop-ups is a security measure to avoid... well... pop-ups. So I'd say it's not possible to go around that.