anchor.diff:                        end
                       end;
                       //done making controls, now set objects
  -                    query.SQL.Text := 'INSERT INTO GENE_CONTROL_OBJECTS (CONTROL_ID, OBJECT_ID, OBJECT_TABLE) VALUES (:CONTROL_ID, :OBJECT_ID, :OBJECT_TABLE)';
  +                    query.SQL.Text := 'INSERT INTO GENE_CONTROL_OBJECTS (CONTROL_ID, OBJECT_ID, OBJECT_TABLE, SIDE, OBJECT_TYPE) VALUES (:CONTROL_ID, :OBJECT_ID, :OBJECT_TABLE, :SIDE, :OBJECT_TYPE)';
                       query.ParamByName('OBJECT_TABLE').Value := 'GENE_ROAD'; //for now can only use GENE_ROAD change when OTConnector is updated
  +                    if selectCategories.Count > 0 then
  +                      query.ParamByName('OBJECT_TYPE').Value := selectCategories.Items[0].Value
  +                    else
  +                      query.ParamByName('OBJECT_TYPE').Clear;
                       for id in objects.Keys do
                       begin
                         query.ParamByName('OBJECT_ID').Value := id;
                         if objects[id] = -1 then
  -                        query.ParamByName('CONTROL_ID').Value := leftID
  +                      begin
  +                        query.ParamByName('CONTROL_ID').Value := leftID;
  +                        query.ParamByName('SIDE').Value := -1;
  +                      end
                         else if objects[id] = 1 then
  -                        query.ParamByName('CONTROL_ID').Value := rightID
  +                      begin
  +                        query.ParamByName('CONTROL_ID').Value := rightID;
  +                        query.ParamByName('SIDE').Value := 1;
  +                      end
                         else
  +                      begin
                           query.ParamByName('CONTROL_ID').Value := mainID;
  +                        query.ParamByName('SIDE').Value := 0;
  +                      end;
                         query.ExecSQL;
                       end;
                       //done writing objects, now set properties
  
positive.code:       end
        else if tag = tagProperties then
        begin
  
        end
        else if tag = tagRemove then
        begin
          //remove control from gene_control, gene_control_object & gene_control_properties
          //remove control from all scenario's...
          //send updates
          //in theory this could go wrong -> lock tables as we go along then commit after?
          deleteIDs := TList<Integer>.Create;
          try
            error := False;
            usProject.OraSession.StartTransaction;
            try
              query := TOraQuery.Create(nil);
              try
                query.Session := usProject.OraSession;
  
                //lock the table
                query.SQL.Text := 'LOCK TABLE GENE_CONTROL IN EXCLUSIVE MODE';
                query.ExecSQL;
  
                //read controls we have to delete from db, so we can process them all
                deleteIDs.Add(controlID);
                deleteString := controlID.ToString;
                while deleteString <> '' do
                begin
                  query.SQL.Text := 'SELECT OBJECT_ID FROM GENE_CONTROL WHERE PARENT_ID in (' + deleteString + ')';
                  deleteString := '';
                  query.ExecSQL;
                  while not query.EoF do
                  begin
                    deleteID := query.FieldByName('OBJECT_ID').AsInteger;
                    deleteIDs.Add(deleteID);
                    if deleteString <> '' then
                      deleteString := deleteString + ',';
                    deleteString := deleteString + deleteID.ToString;
                    query.Next;
                  end;
                end;
  
                deleteTables := TDictionary<string, string>.Create;
                try
                  deleteTables.Add('GENE_CONTROL', 'OBJECT_ID');
                  deleteTables.Add('GENE_CONTROL_OBJECTS', 'CONTROL_ID');
                  deleteTables.Add('GENE_CONTROL_PROPERTIES', 'CONTROL_ID');
  
                  query.SQL.Text := 'SELECT TABLE_NAME FROM All_Tables WHERE OWNER=:OWNER and TABLE_NAME like :REG ORDER BY TABLE_NAME';
                  query.ParamByName('OWNER').Value := query.Session.username.ToUpper;
                  query.ParamByName('REG').Value := 'V%#GENE_CONTROL';
                  query.ExecSQL;
                  while not query.EoF do
                  begin
                    deleteTables.Add(query.FieldByName('TABLE_NAME').AsString, 'OBJECT_ID');
                    query.Next;
                  end;
  
                  deleteString := '';
                  for I := 0 to deleteIDs.Count - 1 do
                  begin
                    if deleteString <> '' then
                      deleteString := deleteString + ',';
                    deleteString := deleteString + deleteIDs[I].ToString;
                    if I mod 1000 = 999 then
                    begin
                      DeleteMultipleIDs(query, deleteString, deleteTables);
                    end;
                  end;
                  if deleteString <> '' then
                    DeleteMultipleIDs(query, deleteString, deleteTables);
                finally
                  deleteTables.Free;
                end;
              finally
                query.Free;
              end;
              usProject.OraSession.Commit;
            except
              error := True;
              usProject.OraSession.Rollback;
            end;
            if not error then
            begin
              table := usProject.GetTableSync('GENE_CONTROL');
              publishEvent := usProject.IMB3Connection.Publish(usProject.OraSession.Username + '.GENE_CONTROL', false);
              try
                for deleteID in deleteIDs do
                begin
                  publishEvent.SignalChangeObject(actionDelete, deleteID);
                  table.SendAnonymousEvent(actionDelete, deleteID);
                end;
              finally
                publishEvent.UnPublish;
              end;
            end;
          finally
            deleteIDs.Free;
          end;
        end;
      end
      else if aPayload.TryGetValue<TJsonObject>('moveto', moveTo) then
  
negative.code:     function getTooltipJSON: string;
    end;
  
    TUSControlProperties = class
    constructor Create(const aControlID: Integer; aQuery: TOraQuery);
    destructor Destroy; override;
    private
      fID: Integer;
      fName: string;
      fDescription: string;
      fProperties: TDictionary<string, string>;
      fChildren: TList<TUSControlProperties>;
    public
      function GetJSON: string;
    end;
  
    TUSControlsLayer = class(TSimpleLayer)
    constructor Create(aScenario: TUSScenario; const aDomain, aID, aName, aDescription: string;
      aDefaultLoad: Boolean; const aConnectString: string; aSourceProjection: TGIS_CSProjectedCoordinateSystem);
  