2015-02-08 6 views
8

Próbuję pracować z klasą SpriteKit SKMutableTexture, ale nie wiem jak pracować z UnsafeMutablePointer<Void>. Mam niejasny pomysł, że jest to wskaźnik do szeregu danych bajtowych w pamięci. Ale jak mogę to zaktualizować? Jak by to wyglądało w kodzie?Co to jest UnsafeMutablePointer <Void>? Jak zmodyfikować pamięć podstawową?

Edit

Oto podstawowe przykładowy kod do pracy. Jak mogę to zrobić, aby zrobić coś tak prostego, jak stworzyć czerwony kwadrat na ekranie?

let tex = SKMutableTexture(size: CGSize(width: 10, height: 10)) 
    tex.modifyPixelDataWithBlock { (ptr:UnsafeMutablePointer<Void>, n:UInt) -> Void in 

     /* ??? */ 

    } 

Odpowiedz

12

Od docs dla SKMutableTexture.modifyPixelDataWithBlock:

Tekstura bajtów Zakłada się być przechowywane w szczelnie zapakowane 32 BPP 8bpc (unsigned integer) danych pikseli RGBA. Dostarczone składniki kolorów powinny już zostać pomnożone przez wartość alfa.

Tak więc, gdy otrzymujesz void*, dane bazowe mają postać strumienia 4x8 bitów.

Można manipulować taką strukturę tak:

// struct of 4 bytes 
struct RGBA { 
    var r: UInt8 
    var g: UInt8 
    var b: UInt8 
    var a: UInt8 
} 

let tex = SKMutableTexture(size: CGSize(width: 10, height: 10)) 
tex.modifyPixelDataWithBlock { voidptr, len in 
    // convert the void pointer into a pointer to your struct 
    let rgbaptr = UnsafeMutablePointer<RGBA>(voidptr) 

    // next, create a collection-like structure from that pointer 
    // (this second part isn’t necessary but can be nicer to work with) 
    // note the length you supply to create the buffer is the number of 
    // RGBA structs, so you need to convert the supplied length accordingly... 
    let pixels = UnsafeMutableBufferPointer(start: rgbaptr, count: Int(len/sizeof(RGBA)) 

    // now, you can manipulate the pixels buffer like any other mutable collection type 
    for i in indices(pixels) { 
     pixels[i].r = 0x00 
     pixels[i].g = 0xff 
     pixels[i].b = 0x00 
     pixels[i].a = 0x20 
    } 
} 
+0

Próbowałem tego z przykładowym projektem SpriteKit w Xcode i wydaje się, że robię to, co trzeba - ale nie wiem nic o SpriteKit, więc nie mogę zagwarantować, że to "droga", aby to zrobić. –

+0

Dziękuję, że to działa. Teraz widzę kwadrat na ekranie, spodziewałem się jednak, że metoda modifyPixelDataWithBlock będzie wywoływana raz na ramkę - jak jakaś alternatywa dla modułu cieniującego fragmentu, ale blok jest wywoływany tylko raz. Więcej kopania ... – Bret

+0

Pamiętaj, że musisz przekazać wstępnie pomnożone przez alfa wartości dla części RGB. Z [docs] (https://developer.apple.com/library/ios/documentation/SpriteKit/Reference/SKMutableTexture_Ref/# // apple_ref/occ/instm/SKMutableTexture/modifyPixelDataWithBlock :) 'Zakładamy, że bajty tekstur są przechowywane jako ciasno spakowane 32 bpp, 8bpc (bez znaku liczby całkowitej) RGBA pixel dane. Podane składniki kolorów powinny już zostać pomnożone przez wartość alfa. " – Benzi

7

UnsafeMutablePointer<Void> jest odpowiednikiem Swift z void* - wskaźnik do niczego w ogóle. Możesz uzyskać dostęp do podstawowej pamięci jako jej własności memory. Zazwyczaj, jeśli wiesz, jaki jest podstawowy typ, najpierw zmusisz go do wskazania tego typu. Następnie można użyć indeksowania, aby osiągnąć określony "slot" w pamięci.

Na przykład, jeśli dane są naprawdę ciągiem wartości Uint8, można powiedzieć:

let buffer = UnsafeMutablePointer<UInt8>(ptr) 

Możesz teraz uzyskać dostęp do poszczególnych wartości UIInt8 jak buffer[0], buffer[1], i tak dalej.

+0

i zobacz moje Swift poradnik o więcej informacji: http://www.apeth.com/swiftBook/apa.html#_c_pointers – matt

+0

sądząc po sposobie podpis [modifyPixelDataWithBlock] (https://developer.apple.com/library/ios/documentation/SpriteKit/Reference/SKMutableTexture_Ref/index.html#//apple_ref/occ/instm/SKMutableTexture/modifyPixelDataWithBlock :), myślę, że podstawowe type to 8-bitowa liczba całkowita. Jak wyglądałaby obsada w kodzie? Naprawdę mam nadzieję na kilka próbek kodu, jak to zrobić – Bret

+0

Jeśli jest to 8-bitowa liczba całkowita, byłby to Int8 lub UInt8. Więc jeśli rzutujesz na UnsafeMutablePointer lub UnsafeMutablePointer , w zależności od tego, który z nich jest, możesz użyć indeksowania, aby uzyskać indywidualny bajt po numerze. – matt